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 2016/12/17 10:27:49 UTC

[13/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java
new file mode 100644
index 0000000..4a00359
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java
@@ -0,0 +1,184 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+import static org.apache.polygene.api.util.Classes.RAW_CLASS;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * JAVADOC
+ */
+public abstract class AbstractModifierModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final Class<?> modifierClass;
+
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+
+    private final Class<Class<?>>[] nextInterfaces;
+
+    @SuppressWarnings( "unchecked" )
+    public AbstractModifierModel( Class<?> declaredModifierClass, Class<?> instantiationClass )
+    {
+        this.modifierClass = instantiationClass;
+        constructorsModel = new ConstructorsModel( modifierClass );
+        injectedFieldsModel = new InjectedFieldsModel( declaredModifierClass );
+        injectedMethodsModel = new InjectedMethodsModel( declaredModifierClass );
+        Class<Class<?>> componentType = (Class<Class<?>>) Class.class.cast( Class.class );
+        nextInterfaces = interfacesOf( declaredModifierClass )
+            .map( RAW_CLASS )
+            .distinct()
+            .toArray( size -> (Class<Class<?>>[]) Array.newInstance( componentType, size ) );
+    }
+
+    public Class<?> modifierClass()
+    {
+        return modifierClass;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<? extends Dependencies> models = Stream.of( this.constructorsModel, injectedFieldsModel, injectedMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    public boolean isGeneric()
+    {
+        return InvocationHandler.class.isAssignableFrom( modifierClass );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+
+        return visitor.visitLeave( this );
+    }
+
+    // Context
+    public InvocationHandler newInstance( ModuleDescriptor module,
+                                          InvocationHandler next,
+                                          ProxyReferenceInvocationHandler proxyHandler,
+                                          Method method
+    )
+    {
+        InjectionContext injectionContext = new InjectionContext( module, wrapNext( next ), proxyHandler );
+
+        Object modifier = constructorsModel.newInstance( injectionContext );
+
+        try
+        {
+            if( FragmentClassLoader.isGenerated( modifier ) )
+            {
+                modifier.getClass().getField( "_instance" ).set( modifier, proxyHandler );
+            }
+        }
+        catch( IllegalAccessException | NoSuchFieldException e )
+        {
+            e.printStackTrace();
+        }
+
+        injectedFieldsModel.inject( injectionContext, modifier );
+        injectedMethodsModel.inject( injectionContext, modifier );
+
+        if( isGeneric() )
+        {
+            return (InvocationHandler) modifier;
+        }
+        else
+        {
+            try
+            {
+                Method invocationMethod = modifierClass.getMethod( "_" + method.getName(), method.getParameterTypes() );
+                TypedModifierInvocationHandler handler = new TypedModifierInvocationHandler();
+                handler.setFragment( modifier );
+                handler.setMethod( invocationMethod );
+                return handler;
+            }
+            catch( NoSuchMethodException e )
+            {
+                throw new ConstructionException( "Could not find modifier method", e );
+            }
+        }
+    }
+
+    private Object wrapNext( InvocationHandler next )
+    {
+        if( isGeneric() )
+        {
+            return next;
+        }
+        else
+        {
+            return Proxy.newProxyInstance( modifierClass.getClassLoader(), nextInterfaces, next );
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        AbstractModifierModel that = (AbstractModifierModel) o;
+        return modifierClass.equals( that.modifierClass );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return modifierClass.hashCode();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java
new file mode 100644
index 0000000..28ee8b2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Method instance pool that keeps a linked list. Uses atomic reference
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class AtomicInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private final AtomicReference<CompositeMethodInstance> first = new AtomicReference<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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java
new file mode 100644
index 0000000..5c44e98
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.composite;
+
+/**
+ * Compaction Level of the StackTrace clenaup operation.
+ *
+ * <pre>
+ * <b>off</b>       = Do not modify the stack trace.
+ * <b>proxy</b>     = Remove all Polygene internal classes and all JDK internal classes from
+ *             the originating method call.
+ * <b>semi</b>      = Remove all JDK internal classes on the entire stack.
+ * <b>extensive</b> = Remove all Polygene internal and JDK internal classes from the entire stack.
+ * </pre>
+ *
+ * <p>
+ * The Compaction is set through the System Property "<code><b>polygene.compacttrace</b></code>" to
+ * any of the above values.
+ * </p>
+ */
+enum CompactLevel
+{
+    off, proxy, semi, extensive
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java
new file mode 100644
index 0000000..5345594
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeConstraintModel
+    extends AbstractConstraintModel
+{
+    private final ValueConstraintsModel constraintsModel;
+
+    public CompositeConstraintModel( Annotation annotation, ValueConstraintsModel constraintsModel )
+    {
+        super( annotation );
+        this.constraintsModel = constraintsModel;
+    }
+
+    @Override
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public ConstraintInstance<?, ?> newInstance()
+    {
+        try
+        {
+            ValueConstraintsInstance compositeConstraintsInstance = constraintsModel.newInstance();
+            Constraint<?, ?> constraint = new CompositeConstraintInstance( compositeConstraintsInstance );
+            return new ConstraintInstance( constraint, annotation );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate constraint implementation", e );
+        }
+    }
+
+    private static class CompositeConstraintInstance
+        implements Constraint<Annotation, Object>
+    {
+        private final ValueConstraintsInstance valueConstraintsInstance;
+
+        private CompositeConstraintInstance( ValueConstraintsInstance valueConstraintsInstance )
+        {
+            this.valueConstraintsInstance = valueConstraintsInstance;
+        }
+
+        @Override
+        public boolean isValid( Annotation annotation, Object value )
+            throws NullPointerException
+        {
+            return valueConstraintsInstance.checkConstraints( value ).isEmpty();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java
new file mode 100644
index 0000000..1867bf1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java
@@ -0,0 +1,83 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeMethodInstance
+{
+    private final InvocationHandler invoker;
+    private final FragmentInvocationHandler mixinInvoker;
+    private final Method method;
+    private final int methodIdx;
+
+    private CompositeMethodInstance next;
+
+    public CompositeMethodInstance( InvocationHandler invoker,
+                                    FragmentInvocationHandler mixinInvoker,
+                                    Method method, int methodIdx
+    )
+    {
+        this.invoker = invoker;
+        this.method = method;
+        this.mixinInvoker = mixinInvoker;
+        this.methodIdx = methodIdx;
+    }
+
+    public Method method()
+    {
+        return method;
+    }
+
+    public Object getMixinFrom( Object[] mixins )
+    {
+        return mixins[ methodIdx ];
+    }
+
+    public Object invoke( Object composite, Object[] params, Object mixin )
+        throws Throwable
+    {
+        mixinInvoker.setFragment( mixin );
+
+        try
+        {
+            return invoker.invoke( composite, method, params );
+        }
+        finally
+        {
+            mixinInvoker.setFragment( null );
+        }
+    }
+
+    public CompositeMethodInstance getNext()
+    {
+        return next;
+    }
+
+    public void setNext( CompositeMethodInstance next )
+    {
+        this.next = next;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
new file mode 100644
index 0000000..267c065
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
@@ -0,0 +1,324 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.NullArgumentException;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeMethodModel
+    implements MethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final Method method;
+    private Method invocationMethod; // This will be the _ prefixed method on typed mixins
+    private final ConstraintsModel constraints;
+    private final ConcernsModel concerns;
+    private final SideEffectsModel sideEffects;
+    private final MixinsModel mixins;
+    private AnnotatedElement annotations;
+
+    // Context
+//    private final SynchronizedCompositeMethodInstancePool instancePool = new SynchronizedCompositeMethodInstancePool();
+    private final AtomicInstancePool instancePool = new AtomicInstancePool();
+    private final ConstraintsInstance constraintsInstance;
+
+    public CompositeMethodModel( Method method,
+                                 ConstraintsModel constraintsModel,
+                                 ConcernsModel concernsModel,
+                                 SideEffectsModel sideEffectsModel,
+                                 MixinsModel mixinsModel
+    )
+    {
+        this.method = method;
+        mixins = mixinsModel;
+        concerns = concernsModel;
+        sideEffects = sideEffectsModel;
+        constraints = constraintsModel;
+        constraintsInstance = constraints.newInstance();
+        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 Stream<DependencyModel> dependencies()
+    {
+        return Stream.of( this.concerns, sideEffects ).filter( Objects::nonNull ).flatMap( Dependencies::dependencies );
+    }
+
+    // Context
+    public Object invoke( Object composite, Object[] params, MixinsInstance mixins, ModuleDescriptor module )
+        throws Throwable
+    {
+        constraintsInstance.checkValid( composite, method, params );
+
+        CompositeMethodInstance methodInstance = getInstance( module );
+        try
+        {
+            return mixins.invoke( composite, params, methodInstance );
+        }
+        finally
+        {
+            instancePool.releaseInstance( methodInstance );
+        }
+    }
+
+    private CompositeMethodInstance getInstance( ModuleDescriptor module )
+    {
+        CompositeMethodInstance methodInstance = instancePool.obtainInstance();
+        if( methodInstance == null )
+        {
+            methodInstance = newCompositeMethodInstance( module );
+        }
+
+        return methodInstance;
+    }
+
+    private CompositeMethodInstance newCompositeMethodInstance( ModuleDescriptor module )
+        throws ConstructionException
+    {
+        FragmentInvocationHandler mixinInvocationHandler = mixins.newInvocationHandler( method );
+        InvocationHandler invoker = mixinInvocationHandler;
+        if( concerns != ConcernsModel.EMPTY_CONCERNS )
+        {
+            ConcernsInstance concernsInstance = concerns.newInstance( method, module, mixinInvocationHandler );
+            invoker = concernsInstance;
+        }
+        if( sideEffects != SideEffectsModel.EMPTY_SIDEEFFECTS )
+        {
+            SideEffectsInstance sideEffectsInstance = sideEffects.newInstance( method, module, invoker );
+            invoker = sideEffectsInstance;
+        }
+
+        if( invocationMethod == null )
+        {
+            MixinModel model = mixins.mixinFor( method );
+            if( !InvocationHandler.class.isAssignableFrom( model.mixinClass() ) )
+            {
+                try
+                {
+                    invocationMethod = model.instantiationClass()
+                        .getMethod( "_" + method.getName(), method.getParameterTypes() );
+                }
+                catch( NoSuchMethodException e )
+                {
+                    invocationMethod = method;
+//                    throw new ConstructionException( "Could not find the subclass method", e );
+                }
+            }
+            else
+            {
+                invocationMethod = method;
+            }
+        }
+
+        mixinInvocationHandler.setMethod( invocationMethod );
+
+        return new CompositeMethodInstance( invoker, mixinInvocationHandler, method, mixins.methodIndex.get( method ) );
+    }
+
+    public AnnotatedElement annotatedElement()
+    {
+        return annotations;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            constraints.accept( modelVisitor );
+            concerns.accept( modelVisitor );
+            sideEffects.accept( modelVisitor );
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return method.toGenericString();
+    }
+
+    public Iterable<Method> invocationsFor( Class<?> mixinClass )
+    {
+        return mixins.invocationsFor( mixinClass ).collect( Collectors.toList() );
+    }
+
+    public class CompositeMethodAnnotatedElement
+        implements AnnotatedElement
+    {
+        @Override
+        public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass )
+        {
+            // Check method
+            if( method.isAnnotationPresent( annotationClass ) )
+            {
+                return true;
+            }
+
+            // Check mixin
+            try
+            {
+                MixinModel model = mixins.mixinFor( method );
+                if( Genericpredicate.INSTANCE.test( 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( !Genericpredicate.INSTANCE.test( model.mixinClass() ) )
+                {
+                    T annotation = annotationClass.cast( model.mixinClass()
+                                                             .getMethod( method.getName(), method.getParameterTypes() )
+                                                             .getAnnotation( annotationClass ) );
+                    if( annotation != null )
+                    {
+                        return annotation;
+                    }
+                }
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Ignore
+            }
+
+            // Check method
+            return method.getAnnotation( annotationClass );
+        }
+
+        @Override
+        public Annotation[] getAnnotations()
+        {
+            // Add mixin annotations
+            List<Annotation> annotations = new ArrayList<Annotation>();
+            MixinModel model = mixins.mixinFor( method );
+            Annotation[] mixinAnnotations = new Annotation[ 0 ];
+            if( !Genericpredicate.INSTANCE.test( model.mixinClass() ) )
+            {
+                mixinAnnotations = model.mixinClass().getAnnotations();
+                annotations.addAll( Arrays.asList( mixinAnnotations ) );
+            }
+
+            // Add method annotations, but don't include duplicates
+            Annotation[] methodAnnotations = method.getAnnotations();
+            next:
+            for( Annotation methodAnnotation : methodAnnotations )
+            {
+                for( int i = 0; i < mixinAnnotations.length; i++ )
+                {
+                    if( annotations.get( i ).annotationType().equals( methodAnnotation.annotationType() ) )
+                    {
+                        continue next;
+                    }
+                }
+
+                annotations.add( methodAnnotation );
+            }
+
+            return annotations.toArray( new Annotation[ annotations.size() ] );
+        }
+
+        @Override
+        public Annotation[] getDeclaredAnnotations()
+        {
+            return new Annotation[ 0 ];
+        }
+
+        // @Override (Since JDK 8)
+        @SuppressWarnings( "unchecked" )
+        public <T extends Annotation> T[] getAnnotationsByType( Class<T> annotationClass )
+        {
+            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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
new file mode 100644
index 0000000..8dc2495
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
@@ -0,0 +1,134 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.MissingMethodException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * Model for Composite methods. This includes both private and public methods.
+ */
+public final class CompositeMethodsModel
+    implements VisitableHierarchy<Object, Object>, Dependencies
+{
+    private final LinkedHashMap<Method, CompositeMethodModel> methods;
+    private final MixinsModel mixinsModel;
+
+    public CompositeMethodsModel( MixinsModel mixinsModel )
+    {
+        methods = new LinkedHashMap<>();
+        this.mixinsModel = mixinsModel;
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        Collection<CompositeMethodModel> compositeMethods = methods.values();
+        return compositeMethods.stream().flatMap( Dependencies.DEPENDENCIES_FUNCTION );
+    }
+
+    // Context
+    public Object invoke( MixinsInstance mixins,
+                          Object proxy,
+                          Method method,
+                          Object[] args,
+                          ModuleDescriptor moduleInstance
+    )
+        throws Throwable
+    {
+        CompositeMethodModel compositeMethod = methods.get( method );
+
+        if( compositeMethod == null )
+        {
+            if( method.getDeclaringClass().equals( Object.class ) )
+            {
+                return mixins.invokeObject( proxy, args, method );
+            }
+
+            // TODO: Figure out what was the intention of this code block, added by Rickard in 2009. It doesn't do anything useful.
+            if( !method.getDeclaringClass().isInterface() )
+            {
+                compositeMethod = mixinsModel.mixinTypes().map( aClass -> {
+                    try
+                    {
+                        Method realMethod = aClass.getMethod( method.getName(), method.getParameterTypes() );
+                        return methods.get( realMethod );
+                    }
+                    catch( NoSuchMethodException | SecurityException e )
+                    {
+
+                    }
+                    return null;
+                }).filter( model -> model != null ).findFirst().orElse( null );
+            }
+            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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java
new file mode 100644
index 0000000..2f1e81d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java
@@ -0,0 +1,278 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+import static java.lang.reflect.Proxy.newProxyInstance;
+
+/**
+ * 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;
+    private volatile Class<?> primaryType;
+    protected Class<? extends Composite> proxyClass;
+    protected Constructor<? extends Composite> proxyConstructor;
+    protected ModuleDescriptor module;
+
+    protected CompositeModel( final ModuleDescriptor module,
+                              final List<Class<?>> types,
+                              final Visibility visibility,
+                              final MetaInfo metaInfo,
+                              final MixinsModel mixinsModel,
+                              final StateModel stateModel,
+                              final CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        this.module = module;
+        this.types = new LinkedHashSet<>( types );
+        this.visibility = visibility;
+        this.metaInfo = metaInfo;
+        this.stateModel = stateModel;
+        this.compositeMethodsModel = compositeMethodsModel;
+        this.mixinsModel = mixinsModel;
+
+        // Create proxy class
+        createProxyClass();
+        primaryType = mixinTypes()
+            .reduce( null, ( primary, type ) ->
+            {
+                if( primary == null )
+                {
+                    return type;
+                }
+                else if( primary.isAssignableFrom( type ) )
+                {
+                    return type;
+                }
+                return primary;
+            } );
+    }
+
+    // Model
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    public StateModel state()
+    {
+        return stateModel;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return visibility;
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        for( Class<?> aClass : types )
+        {
+            if( type.isAssignableFrom( aClass ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public MixinsModel mixinsModel()
+    {
+        return mixinsModel;
+    }
+
+    @Override
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public Class<?> primaryType()
+    {
+        return primaryType;
+    }
+
+    @Override
+    public Stream<Class<?>> mixinTypes()
+    {
+        return mixinsModel.mixinTypes();
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<Dependencies> models = Stream.of( this.mixinsModel, compositeMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( compositeMethodsModel.accept( visitor ) )
+            {
+                if( stateModel.accept( visitor ) )
+                {
+                    mixinsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    private void createProxyClass()
+    {
+        Class<?> mainType = types.stream().findFirst().get();
+        if( mainType.isInterface() )
+        {
+            ClassLoader proxyClassloader = mainType.getClassLoader();
+
+            Class<?>[] interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new );
+            proxyClass = (Class<? extends Composite>) ProxyGenerator.createProxyClass( proxyClassloader, interfaces );
+
+            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
+    )
+        throws Throwable
+    {
+        return compositeMethodsModel.invoke( mixins, proxy, method, args, module );
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    public Composite newProxy( InvocationHandler invocationHandler )
+        throws ConstructionException
+    {
+        Class<?> mainType = types.stream().findFirst().get();
+        if( mainType.isInterface() )
+        {
+            try
+            {
+                return Composite.class.cast( proxyConstructor.newInstance( invocationHandler ) );
+            }
+            catch( Exception e )
+            {
+                throw new ConstructionException( e );
+            }
+        }
+        else
+        {
+            try
+            {
+                Object[] args = new Object[ proxyConstructor.getParameterTypes().length ];
+                Composite composite = Composite.class.cast( proxyConstructor.newInstance( args ) );
+                proxyClass.getField( "_instance" ).set( composite, invocationHandler );
+                return composite;
+            }
+            catch( Exception e )
+            {
+                throw new ConstructionException( e );
+            }
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    public <T> T newProxy( InvocationHandler invocationHandler, Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+
+//        if (!matchesAny( isAssignableFrom( mixinType ), types ))
+        if( !mixinsModel.isImplemented( mixinType ) )
+        {
+            String message = "Composite " + primaryType().getName() + " does not implement type " + mixinType.getName();
+            throw new IllegalArgumentException( message );
+        }
+
+        // Instantiate proxy for given mixin interface
+        return mixinType.cast( newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, invocationHandler ) );
+    }
+
+    @Override
+    public String toString()
+    {
+        return types.toString();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java
new file mode 100644
index 0000000..b583aaf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import org.apache.polygene.api.concern.ConcernDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernModel extends AbstractModifierModel
+    implements ConcernDescriptor
+{
+    public ConcernModel( Class concernClass, Class instantiationClass )
+    {
+        super( concernClass, instantiationClass );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java
new file mode 100644
index 0000000..da2fe20
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernsInstance
+    implements InvocationHandler
+{
+    private final InvocationHandler firstConcern;
+    private final FragmentInvocationHandler mixinInvocationHandler;
+    private final ProxyReferenceInvocationHandler proxyHandler;
+
+    public ConcernsInstance( InvocationHandler firstConcern,
+                             FragmentInvocationHandler mixinInvocationHandler,
+                             ProxyReferenceInvocationHandler proxyHandler
+    )
+    {
+        this.firstConcern = firstConcern;
+        this.mixinInvocationHandler = mixinInvocationHandler;
+        this.proxyHandler = proxyHandler;
+    }
+
+    public boolean isEmpty()
+    {
+        return firstConcern == mixinInvocationHandler;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] params )
+        throws Throwable
+    {
+        proxyHandler.setProxy( proxy );
+        try
+        {
+            return firstConcern.invoke( proxy, method, params );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        finally
+        {
+            proxyHandler.clearProxy();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
new file mode 100644
index 0000000..aa8d3ce
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.concern.ConcernsDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernsModel
+    implements ConcernsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    public static final ConcernsModel EMPTY_CONCERNS = new ConcernsModel( Collections.<ConcernModel>emptyList() );
+
+    private List<ConcernModel> concernsFor;
+
+    public ConcernsModel( List<ConcernModel> concernsFor )
+    {
+        this.concernsFor = concernsFor;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return concernsFor.stream().flatMap( ConcernModel::dependencies );
+    }
+
+    // Context
+    public ConcernsInstance newInstance( Method method, ModuleDescriptor module,
+                                         FragmentInvocationHandler mixinInvocationHandler
+    )
+    {
+        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
+        InvocationHandler nextConcern = mixinInvocationHandler;
+        for( int i = concernsFor.size() - 1; i >= 0; i-- )
+        {
+            ConcernModel concernModel = concernsFor.get( i );
+
+            nextConcern = concernModel.newInstance( module, nextConcern, proxyHandler, method );
+        }
+
+        return new ConcernsInstance( nextConcern, mixinInvocationHandler, proxyHandler );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( ConcernModel concernModel : concernsFor )
+            {
+                if( !concernModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java
new file mode 100644
index 0000000..9826681
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintDeclaration
+{
+    private final Class<? extends Constraint<?, ?>> constraintClass;
+    @SuppressWarnings( "raw" )
+    private final Class constraintAnnotationType;
+    private final Type constraintValueType;
+
+    @SuppressWarnings( "unchecked" )
+    public ConstraintDeclaration( Class<? extends Constraint<?, ?>> constraintClass )
+    {
+        this.constraintClass = constraintClass;
+
+        constraintAnnotationType = (Class<? extends Annotation>) ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] )
+            .getActualTypeArguments()[ 0 ];
+        constraintValueType = ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
+    }
+
+    public Class<? extends Constraint<?, ?>> constraintClass()
+    {
+        return constraintClass;
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public boolean appliesTo( Class annotationType, Type valueType )
+    {
+        if( constraintValueType instanceof Class )
+        {
+            Class constraintValueClass = (Class) constraintValueType;
+            Class valueClass = Classes.RAW_CLASS.apply( valueType );
+            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
+        }
+        else if( constraintValueType instanceof ParameterizedType )
+        {
+            // TODO Handle nested generics
+            Class constraintValueClass = Classes.RAW_CLASS.apply( constraintValueType );
+            Class valueClass = Classes.RAW_CLASS.apply( valueType );
+            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
+        }
+        else
+        {
+            return false; // TODO Handles more cases. What are they?
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java
new file mode 100644
index 0000000..40645f9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintInstance<A extends Annotation, T>
+{
+    private final Constraint<A, T> constraint;
+    private final A annotation;
+
+    public ConstraintInstance( Constraint<A, T> constraint, A annotation )
+    {
+        this.constraint = constraint;
+        this.annotation = annotation;
+    }
+
+    public A annotation()
+    {
+        return annotation;
+    }
+
+    public boolean isValid( T value )
+    {
+        return constraint.isValid( annotation, value );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java
new file mode 100644
index 0000000..1452eeb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintModel
+    extends AbstractConstraintModel
+{
+    private final Class<? extends Constraint<?, ?>> constraintClass;
+
+    public ConstraintModel( Annotation annotation, Class<? extends Constraint<?, ?>> constraintClass )
+    {
+        super( annotation );
+        this.constraintClass = constraintClass;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public ConstraintInstance<?, ?> newInstance()
+    {
+        try
+        {
+            Constraint<?, ?> constraint = constraintClass.newInstance();
+            return new ConstraintInstance( constraint, annotation );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate constraint implementation", e );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java
new file mode 100644
index 0000000..1f72dc3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+/**
+ * Call this to perform a value constraint check
+ */
+public interface ConstraintsCheck
+{
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java
new file mode 100644
index 0000000..23e8f98
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java
@@ -0,0 +1,84 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintsInstance
+{
+    private final List<ValueConstraintsInstance> valueConstraintsInstances;
+
+    public ConstraintsInstance( List<ValueConstraintsInstance> parameterConstraints )
+    {
+        valueConstraintsInstances = parameterConstraints;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void checkValid( Object instance, Method method, Object[] params )
+        throws ConstraintViolationException
+    {
+        if( valueConstraintsInstances.isEmpty() )
+        {
+            return; // No constraints to check
+        }
+
+        // Check constraints
+        List<ConstraintViolation> violations = null;
+        for( int i = 0; i < params.length; i++ )
+        {
+            Object param = params[ i ];
+            List<ConstraintViolation> paramViolations = valueConstraintsInstances.get( i ).checkConstraints( param );
+            if( !paramViolations.isEmpty() )
+            {
+                if( violations == null )
+                {
+                    violations = new ArrayList<>();
+                }
+                violations.addAll( paramViolations );
+            }
+        }
+
+        // Check if any constraint failed
+        if( violations != null )
+        {
+            if( instance instanceof Composite )
+            {
+                throw new ConstraintViolationException( (Composite) instance, method, violations );
+            }
+            if( instance instanceof CompositeInstance )
+            {
+                throw new ConstraintViolationException( ( (CompositeInstance) instance ).proxy(), method, violations );
+            }
+            Stream<Class<?>> types = Stream.of( instance.getClass() );
+            throw new ConstraintViolationException( instance.toString(), types, method, violations );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java
new file mode 100644
index 0000000..542217e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java
@@ -0,0 +1,82 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.api.constraint.ConstraintsDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintsModel
+    implements ConstraintsDescriptor, VisitableHierarchy<Object, Object>
+{
+    private List<ValueConstraintsModel> parameterConstraintModels;
+
+    private static ConstraintsInstance EMPTY_CONSTRAINTS = new ConstraintsInstance( Collections.<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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java
new file mode 100644
index 0000000..3df1ad5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java
@@ -0,0 +1,112 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.ConstructorDescriptor;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedParametersModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class ConstructorModel
+    implements ConstructorDescriptor, VisitableHierarchy<Object, Object>
+{
+    private Constructor<?> constructor;
+
+    private InjectedParametersModel parameters;
+
+    public ConstructorModel( Constructor<?> constructor, InjectedParametersModel parameters )
+    {
+        this.constructor = constructor;
+        this.parameters = parameters;
+        this.constructor.setAccessible( true );
+    }
+
+    @Override
+    public Constructor<?> constructor()
+    {
+        return constructor;
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameters.dependencies();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            parameters.accept( modelVisitor );
+        }
+
+        return modelVisitor.visitLeave( this );
+    }
+
+    // Context
+
+    public Object newInstance( InjectionContext context )
+        throws ConstructionException
+    {
+        // Create parameters
+        Object[] parametersInstance = parameters.newParametersInstance( context );
+        // Invoke constructor
+        try
+        {
+            return constructor.newInstance( parametersInstance );
+        }
+        catch( InvocationTargetException e )
+        {
+            Throwable targetException = e.getTargetException();
+            if( targetException instanceof InvalidCompositeException )
+            {
+                throw (InvalidCompositeException) targetException;
+            }
+            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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java
new file mode 100644
index 0000000..bc4be4a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java
@@ -0,0 +1,298 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.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 java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedParametersModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.ParameterizedTypeInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class ConstructorsModel
+    implements Binder, Dependencies, VisitableHierarchy<Object, Object>
+{
+    @SuppressWarnings( "raw" )
+    private final Class<?> fragmentClass;
+    private final List<ConstructorModel> constructorModels;
+    private List<ConstructorModel> boundConstructors;
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ConstructorsModel( Class<?> fragmentClass )
+    {
+        this.fragmentClass = fragmentClass;
+        validate( fragmentClass );
+        constructorModels = new ArrayList<>();
+        Constructor<?>[] realConstructors = this.fragmentClass.getDeclaredConstructors();
+        Class<?> injectionClass = FragmentClassLoader.getSourceClass( fragmentClass );
+        for( Constructor<?> constructor : realConstructors )
+        {
+            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 Stream<DependencyModel> dependencies()
+    {
+        if( boundConstructors == null )
+        {
+            return constructorModels.stream().flatMap( ConstructorModel::dependencies );
+        }
+        return boundConstructors.stream().flatMap( ConstructorModel::dependencies );
+    }
+
+    @SuppressWarnings( "raw" )
+    private ConstructorModel newConstructorModel( Class<?> fragmentClass,
+                                                  Constructor<?> realConstructor,
+                                                  Constructor<?> injectedConstructor
+    )
+    {
+        int idx = 0;
+        InjectedParametersModel parameters = new InjectedParametersModel();
+        Annotation[][] parameterAnnotations = injectedConstructor.getParameterAnnotations();
+        for( Type type : injectedConstructor.getGenericParameterTypes() )
+        {
+            Annotation injectionAnnotation = Stream.of( parameterAnnotations[ idx ] )
+                                                   .filter( typeHasAnnotation( InjectionScope.class ) )
+                                                   .findFirst().orElse( null );
+
+            if( injectionAnnotation == null )
+            {
+                if( fragmentClass.getSuperclass().isMemberClass() )
+                {
+                    injectionAnnotation = new Uses()
+                    {
+                        @Override
+                        public Class<? extends Annotation> annotationType()
+                        {
+                            return Uses.class;
+                        }
+                    };
+                }
+                else
+                {
+                    return null; // invalid constructor parameter
+                }
+            }
+
+            boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ idx ] );
+
+            Type genericType = type;
+            if( genericType instanceof ParameterizedType )
+            {
+                genericType = new ParameterizedTypeInstance( ( (ParameterizedType) genericType ).getActualTypeArguments(), ( (ParameterizedType) genericType )
+                    .getRawType(), ( (ParameterizedType) genericType ).getOwnerType() );
+
+                for( int i = 0; i < ( (ParameterizedType) genericType ).getActualTypeArguments().length; i++ )
+                {
+                    Type typeArg = ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ];
+                    if( typeArg instanceof TypeVariable )
+                    {
+                        typeArg = Classes.resolveTypeVariable( (TypeVariable) typeArg, realConstructor.getDeclaringClass(), fragmentClass );
+                        ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ] = typeArg;
+                    }
+                }
+            }
+
+            DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional,
+                                                                   parameterAnnotations[ idx ] );
+            parameters.addDependency( dependencyModel );
+            idx++;
+        }
+        return new ConstructorModel( realConstructor, parameters );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( boundConstructors != null )
+            {
+                for( ConstructorModel constructorModel : boundConstructors )
+                {
+                    if( !constructorModel.accept( visitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                for( ConstructorModel constructorModel : constructorModels )
+                {
+                    if( !constructorModel.accept( visitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Binding
+    @Override
+    public void bind( final Resolution resolution )
+        throws BindingException
+    {
+        boundConstructors = new ArrayList<>();
+        for( ConstructorModel constructorModel : constructorModels )
+        {
+            try
+            {
+                constructorModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
+                {
+                    @Override
+                    public boolean visit( Object visitor )
+                        throws BindingException
+                    {
+                        if( visitor instanceof Binder )
+                        {
+                            ( (Binder) visitor ).bind( resolution );
+                        }
+                        return true;
+                    }
+                } );
+                boundConstructors.add( constructorModel );
+            }
+            catch( Exception e )
+            {
+                // Ignore
+                e.printStackTrace();
+            }
+        }
+
+        if( boundConstructors.isEmpty() )
+        {
+            StringBuilder messageBuilder = new StringBuilder( "Found no constructor that could be bound: " );
+            if( resolution.model() instanceof CompositeDescriptor )
+            {
+                messageBuilder.append( fragmentClass.getName() )
+                    .append( " in " )
+                    .append( resolution.model().toString() );
+            }
+            else
+            {
+                messageBuilder.append( resolution.model().toString() );
+            }
+
+            if( messageBuilder.indexOf( "$" ) >= 0 )
+            {
+                // This could be ok if instance is created manually
+                return;
+//                messageBuilder.append( "\nInner classes can not be used." );
+            }
+            String message = messageBuilder.toString();
+            throw new BindingException( message );
+        }
+
+        // Sort based on parameter count
+        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;
+    }
+}