    public static <T> T templateFor( Class<T> clazz )
    {
        NullArgumentException.validateNotNull( "Template class", clazz );
        if( clazz.isInterface() )
        {
            return clazz.cast( Proxy.newProxyInstance( clazz.getClassLoader(),
                                                       new Class<?>[] { clazz },
                                                       new TemplateHandler<T>( null, null, null ) ) );
        }
        else
        {
            try
            {
                T mixin = clazz.newInstance();
                for( Field field : clazz.getFields() )
                {
                    if( field.getAnnotation( State.class ) != null )
                    {
                        if( field.getType().equals( Property.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, field ) ) ) );
                        }
                        else if( field.getType().equals( Association.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new AssociationReferenceHandler<>( new AssociationFunction<T>( null, null, field ) ) ) );
                        }
                        else if( field.getType().equals( Property.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( null, null, field ) ) ) );
                        }
                    }
                }
                return mixin;
            }
            catch( IllegalAccessException | IllegalArgumentException | InstantiationException | SecurityException e )
            {
                throw new IllegalArgumentException( "Cannot use class as template", e );
            }
        }
    }

    public static <T> T templateFor( Class<T> clazz )
    {
        NullArgumentException.validateNotNull( "Template class", clazz );
        if( clazz.isInterface() )
        {
            return clazz.cast( Proxy.newProxyInstance( clazz.getClassLoader(),
                                                       new Class<?>[] { clazz },
                                                       new TemplateHandler<T>( null, null, null ) ) );
        }
        else
        {
            try
            {
                T mixin = clazz.newInstance();
                for( Field field : clazz.getFields() )
                {
                    if( field.getAnnotation( State.class ) != null )
                    {
                        if( field.getType().equals( Property.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, field ) ) ) );
                        }
                        else if( field.getType().equals( Association.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new AssociationReferenceHandler<>( new AssociationFunction<T>( null, null, field ) ) ) );
                        }
                        else if( field.getType().equals( ManyAssociation.class ) )
                        {
                            field.set( mixin,
                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
                                                               new Class<?>[]{ field.getType() },
                                                               new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( null, null, field ) ) ) );
                        }
                    }
                }
                return mixin;
            }
            catch( IllegalAccessException | IllegalArgumentException | InstantiationException | SecurityException e )
            {
                throw new IllegalArgumentException( "Cannot use class as template", e );
            }
        }
    }
