polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [14/80] [partial] zest-java git commit: First round of changes to move to org.apache.zest namespace.
Date Thu, 30 Jul 2015 19:48:13 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractConstraintModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractConstraintModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractConstraintModel.java
new file mode 100644
index 0000000..d8c9ff6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractConstraintModel.java
@@ -0,0 +1,49 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.zest.api.constraint.ConstraintDescriptor;
+import org.apache.zest.functional.Visitable;
+import org.apache.zest.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

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractModifierModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractModifierModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractModifierModel.java
new file mode 100644
index 0000000..a2478ce
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AbstractModifierModel.java
@@ -0,0 +1,177 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import org.apache.zest.api.common.ConstructionException;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.runtime.injection.InjectedFieldsModel;
+import org.apache.zest.runtime.injection.InjectedMethodsModel;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.spi.module.ModuleSpi;
+
+import static org.apache.zest.api.util.Classes.RAW_CLASS;
+import static org.apache.zest.api.util.Classes.interfacesOf;
+import static org.apache.zest.functional.Iterables.flattenIterables;
+import static org.apache.zest.functional.Iterables.iterable;
+import static org.apache.zest.functional.Iterables.map;
+import static org.apache.zest.functional.Iterables.toArray;
+import static org.apache.zest.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

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/AtomicInstancePool.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/AtomicInstancePool.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AtomicInstancePool.java
new file mode 100644
index 0000000..4929297
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/AtomicInstancePool.java
@@ -0,0 +1,53 @@
+/*
+ * 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.apache.zest.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 ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompactLevel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompactLevel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompactLevel.java
new file mode 100644
index 0000000..42a0dee
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompactLevel.java
@@ -0,0 +1,36 @@
+/*
+ * 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.apache.zest.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

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeConstraintModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeConstraintModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeConstraintModel.java
new file mode 100644
index 0000000..bcf068c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeConstraintModel.java
@@ -0,0 +1,68 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.zest.api.common.ConstructionException;
+import org.apache.zest.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

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodInstance.java
new file mode 100644
index 0000000..ae3f706
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodInstance.java
@@ -0,0 +1,77 @@
+/*
+ * 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.apache.zest.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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
new file mode 100644
index 0000000..9258dbc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
@@ -0,0 +1,321 @@
+/*
+ * 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.apache.zest.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.apache.zest.api.common.ConstructionException;
+import org.apache.zest.api.composite.MethodDescriptor;
+import org.apache.zest.api.util.NullArgumentException;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.spi.module.ModuleSpi;
+
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Iterables.flattenIterables;
+import static org.apache.zest.functional.Iterables.iterable;
+import static org.apache.zest.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 );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodsModel.java
new file mode 100644
index 0000000..62d44c2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodsModel.java
@@ -0,0 +1,132 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import org.apache.zest.api.composite.MissingMethodException;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.spi.module.ModuleSpi;
+
+import static org.apache.zest.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();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeModel.java
new file mode 100644
index 0000000..a9554f3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeModel.java
@@ -0,0 +1,267 @@
+/*
+ * 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.apache.zest.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.apache.zest.api.common.ConstructionException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.composite.CompositeDescriptor;
+import org.apache.zest.api.composite.InvalidCompositeException;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.spi.module.ModuleSpi;
+
+import static java.lang.reflect.Proxy.newProxyInstance;
+import static org.apache.zest.functional.Iterables.first;
+import static org.apache.zest.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

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernModel.java
new file mode 100644
index 0000000..4de8f64
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernModel.java
@@ -0,0 +1,29 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import org.apache.zest.api.concern.ConcernDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernModel extends AbstractModifierModel
+    implements ConcernDescriptor
+{
+    public ConcernModel( Class concernClass, Class instantiationClass )
+    {
+        super( concernClass, instantiationClass );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsInstance.java
new file mode 100644
index 0000000..eeecc8f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsInstance.java
@@ -0,0 +1,64 @@
+/*
+ * 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.apache.zest.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();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsModel.java
new file mode 100644
index 0000000..22092fc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConcernsModel.java
@@ -0,0 +1,83 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import org.apache.zest.api.concern.ConcernsDescriptor;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.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 );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintDeclaration.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintDeclaration.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintDeclaration.java
new file mode 100644
index 0000000..18184cc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintDeclaration.java
@@ -0,0 +1,69 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.zest.api.constraint.Constraint;
+import org.apache.zest.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?
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintInstance.java
new file mode 100644
index 0000000..3f855be
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintInstance.java
@@ -0,0 +1,43 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.zest.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 );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintModel.java
new file mode 100644
index 0000000..f73f8d7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintModel.java
@@ -0,0 +1,49 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.zest.api.common.ConstructionException;
+import org.apache.zest.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 );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsCheck.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsCheck.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsCheck.java
new file mode 100644
index 0000000..096c8cd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsCheck.java
@@ -0,0 +1,26 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import org.apache.zest.api.constraint.ConstraintViolationException;
+
+/**
+ * Call this to perform a value constraint check
+ */
+public interface ConstraintsCheck
+{
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsInstance.java
new file mode 100644
index 0000000..4e3b313
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsInstance.java
@@ -0,0 +1,80 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.constraint.ConstraintViolation;
+import org.apache.zest.api.constraint.ConstraintViolationException;
+
+import static org.apache.zest.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 );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsModel.java
new file mode 100644
index 0000000..0ea5139
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstraintsModel.java
@@ -0,0 +1,76 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.zest.api.constraint.ConstraintsDescriptor;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.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 );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorModel.java
new file mode 100644
index 0000000..e78481f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorModel.java
@@ -0,0 +1,105 @@
+/*
+ * 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.apache.zest.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import org.apache.zest.api.common.ConstructionException;
+import org.apache.zest.api.composite.ConstructorDescriptor;
+import org.apache.zest.api.composite.InvalidCompositeException;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.runtime.injection.InjectedParametersModel;
+import org.apache.zest.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();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorsModel.java
new file mode 100644
index 0000000..4b14cc3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ConstructorsModel.java
@@ -0,0 +1,301 @@
+/*
+ * 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.apache.zest.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.apache.zest.api.common.ConstructionException;
+import org.apache.zest.api.composite.CompositeDescriptor;
+import org.apache.zest.api.composite.InvalidCompositeException;
+import org.apache.zest.api.injection.InjectionScope;
+import org.apache.zest.api.injection.scope.Uses;
+import org.apache.zest.api.util.Annotations;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.bootstrap.BindingException;
+import org.apache.zest.functional.Function;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.HierarchicalVisitorAdapter;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specifications;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.injection.Dependencies;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.runtime.injection.InjectedParametersModel;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.runtime.injection.ParameterizedTypeInstance;
+import org.apache.zest.runtime.model.Binder;
+import org.apache.zest.runtime.model.Resolution;
+
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Iterables.first;
+import static org.apache.zest.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;
+    }
+}


Mime
View raw message