You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/07/31 04:59:30 UTC
[50/81] [abbrv] [partial] zest-java git commit: First round of
changes to move to org.apache.zest namespace.
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/Documentation.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/Documentation.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/Documentation.groovy
new file mode 100644
index 0000000..3c06602
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/Documentation.groovy
@@ -0,0 +1,240 @@
+/*
+ * 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.apache.zest.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
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/ModuleReleaseSpecification.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/ModuleReleaseSpecification.groovy b/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/ModuleReleaseSpecification.groovy
new file mode 100644
index 0000000..2d4e34e
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/zest/gradle/plugin/ModuleReleaseSpecification.groovy
@@ -0,0 +1,40 @@
+/*
+ * 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.apache.zest.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
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/Documentation.groovy
----------------------------------------------------------------------
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
- }
-}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/ModuleReleaseSpecification.groovy
----------------------------------------------------------------------
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
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/Qi4j.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/Qi4j.java b/core/api/src/main/java/org/apache/zest/api/Qi4j.java
new file mode 100644
index 0000000..470c166
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/Qi4j.java
@@ -0,0 +1,192 @@
+/*
+ * 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.apache.zest.api;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import org.apache.zest.api.association.AbstractAssociation;
+import org.apache.zest.api.association.AssociationDescriptor;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.composite.CompositeDescriptor;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.composite.InvalidCompositeException;
+import org.apache.zest.api.composite.ModelDescriptor;
+import org.apache.zest.api.composite.TransientDescriptor;
+import org.apache.zest.api.entity.EntityDescriptor;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.property.PropertyDescriptor;
+import org.apache.zest.api.service.ServiceDescriptor;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.value.ValueDescriptor;
+import org.apache.zest.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;
+ }
+ }
+ };
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/Activation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/Activation.java b/core/api/src/main/java/org/apache/zest/api/activation/Activation.java
new file mode 100644
index 0000000..5be35e7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/Activation.java
@@ -0,0 +1,55 @@
+/*
+ * 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.apache.zest.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;
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivationEvent.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivationEvent.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEvent.java
new file mode 100644
index 0000000..c54f4b8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEvent.java
@@ -0,0 +1,81 @@
+/*
+ * 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.apache.zest.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
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListener.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListener.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListener.java
new file mode 100644
index 0000000..a6e3bb1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.apache.zest.api.activation;
+
+/**
+ * Listener for ActivationEvent events
+ */
+public interface ActivationEventListener
+{
+ void onEvent( ActivationEvent event )
+ throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListenerRegistration.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListenerRegistration.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListenerRegistration.java
new file mode 100644
index 0000000..c7d0c2a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivationEventListenerRegistration.java
@@ -0,0 +1,33 @@
+/*
+ * 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.apache.zest.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
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivationException.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivationException.java
new file mode 100644
index 0000000..0008ec9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivationException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.apache.zest.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 );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/Activator.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/Activator.java b/core/api/src/main/java/org/apache/zest/api/activation/Activator.java
new file mode 100644
index 0000000..a57b353
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/Activator.java
@@ -0,0 +1,54 @@
+/*
+ * 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.zest.api.activation;
+
+/**
+ * Assemble Activators to hook Services Activation.
+ *
+ * @param <ActivateeType> Type of the activatee.
+ *
+ * @see ActivatorAdapter
+ * @see org.apache.zest.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;
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivatorAdapter.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivatorAdapter.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivatorAdapter.java
new file mode 100644
index 0000000..666b6ec
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivatorAdapter.java
@@ -0,0 +1,68 @@
+/*
+ * 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.zest.api.activation;
+
+/**
+ * Adapter for Activator.
+ * <p>If you are thinking about Service activation, see {@link org.apache.zest.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
+ {
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ActivatorDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ActivatorDescriptor.java b/core/api/src/main/java/org/apache/zest/api/activation/ActivatorDescriptor.java
new file mode 100644
index 0000000..e6da0b2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ActivatorDescriptor.java
@@ -0,0 +1,25 @@
+/*
+ * 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.apache.zest.api.activation;
+
+/**
+ * Activator Descriptor.
+ */
+public interface ActivatorDescriptor
+{
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/Activators.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/Activators.java b/core/api/src/main/java/org/apache/zest/api/activation/Activators.java
new file mode 100644
index 0000000..d62b989
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/Activators.java
@@ -0,0 +1,39 @@
+/*
+ * 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.zest.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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/ApplicationPassivationThread.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/ApplicationPassivationThread.java b/core/api/src/main/java/org/apache/zest/api/activation/ApplicationPassivationThread.java
new file mode 100644
index 0000000..f8bbf12
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/ApplicationPassivationThread.java
@@ -0,0 +1,112 @@
+/*
+ * 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.apache.zest.api.activation;
+
+import java.io.PrintStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.zest.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();
+ }
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/PassivationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/PassivationException.java b/core/api/src/main/java/org/apache/zest/api/activation/PassivationException.java
new file mode 100644
index 0000000..7b5d195
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/PassivationException.java
@@ -0,0 +1,59 @@
+/*
+ * 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.apache.zest.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;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/activation/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/activation/package.html b/core/api/src/main/java/org/apache/zest/api/activation/package.html
new file mode 100644
index 0000000..47b333a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/activation/package.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>
+ <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>
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AbstractAssociation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AbstractAssociation.java b/core/api/src/main/java/org/apache/zest/api/association/AbstractAssociation.java
new file mode 100644
index 0000000..d97cf55
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AbstractAssociation.java
@@ -0,0 +1,22 @@
+/*
+ * 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.apache.zest.api.association;
+
+/**
+ * Base interface for all associations.
+ */
+public interface AbstractAssociation
+{
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/Association.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/Association.java b/core/api/src/main/java/org/apache/zest/api/association/Association.java
new file mode 100644
index 0000000..10ededb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/Association.java
@@ -0,0 +1,46 @@
+/*
+ * 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.apache.zest.api.association;
+
+import org.apache.zest.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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AssociationDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AssociationDescriptor.java b/core/api/src/main/java/org/apache/zest/api/association/AssociationDescriptor.java
new file mode 100644
index 0000000..5c8cbb1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AssociationDescriptor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import org.apache.zest.api.common.QualifiedName;
+import org.apache.zest.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<String> 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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AssociationMixin.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AssociationMixin.java b/core/api/src/main/java/org/apache/zest/api/association/AssociationMixin.java
new file mode 100644
index 0000000..c6079fd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AssociationMixin.java
@@ -0,0 +1,52 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.zest.api.common.AppliesTo;
+import org.apache.zest.api.common.AppliesToFilter;
+import org.apache.zest.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() );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AssociationStateDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AssociationStateDescriptor.java b/core/api/src/main/java/org/apache/zest/api/association/AssociationStateDescriptor.java
new file mode 100644
index 0000000..a6609da
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AssociationStateDescriptor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.apache.zest.api.association;
+
+import org.apache.zest.api.common.QualifiedName;
+import org.apache.zest.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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AssociationStateHolder.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AssociationStateHolder.java b/core/api/src/main/java/org/apache/zest/api/association/AssociationStateHolder.java
new file mode 100644
index 0000000..2a9c035
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AssociationStateHolder.java
@@ -0,0 +1,77 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.zest.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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/AssociationWrapper.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/AssociationWrapper.java b/core/api/src/main/java/org/apache/zest/api/association/AssociationWrapper.java
new file mode 100644
index 0000000..600756f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/AssociationWrapper.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.zest.api.association;
+
+import org.apache.zest.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();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/GenericAssociationInfo.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/GenericAssociationInfo.java b/core/api/src/main/java/org/apache/zest/api/association/GenericAssociationInfo.java
new file mode 100644
index 0000000..8641cc5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/GenericAssociationInfo.java
@@ -0,0 +1,58 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import static org.apache.zest.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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/ManyAssociation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/ManyAssociation.java b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociation.java
new file mode 100644
index 0000000..e24681f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociation.java
@@ -0,0 +1,51 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.zest.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();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationMixin.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationMixin.java b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationMixin.java
new file mode 100644
index 0000000..9d79dbd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationMixin.java
@@ -0,0 +1,52 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.zest.api.common.AppliesTo;
+import org.apache.zest.api.common.AppliesToFilter;
+import org.apache.zest.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
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationWrapper.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationWrapper.java b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationWrapper.java
new file mode 100644
index 0000000..3f29dd4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/ManyAssociationWrapper.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.zest.api.association;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.zest.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();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/NamedAssociation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/NamedAssociation.java b/core/api/src/main/java/org/apache/zest/api/association/NamedAssociation.java
new file mode 100644
index 0000000..ed31e29
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/NamedAssociation.java
@@ -0,0 +1,91 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.util.Map;
+import org.apache.zest.api.entity.EntityReference;
+
+/**
+ * Association to named Entities.
+ * The Iterable<String> 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 );
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/api/src/main/java/org/apache/zest/api/association/NamedAssociationMixin.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/association/NamedAssociationMixin.java b/core/api/src/main/java/org/apache/zest/api/association/NamedAssociationMixin.java
new file mode 100644
index 0000000..b289497
--- /dev/null
+++ b/core/api/src/main/java/org/apache/zest/api/association/NamedAssociationMixin.java
@@ -0,0 +1,57 @@
+/*
+ * 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.apache.zest.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.zest.api.common.AppliesTo;
+import org.apache.zest.api.common.AppliesToFilter;
+import org.apache.zest.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() );
+ }
+ }
+
+}