polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [16/80] [partial] zest-java git commit: First round of changes to move to org.apache.zest namespace.
Date Thu, 30 Jul 2015 19:48:15 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/CompositeAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/CompositeAssemblyImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/CompositeAssemblyImpl.java
new file mode 100644
index 0000000..458ff79
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/CompositeAssemblyImpl.java
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, 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.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.common.QualifiedName;
+import org.apache.zest.api.common.UseDefaults;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.InvalidCompositeException;
+import org.apache.zest.api.concern.Concerns;
+import org.apache.zest.api.constraint.Constraint;
+import org.apache.zest.api.constraint.ConstraintDeclaration;
+import org.apache.zest.api.constraint.Constraints;
+import org.apache.zest.api.constraint.Name;
+import org.apache.zest.api.entity.Lifecycle;
+import org.apache.zest.api.injection.scope.State;
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.mixin.Initializable;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.GenericPropertyInfo;
+import org.apache.zest.api.property.Immutable;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.sideeffect.SideEffects;
+import org.apache.zest.api.type.HasTypes;
+import org.apache.zest.api.util.Annotations;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.api.util.Fields;
+import org.apache.zest.bootstrap.StateDeclarations;
+import org.apache.zest.functional.ForEach;
+import org.apache.zest.functional.Function;
+import org.apache.zest.functional.HierarchicalVisitorAdapter;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.functional.Visitor;
+import org.apache.zest.runtime.composite.AbstractConstraintModel;
+import org.apache.zest.runtime.composite.CompositeConstraintModel;
+import org.apache.zest.runtime.composite.CompositeMethodModel;
+import org.apache.zest.runtime.composite.CompositeMethodsModel;
+import org.apache.zest.runtime.composite.ConcernModel;
+import org.apache.zest.runtime.composite.ConcernsModel;
+import org.apache.zest.runtime.composite.ConstraintModel;
+import org.apache.zest.runtime.composite.ConstraintsModel;
+import org.apache.zest.runtime.composite.GenericSpecification;
+import org.apache.zest.runtime.composite.MixinModel;
+import org.apache.zest.runtime.composite.MixinsModel;
+import org.apache.zest.runtime.composite.SideEffectModel;
+import org.apache.zest.runtime.composite.SideEffectsModel;
+import org.apache.zest.runtime.composite.StateModel;
+import org.apache.zest.runtime.composite.ValueConstraintsInstance;
+import org.apache.zest.runtime.composite.ValueConstraintsModel;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.runtime.property.PropertiesModel;
+import org.apache.zest.runtime.property.PropertyModel;
+
+import static java.util.Arrays.asList;
+import static org.apache.zest.api.util.Annotations.hasAnnotation;
+import static org.apache.zest.api.util.Annotations.isType;
+import static org.apache.zest.api.util.Annotations.type;
+import static org.apache.zest.api.util.Classes.classHierarchy;
+import static org.apache.zest.api.util.Classes.interfacesOf;
+import static org.apache.zest.api.util.Classes.isAssignableFrom;
+import static org.apache.zest.api.util.Classes.typeOf;
+import static org.apache.zest.api.util.Classes.typesOf;
+import static org.apache.zest.api.util.Classes.wrapperClass;
+import static org.apache.zest.functional.Iterables.addAll;
+import static org.apache.zest.functional.Iterables.cast;
+import static org.apache.zest.functional.Iterables.empty;
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Iterables.first;
+import static org.apache.zest.functional.Iterables.flatten;
+import static org.apache.zest.functional.Iterables.flattenIterables;
+import static org.apache.zest.functional.Iterables.iterable;
+import static org.apache.zest.functional.Iterables.map;
+import static org.apache.zest.functional.Iterables.matchesAny;
+import static org.apache.zest.functional.Iterables.toList;
+import static org.apache.zest.functional.Specifications.and;
+import static org.apache.zest.functional.Specifications.in;
+import static org.apache.zest.functional.Specifications.not;
+import static org.apache.zest.functional.Specifications.or;
+import static org.apache.zest.functional.Specifications.translate;
+
+/**
+ * Declaration of a Composite.
+ */
+public abstract class CompositeAssemblyImpl
+    implements HasTypes
+{
+    protected List<Class<?>> concerns = new ArrayList<>();
+    protected List<Class<?>> sideEffects = new ArrayList<>();
+    protected List<Class<?>> mixins = new ArrayList<>();
+    protected List<Class<?>> types = new ArrayList<>();
+    protected MetaInfo metaInfo = new MetaInfo();
+    protected Visibility visibility = Visibility.module;
+
+    protected boolean immutable;
+    protected PropertiesModel propertiesModel;
+    protected StateModel stateModel;
+    protected MixinsModel mixinsModel;
+    protected CompositeMethodsModel compositeMethodsModel;
+    private AssemblyHelper helper;
+    protected StateDeclarations stateDeclarations;
+
+    protected Set<String> registeredStateNames = new HashSet<>();
+
+    public CompositeAssemblyImpl( Class<?> mainType )
+    {
+        types.add( mainType );
+    }
+
+    @Override
+    public Iterable<Class<?>> types()
+    {
+        return types;
+    }
+
+    protected StateModel createStateModel()
+    {
+        return new StateModel( propertiesModel );
+    }
+
+    protected MixinsModel createMixinsModel()
+    {
+        return new MixinsModel();
+    }
+
+    protected void buildComposite( AssemblyHelper helper,
+                                   StateDeclarations stateDeclarations
+    )
+    {
+        this.stateDeclarations = stateDeclarations;
+        this.helper = helper;
+        for( Class<?> compositeType : types )
+        {
+            metaInfo = new MetaInfo( metaInfo ).withAnnotations( compositeType );
+            addAnnotationsMetaInfo( compositeType, metaInfo );
+        }
+
+        immutable = metaInfo.get( Immutable.class ) != null;
+        propertiesModel = new PropertiesModel();
+        stateModel = createStateModel();
+        mixinsModel = createMixinsModel();
+        compositeMethodsModel = new CompositeMethodsModel( mixinsModel );
+
+        // Implement composite methods
+        ArrayList<Type> allTypes = getTypes( this.types );
+        Iterable<Class<? extends Constraint<?, ?>>> constraintClasses = constraintDeclarations( getTypes( this.types ) );
+        Iterable<Class<?>> concernClasses = flatten( concerns, concernDeclarations( allTypes ) );
+        Iterable<Class<?>> sideEffectClasses = flatten( sideEffects, sideEffectDeclarations( allTypes ) );
+        Iterable<Class<?>> mixinClasses = flatten( mixins, mixinDeclarations( this.types ) );
+        implementMixinType( types, constraintClasses, concernClasses, sideEffectClasses, mixinClasses );
+
+        // Add state from methods and fields
+        addState( constraintClasses );
+    }
+
+    protected void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo )
+    {
+        Class[] declaredInterfaces = type.getInterfaces();
+        for( int i = declaredInterfaces.length - 1; i >= 0; i-- )
+        {
+            addAnnotationsMetaInfo( declaredInterfaces[ i], compositeMetaInfo );
+        }
+        compositeMetaInfo.withAnnotations( type );
+    }
+
+    protected void implementMixinType( Iterable<? extends Class<?>> types,
+                                       Iterable<Class<? extends Constraint<?, ?>>> constraintClasses,
+                                       Iterable<Class<?>> concernClasses,
+                                       Iterable<Class<?>> sideEffectClasses,
+                                       Iterable<Class<?>> mixinClasses
+    )
+    {
+        Set<Class<?>> thisDependencies = new HashSet<>();
+        for( Class<?> mixinType : types )
+        {
+            for( Method method : mixinType.getMethods() )
+            {
+                if( !compositeMethodsModel.isImplemented( method )
+                    && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() )
+                    && !Proxy.class.equals( method.getDeclaringClass() )
+                    && !Modifier.isStatic( method.getModifiers() ) )
+                {
+                    MixinModel mixinModel = implementMethod( method, mixinClasses );
+                    ConcernsModel concernsModel = concernsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        Iterables.<Class<?>>flatten( concernDeclarations( mixinModel.mixinClass() ),
+                                                     concernClasses )
+                    );
+                    SideEffectsModel sideEffectsModel = sideEffectsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        Iterables.<Class<?>>flatten( sideEffectDeclarations( mixinModel.mixinClass() ),
+                                                     sideEffectClasses )
+                    );
+                    method.setAccessible( true );
+                    ConstraintsModel constraints = constraintsFor(
+                        method,
+                        Iterables.<Class<? extends Constraint<?, ?>>>flatten( constraintDeclarations( mixinModel.mixinClass() ),
+                                                                              constraintClasses )
+                    );
+                    CompositeMethodModel methodComposite = new CompositeMethodModel(
+                        method,
+                        constraints,
+                        concernsModel,
+                        sideEffectsModel,
+                        mixinsModel
+                    );
+
+                    // Implement @This references
+                    Iterable<Class<?>> map = map( new DependencyModel.InjectionTypeFunction(),
+                                                  filter( new DependencyModel.ScopeSpecification( This.class ),
+                                                          methodComposite.dependencies() ) );
+                    Iterable<Class<?>> map1 = map( new DependencyModel.InjectionTypeFunction(),
+                                                   filter( new DependencyModel.ScopeSpecification( This.class ),
+                                                           mixinModel.dependencies() ) );
+                    @SuppressWarnings( "unchecked" )
+                    Iterable<Class<?>> filter = filter(
+                        not( in( Initializable.class, Lifecycle.class, InvocationHandler.class ) ),
+                        map( Classes.RAW_CLASS, interfacesOf( mixinModel.mixinClass() ) )
+                    );
+                    Iterable<? extends Class<?>> flatten = flatten( map, map1, filter );
+                    addAll( thisDependencies, flatten );
+
+                    compositeMethodsModel.addMethod( methodComposite );
+                }
+            }
+            // Add type to set of mixin types
+            mixinsModel.addMixinType( mixinType );
+        }
+
+        // Implement all @This dependencies that were found
+        for( Class<?> thisDependency : thisDependencies )
+        {
+            // Add additional declarations from the @This type
+            Iterable<Class<? extends Constraint<?, ?>>> typeConstraintClasses = flatten(
+                constraintClasses,
+                constraintDeclarations( thisDependency ) );
+            Iterable<Class<?>> typeConcernClasses = flatten(
+                concernClasses,
+                concernDeclarations( thisDependency ) );
+            Iterable<Class<?>> typeSideEffectClasses = flatten(
+                sideEffectClasses,
+                sideEffectDeclarations( thisDependency ) );
+            Iterable<Class<?>> typeMixinClasses = flatten(
+                mixinClasses,
+                mixinDeclarations( thisDependency ) );
+
+            @SuppressWarnings( "unchecked" )
+            Iterable<? extends Class<?>> singleton = iterable( thisDependency );
+            implementMixinType( singleton, typeConstraintClasses, typeConcernClasses, typeSideEffectClasses, typeMixinClasses );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    protected MixinModel implementMethod( Method method, Iterable<Class<?>> mixinDeclarations )
+    {
+        MixinModel implementationModel = mixinsModel.mixinFor( method );
+        if( implementationModel != null )
+        {
+            return implementationModel;
+        }
+        Class mixinClass = findTypedImplementation( method, mixinDeclarations );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+
+        // Check generic implementations
+        mixinClass = findGenericImplementation( method, mixinDeclarations );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+
+        throw new InvalidCompositeException( "No implementation found for method \n    " + method.toGenericString()
+                                             + "\nin\n    " + types );
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    private Class findTypedImplementation( final Method method, Iterable<Class<?>> mixins )
+    {
+        // Check if mixinClass implements the method. If so, check if the mixinClass is generic or if the filter passes.
+        // If a mixinClass is both generic AND non-generic at the same time, then the filter applies to the non-generic
+        // side only.
+        Specification<Class<?>> appliesToSpec = new Specification<Class<?>>()
+        {
+            @Override
+            public boolean satisfiedBy( Class<?> item )
+            {
+                return helper.appliesTo( item, method, types, item );
+            }
+        };
+        return first( filter( and( isAssignableFrom( method.getDeclaringClass() ),
+                                   or( GenericSpecification.INSTANCE, appliesToSpec ) ),
+                              mixins ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Class<?> findGenericImplementation( final Method method, Iterable<Class<?>> mixins )
+    {
+        // Check if mixinClass is generic and the applies-to filter passes
+        return first( filter( and( GenericSpecification.INSTANCE, new Specification<Class<?>>()
+        {
+            @Override
+            public boolean satisfiedBy( Class<?> item )
+            {
+                return helper.appliesTo( item, method, types, item );
+            }
+        } ), mixins ) );
+    }
+
+    private MixinModel implementMethodWithClass( Method method, Class mixinClass )
+    {
+        MixinModel mixinModel = mixinsModel.getMixinModel( mixinClass );
+        if( mixinModel == null )
+        {
+            mixinModel = helper.getMixinModel( mixinClass );
+            mixinsModel.addMixinModel( mixinModel );
+        }
+
+        mixinsModel.addMethodMixin( method, mixinModel );
+
+        return mixinModel;
+    }
+
+    protected void addState( final Iterable<Class<? extends Constraint<?, ?>>> constraintClasses )
+    {
+        // Add method state
+        compositeMethodsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof CompositeMethodModel )
+                {
+                    CompositeMethodModel methodModel = (CompositeMethodModel) visited;
+                    if( methodModel.method().getParameterTypes().length == 0 )
+                    {
+                        addStateFor( methodModel.method(), constraintClasses );
+                    }
+
+                    return false;
+                }
+
+                return super.visitEnter( visited );
+            }
+        } );
+
+        // Add field state
+        mixinsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof MixinModel )
+                {
+                    MixinModel model = (MixinModel) visited;
+                    Visitor<Field, RuntimeException> addState = new Visitor<Field, RuntimeException>()
+                    {
+                        @Override
+                        public boolean visit( Field visited )
+                            throws RuntimeException
+                        {
+                            addStateFor( visited, constraintClasses );
+                            return true;
+                        }
+                    };
+                    ForEach.forEach( Fields.FIELDS_OF.map( model.mixinClass() ) ).
+                        filter( Annotations.hasAnnotation( State.class ) ).
+                        visit( addState );
+                    return false;
+                }
+                return super.visitEnter( visited );
+            }
+        } );
+    }
+
+    protected void addStateFor( AccessibleObject accessor,
+                                Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        String stateName = QualifiedName.fromAccessor( accessor ).name();
+
+        if( registeredStateNames.contains( stateName ) )
+        {
+            return; // Skip already registered names
+        }
+
+        if( Property.class.isAssignableFrom( Classes.RAW_CLASS.map( typeOf( accessor ) ) ) )
+        {
+            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+    }
+
+    protected PropertyModel newPropertyModel( AccessibleObject accessor,
+                                              Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
+        ValueConstraintsModel valueConstraintsModel = constraintsFor(
+            annotations,
+            GenericPropertyInfo.propertyTypeOf( accessor ),
+            ( (Member) accessor ).getName(),
+            optional,
+            constraintClasses,
+            accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        Object initialValue = stateDeclarations.initialValueOf( accessor );
+        boolean useDefaults = metaInfo.get( UseDefaults.class ) != null || stateDeclarations.useDefaults( accessor );
+        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
+        PropertyModel propertyModel = new PropertyModel(
+            accessor,
+            immutable,
+            useDefaults,
+            valueConstraintsInstance,
+            metaInfo,
+            initialValue );
+        return propertyModel;
+    }
+
+    // Model
+    private ConstraintsModel constraintsFor( Method method,
+                                             Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        List<ValueConstraintsModel> parameterConstraintModels = Collections.emptyList();
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        Type[] parameterTypes = method.getGenericParameterTypes();
+        boolean constrained = false;
+        for( int i = 0; i < parameterAnnotations.length; i++ )
+        {
+            Annotation[] parameterAnnotation = parameterAnnotations[i];
+
+            Name nameAnnotation = (Name) first( filter( isType( Name.class ), iterable( parameterAnnotation ) ) );
+            String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value();
+
+            boolean optional = first( filter( isType( Optional.class ), iterable( parameterAnnotation ) ) ) != null;
+            ValueConstraintsModel parameterConstraintsModel = constraintsFor(
+                asList( parameterAnnotation ),
+                parameterTypes[i],
+                name,
+                optional,
+                constraintClasses,
+                method );
+            if( parameterConstraintsModel.isConstrained() )
+            {
+                constrained = true;
+            }
+
+            if( parameterConstraintModels.isEmpty() )
+            {
+                parameterConstraintModels = new ArrayList<>();
+            }
+            parameterConstraintModels.add( parameterConstraintsModel );
+        }
+
+        if( !constrained )
+        {
+            return new ConstraintsModel( Collections.<ValueConstraintsModel>emptyList() );
+        }
+        else
+        {
+            return new ConstraintsModel( parameterConstraintModels );
+        }
+    }
+
+    protected ValueConstraintsModel constraintsFor(
+        Iterable<Annotation> constraintAnnotations,
+        Type valueType,
+        String name,
+        boolean optional,
+        Iterable<Class<? extends Constraint<?, ?>>> constraintClasses,
+        AccessibleObject accessor
+    )
+    {
+        valueType = wrapperClass( valueType );
+
+        List<AbstractConstraintModel> constraintModels = new ArrayList<>();
+        nextConstraint:
+        for( Annotation constraintAnnotation : filter( translate( type(), hasAnnotation( ConstraintDeclaration.class ) ),
+                                                       constraintAnnotations ) )
+        {
+            // Check composite declarations first
+            Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
+            for( Class<? extends Constraint<?, ?>> constraint : constraintClasses )
+            {
+                if( helper.appliesTo( constraint, annotationType, valueType ) )
+                {
+                    constraintModels.add( new ConstraintModel( constraintAnnotation, constraint ) );
+                    continue nextConstraint;
+                }
+            }
+
+            // Check the annotation itself
+            Constraints constraints = annotationType.getAnnotation( Constraints.class );
+            if( constraints != null )
+            {
+                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
+                {
+                    if( helper.appliesTo( constraintClass, annotationType, valueType ) )
+                    {
+                        constraintModels.add( new ConstraintModel( constraintAnnotation, constraintClass ) );
+                        continue nextConstraint;
+                    }
+                }
+            }
+
+            // No implementation found!
+            // Check if if it's a composite constraints
+            Iterable<Annotation> annotations = iterable( annotationType.getAnnotations() );
+            if( matchesAny( translate( type(), hasAnnotation( ConstraintDeclaration.class ) ), annotations ) )
+            {
+                ValueConstraintsModel valueConstraintsModel = constraintsFor(
+                    annotations,
+                    valueType,
+                    name,
+                    optional,
+                    constraintClasses,
+                    accessor );
+                CompositeConstraintModel compositeConstraintModel = new CompositeConstraintModel(
+                    constraintAnnotation,
+                    valueConstraintsModel );
+                constraintModels.add( compositeConstraintModel );
+                continue nextConstraint;
+            }
+
+            throw new InvalidCompositeException(
+                "Cannot find implementation of constraint @"
+                + annotationType.getSimpleName()
+                + " for "
+                + valueType
+                + " in method "
+                + ( (Member) accessor ).getName()
+                + " of composite " + types );
+        }
+
+        return new ValueConstraintsModel( constraintModels, name, optional );
+    }
+
+    private ConcernsModel concernsFor( Method method,
+                                       Class<?> mixinClass,
+                                       Iterable<Class<?>> concernClasses
+    )
+    {
+        List<ConcernModel> concernsFor = new ArrayList<>();
+        for( Class<?> concern : concernClasses )
+        {
+            if( helper.appliesTo( concern, method, types, mixinClass ) )
+            {
+                concernsFor.add( helper.getConcernModel( concern ) );
+            }
+            else
+            {
+                // Lookup method in mixin
+                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                {
+                    try
+                    {
+                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                        if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) )
+                        {
+                            concernsFor.add( helper.getConcernModel( concern ) );
+                        }
+                    }
+                    catch( NoSuchMethodException e )
+                    {
+                        // Ignore
+                    }
+                }
+            }
+        }
+
+        // Check annotations on method that have @Concerns annotations themselves
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            @SuppressWarnings( "raw" )
+            Concerns concerns = annotation.annotationType().getAnnotation( Concerns.class );
+            if( concerns != null )
+            {
+                for( Class<?> concern : concerns.value() )
+                {
+                    if( helper.appliesTo( concern, method, types, mixinClass ) )
+                    {
+                        concernsFor.add( helper.getConcernModel( concern ) );
+                    }
+                }
+            }
+        }
+
+        if( concernsFor.isEmpty() )
+        {
+            return ConcernsModel.EMPTY_CONCERNS;
+        }
+        else
+        {
+            return new ConcernsModel( concernsFor );
+        }
+    }
+
+    private SideEffectsModel sideEffectsFor( Method method,
+                                             Class<?> mixinClass,
+                                             Iterable<Class<?>> sideEffectClasses
+    )
+    {
+        List<SideEffectModel> sideEffectsFor = new ArrayList<>();
+        for( Class<?> sideEffect : sideEffectClasses )
+        {
+            if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
+            {
+                sideEffectsFor.add( helper.getSideEffectModel( sideEffect ) );
+            }
+            else
+            {
+                // Lookup method in mixin
+                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                {
+                    try
+                    {
+                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                        if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) )
+                        {
+                            sideEffectsFor.add( helper.getSideEffectModel( sideEffect ) );
+                        }
+                    }
+                    catch( NoSuchMethodException e )
+                    {
+                        // Ignore
+                    }
+                }
+            }
+        }
+
+        if( sideEffectsFor.isEmpty() )
+        {
+            return SideEffectsModel.EMPTY_SIDEEFFECTS;
+        }
+        else
+        {
+            return new SideEffectsModel( sideEffectsFor );
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Iterable<Class<? extends Constraint<?, ?>>> constraintDeclarations( Class<?> type )
+    {
+        ArrayList<Type> allTypes = getTypes( type );
+        return constraintDeclarations( allTypes );
+    }
+
+    private Iterable<Class<? extends Constraint<?, ?>>> constraintDeclarations( ArrayList<Type> allTypes )
+    {
+        // Find all constraints and flatten them into an iterable
+        Function<Type, Iterable<Class<? extends Constraint<?, ?>>>> function = new Function<Type, Iterable<Class<? extends Constraint<?, ?>>>>()
+        {
+            @Override
+            public Iterable<Class<? extends Constraint<?, ?>>> map( Type type )
+            {
+                Constraints constraints = Annotations.annotationOn( type, Constraints.class );
+                if( constraints == null )
+                {
+                    return empty();
+                }
+                else
+                {
+                    return iterable( constraints.value() );
+                }
+            }
+        };
+        Iterable<Class<? extends Constraint<?, ?>>> flatten = flattenIterables( map( function, allTypes ) );
+        return toList( flatten );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Iterable<Class<?>> concernDeclarations( Class<?> type )
+    {
+        Iterable<? extends Class<?>> iterable = iterable( type );
+        return concernDeclarations( getTypes( iterable ) );
+    }
+
+    private Iterable<Class<?>> concernDeclarations( ArrayList<Type> allTypes )
+    {
+        // Find all concerns and flattern them into an iterable
+        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
+        {
+            @Override
+            public Iterable<Class<?>> map( Type type )
+            {
+                Concerns concerns = Annotations.annotationOn( type, Concerns.class );
+                if( concerns == null )
+                {
+                    return empty();
+                }
+                else
+                {
+                    return iterable( concerns.value() );
+                }
+            }
+        };
+        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
+        return toList( flatten );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected Iterable<Class<?>> sideEffectDeclarations( Class<?> type )
+    {
+        Iterable<? extends Class<?>> iterable = iterable( type );
+        return sideEffectDeclarations( getTypes( iterable ) );
+    }
+
+    protected Iterable<Class<?>> sideEffectDeclarations( ArrayList<Type> allTypes )
+    {
+        // Find all side-effects and flattern them into an iterable
+        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
+        {
+            @Override
+            public Iterable<Class<?>> map( Type type )
+            {
+                SideEffects sideEffects = Annotations.annotationOn( type, SideEffects.class );
+                if( sideEffects == null )
+                {
+                    return empty();
+                }
+                else
+                {
+                    return iterable( sideEffects.value() );
+                }
+            }
+        };
+        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
+        return toList( flatten );
+    }
+
+    private ArrayList<Type> getTypes( Class<?> type )
+    {
+        Iterable<? extends Class<?>> iterable = iterable( type );
+        return getTypes( iterable );
+    }
+
+    private ArrayList<Type> getTypes( Iterable<? extends Class<?>> typess )
+    {
+        // Find side-effect declarations
+        ArrayList<Type> allTypes = new ArrayList<>();
+        for( Class<?> type : typess )
+        {
+            Iterable<Type> types;
+            if( type.isInterface() )
+            {
+                types = typesOf( type );
+            }
+            else
+            {
+                types = cast( classHierarchy( type ) );
+            }
+            addAll( allTypes, types );
+        }
+        return allTypes;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected Iterable<Class<?>> mixinDeclarations( Class<?> type )
+    {
+        Iterable<? extends Class<?>> iterable = iterable( type );
+        return mixinDeclarations( iterable );
+    }
+
+    protected Iterable<Class<?>> mixinDeclarations( Iterable<? extends Class<?>> typess )
+    {
+        // Find mixin declarations
+        ArrayList<Type> allTypes = new ArrayList<>();
+        for( Class<?> type : typess )
+        {
+            Iterable<Type> types = typesOf( type );
+            addAll( allTypes, types );
+        }
+
+        // Find all mixins and flattern them into an iterable
+        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
+        {
+            @Override
+            public Iterable<Class<?>> map( Type type )
+            {
+                Mixins mixins = Annotations.annotationOn( type, Mixins.class );
+                if( mixins == null )
+                {
+                    return empty();
+                }
+                else
+                {
+                    return iterable( mixins.value() );
+                }
+            }
+        };
+        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
+        return toList( flatten );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationAssemblyImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationAssemblyImpl.java
new file mode 100644
index 0000000..f755d85
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationAssemblyImpl.java
@@ -0,0 +1,42 @@
+/*
+ *  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.bootstrap;
+
+import org.apache.zest.bootstrap.ConfigurationAssembly;
+
+/**
+ * Declaration of a EntityComposite.
+ */
+public final class ConfigurationAssemblyImpl
+    implements ConfigurationAssembly
+{
+    private ValueAssemblyImpl value;
+    private EntityAssemblyImpl entity;
+
+    public ConfigurationAssemblyImpl( Class<?> mainType )
+    {
+        value = new ValueAssemblyImpl( mainType );
+        entity = new EntityAssemblyImpl( mainType );
+    }
+
+    @Override
+    public Iterable<Class<?>> types()
+    {
+        return value.types();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationDeclarationImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationDeclarationImpl.java
new file mode 100644
index 0000000..1076390
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ConfigurationDeclarationImpl.java
@@ -0,0 +1,124 @@
+/*
+ *  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.bootstrap;
+
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.bootstrap.ConfigurationDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.zest.bootstrap.ModuleAssembly#configurations(Class[])}.
+ */
+public final class ConfigurationDeclarationImpl
+    implements ConfigurationDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+    private final Iterable<ValueAssemblyImpl> values;
+
+    public ConfigurationDeclarationImpl( Iterable<EntityAssemblyImpl> entities, Iterable<ValueAssemblyImpl> values  )
+    {
+        this.entities = entities;
+        this.values = values;
+    }
+
+    @Override
+    public ConfigurationDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityAssemblyImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityAssemblyImpl.java
new file mode 100644
index 0000000..6daba43
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityAssemblyImpl.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2007-2011, Rickard Öberg. 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.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import org.apache.zest.api.association.Association;
+import org.apache.zest.api.association.GenericAssociationInfo;
+import org.apache.zest.api.association.ManyAssociation;
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.common.InvalidApplicationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.common.QualifiedName;
+import org.apache.zest.api.common.UseDefaults;
+import org.apache.zest.api.constraint.Constraint;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.property.GenericPropertyInfo;
+import org.apache.zest.api.property.Immutable;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.util.Annotations;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.bootstrap.AssociationDeclarations;
+import org.apache.zest.bootstrap.EntityAssembly;
+import org.apache.zest.bootstrap.ManyAssociationDeclarations;
+import org.apache.zest.bootstrap.NamedAssociationDeclarations;
+import org.apache.zest.bootstrap.StateDeclarations;
+import org.apache.zest.runtime.association.AssociationModel;
+import org.apache.zest.runtime.association.AssociationsModel;
+import org.apache.zest.runtime.association.ManyAssociationModel;
+import org.apache.zest.runtime.association.ManyAssociationsModel;
+import org.apache.zest.runtime.association.NamedAssociationModel;
+import org.apache.zest.runtime.association.NamedAssociationsModel;
+import org.apache.zest.runtime.composite.MixinsModel;
+import org.apache.zest.runtime.composite.StateModel;
+import org.apache.zest.runtime.composite.ValueConstraintsInstance;
+import org.apache.zest.runtime.composite.ValueConstraintsModel;
+import org.apache.zest.runtime.entity.EntityMixinsModel;
+import org.apache.zest.runtime.entity.EntityModel;
+import org.apache.zest.runtime.entity.EntityStateModel;
+import org.apache.zest.runtime.property.PropertyModel;
+
+import static org.apache.zest.api.util.Annotations.isType;
+import static org.apache.zest.api.util.Classes.typeOf;
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Iterables.first;
+
+/**
+ * Declaration of a EntityComposite.
+ */
+public final class EntityAssemblyImpl
+    extends CompositeAssemblyImpl
+    implements EntityAssembly
+{
+    private AssociationDeclarations associationDeclarations;
+    private ManyAssociationDeclarations manyAssociationDeclarations;
+    private NamedAssociationDeclarations namedAssociationDeclarations;
+    private AssociationsModel associationsModel;
+    private ManyAssociationsModel manyAssociationsModel;
+    private NamedAssociationsModel namedAssociationsModel;
+
+    public EntityAssemblyImpl( Class<?> entityType )
+    {
+        super( entityType );
+        // The composite must always implement EntityComposite, as a marker interface
+        if( !EntityComposite.class.isAssignableFrom( entityType ) )
+        {
+            types.add( EntityComposite.class );
+        }
+    }
+
+    @Override
+    protected MixinsModel createMixinsModel()
+    {
+        return new EntityMixinsModel();
+    }
+
+    @Override
+    protected StateModel createStateModel()
+    {
+        return new EntityStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
+    }
+
+    EntityModel newEntityModel(
+        StateDeclarations stateDeclarations,
+        AssociationDeclarations associationDecs,
+        ManyAssociationDeclarations manyAssociationDecs,
+        NamedAssociationDeclarations namedAssociationDecs,
+        AssemblyHelper helper
+    )
+    {
+        this.associationDeclarations = associationDecs;
+        this.manyAssociationDeclarations = manyAssociationDecs;
+        this.namedAssociationDeclarations = namedAssociationDecs;
+        try
+        {
+            associationsModel = new AssociationsModel();
+            manyAssociationsModel = new ManyAssociationsModel();
+            namedAssociationsModel = new NamedAssociationsModel();
+            buildComposite( helper, stateDeclarations );
+
+            EntityModel entityModel = new EntityModel(
+                types, visibility, metaInfo, (EntityMixinsModel) mixinsModel, (EntityStateModel) stateModel, compositeMethodsModel );
+
+            return entityModel;
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + types, e );
+        }
+    }
+
+    @Override
+    protected void addStateFor( AccessibleObject accessor,
+                                Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        String stateName = QualifiedName.fromAccessor( accessor ).name();
+
+        if( registeredStateNames.contains( stateName ) )
+        {
+            return; // Skip already registered names
+        }
+
+        Class<?> accessorType = Classes.RAW_CLASS.map( typeOf( accessor ) );
+        if( Property.class.isAssignableFrom( accessorType ) )
+        {
+            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( Association.class.isAssignableFrom( accessorType ) )
+        {
+            associationsModel.addAssociation( newAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( ManyAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            manyAssociationsModel.addManyAssociation( newManyAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( NamedAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            namedAssociationsModel.addNamedAssociation( newNamedAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+    }
+
+    @Override
+    protected PropertyModel newPropertyModel( AccessibleObject accessor,
+                                              Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericPropertyInfo.propertyTypeOf( accessor ), ( (Member) accessor )
+            .getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        Object defaultValue = stateDeclarations.initialValueOf( accessor );
+        boolean useDefaults = metaInfo.get( UseDefaults.class ) != null || stateDeclarations.useDefaults( accessor );
+        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
+        PropertyModel propertyModel = new PropertyModel( accessor, immutable, useDefaults, valueConstraintsInstance, metaInfo, defaultValue );
+        return propertyModel;
+    }
+
+    public AssociationModel newAssociationModel( AccessibleObject accessor,
+                                                 Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
+
+        // Constraints for Association references
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the Association itself
+        valueConstraintsModel = constraintsFor( annotations, Association.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance associationValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            associationValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        MetaInfo metaInfo = associationDeclarations.metaInfoFor( accessor );
+        AssociationModel associationModel = new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance, metaInfo );
+        return associationModel;
+    }
+
+    public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
+                                                         Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
+
+        // Constraints for entities in ManyAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the ManyAssociation itself
+        valueConstraintsModel = constraintsFor( annotations, ManyAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance manyValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            manyValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = manyAssociationDeclarations.metaInfoFor( accessor );
+        ManyAssociationModel associationModel = new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance, metaInfo );
+        return associationModel;
+    }
+
+    public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
+                                                           Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
+    )
+    {
+        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
+
+        // Constraints for entities in NamedAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the NamedAssociation itself
+        valueConstraintsModel = constraintsFor( annotations, NamedAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance namedValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            namedValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = namedAssociationDeclarations.metaInfoFor( accessor );
+        NamedAssociationModel associationModel = new NamedAssociationModel( accessor, valueConstraintsInstance, namedValueConstraintsInstance, metaInfo );
+        return associationModel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityDeclarationImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityDeclarationImpl.java
new file mode 100644
index 0000000..ada560e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/EntityDeclarationImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.bootstrap;
+
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.bootstrap.EntityDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.zest.bootstrap.ModuleAssembly#transients(Class[])}.
+ */
+public final class EntityDeclarationImpl
+    implements EntityDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+
+    public EntityDeclarationImpl( Iterable<EntityAssemblyImpl> entities )
+    {
+        this.entities = entities;
+    }
+
+    @Override
+    public EntityDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImplementsMethodAppliesToFilter.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
new file mode 100644
index 0000000..f7ec1ec
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.bootstrap;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.apache.zest.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class ImplementsMethodAppliesToFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        try
+        {
+            return !Modifier.isAbstract( fragmentClass.getMethod( method.getName(), method.getParameterTypes() )
+                                             .getModifiers() );
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceAssemblyImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceAssemblyImpl.java
new file mode 100644
index 0000000..a07b4f8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceAssemblyImpl.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.activation.Activator;
+import org.apache.zest.api.common.InvalidApplicationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.service.ServiceImporter;
+import org.apache.zest.api.service.importer.InstanceImporter;
+import org.apache.zest.bootstrap.ImportedServiceAssembly;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+import org.apache.zest.runtime.service.ImportedServiceModel;
+
+/**
+ * Declaration of an imported Service.
+ *
+ * Created by {@link org.apache.zest.runtime.bootstrap.ModuleAssemblyImpl#importedServices(Class[])}.
+ */
+public final class ImportedServiceAssemblyImpl
+    implements ImportedServiceAssembly
+{
+    private final Class<?> serviceType;
+    private final ModuleAssemblyImpl moduleAssembly;
+    @SuppressWarnings( "raw" )
+    Class<? extends ServiceImporter> serviceProvider = InstanceImporter.class;
+    String identity;
+    boolean importOnStartup = false;
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
+
+    public ImportedServiceAssemblyImpl( Class<?> serviceType, ModuleAssemblyImpl moduleAssembly )
+    {
+        this.serviceType = serviceType;
+        this.moduleAssembly = moduleAssembly;
+    }
+
+    @Override
+    public Iterable<Class<?>> types()
+    {
+        return Iterables.<Class<?>>iterable( serviceType );
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    void addImportedServiceModel( List<ImportedServiceModel> serviceModels )
+    {
+        try
+        {
+            String id = identity;
+            if( id == null )
+            {
+                id = generateId( serviceModels, serviceType );
+            }
+
+            ImportedServiceModel serviceModel = new ImportedServiceModel( serviceType,
+                                                                          visibility,
+                                                                          serviceProvider,
+                                                                          id,
+                                                                          importOnStartup,
+                                                                          new MetaInfo( metaInfo ).withAnnotations( serviceType ),
+                                                                          new ActivatorsModel( activators ),
+                                                                          moduleAssembly.name() );
+            serviceModels.add( serviceModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + serviceType.getName(), e );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private String generateId( List<ImportedServiceModel> serviceModels, Class serviceType )
+    {
+        // Find identity that is not yet used
+        int idx = 0;
+        String id = serviceType.getSimpleName();
+        boolean invalid;
+        do
+        {
+            invalid = false;
+            for( ImportedServiceModel serviceModel : serviceModels )
+            {
+                if( serviceModel.identity().equals( id ) )
+                {
+                    idx++;
+                    id = serviceType.getSimpleName() + "_" + idx;
+                    invalid = true;
+                    break;
+                }
+            }
+        }
+        while( invalid );
+        return id;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceDeclarationImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceDeclarationImpl.java
new file mode 100644
index 0000000..d1263e1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/bootstrap/ImportedServiceDeclarationImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.zest.api.activation.Activator;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.service.ServiceImporter;
+import org.apache.zest.api.service.qualifier.ServiceTags;
+import org.apache.zest.bootstrap.ImportedServiceDeclaration;
+
+/**
+ * Declaration of an imported Service.
+ */
+public final class ImportedServiceDeclarationImpl
+    implements ImportedServiceDeclaration
+{
+    private final Iterable<ImportedServiceAssemblyImpl> assemblies;
+
+    public ImportedServiceDeclarationImpl( Iterable<ImportedServiceAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public ImportedServiceDeclaration importOnStartup()
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.importOnStartup = true;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration visibleIn( Visibility visibility )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings( "raw" )
+    public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> sip )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.serviceProvider = sip;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration identifiedBy( String identity )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.identity = identity;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration taggedWith( String... tags )
+    {
+        for( ImportedServiceAssemblyImpl serviceAssembly : assemblies )
+        {
+            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
+            if( previousTags != null )
+            {
+                List<String> tagList = new ArrayList<>();
+                Collections.addAll( tagList, previousTags.tags() );
+                Collections.addAll( tagList, tags );
+                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
+            }
+            else
+            {
+                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
+            }
+        }
+
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( serviceAttribute );
+        }
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+    {
+        for ( ImportedServiceAssemblyImpl serviceAssembly : assemblies ) {
+            serviceAssembly.activators.addAll( Arrays.asList( activators ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file


Mime
View raw message