polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [12/81] [abbrv] [partial] zest-java git commit: First round of changes to move to org.apache.zest namespace.
Date Fri, 31 Jul 2015 02:58:52 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/SynchronizedCompositeMethodInstancePool.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/SynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/SynchronizedCompositeMethodInstancePool.java
new file mode 100644
index 0000000..2efa326
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/SynchronizedCompositeMethodInstancePool.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+/**
+ * Method instance pool that keeps a linked list. Uses synchronization
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class SynchronizedCompositeMethodInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private CompositeMethodInstance first = null;
+
+    @Override
+    public synchronized CompositeMethodInstance obtainInstance()
+    {
+        CompositeMethodInstance instance = first;
+        if( instance != null )
+        {
+            first = instance.getNext();
+        }
+        return instance;
+    }
+
+    @Override
+    public synchronized void releaseInstance( CompositeMethodInstance instance )
+    {
+        instance.setNext( first );
+        first = instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientBuilderInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientBuilderInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientBuilderInstance.java
new file mode 100644
index 0000000..e834262
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientBuilderInstance.java
@@ -0,0 +1,98 @@
+/*
+ * 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.common.ConstructionException;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.composite.TransientBuilder;
+import org.apache.zest.api.property.PropertyDescriptor;
+import org.apache.zest.runtime.property.PropertyInfo;
+import org.apache.zest.runtime.property.PropertyInstance;
+import org.apache.zest.spi.module.ModelModule;
+
+/**
+ * JAVADOC
+ */
+public final class TransientBuilderInstance<T>
+    implements TransientBuilder<T>
+{
+    private ModelModule<TransientModel> model;
+
+    // lazy initialized in accessor
+    private UsesInstance uses = UsesInstance.EMPTY_USES;
+
+    // lazy initialized in accessor
+    private CompositeInstance prototypeInstance;
+
+    private TransientStateInstance state;
+
+    public TransientBuilderInstance( ModelModule<TransientModel> model,
+                                     TransientStateInstance state,
+                                     UsesInstance uses
+    )
+    {
+        this.model = model;
+        this.state = state;
+        this.uses = uses;
+    }
+
+    @Override
+    public TransientBuilder<T> use( Object... usedObjects )
+    {
+        uses = uses.use( usedObjects );
+        return this;
+    }
+
+    @Override
+    public T prototype()
+    {
+        // Instantiate given value type
+        if( prototypeInstance == null )
+        {
+            prototypeInstance = model.model().newInstance( model.module(), uses, state );
+        }
+
+        return prototypeInstance.<T>proxy();
+    }
+
+    @Override
+    public <K> K prototypeFor( Class<K> mixinType )
+    {
+        // Instantiate given value type
+        if( prototypeInstance == null )
+        {
+            prototypeInstance = model.model().newInstance( model.module(), uses, state );
+        }
+
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    public T newInstance()
+        throws ConstructionException
+    {
+        // Set correct info's (immutable) on the state
+        for( PropertyDescriptor propertyDescriptor : model.model().state().properties() )
+        {
+            ( (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() ) ).setPropertyInfo( (PropertyInfo) propertyDescriptor );
+        }
+
+        model.model().checkConstraints( state );
+
+        CompositeInstance compositeInstance =
+            model.model().newInstance( model.module(), uses, state );
+        return compositeInstance.<T>proxy();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientClassLoader.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientClassLoader.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientClassLoader.java
new file mode 100644
index 0000000..fc38920
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientClassLoader.java
@@ -0,0 +1,804 @@
+/*
+ * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.apache.zest.api.entity.Lifecycle;
+import org.apache.zest.api.mixin.Initializable;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.api.util.Methods;
+import org.apache.zest.functional.Iterables;
+
+import static org.objectweb.asm.Opcodes.AASTORE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ANEWARRAY;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.ATHROW;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.CHECKCAST;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DRETURN;
+import static org.objectweb.asm.Opcodes.DUP;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.FRETURN;
+import static org.objectweb.asm.Opcodes.GETFIELD;
+import static org.objectweb.asm.Opcodes.GETSTATIC;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_3;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.ICONST_5;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.IRETURN;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.LRETURN;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.PUTSTATIC;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Type.getInternalName;
+import static org.apache.zest.api.util.Classes.interfacesOf;
+
+/**
+ * Generate subclasses of classes used for transients. All methods delegate to CompositeInvoker.
+ */
+@SuppressWarnings( "raw" )
+/* package */ final class TransientClassLoader
+    extends ClassLoader
+{
+    private static final int JDK_VERSION;
+    public static final String GENERATED_POSTFIX = "_Proxy";
+
+    static
+    {
+        String jdkString = System.getProperty( "java.specification.version" );
+        switch( jdkString )
+        {
+            case "1.8":
+                JDK_VERSION = Opcodes.V1_8;
+                break;
+            case "1.7":
+            default:
+                JDK_VERSION = Opcodes.V1_7;
+                break;
+        }
+    }
+
+    /* package */ TransientClassLoader( ClassLoader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    protected Class findClass( String name )
+        throws ClassNotFoundException
+    {
+        if( name.endsWith( GENERATED_POSTFIX ) )
+        {
+            Class baseClass;
+            String baseName = name.substring( 0, name.length() - 6 );
+            try
+            {
+                baseClass = loadClass( baseName );
+            }
+            catch( ClassNotFoundException e )
+            {
+                // Try replacing the last _ with $
+                while( true )
+                {
+                    int idx = baseName.lastIndexOf( "_" );
+                    if( idx != -1 )
+                    {
+                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
+                        try
+                        {
+                            baseClass = loadClass( baseName );
+                            break;
+                        }
+                        catch( ClassNotFoundException e1 )
+                        {
+                            // Try again
+                        }
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+            }
+
+            byte[] b = generateClass( name, baseClass );
+            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
+        }
+
+        // Try the classloader of this classloader -> get classes in Zest such as CompositeInvoker
+        return getClass().getClassLoader().loadClass( name );
+    }
+
+    public static byte[] generateClass( String name, Class baseClass )
+        throws ClassNotFoundException
+    {
+        String classSlash = name.replace( '.', '/' );
+        String baseClassSlash = getInternalName( baseClass );
+
+        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
+        FieldVisitor fv;
+        MethodVisitor mv;
+        AnnotationVisitor av0;
+
+        // Class definition start
+        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null );
+
+        // Composite reference
+        {
+            fv = cw.visitField( ACC_PUBLIC, "_instance", "Lorg/qi4j/api/composite/CompositeInvoker;", null, null );
+            fv.visitEnd();
+        }
+
+        // Static Method references
+        {
+            int idx = 1;
+            for( Method method : baseClass.getMethods() )
+            {
+                if( isOverloaded( method, baseClass ) )
+                {
+                    fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null,
+                                        null );
+                    fv.visitEnd();
+                }
+            }
+        }
+
+        // Constructors
+        for( Constructor constructor : baseClass.getDeclaredConstructors() )
+        {
+            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
+            {
+                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
+                mv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
+                mv.visitCode();
+                mv.visitVarInsn( ALOAD, 0 );
+
+                int idx = 1;
+                for( Class aClass : constructor.getParameterTypes() )
+                {
+                    // TODO Handle other types than objects (?)
+                    mv.visitVarInsn( ALOAD, idx++ );
+                }
+
+                mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, "<init>", desc, false );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( idx, idx );
+                mv.visitEnd();
+            }
+        }
+
+        // Overloaded and unimplemented methods
+        Method[] methods = baseClass.getMethods();
+        int idx = 0;
+        List<Label> exceptionLabels = new ArrayList<>();
+        for( Method method : methods )
+        {
+            if( isOverloaded( method, baseClass ) )
+            {
+                idx++;
+                String methodName = method.getName();
+                String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
+
+                String[] exceptions = null;
+                {
+                    mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, exceptions );
+                    if( isInternalQi4jMethod( method, baseClass ) )
+                    {
+                        // generate a NoOp method...
+                        mv.visitInsn( RETURN );
+                    }
+                    else
+                    {
+                        Label endLabel = null; // Use this if return type is void
+                        if( method.getExceptionTypes().length > 0 )
+                        {
+                            exceptions = new String[ method.getExceptionTypes().length ];
+                            for( int i = 0; i < method.getExceptionTypes().length; i++ )
+                            {
+                                Class<?> aClass = method.getExceptionTypes()[ i ];
+                                exceptions[ i ] = getInternalName( aClass );
+                            }
+                        }
+                        mv.visitCode();
+                        Label l0 = new Label();
+                        Label l1 = new Label();
+
+                        exceptionLabels.clear();
+                        for( Class<?> declaredException : method.getExceptionTypes() )
+                        {
+                            Label ld = new Label();
+                            mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
+                            exceptionLabels.add( ld ); // Reuse this further down for the catch
+                        }
+
+                        Label lruntime = new Label();
+                        mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
+                        Label lerror = new Label();
+                        mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
+
+                        mv.visitLabel( l0 );
+                        mv.visitVarInsn( ALOAD, 0 );
+                        mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
+                                           "Lorg/qi4j/api/composite/CompositeInvoker;" );
+                        mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
+
+                        int paramCount = method.getParameterTypes().length;
+                        int stackIdx = 0;
+                        if( paramCount == 0 )
+                        {
+                            // Send in null as parameter
+                            mv.visitInsn( ACONST_NULL );
+                        }
+                        else
+                        {
+                            insn( mv, paramCount );
+                            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+                            int pidx = 0;
+                            for( Class<?> aClass : method.getParameterTypes() )
+                            {
+                                mv.visitInsn( DUP );
+                                insn( mv, pidx++ );
+                                stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
+                                mv.visitInsn( AASTORE );
+                            }
+                        }
+
+                        // Call method
+                        mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/api/composite/CompositeInvoker",
+                                            "invokeComposite",
+                                            "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+
+                        // Return value
+                        if( !method.getReturnType().equals( Void.TYPE ) )
+                        {
+                            unwrapResult( mv, method.getReturnType(), l1 );
+                        }
+                        else
+                        {
+                            mv.visitInsn( POP );
+                            mv.visitLabel( l1 );
+                            endLabel = new Label();
+                            mv.visitJumpInsn( GOTO, endLabel );
+                        }
+
+                        // Increase stack to beyond method args
+                        stackIdx++;
+
+                        // Declared exceptions
+                        int exceptionIdx = 0;
+                        for( Class<?> aClass : method.getExceptionTypes() )
+                        {
+                            mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitInsn( ATHROW );
+                        }
+
+                        // RuntimeException and Error catch-all
+                        mv.visitLabel( lruntime );
+                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
+                        mv.visitVarInsn( ASTORE, stackIdx );
+                        mv.visitVarInsn( ALOAD, stackIdx );
+                        mv.visitInsn( ATHROW );
+
+                        mv.visitLabel( lerror );
+                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+                        mv.visitVarInsn( ASTORE, stackIdx );
+                        mv.visitVarInsn( ALOAD, stackIdx );
+                        mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
+                        mv.visitInsn( ATHROW );
+
+                        // Return type = void
+                        if( endLabel != null )
+                        {
+                            mv.visitLabel( endLabel );
+                            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                            mv.visitInsn( RETURN );
+                        }
+
+                        mv.visitMaxs( 0, 0 );
+                        mv.visitEnd();
+                    }
+                }
+
+                if( !Modifier.isAbstract( method.getModifiers() ) )
+                {
+                    // Add method with _ as prefix
+                    mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
+                    mv.visitCode();
+                    mv.visitVarInsn( ALOAD, 0 );
+
+                    // Parameters
+                    int stackIdx = 1;
+                    for( Class<?> aClass : method.getParameterTypes() )
+                    {
+                        stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
+                    }
+
+                    // Call method
+                    mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
+
+                    // Return value
+                    if( !method.getReturnType().equals( Void.TYPE ) )
+                    {
+                        returnResult( mv, method.getReturnType() );
+                    }
+                    else
+                    {
+                        mv.visitInsn( RETURN );
+                    }
+
+                    mv.visitMaxs( 1, 1 );
+                    mv.visitEnd();
+                }
+            }
+        }
+
+        // Class initializer
+        {
+            mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
+            mv.visitLabel( l0 );
+
+            // Lookup methods and store in static variables
+            int midx = 0;
+            for( Method method : methods )
+            {
+                if( isOverloaded( method, baseClass ) )
+                {
+                    method.setAccessible( true );
+                    Class methodClass;
+                    methodClass = method.getDeclaringClass();
+
+                    midx++;
+
+                    mv.visitLdcInsn( Type.getType( methodClass ) );
+                    mv.visitLdcInsn( method.getName() );
+                    insn( mv, method.getParameterTypes().length );
+                    mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+
+                    int pidx = 0;
+                    for( Class<?> aClass : method.getParameterTypes() )
+                    {
+                        mv.visitInsn( DUP );
+                        insn( mv, pidx++ );
+                        type( mv, aClass );
+                        mv.visitInsn( AASTORE );
+                    }
+
+                    mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                        "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+                    mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
+                }
+            }
+
+            mv.visitLabel( l1 );
+            Label l3 = new Label();
+            mv.visitJumpInsn( GOTO, l3 );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
+            mv.visitVarInsn( ASTORE, 0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 6, 1 );
+            mv.visitEnd();
+        }
+
+        cw.visitEnd();
+
+        return cw.toByteArray();
+    }
+
+    private static boolean isOverloaded( Method method, Class baseClass )
+    {
+        if( Modifier.isFinal( method.getModifiers() ) )
+        {
+            return false; // Cannot override final methods
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    private static boolean isInternalQi4jMethod( Method method, Class baseClass )
+    {
+        return isDeclaredIn( method, Initializable.class, baseClass )
+               || isDeclaredIn( method, Lifecycle.class, baseClass );
+    }
+
+    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
+    {
+        if( !clazz.isAssignableFrom( baseClass ) )
+        {
+            return false;
+        }
+
+        try
+        {
+            clazz.getMethod( method.getName(), method.getParameterTypes() );
+            return true;
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+
+    private static Class getInterfaceMethodDeclaration( Method method, Class clazz )
+        throws NoSuchMethodException
+    {
+        Iterable<Class<?>> interfaces = Iterables.map( Classes.RAW_CLASS, interfacesOf( clazz ) );
+        for( Class<?> anInterface : interfaces )
+        {
+            try
+            {
+                anInterface.getMethod( method.getName(), method.getParameterTypes() );
+                return anInterface;
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Try next
+            }
+        }
+
+        throw new NoSuchMethodException( method.getName() );
+    }
+
+    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
+    {
+        for( Class<?> aClass : Iterables.filter( Methods.HAS_METHODS, Iterables.map( Classes.RAW_CLASS, interfacesOf( baseClass ) ) ) )
+        {
+            try
+            {
+                Method m = aClass.getMethod( method.getName(), method.getParameterTypes() );
+                m.setAccessible( true );
+                return true;
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Ignore
+            }
+        }
+        return false;
+    }
+
+    private static void type( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
+        }
+        else
+        {
+            mv.visitLdcInsn( Type.getType( aClass ) );
+        }
+    }
+
+    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
+            mv.visitLabel( label );
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
+            mv.visitLabel( label );
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
+            mv.visitLabel( label );
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitLabel( label );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void returnResult( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static void insn( MethodVisitor mv, int length )
+    {
+        switch( length )
+        {
+        case 0:
+            mv.visitInsn( ICONST_0 );
+            return;
+        case 1:
+            mv.visitInsn( ICONST_1 );
+            return;
+        case 2:
+            mv.visitInsn( ICONST_2 );
+            return;
+        case 3:
+            mv.visitInsn( ICONST_3 );
+            return;
+        case 4:
+            mv.visitInsn( ICONST_4 );
+            return;
+        case 5:
+            mv.visitInsn( ICONST_5 );
+            return;
+        default:
+            mv.visitIntInsn( BIPUSH, length );
+        }
+    }
+
+    public static boolean isGenerated( Class clazz )
+    {
+        return clazz.getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public static boolean isGenerated( Object object )
+    {
+        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public Class loadFragmentClass( Class fragmentClass )
+        throws ClassNotFoundException
+    {
+        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
+    }
+
+    public static Class getSourceClass( Class fragmentClass )
+    {
+        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientInstance.java
new file mode 100644
index 0000000..9d70a62
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientInstance.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2007, Alin Dreghiciu. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import org.apache.zest.api.Qi4j;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.property.StateHolder;
+import org.apache.zest.api.structure.Layer;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.runtime.structure.ModuleInstance;
+import org.apache.zest.spi.module.ModuleSpi;
+
+/**
+ * InvocationHandler for proxy objects.
+ */
+public class TransientInstance
+    implements CompositeInstance, MixinsInstance
+{
+    public static TransientInstance compositeInstanceOf( Composite composite )
+    {
+        InvocationHandler handler = Proxy.getInvocationHandler( composite );
+        return (TransientInstance) handler;
+    }
+
+    private final Composite proxy;
+    protected final Object[] mixins;
+    protected StateHolder state;
+    protected final CompositeModel compositeModel;
+    private final ModuleSpi moduleInstance;
+
+    public TransientInstance( CompositeModel compositeModel,
+                              ModuleSpi moduleInstance,
+                              Object[] mixins,
+                              StateHolder state
+    )
+    {
+        this.compositeModel = compositeModel;
+        this.moduleInstance = moduleInstance;
+        this.mixins = mixins;
+        this.state = state;
+
+        proxy = compositeModel.newProxy( this );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return compositeModel.invoke( this, proxy, method, args, moduleInstance );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T proxy()
+    {
+        return (T) proxy;
+    }
+
+    @Override
+    public <T> T newProxy( Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+        return compositeModel.newProxy( this, mixinType );
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        return compositeModel.invoke( this, proxy, method, args, moduleInstance );
+    }
+
+    @Override
+    public CompositeModel descriptor()
+    {
+        return compositeModel;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return compositeModel.metaInfo( infoType );
+    }
+
+    @Override
+    public Iterable<Class<?>> types()
+    {
+        return compositeModel.types();
+    }
+
+    @Override
+    public Module module()
+    {
+        return moduleInstance;
+    }
+
+    public Layer layer()
+    {
+        return ( (ModuleInstance) moduleInstance ).layerInstance();
+    }
+
+    @Override
+    public StateHolder state()
+    {
+        return state;
+    }
+
+    @Override
+    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable
+    {
+        Object mixin = methodInstance.getMixinFrom( mixins );
+        return methodInstance.invoke( proxy, params, mixin );
+    }
+
+    @Override
+    public Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable
+    {
+        return method.invoke( this, args );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( o == null )
+        {
+            return false;
+        }
+        if( !Proxy.isProxyClass( o.getClass() ) )
+        {
+            return false;
+        }
+        TransientInstance other = (TransientInstance) Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (Composite) o );
+        if( other.mixins.length != mixins.length )
+        {
+            return false;
+        }
+
+        for( int i = 0; i < mixins.length; i++ )
+        {
+            if( !mixins[ i ].equals( other.mixins[ i ] ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hashCode = 0;
+        for( Object mixin : mixins )
+        {
+            hashCode = hashCode * 31 + mixin.hashCode();
+        }
+        return hashCode;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder buffer = new StringBuilder();
+        boolean first = true;
+        for( Object mixin : mixins )
+        {
+            try
+            {
+                if( mixin != null )  // Can happen during construction of incorrect composites, during exception creation.
+                {
+                    Class<?> type = mixin.getClass();
+                    Method toStringMethod = type.getMethod( "toString" );
+                    Class<?> declaringClass = toStringMethod.getDeclaringClass();
+                    if( !declaringClass.equals( Object.class ) )
+                    {
+                        if( !first )
+                        {
+                            buffer.append( ", " );
+                        }
+                        first = false;
+                        buffer.append( mixin.toString() );
+                    }
+                }
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Can not happen??
+                e.printStackTrace();
+            }
+        }
+        if( first )
+        {
+            String modelTypeName = compositeModel.getClass().getSimpleName();
+            String metaTypeModel = modelTypeName.substring( 0, modelTypeName.length() - 5 );
+            return metaTypeModel + "Instance{" +
+                   "mixins=" + ( mixins == null ? null : Arrays.asList( mixins ) ) +
+                   ", state=" + state +
+                   ", compositeModel=" + compositeModel +
+                   ", module=" + moduleInstance +
+                   '}';
+        }
+        return buffer.toString();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientModel.java
new file mode 100644
index 0000000..0d0ecac
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientModel.java
@@ -0,0 +1,70 @@
+/*
+ * 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.common.MetaInfo;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.TransientDescriptor;
+import org.apache.zest.api.constraint.ConstraintViolationException;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.runtime.property.PropertyModel;
+import org.apache.zest.spi.module.ModuleSpi;
+
+/**
+ * Model for Transient Composites
+ */
+public class TransientModel
+    extends CompositeModel
+    implements TransientDescriptor
+{
+    public TransientModel( Iterable<Class<?>> types, final Visibility visibility,
+                           final MetaInfo metaInfo,
+                           final MixinsModel mixinsModel,
+                           final StateModel stateModel,
+                           final CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        super( types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+    }
+
+    public TransientInstance newInstance( ModuleSpi moduleInstance,
+                                          UsesInstance uses,
+                                          TransientStateInstance state
+    )
+    {
+        Object[] mixins = mixinsModel.newMixinHolder();
+        TransientInstance compositeInstance = new TransientInstance( this, moduleInstance, mixins, state );
+
+        // Instantiate all mixins
+        int i = 0;
+        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+        for( MixinModel mixinModel : mixinsModel.mixinModels() )
+        {
+            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+        }
+
+        // Return
+        return compositeInstance;
+    }
+
+    public void checkConstraints( TransientStateInstance instanceState )
+        throws ConstraintViolationException
+    {
+        for( PropertyModel propertyModel : stateModel.properties() )
+        {
+            propertyModel.checkConstraints( instanceState.<Object>propertyFor( propertyModel.accessor() ).get() );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientStateInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientStateInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientStateInstance.java
new file mode 100644
index 0000000..14d0901
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientStateInstance.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.zest.runtime.composite;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.Map;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.property.StateHolder;
+
+/**
+ * TODO
+ */
+public final class TransientStateInstance
+    implements StateHolder
+{
+    private final Map<AccessibleObject, Property<?>> properties;
+
+    public TransientStateInstance( Map<AccessibleObject, Property<?>> properties
+    )
+    {
+        this.properties = properties;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Property<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Property<T> property = (Property<T>) properties.get( accessor );
+
+        if( property == null )
+        {
+            throw new IllegalArgumentException( "No such property:" + accessor );
+        }
+
+        return property;
+    }
+
+    @Override
+    public Iterable<Property<?>> properties()
+    {
+        return properties.values();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientsModel.java
new file mode 100644
index 0000000..102719e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TransientsModel.java
@@ -0,0 +1,55 @@
+/*
+ * 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.List;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class TransientsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<TransientModel> transientModels;
+
+    public TransientsModel( List<TransientModel> transientModels )
+    {
+        this.transientModels = transientModels;
+    }
+
+    public Iterable<TransientModel> models()
+    {
+        return transientModels;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( TransientModel transientModel : transientModels )
+            {
+                if( !transientModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/TypedModifierInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/TypedModifierInvocationHandler.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TypedModifierInvocationHandler.java
new file mode 100644
index 0000000..3c5366d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/TypedModifierInvocationHandler.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2007 Rickard Öberg
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package org.apache.zest.runtime.composite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.apache.zest.api.composite.InvalidCompositeException;
+
+/**
+ * JAVADOC
+ */
+public final class TypedModifierInvocationHandler
+    extends FragmentInvocationHandler
+{
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            return this.method.invoke( fragment, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw cleanStackTrace( e.getTargetException(), proxy, method );
+        }
+        catch( Throwable e )
+        {
+            if( fragment == null )
+            {
+                throw new InvalidCompositeException( "No fragment available for method " + method.getName() );
+            }
+            throw cleanStackTrace( e, proxy, method );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
new file mode 100644
index 0000000..5aa0e74
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+/**
+ * Method instance pool that keeps a linked list. Uses synchronization
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class UnsynchronizedCompositeMethodInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private CompositeMethodInstance first = null;
+
+    @Override
+    public CompositeMethodInstance obtainInstance()
+    {
+        CompositeMethodInstance instance = first;
+        if( instance != null )
+        {
+            first = instance.getNext();
+        }
+        return instance;
+    }
+
+    @Override
+    public void releaseInstance( CompositeMethodInstance instance )
+    {
+        instance.setNext( first );
+        first = instance;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsageGraph.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsageGraph.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsageGraph.java
new file mode 100644
index 0000000..540a886
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsageGraph.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2008 Niclas Hedhman. All rights Reserved.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License. 
+ */
+package org.apache.zest.runtime.composite;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.zest.bootstrap.BindingException;
+
+/**
+ * This class is NOT thread-safe.
+ * //TODO: Algorithm need to be optimized.
+ */
+public final class UsageGraph<K>
+{
+    private final Collection<K> data;
+    private final Use<K> use;
+    private final boolean allowCyclic;
+    private List<K> resolved;
+    private HashMap<K, List<K>> transitive;
+
+    public UsageGraph( Collection<K> data, Use<K> use, boolean allowCyclic )
+    {
+        this.data = data;
+        this.use = use;
+        this.allowCyclic = allowCyclic;
+    }
+
+    public boolean transitiveUse( K source, K other )
+        throws BindingException
+    {
+        if( transitive == null )
+        {
+            buildUsageGraph();
+        }
+        return transitive.containsKey( source ) && transitive.get( source ).contains( other );
+    }
+
+    private void checkCyclic( List<K> visited, K sourceItem, K used )
+        throws BindingException
+    {
+        Collection<K> nextLevel = use.uses( used );
+        for( K next : nextLevel )
+        {
+            if( next == sourceItem )
+            {
+                if( !allowCyclic )
+                {
+                    visited.add( next );
+                    throw new BindingException( "Cyclic usage detected: " + sourceItem + " -> " + visited );
+                }
+            }
+            if( !visited.contains( next ) )
+            {
+                visited.add( next );
+                checkCyclic( visited, sourceItem, next );
+            }
+        }
+    }
+
+    /**
+     * Must be called if the data set has been modified.
+     */
+    public void invalidate()
+    {
+        resolved = null;
+        transitive = null;
+    }
+
+    public List<K> resolveOrder()
+        throws BindingException
+    {
+        if( resolved == null )
+        {
+            buildUsageGraph();
+            resolved = new LinkedList<K>();
+            for( K item : data )
+            {
+                int pos = resolved.size();
+                for( K entry : resolved )
+                {
+                    if( transitiveUse( entry, item ) )
+                    {
+                        pos = resolved.indexOf( entry );
+                        break;
+                    }
+                }
+                resolved.add( pos, item );
+            }
+        }
+        return resolved;
+    }
+
+    private void buildUsageGraph()
+        throws BindingException
+    {
+        transitive = new HashMap<K, List<K>>();
+        for( K sourceItem : data )
+        {
+            LinkedList<K> visited = new LinkedList<K>();
+            checkCyclic( visited, sourceItem, sourceItem );
+            transitive.put( sourceItem, visited );
+        }
+    }
+
+    public interface Use<K>
+    {
+
+        /**
+         * @param source The item to be queried.
+         *
+         * @return A list of items it uses.
+         */
+        Collection<K> uses( K source );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsesInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsesInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsesInstance.java
new file mode 100644
index 0000000..14cdf32
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/UsesInstance.java
@@ -0,0 +1,107 @@
+/*
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.zest.functional.Iterables;
+
+/**
+ * JAVADOC
+ */
+public final class UsesInstance
+{
+    public static final UsesInstance EMPTY_USES;
+    private final Set<Object> uses;
+
+    static
+    {
+        EMPTY_USES = new UsesInstance( new HashSet<>() );
+    }
+
+    private UsesInstance( HashSet<Object> uses )
+    {
+        this.uses = Collections.unmodifiableSet( uses );
+    }
+
+    public UsesInstance use( Object... objects )
+    {
+        HashSet<Object> useObjects = new HashSet<>();
+        if( !uses.isEmpty() )
+        {
+            useObjects.addAll( uses );
+            for( Object object : objects )
+            {
+                Object oldUseForType = useForType( object.getClass() );
+                if( oldUseForType != null )
+                {
+                    useObjects.remove( oldUseForType );
+                }
+            }
+        }
+        useObjects.addAll( Arrays.asList( objects ) );
+        return new UsesInstance( useObjects );
+    }
+
+    public Object useForType( Class<?> type )
+    {
+        // Check instances first
+        for( Object use : uses )
+        {
+            if( type.isInstance( use ) )
+            {
+                return use;
+            }
+        }
+
+        return null;
+    }
+
+    public Object[] toArray()
+    {
+        return Iterables.toArray( uses );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        UsesInstance that = (UsesInstance) o;
+        return uses.equals( that.uses );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return uses.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return "UsesInstance{" +
+               "uses=" + uses +
+               '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsInstance.java
new file mode 100644
index 0000000..25dddca
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsInstance.java
@@ -0,0 +1,125 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.constraint.ConstraintViolation;
+
+/**
+ * JAVADOC
+ */
+public final class ValueConstraintsInstance
+{
+    private static final Optional OPTIONAL;
+
+    static
+    {
+        OPTIONAL = new OptionalDummy();
+    }
+
+    @SuppressWarnings( "raw" )
+    private final List<ConstraintInstance> constraints;
+    private String name;
+    private boolean optional;
+
+    public ValueConstraintsInstance( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
+    {
+        this.name = name;
+        this.optional = optional;
+        constraints = new ArrayList<>();
+        for( AbstractConstraintModel constraintModel : constraintModels )
+        {
+            constraints.add( constraintModel.newInstance() );
+        }
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public List<ConstraintViolation> checkConstraints( Object value )
+    {
+        List<ConstraintViolation> violations = null;
+
+        // Check optional first - this avoids NPE's in constraints
+        if( optional )
+        {
+            if( value == null )
+            {
+                violations = Collections.emptyList();
+            }
+        }
+        else
+        {
+            if( value == null )
+            {
+                violations = new ArrayList<>();
+                violations.add( new ConstraintViolation( name, OPTIONAL, null ) );
+            }
+        }
+
+        if( violations == null && value != null )
+        {
+            for( ConstraintInstance constraint : constraints )
+            {
+                boolean valid;
+                try
+                {
+                    valid = constraint.isValid( value );
+                }
+                catch( NullPointerException e )
+                {
+                    // A NPE is the same as a failing constraint
+                    valid = false;
+                }
+
+                if( !valid )
+                {
+                    if( violations == null )
+                    {
+                        violations = new ArrayList<>();
+                    }
+                    ConstraintViolation violation = new ConstraintViolation( name, constraint.annotation(), value );
+                    violations.add( violation );
+                }
+            }
+        }
+
+        if( violations == null )
+        {
+            violations = Collections.emptyList();
+        }
+
+        return violations;
+    }
+
+    @SuppressWarnings( "AnnotationAsSuperInterface" )
+    private static class OptionalDummy
+        implements Optional
+    {
+        @Override
+        public Class<? extends Annotation> annotationType()
+        {
+            return Optional.class;
+        }
+
+        @Override
+        public String toString()
+        {
+            return "not optional";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsModel.java
new file mode 100644
index 0000000..4eb6007
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/ValueConstraintsModel.java
@@ -0,0 +1,66 @@
+/*
+ * 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.List;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class ValueConstraintsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<AbstractConstraintModel> constraintModels;
+    private String name;
+    private boolean optional;
+
+    public ValueConstraintsModel( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
+    {
+        this.constraintModels = constraintModels;
+        this.name = name;
+        this.optional = optional;
+    }
+
+    public ValueConstraintsInstance newInstance()
+    {
+        return new ValueConstraintsInstance( constraintModels, name, optional );
+    }
+
+    public boolean isConstrained()
+    {
+        if( !constraintModels.isEmpty() )
+        {
+            return true;
+        }
+
+        return !optional;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        for( AbstractConstraintModel constraintModel : constraintModels )
+        {
+            if( constraintModel.accept( modelVisitor ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntitiesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntitiesModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntitiesModel.java
new file mode 100644
index 0000000..56deeb7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntitiesModel.java
@@ -0,0 +1,55 @@
+/*
+ * 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.entity;
+
+import java.util.List;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+
+/**
+ * Model of entities in a particular Module.
+ */
+public class EntitiesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<EntityModel> entityModels;
+
+    public EntitiesModel( List<EntityModel> entityModels )
+    {
+        this.entityModels = entityModels;
+    }
+
+    public Iterable<EntityModel> models()
+    {
+        return entityModels;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( EntityModel entityModel : entityModels )
+            {
+                if( !entityModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityInstance.java
new file mode 100644
index 0000000..8512a87
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityInstance.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2008-2009, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2009-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.zest.api.association.Association;
+import org.apache.zest.api.association.AssociationDescriptor;
+import org.apache.zest.api.association.AssociationStateDescriptor;
+import org.apache.zest.api.association.ManyAssociation;
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.composite.CompositeDescriptor;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.constraint.ConstraintViolationException;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.entity.EntityReference;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.entity.LifecycleException;
+import org.apache.zest.api.unitofwork.NoSuchEntityException;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.UnitOfWorkException;
+import org.apache.zest.runtime.composite.CompositeMethodInstance;
+import org.apache.zest.runtime.composite.MixinsInstance;
+import org.apache.zest.runtime.structure.ModuleUnitOfWork;
+import org.apache.zest.spi.entity.EntityState;
+import org.apache.zest.spi.entity.EntityStatus;
+import org.apache.zest.spi.module.ModuleSpi;
+
+/**
+ * Entity instance
+ */
+public final class EntityInstance
+    implements CompositeInstance, MixinsInstance
+{
+    public static EntityInstance entityInstanceOf( EntityComposite composite )
+    {
+        return (EntityInstance) Proxy.getInvocationHandler( composite );
+    }
+
+    private final EntityComposite proxy;
+    private final ModuleUnitOfWork uow;
+    private final ModuleSpi moduleInstance;
+    private final EntityModel entityModel;
+    private final EntityReference identity;
+    private final EntityState entityState;
+
+    private Object[] mixins;
+    private EntityStateInstance state;
+
+    public EntityInstance( ModuleUnitOfWork uow,
+                           ModuleSpi moduleInstance,
+                           EntityModel entityModel,
+                           EntityState entityState
+    )
+    {
+        this.uow = uow;
+        this.moduleInstance = moduleInstance;
+        this.entityModel = entityModel;
+        this.identity = entityState.identity();
+        this.entityState = entityState;
+
+        proxy = (EntityComposite) entityModel.newProxy( this );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return entityModel.invoke( this, this.proxy, method, args, moduleInstance );
+    }
+
+    public EntityReference identity()
+    {
+        return identity;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T proxy()
+    {
+        return (T) proxy;
+    }
+
+    @Override
+    public CompositeDescriptor descriptor()
+    {
+        return entityModel;
+    }
+
+    @Override
+    public <T> T newProxy( Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+        return entityModel.newProxy( this, mixinType );
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        return entityModel.invoke( this, proxy, method, args, moduleInstance );
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return entityModel.metaInfo( infoType );
+    }
+
+    public EntityModel entityModel()
+    {
+        return entityModel;
+    }
+
+    @Override
+    public Iterable<Class<?>> types()
+    {
+        return entityModel.types();
+    }
+
+    @Override
+    public ModuleSpi module()
+    {
+        return moduleInstance;
+    }
+
+    public UnitOfWork unitOfWork()
+    {
+        return uow;
+    }
+
+    public EntityState entityState()
+    {
+        return entityState;
+    }
+
+    @Override
+    public EntityStateInstance state()
+    {
+        if( state == null )
+        {
+            initState();
+        }
+
+        return state;
+    }
+
+    public EntityStatus status()
+    {
+        return entityState.status();
+    }
+
+    @Override
+    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable
+    {
+        if( mixins == null )
+        {
+            initState();
+        }
+
+        Object mixin = methodInstance.getMixinFrom( mixins );
+
+        if( mixin == null )
+        {
+            mixin = entityModel.newMixin( mixins, state, this, methodInstance.method() );
+        }
+
+        return methodInstance.invoke( proxy, params, mixin );
+    }
+
+    @Override
+    public Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable
+    {
+        return method.invoke( this, args );
+    }
+
+    private void initState()
+    {
+        if( !uow.isOpen() )
+        {
+            throw new UnitOfWorkException( "Unit of work has been closed" );
+        }
+
+        if( status() == EntityStatus.REMOVED )
+        {
+            throw new NoSuchEntityException( identity, entityModel.types(), unitOfWork().usecase() );
+        }
+
+        mixins = entityModel.newMixinHolder();
+        state = new EntityStateInstance( entityModel.state(), uow, entityState );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return identity.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        try
+        {
+            Identity other = ( (Identity) o );
+            return other != null && other.identity().get().equals( identity.identity() );
+        }
+        catch( ClassCastException e )
+        {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return identity.toString();
+    }
+
+    public void remove( UnitOfWork unitOfWork )
+        throws LifecycleException
+    {
+        invokeRemove();
+
+        removeAggregatedEntities( unitOfWork );
+
+        entityState.remove();
+        mixins = null;
+    }
+
+    public void invokeCreate()
+    {
+        lifecyleInvoke( true );
+    }
+
+    private void invokeRemove()
+    {
+        lifecyleInvoke( false );
+    }
+
+    private void lifecyleInvoke( boolean create )
+    {
+        if( mixins == null )
+        {
+            initState();
+        }
+
+        entityModel.invokeLifecycle( create, mixins, this, state );
+    }
+
+    private void removeAggregatedEntities( UnitOfWork unitOfWork )
+    {
+        // Calculate aggregated Entities
+        AssociationStateDescriptor stateDescriptor = entityModel.state();
+        Set<Object> aggregatedEntities = new HashSet<>();
+        Iterable<? extends AssociationDescriptor> associations = stateDescriptor.associations();
+        for( AssociationDescriptor association : associations )
+        {
+            if( association.isAggregated() )
+            {
+                Association<?> assoc = state.associationFor( association.accessor() );
+                Object aggregatedEntity = assoc.get();
+                if( aggregatedEntity != null )
+                {
+                    aggregatedEntities.add( aggregatedEntity );
+                }
+            }
+        }
+        Iterable<? extends AssociationDescriptor> manyAssociations = stateDescriptor.manyAssociations();
+        for( AssociationDescriptor association : manyAssociations )
+        {
+            if( association.isAggregated() )
+            {
+                ManyAssociation<?> manyAssoc = state.manyAssociationFor( association.accessor() );
+                for( Object entity : manyAssoc )
+                {
+                    aggregatedEntities.add( entity );
+                }
+            }
+        }
+        Iterable<? extends AssociationDescriptor> namedAssociations = stateDescriptor.namedAssociations();
+        for( AssociationDescriptor association : namedAssociations )
+        {
+            if( association.isAggregated() )
+            {
+                NamedAssociation<?> namedAssoc = state.namedAssociationFor( association.accessor() );
+                for( String name : namedAssoc )
+                {
+                    aggregatedEntities.add( namedAssoc.get( name ) );
+                }
+            }
+        }
+
+        // Remove aggregated Entities
+        for( Object aggregatedEntity : aggregatedEntities )
+        {
+            unitOfWork.remove( aggregatedEntity );
+        }
+    }
+
+    public void checkConstraints()
+    {
+        try
+        {
+            state.checkConstraints();
+        }
+        catch( ConstraintViolationException e )
+        {
+            throw new ConstraintViolationException( identity.identity(), entityModel.types(), e.mixinTypeName(), e.methodName(), e
+                .constraintViolations() );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/061ddaa0/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityMixinsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityMixinsModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityMixinsModel.java
new file mode 100644
index 0000000..2ad5b05
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/entity/EntityMixinsModel.java
@@ -0,0 +1,94 @@
+/*
+ * 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.entity;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.entity.Lifecycle;
+import org.apache.zest.api.property.StateHolder;
+import org.apache.zest.bootstrap.BindingException;
+import org.apache.zest.runtime.composite.MixinModel;
+import org.apache.zest.runtime.composite.MixinsModel;
+import org.apache.zest.runtime.composite.UsesInstance;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class EntityMixinsModel
+    extends MixinsModel
+{
+    List<Integer> lifecycleMixins;
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        super.bind( resolution );
+
+        // Find what mixins implement Lifecycle
+        for( int i = 0; i < mixinModels.size(); i++ )
+        {
+            MixinModel mixinModel = mixinModels.get( i );
+            if( Lifecycle.class.isAssignableFrom( mixinModel.mixinClass() ) )
+            {
+                if( lifecycleMixins == null )
+                {
+                    lifecycleMixins = new ArrayList<Integer>();
+                }
+
+                lifecycleMixins.add( i );
+            }
+        }
+    }
+
+    public Object newMixin( EntityInstance entityInstance, StateHolder state, Object[] mixins, Method method )
+    {
+        MixinModel model = methodImplementation.get( method );
+        InjectionContext injectionContext = new InjectionContext( entityInstance, UsesInstance.EMPTY_USES, state );
+        Object mixin = model.newInstance( injectionContext );
+        mixins[ methodIndex.get( method ) ] = mixin;
+        return mixin;
+    }
+
+    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
+    {
+        if( lifecycleMixins != null )
+        {
+            InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
+            for( Integer lifecycleMixin : lifecycleMixins )
+            {
+                Lifecycle lifecycle = (Lifecycle) mixins[ lifecycleMixin ];
+
+                if( lifecycle == null )
+                {
+                    lifecycle = (Lifecycle) mixinModels.get( lifecycleMixin ).newInstance( injectionContext );
+                }
+
+                if( create )
+                {
+                    lifecycle.create();
+                }
+                else
+                {
+                    lifecycle.remove();
+                }
+            }
+        }
+    }
+}


Mime
View raw message