polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [05/51] [abbrv] [partial] zest-java git commit: Revert "First round of changes to move to org.apache.zest namespace."
Date Fri, 31 Jul 2015 02:47:24 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java
new file mode 100644
index 0000000..04fc728
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012-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.qi4j.runtime.activation;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.qi4j.api.activation.ActivationException;
+import org.qi4j.api.activation.Activator;
+import org.qi4j.api.structure.Module;
+import org.qi4j.functional.HierarchicalVisitor;
+import org.qi4j.functional.VisitableHierarchy;
+import org.qi4j.runtime.composite.UsesInstance;
+import org.qi4j.runtime.injection.InjectionContext;
+import org.qi4j.runtime.structure.ModuleInstance;
+
+/**
+ * Activators Model.
+ *
+ * @param <ActivateeType> Type of the activation target
+ */
+public class ActivatorsModel<ActivateeType>
+    implements VisitableHierarchy<Object, Object>
+{
+
+    private final List<ActivatorModel<ActivateeType>> activatorModels = new ArrayList<>();
+    private final Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses;
+
+    public ActivatorsModel( Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses )
+    {
+        this.activatorsClasses = activatorsClasses;
+        for( Class<? extends Activator<ActivateeType>> activatorClass : activatorsClasses )
+        {
+            activatorModels.add( new ActivatorModel<>( activatorClass ) );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+            {
+                if( !activatorModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Iterable<ActivatorModel<ActivateeType>> models()
+    {
+        return activatorModels;
+    }
+
+    public Iterable<Activator<ActivateeType>> newInstances()
+        throws ActivationException
+    {
+        List<Activator<ActivateeType>> activators = new ArrayList<>();
+        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+        {
+            activators.add( activatorModel.newInstance() );
+        }
+        return activators;
+    }
+
+    public Iterable<Activator<ActivateeType>> newInstances( Module module )
+        throws ActivationException
+    {
+        List<Activator<ActivateeType>> activators = new ArrayList<>();
+        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+        {
+            InjectionContext injectionContext = new InjectionContext( (ModuleInstance) module, UsesInstance.EMPTY_USES );
+            activators.add( activatorModel.newInstance( injectionContext ) );
+        }
+        return activators;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
new file mode 100644
index 0000000..21d696a
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
@@ -0,0 +1,93 @@
+/*
+ * 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.qi4j.runtime.association;
+
+import java.lang.reflect.Type;
+import org.qi4j.api.association.AbstractAssociation;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
+import org.qi4j.functional.Function2;
+
+/**
+ * Implementation of AbstractAssociation. Includes helper methods for subclasses
+ */
+public abstract class AbstractAssociationInstance<T>
+    implements AbstractAssociation
+{
+    protected AssociationInfo associationInfo;
+    private final Function2<EntityReference, Type, Object> entityFunction;
+
+    public AbstractAssociationInstance( AssociationInfo associationInfo,
+                                        Function2<EntityReference, Type, Object> entityFunction
+    )
+    {
+        this.associationInfo = associationInfo;
+        this.entityFunction = entityFunction;
+    }
+
+    public AssociationInfo associationInfo()
+    {
+        return associationInfo;
+    }
+
+    public void setAssociationInfo( AssociationInfo newInfo )
+    {
+        this.associationInfo = newInfo;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected T getEntity( EntityReference entityId )
+    {
+        if( entityId == null )
+        {
+            return null;
+        }
+
+        return (T) entityFunction.map( entityId, associationInfo.type() );
+    }
+
+    protected EntityReference getEntityReference( Object composite )
+    {
+        if( composite == null )
+        {
+            return null;
+        }
+
+        return new EntityReference( ( (Identity) composite ).identity().get() );
+    }
+
+    protected void checkType( Object instance )
+    {
+
+        if( instance instanceof Identity || instance == null )
+        {
+            return;
+        }
+        throw new IllegalArgumentException( "Object must be a subtype of org.qi4j.api.identity.Identity: " + instance.getClass() );
+    }
+
+    protected void checkImmutable()
+        throws IllegalStateException
+    {
+        if( associationInfo.isImmutable() )
+        {
+            throw new IllegalStateException( "Association [" + associationInfo.qualifiedName() + "] is immutable." );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java
new file mode 100644
index 0000000..fd6695d
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java
@@ -0,0 +1,36 @@
+/*
+ * 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.qi4j.runtime.association;
+
+import java.lang.reflect.Type;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.runtime.composite.ConstraintsCheck;
+
+/**
+ * TODO
+ */
+public interface AssociationInfo
+    extends ConstraintsCheck
+{
+    boolean isImmutable();
+
+    QualifiedName qualifiedName();
+
+    Type type();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
new file mode 100644
index 0000000..e42d8eb
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
@@ -0,0 +1,132 @@
+/*
+ * 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.qi4j.runtime.association;
+
+import java.lang.reflect.Type;
+import org.qi4j.api.association.Association;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.AssociationWrapper;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
+import org.qi4j.api.property.Property;
+import org.qi4j.functional.Function2;
+
+/**
+ * Implementation of Association to a single Entity.
+ */
+public final class AssociationInstance<T>
+    extends AbstractAssociationInstance<T>
+    implements Association<T>
+{
+    private Property<EntityReference> associationState;
+
+    public AssociationInstance( AssociationInfo associationInfo,
+                                Function2<EntityReference, Type, Object> entityFunction,
+                                Property<EntityReference> associationState
+    )
+    {
+        super( associationInfo, entityFunction );
+        this.associationState = associationState;
+    }
+
+    // Association implementation
+    @Override
+    public T get()
+    {
+        return getEntity( associationState.get() );
+    }
+
+    @Override
+    public void set( T newValue )
+        throws IllegalArgumentException
+    {
+        checkImmutable();
+        checkType( newValue );
+
+        associationInfo.checkConstraints( newValue );
+
+        // Change association
+        associationState.set( EntityReference.create( (Identity) newValue ));
+    }
+
+    @Override
+    public EntityReference reference()
+    {
+        return associationState.get();
+    }
+
+    public Property<EntityReference> getAssociationState()
+    {
+        return associationState;
+    }
+
+    @Override
+    public String toString()
+    {
+        if( associationState.get() == null )
+        {
+            return "";
+        }
+        else
+        {
+            return associationState.get().toString();
+        }
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 39; // Descriptor
+        if( associationState.get() != null )
+        {
+            hash = hash * 997 + associationState.get().hashCode(); // State
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        Association<?> that = (Association) o;
+        // Unwrap if needed
+        while( that instanceof AssociationWrapper )
+        {
+            that = ( (AssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        AssociationInstance<?> thatInstance = (AssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( associationState.get() != null
+            ? !associationState.get().equals( thatInstance.associationState.get() )
+            : thatInstance.associationState.get() != null )
+        {
+            return false;
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java
new file mode 100644
index 0000000..d1d5f36
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java
@@ -0,0 +1,251 @@
+/*
+ * 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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import org.qi4j.api.association.Association;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.GenericAssociationInfo;
+import org.qi4j.api.common.MetaInfo;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.api.composite.Composite;
+import org.qi4j.api.constraint.ConstraintViolation;
+import org.qi4j.api.constraint.ConstraintViolationException;
+import org.qi4j.api.entity.Aggregated;
+import org.qi4j.api.entity.Queryable;
+import org.qi4j.api.property.Immutable;
+import org.qi4j.api.util.Classes;
+import org.qi4j.bootstrap.BindingException;
+import org.qi4j.functional.Visitable;
+import org.qi4j.functional.Visitor;
+import org.qi4j.runtime.composite.ValueConstraintsInstance;
+import org.qi4j.runtime.model.Binder;
+import org.qi4j.runtime.model.Resolution;
+
+import static org.qi4j.functional.Iterables.empty;
+import static org.qi4j.functional.Iterables.first;
+
+/**
+ * Model for an Association.
+ *
+ * <p>Equality is based on the Association accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class AssociationModel
+    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<AssociationModel>
+{
+    private MetaInfo metaInfo;
+    private Type type;
+    private AccessibleObject accessor;
+    private QualifiedName qualifiedName;
+    private ValueConstraintsInstance constraints;
+    private ValueConstraintsInstance associationConstraints;
+    private boolean queryable;
+    private boolean immutable;
+    private boolean aggregated;
+    private AssociationInfo builderInfo;
+
+    public AssociationModel( AccessibleObject accessor,
+                             ValueConstraintsInstance valueConstraintsInstance,
+                             ValueConstraintsInstance associationConstraintsInstance,
+                             MetaInfo metaInfo
+    )
+    {
+        this.metaInfo = metaInfo;
+        this.constraints = valueConstraintsInstance;
+        this.associationConstraints = associationConstraintsInstance;
+        this.accessor = accessor;
+        initialize();
+    }
+
+    private void initialize()
+    {
+        this.type = GenericAssociationInfo.associationTypeOf( accessor );
+        this.qualifiedName = QualifiedName.fromAccessor( accessor );
+        this.immutable = metaInfo.get( Immutable.class ) != null;
+        this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+        final Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    @Override
+    public boolean isAggregated()
+    {
+        return aggregated;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    public AssociationInfo getBuilderInfo()
+    {
+        return builderInfo;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super AssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException
+    {
+        if( constraints != null )
+        {
+            List<ConstraintViolation> violations = constraints.checkConstraints( value );
+            if( !violations.isEmpty() )
+            {
+                Iterable<Class<?>> empty = empty();
+                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+            }
+        }
+    }
+
+    public void checkAssociationConstraints( Association<?> association )
+        throws ConstraintViolationException
+    {
+        if( associationConstraints != null )
+        {
+            List<ConstraintViolation> violations = associationConstraints.checkConstraints( association );
+            if( !violations.isEmpty() )
+            {
+                throw new ConstraintViolationException( (Composite) association.get(), (Member) accessor, violations );
+            }
+        }
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        builderInfo = new AssociationInfo()
+        {
+            @Override
+            public boolean isImmutable()
+            {
+                return false;
+            }
+
+            @Override
+            public QualifiedName qualifiedName()
+            {
+                return qualifiedName;
+            }
+
+            @Override
+            public Type type()
+            {
+                return type;
+            }
+
+            @Override
+            public void checkConstraints( Object value )
+                throws ConstraintViolationException
+            {
+                AssociationModel.this.checkConstraints( value );
+            }
+        };
+
+        if( type instanceof TypeVariable )
+        {
+
+            Class mainType = first( resolution.model().types() );
+            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        AssociationModel that = (AssociationModel) o;
+
+        if( !accessor.equals( that.accessor ) )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java
new file mode 100644
index 0000000..310632d
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2008-2011, 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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.qi4j.api.association.Association;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.AssociationStateHolder;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.functional.HierarchicalVisitor;
+import org.qi4j.functional.VisitableHierarchy;
+
+/**
+ * Model for Associations.
+ */
+public final class AssociationsModel
+    implements VisitableHierarchy<AssociationsModel, AssociationModel>
+{
+    private final Map<AccessibleObject, AssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public AssociationsModel()
+    {
+    }
+
+    public Iterable<AssociationModel> associations()
+    {
+        return mapAccessorAssociationModel.values();
+    }
+
+    public void addAssociation( AssociationModel associationModel )
+    {
+        mapAccessorAssociationModel.put( associationModel.accessor(), associationModel );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super AssociationsModel, ? super AssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public AssociationModel getAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        AssociationModel associationModel = mapAccessorAssociationModel.get( accessor );
+        if( associationModel == null )
+        {
+            throw new IllegalArgumentException( "No association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return associationModel;
+    }
+
+    public AssociationDescriptor getAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No association found with name:" + name );
+    }
+
+    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( AssociationStateHolder state )
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            Association<Object> association = state.<Object>associationFor( associationModel.accessor() );
+            associationModel.checkAssociationConstraints( association );
+            associationModel.checkConstraints( association.get() );
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
new file mode 100644
index 0000000..5c8b4b8
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
@@ -0,0 +1,225 @@
+/*
+ * 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.qi4j.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.association.ManyAssociationWrapper;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
+import org.qi4j.api.util.NullArgumentException;
+import org.qi4j.functional.Function2;
+import org.qi4j.functional.Iterables;
+import org.qi4j.spi.entity.ManyAssociationState;
+
+/**
+ * JAVADOC
+ */
+public class ManyAssociationInstance<T>
+    extends AbstractAssociationInstance<T>
+    implements ManyAssociation<T>
+{
+    private ManyAssociationState manyAssociationState;
+
+    public ManyAssociationInstance( AssociationInfo associationInfo,
+                                    Function2<EntityReference, Type, Object> associationFunction,
+                                    ManyAssociationState manyAssociationState
+    )
+    {
+        super( associationInfo, associationFunction );
+        this.manyAssociationState = manyAssociationState;
+    }
+
+    @Override
+    public int count()
+    {
+        return manyAssociationState.count();
+    }
+
+    @Override
+    public boolean contains( T entity )
+    {
+        return manyAssociationState.contains( getEntityReference( entity ) );
+    }
+
+    @Override
+    public boolean add( int i, T entity )
+    {
+        NullArgumentException.validateNotNull( "entity", entity );
+        checkImmutable();
+        checkType( entity );
+        associationInfo.checkConstraints( entity );
+        return manyAssociationState.add( i, new EntityReference( ( (Identity) entity ).identity().get() ) );
+    }
+
+    @Override
+    public boolean add( T entity )
+    {
+        return add( manyAssociationState.count(), entity );
+    }
+
+    @Override
+    public boolean remove( T entity )
+    {
+        NullArgumentException.validateNotNull( "entity", entity );
+        checkImmutable();
+        checkType( entity );
+
+        return manyAssociationState.remove( new EntityReference( ( (Identity) entity ).identity().get() ) );
+    }
+
+    @Override
+    public T get( int i )
+    {
+        return getEntity( manyAssociationState.get( i ) );
+    }
+
+    @Override
+    public List<T> toList()
+    {
+        ArrayList<T> list = new ArrayList<>();
+        for( EntityReference entityReference : manyAssociationState )
+        {
+            list.add( getEntity( entityReference ) );
+        }
+
+        return list;
+    }
+
+    @Override
+    public Set<T> toSet()
+    {
+        Set<T> set = new HashSet<>();
+        for( EntityReference entityReference : manyAssociationState )
+        {
+            set.add( getEntity( entityReference ) );
+        }
+
+        return set;
+    }
+
+    @Override
+    public Iterable<EntityReference> references()
+    {
+        return Iterables.toList( manyAssociationState );
+    }
+
+    @Override
+    public String toString()
+    {
+        return manyAssociationState.toString();
+    }
+
+    @Override
+    public Iterator<T> iterator()
+    {
+        return new ManyAssociationIterator( manyAssociationState.iterator() );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        ManyAssociation<?> that = (ManyAssociation) o;
+        // Unwrap if needed
+        while( that instanceof ManyAssociationWrapper )
+        {
+            that = ( (ManyAssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        ManyAssociationInstance<?> thatInstance = (ManyAssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( manyAssociationState.count() != thatInstance.manyAssociationState.count() )
+        {
+            return false;
+        }
+        for( EntityReference ref : manyAssociationState )
+        {
+            if( !thatInstance.manyAssociationState.contains( ref ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 31; // Descriptor
+        for( EntityReference ref : manyAssociationState )
+        {
+            hash += ref.hashCode() * 7; // State
+        }
+        return hash;
+    }
+
+    public ManyAssociationState getManyAssociationState()
+    {
+        return manyAssociationState;
+    }
+
+    protected class ManyAssociationIterator
+        implements Iterator<T>
+    {
+        private final Iterator<EntityReference> idIterator;
+
+        public ManyAssociationIterator( Iterator<EntityReference> idIterator )
+        {
+            this.idIterator = idIterator;
+        }
+
+        @Override
+        public boolean hasNext()
+        {
+            return idIterator.hasNext();
+        }
+
+        @Override
+        public T next()
+        {
+            return getEntity( idIterator.next() );
+        }
+
+        @Override
+        public void remove()
+        {
+            checkImmutable();
+            idIterator.remove();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java
new file mode 100644
index 0000000..3cc5d81
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2008-2011, 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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.GenericAssociationInfo;
+import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.common.MetaInfo;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.api.constraint.ConstraintViolation;
+import org.qi4j.api.constraint.ConstraintViolationException;
+import org.qi4j.api.entity.Aggregated;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Queryable;
+import org.qi4j.api.property.Immutable;
+import org.qi4j.api.util.Classes;
+import org.qi4j.bootstrap.BindingException;
+import org.qi4j.functional.Function2;
+import org.qi4j.functional.Visitable;
+import org.qi4j.functional.Visitor;
+import org.qi4j.runtime.composite.ValueConstraintsInstance;
+import org.qi4j.runtime.model.Binder;
+import org.qi4j.runtime.model.Resolution;
+import org.qi4j.runtime.structure.ModuleUnitOfWork;
+import org.qi4j.runtime.unitofwork.BuilderEntityState;
+import org.qi4j.spi.entity.EntityState;
+
+import static org.qi4j.functional.Iterables.empty;
+import static org.qi4j.functional.Iterables.first;
+
+/**
+ * Model for a ManyAssociation.
+ *
+ * <p>Equality is based on the ManyAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class ManyAssociationModel
+    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<ManyAssociationModel>
+{
+    private final ValueConstraintsInstance associationConstraints;
+    private final MetaInfo metaInfo;
+    private Type type;
+    private final AccessibleObject accessor;
+    private QualifiedName qualifiedName;
+    private final ValueConstraintsInstance constraints;
+    private boolean queryable;
+    private boolean immutable;
+    private boolean aggregated;
+    private AssociationInfo builderInfo;
+
+    public ManyAssociationModel( AccessibleObject accessor,
+                                 ValueConstraintsInstance valueConstraintsInstance,
+                                 ValueConstraintsInstance associationConstraintsInstance,
+                                 MetaInfo metaInfo
+    )
+    {
+        this.metaInfo = metaInfo;
+        this.constraints = valueConstraintsInstance;
+        this.associationConstraints = associationConstraintsInstance;
+        this.accessor = accessor;
+        initialize();
+    }
+
+    private void initialize()
+    {
+        this.type = GenericAssociationInfo.associationTypeOf( accessor );
+        this.qualifiedName = QualifiedName.fromAccessor( accessor );
+        this.immutable = metaInfo.get( Immutable.class ) != null;
+        this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+        final Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    @Override
+    public boolean isAggregated()
+    {
+        return aggregated;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    public AssociationInfo getBuilderInfo()
+    {
+        return builderInfo;
+    }
+
+    public <T> ManyAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+    {
+        return new ManyAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new Function2<EntityReference, Type, Object>()
+        {
+            @Override
+            public Object map( EntityReference entityReference, Type type )
+            {
+                return uow.get( Classes.RAW_CLASS.map( type ), entityReference.identity() );
+            }
+        }, state.manyAssociationValueOf( qualifiedName ) );
+    }
+
+    @Override
+    public void checkConstraints( Object composite )
+        throws ConstraintViolationException
+    {
+        if( constraints != null )
+        {
+            List<ConstraintViolation> violations = constraints.checkConstraints( composite );
+            if( !violations.isEmpty() )
+            {
+                Iterable<Class<?>> empty = empty();
+                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+            }
+        }
+    }
+
+    public void checkAssociationConstraints( ManyAssociation manyAssociation )
+        throws ConstraintViolationException
+    {
+        if( associationConstraints != null )
+        {
+            List<ConstraintViolation> violations = associationConstraints.checkConstraints( manyAssociation );
+            if( !violations.isEmpty() )
+            {
+                Iterable<Class<?>> empty = empty();
+                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+            }
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ManyAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        builderInfo = new AssociationInfo()
+        {
+            @Override
+            public boolean isImmutable()
+            {
+                return false;
+            }
+
+            @Override
+            public QualifiedName qualifiedName()
+            {
+                return qualifiedName;
+            }
+
+            @Override
+            public Type type()
+            {
+                return type;
+            }
+
+            @Override
+            public void checkConstraints( Object value )
+                throws ConstraintViolationException
+            {
+                ManyAssociationModel.this.checkConstraints( value );
+            }
+        };
+
+        if( type instanceof TypeVariable )
+        {
+            Class mainType = first( resolution.model().types() );
+            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        ManyAssociationModel that = (ManyAssociationModel) o;
+
+        return accessor.equals( that.accessor );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java
new file mode 100644
index 0000000..40c5653
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2008-2011, 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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.functional.HierarchicalVisitor;
+import org.qi4j.functional.VisitableHierarchy;
+import org.qi4j.runtime.structure.ModuleUnitOfWork;
+import org.qi4j.runtime.value.ValueStateInstance;
+import org.qi4j.spi.entity.EntityState;
+
+/**
+ * Model for ManyAssociations.
+ */
+public final class ManyAssociationsModel
+    implements VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>
+{
+    private final Map<AccessibleObject, ManyAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public ManyAssociationsModel()
+    {
+    }
+
+    public Iterable<ManyAssociationModel> manyAssociations()
+    {
+        return mapAccessorAssociationModel.values();
+    }
+
+    public void addManyAssociation( ManyAssociationModel model )
+    {
+        mapAccessorAssociationModel.put( model.accessor(), model );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super ManyAssociationsModel, ? super ManyAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public <T> ManyAssociation<T> newInstance( AccessibleObject accessor,
+                                               EntityState entityState,
+                                               ModuleUnitOfWork uow )
+    {
+        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+    }
+
+    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        ManyAssociationModel manyAssociationModel = mapAccessorAssociationModel.get( accessor );
+        if( manyAssociationModel == null )
+        {
+            throw new IllegalArgumentException( "No many-association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return manyAssociationModel;
+    }
+
+    public AssociationDescriptor getManyAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No many-association found with name:" + name );
+    }
+
+    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No many-association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( ValueStateInstance state )
+    {
+        for( ManyAssociationModel manyAssociationModel : mapAccessorAssociationModel.values() )
+        {
+            manyAssociationModel.checkAssociationConstraints( state.manyAssociationFor( manyAssociationModel.accessor() ) );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
new file mode 100644
index 0000000..c38ef1a
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011-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.qi4j.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.association.ManyAssociationWrapper;
+import org.qi4j.api.association.NamedAssociation;
+import org.qi4j.api.association.NamedAssociationWrapper;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
+import org.qi4j.api.util.NullArgumentException;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Function2;
+import org.qi4j.functional.Iterables;
+import org.qi4j.spi.entity.NamedAssociationState;
+
+import static org.qi4j.functional.Iterables.map;
+
+public class NamedAssociationInstance<T>
+    extends AbstractAssociationInstance<T>
+    implements NamedAssociation<T>
+{
+
+    private final NamedAssociationState namedAssociationState;
+
+    public NamedAssociationInstance( AssociationInfo associationInfo,
+                                     Function2<EntityReference, Type, Object> associationFunction,
+                                     NamedAssociationState namedAssociationState
+    )
+    {
+        super( associationInfo, associationFunction );
+        this.namedAssociationState = namedAssociationState;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return namedAssociationState.iterator();
+    }
+
+    @Override
+    public int count()
+    {
+        return namedAssociationState.count();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return namedAssociationState.containsName( name );
+    }
+
+    @Override
+    public boolean put( String name, T entity )
+    {
+        NullArgumentException.validateNotNull( "entity", entity );
+        checkImmutable();
+        checkType( entity );
+        associationInfo.checkConstraints( entity );
+        return namedAssociationState.put( name, new EntityReference( ( (Identity) entity ).identity().get() ) );
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        checkImmutable();
+        return namedAssociationState.remove( name );
+    }
+
+    @Override
+    public T get( String name )
+    {
+        return getEntity( namedAssociationState.get( name ) );
+    }
+
+    @Override
+    public String nameOf( T entity )
+    {
+        return namedAssociationState.nameOf( getEntityReference( entity ) );
+    }
+
+    @Override
+    public Map<String, T> toMap()
+    {
+        Map<String, T> map = new HashMap<>();
+        for( String name : namedAssociationState )
+        {
+            map.put( name, getEntity( namedAssociationState.get( name ) ) );
+        }
+        return map;
+    }
+
+    @Override
+    public Iterable<EntityReference> references()
+    {
+        return map( new Function<String, EntityReference>()
+        {
+            @Override
+            public EntityReference map( String name )
+            {
+                return namedAssociationState.get( name );
+            }
+        }, namedAssociationState );
+    }
+
+    @Override
+    public EntityReference referenceOf( String name )
+    {
+        return namedAssociationState.get( name );
+    }
+
+    public Iterable<Map.Entry<String, EntityReference>> getEntityReferences()
+    {
+        return map( new Function<String, Map.Entry<String, EntityReference>>()
+        {
+            @Override
+            public Map.Entry<String, EntityReference> map( final String key )
+            {
+                final EntityReference value = namedAssociationState.get( key );
+                return new Map.Entry<String, EntityReference>()
+                {
+                    @Override
+                    public String getKey()
+                    {
+                        return key;
+                    }
+
+                    @Override
+                    public EntityReference getValue()
+                    {
+                        return value;
+                    }
+
+                    @Override
+                    public EntityReference setValue( EntityReference value )
+                    {
+                        throw new UnsupportedOperationException( "Immutable Map" );
+                    }
+
+                    @Override
+                    public boolean equals( Object o )
+                    {
+                        if( o instanceof Map.Entry )
+                        {
+                            Map.Entry other = (Map.Entry) o;
+                            return key.equals( other.getKey() );
+                        }
+                        return false;
+                    }
+
+                    @Override
+                    public int hashCode()
+                    {
+                        return 997 * key.hashCode() + 981813497;
+                    }
+                };
+            }
+        }, namedAssociationState );
+    }
+
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        NamedAssociation<?> that = (NamedAssociation) o;
+        // Unwrap if needed
+        while( that instanceof NamedAssociationWrapper )
+        {
+            that = ( (NamedAssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        NamedAssociationInstance<?> thatInstance = (NamedAssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( namedAssociationState.count() != thatInstance.namedAssociationState.count() )
+        {
+            return false;
+        }
+        for( String name : namedAssociationState )
+        {
+            if( !thatInstance.namedAssociationState.containsName( name ) )
+            {
+                return false;
+            }
+            EntityReference thisReference = namedAssociationState.get( name );
+            EntityReference thatReference = thatInstance.namedAssociationState.get( name );
+            if( !thisReference.equals( thatReference ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 31; // Descriptor
+        for( String name : namedAssociationState )
+        {
+            hash += name.hashCode();
+            hash += namedAssociationState.get( name ).hashCode() * 7; // State
+        }
+        return hash;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java
new file mode 100644
index 0000000..7c144d0
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2011-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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.GenericAssociationInfo;
+import org.qi4j.api.association.NamedAssociation;
+import org.qi4j.api.common.MetaInfo;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.api.constraint.ConstraintViolation;
+import org.qi4j.api.constraint.ConstraintViolationException;
+import org.qi4j.api.entity.Aggregated;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Queryable;
+import org.qi4j.api.property.Immutable;
+import org.qi4j.api.util.Classes;
+import org.qi4j.bootstrap.BindingException;
+import org.qi4j.functional.Function2;
+import org.qi4j.functional.Visitable;
+import org.qi4j.functional.Visitor;
+import org.qi4j.runtime.composite.ValueConstraintsInstance;
+import org.qi4j.runtime.model.Binder;
+import org.qi4j.runtime.model.Resolution;
+import org.qi4j.runtime.structure.ModuleUnitOfWork;
+import org.qi4j.runtime.unitofwork.BuilderEntityState;
+import org.qi4j.spi.entity.EntityState;
+
+import static org.qi4j.functional.Iterables.empty;
+import static org.qi4j.functional.Iterables.first;
+
+/**
+ * Model for a NamedAssociation.
+ *
+ * <p>Equality is based on the NamedAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class NamedAssociationModel
+    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<NamedAssociationModel>
+{
+    private final ValueConstraintsInstance associationConstraints;
+    private final MetaInfo metaInfo;
+    private Type type;
+    private final AccessibleObject accessor;
+    private QualifiedName qualifiedName;
+    private final ValueConstraintsInstance constraints;
+    private boolean queryable;
+    private boolean immutable;
+    private boolean aggregated;
+    private AssociationInfo builderInfo;
+
+    public NamedAssociationModel( AccessibleObject accessor,
+                                  ValueConstraintsInstance valueConstraintsInstance,
+                                  ValueConstraintsInstance associationConstraintsInstance,
+                                  MetaInfo metaInfo
+    )
+    {
+        this.metaInfo = metaInfo;
+        this.constraints = valueConstraintsInstance;
+        this.associationConstraints = associationConstraintsInstance;
+        this.accessor = accessor;
+        initialize();
+    }
+
+    private void initialize()
+    {
+        this.type = GenericAssociationInfo.associationTypeOf( accessor );
+        this.qualifiedName = QualifiedName.fromAccessor( accessor );
+        this.immutable = metaInfo.get( Immutable.class ) != null;
+        this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+        final Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    @Override
+    public boolean isAggregated()
+    {
+        return aggregated;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    public AssociationInfo getBuilderInfo()
+    {
+        return builderInfo;
+    }
+
+    public <T> NamedAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+    {
+        return new NamedAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new Function2<EntityReference, Type, Object>()
+        {
+            @Override
+            public Object map( EntityReference entityReference, Type type )
+            {
+                return uow.get( Classes.RAW_CLASS.map( type ), entityReference.identity() );
+            }
+        }, state.namedAssociationValueOf( qualifiedName ) );
+    }
+
+    @Override
+    public void checkConstraints( Object composite )
+        throws ConstraintViolationException
+    {
+        if( constraints != null )
+        {
+            List<ConstraintViolation> violations = constraints.checkConstraints( composite );
+            if( !violations.isEmpty() )
+            {
+                Iterable<Class<?>> empty = empty();
+                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+            }
+        }
+    }
+
+    public void checkAssociationConstraints( NamedAssociation association )
+        throws ConstraintViolationException
+    {
+        if( associationConstraints != null )
+        {
+            List<ConstraintViolation> violations = associationConstraints.checkConstraints( association );
+            if( !violations.isEmpty() )
+            {
+                Iterable<Class<?>> empty = empty();
+                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+            }
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super NamedAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        builderInfo = new AssociationInfo()
+        {
+            @Override
+            public boolean isImmutable()
+            {
+                return false;
+            }
+
+            @Override
+            public QualifiedName qualifiedName()
+            {
+                return qualifiedName;
+            }
+
+            @Override
+            public Type type()
+            {
+                return type;
+            }
+
+            @Override
+            public void checkConstraints( Object value )
+                throws ConstraintViolationException
+            {
+                NamedAssociationModel.this.checkConstraints( value );
+            }
+        };
+
+        if( type instanceof TypeVariable )
+        {
+            Class mainType = first( resolution.model().types() );
+            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        NamedAssociationModel that = (NamedAssociationModel) o;
+
+        return accessor.equals( that.accessor );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java
new file mode 100644
index 0000000..4f3fac5
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2011-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.qi4j.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.NamedAssociation;
+import org.qi4j.api.common.QualifiedName;
+import org.qi4j.functional.HierarchicalVisitor;
+import org.qi4j.functional.VisitableHierarchy;
+import org.qi4j.runtime.structure.ModuleUnitOfWork;
+import org.qi4j.runtime.value.ValueStateInstance;
+import org.qi4j.spi.entity.EntityState;
+
+/**
+ * Model for NamedAssociations.
+ */
+public final class NamedAssociationsModel
+    implements VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>
+{
+    private final Map<AccessibleObject, NamedAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public NamedAssociationsModel()
+    {
+    }
+
+    public Iterable<NamedAssociationModel> namedAssociations()
+    {
+        return mapAccessorAssociationModel.values();
+    }
+
+    public void addNamedAssociation( NamedAssociationModel model )
+    {
+        mapAccessorAssociationModel.put( model.accessor(), model );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NamedAssociationsModel, ? super NamedAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public <T> NamedAssociation<T> newInstance( AccessibleObject accessor,
+                                                EntityState entityState,
+                                                ModuleUnitOfWork uow )
+    {
+        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+    }
+
+    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        if( false )
+        {
+            return (NamedAssociationModel) getNamedAssociationByName( QualifiedName.fromAccessor( accessor ).name() );
+        }
+        NamedAssociationModel namedAssociationModel = mapAccessorAssociationModel.get( accessor );
+        if( namedAssociationModel == null )
+        {
+            throw new IllegalArgumentException( "No named-association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return namedAssociationModel;
+    }
+
+    public AssociationDescriptor getNamedAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No named-association found with name:" + name );
+    }
+
+    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No named-association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( ValueStateInstance state )
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            associationModel.checkAssociationConstraints( state.namedAssociationFor( associationModel.accessor() ) );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java
new file mode 100644
index 0000000..fafc6b7
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.qi4j.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.qi4j.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AndAppliesToFilter
+    implements AppliesToFilter
+{
+    private final AppliesToFilter left;
+    private final AppliesToFilter right;
+
+    AndAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
+    {
+        this.left = left;
+        this.right = right;
+    }
+
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return left.appliesTo( method, mixin, compositeType, fragmentClass ) &&
+               right.appliesTo( method, mixin, compositeType, fragmentClass );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java
new file mode 100644
index 0000000..54cf2ad
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.qi4j.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.qi4j.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AnnotationAppliesToFilter
+    implements AppliesToFilter
+{
+    @SuppressWarnings( "raw" )
+    private final Class annotationType;
+
+    @SuppressWarnings( "raw" )
+    AnnotationAppliesToFilter( Class type )
+    {
+        this.annotationType = type;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return method.getAnnotation( annotationType ) != null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
new file mode 100644
index 0000000..7a25eed
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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.qi4j.runtime.bootstrap;
+
+import org.qi4j.bootstrap.ApplicationAssembly;
+import org.qi4j.bootstrap.ApplicationAssemblyFactory;
+import org.qi4j.bootstrap.Assembler;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+
+/**
+ * Factory for ApplicationAssembly.
+ */
+public final class ApplicationAssemblyFactoryImpl
+    implements ApplicationAssemblyFactory
+{
+    @Override
+    public ApplicationAssembly newApplicationAssembly( Assembler assembler )
+        throws AssemblyException
+    {
+        return newApplicationAssembly( new Assembler[][][]{ { { assembler } } } );
+    }
+
+    @Override
+    public ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
+        throws AssemblyException
+    {
+        ApplicationAssembly applicationAssembly = newApplicationAssembly();
+
+        // Build all layers bottom-up
+        LayerAssembly below = null;
+        for( int layer = assemblers.length - 1; layer >= 0; layer-- )
+        {
+            // Create Layer
+            LayerAssembly layerAssembly = applicationAssembly.layer( "Layer " + ( layer + 1 ) );
+            for( int module = 0; module < assemblers[ layer ].length; module++ )
+            {
+                // Create Module
+                ModuleAssembly moduleAssembly = layerAssembly.module( "Module " + ( module + 1 ) );
+                for( Assembler assembler : assemblers[ layer ][ module ] )
+                {
+                    // Register Assembler
+                    assembler.assemble( moduleAssembly );
+                }
+            }
+            if( below != null )
+            {
+                layerAssembly.uses( below ); // Link layers
+            }
+            below = layerAssembly;
+        }
+        return applicationAssembly;
+    }
+
+    @Override
+    public ApplicationAssembly newApplicationAssembly()
+    {
+        return new ApplicationAssemblyImpl();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java
new file mode 100644
index 0000000..48438e1
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java
@@ -0,0 +1,152 @@
+/*
+ * 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.qi4j.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.qi4j.api.activation.Activator;
+import org.qi4j.api.common.MetaInfo;
+import org.qi4j.api.structure.Application;
+import org.qi4j.bootstrap.ApplicationAssembly;
+import org.qi4j.bootstrap.AssemblyVisitor;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+
+/**
+ * The representation of an entire application. From
+ * this you can set information about the application
+ * and create LayerAssemblies.
+ */
+public final class ApplicationAssemblyImpl
+    implements ApplicationAssembly
+{
+    private final Map<String, LayerAssemblyImpl> layerAssemblies = new LinkedHashMap<>();
+    private String name = "Application";
+    private String version = "1.0"; // Default version
+    private Application.Mode mode;
+    private final MetaInfo metaInfo = new MetaInfo();
+    private final List<Class<? extends Activator<Application>>> activators = new ArrayList<>();
+
+    public ApplicationAssemblyImpl()
+    {
+        mode = Application.Mode.valueOf( System.getProperty( "mode", "production" ) );
+    }
+
+    @Override
+    public LayerAssembly layer( String name )
+    {
+        if( name != null )
+        {
+            LayerAssemblyImpl existing = layerAssemblies.get( name );
+            if( existing != null )
+            {
+                return existing;
+            }
+        }
+        LayerAssemblyImpl layerAssembly = new LayerAssemblyImpl( this, name );
+        layerAssemblies.put( name, layerAssembly );
+        return layerAssembly;
+    }
+
+    @Override
+    public ModuleAssembly module( String layerName, String moduleName )
+    {
+        return layer( layerName ).module( moduleName );
+    }
+
+    @Override
+    public ApplicationAssembly setName( String name )
+    {
+        this.name = name;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setVersion( String version )
+    {
+        this.version = version;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setMode( Application.Mode mode )
+    {
+        this.mode = mode;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setMetaInfo( Object info )
+    {
+        metaInfo.set( info );
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators )
+    {
+        this.activators.addAll( Arrays.asList( activators ) );
+        return this;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType
+    {
+        visitor.visitApplication( this );
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies.values() )
+        {
+            layerAssembly.visit( visitor );
+        }
+    }
+
+    public Collection<LayerAssemblyImpl> layerAssemblies()
+    {
+        return layerAssemblies.values();
+    }
+
+    public List<Class<? extends Activator<Application>>> activators()
+    {
+        return activators;
+    }
+
+    public MetaInfo metaInfo()
+    {
+        return metaInfo;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public String version()
+    {
+        return version;
+    }
+
+    @Override
+    public Application.Mode mode()
+    {
+        return mode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java
new file mode 100644
index 0000000..8669ed7
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java
@@ -0,0 +1,192 @@
+/*
+ * 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.qi4j.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.qi4j.api.composite.ModelDescriptor;
+import org.qi4j.api.structure.Application;
+import org.qi4j.api.structure.ApplicationDescriptor;
+import org.qi4j.api.structure.Layer;
+import org.qi4j.bootstrap.ApplicationAssembly;
+import org.qi4j.bootstrap.ApplicationModelFactory;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.BindingException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.functional.HierarchicalVisitor;
+import org.qi4j.runtime.activation.ActivatorsModel;
+import org.qi4j.runtime.composite.CompositeMethodModel;
+import org.qi4j.runtime.injection.InjectedFieldModel;
+import org.qi4j.runtime.model.Binder;
+import org.qi4j.runtime.model.Resolution;
+import org.qi4j.runtime.structure.ApplicationModel;
+import org.qi4j.runtime.structure.LayerModel;
+import org.qi4j.runtime.structure.ModuleModel;
+import org.qi4j.runtime.structure.UsedLayersModel;
+
+/**
+ * Factory for Applications.
+ */
+public final class ApplicationModelFactoryImpl
+    implements ApplicationModelFactory
+{
+    @Override
+    public ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
+        throws AssemblyException
+    {
+        AssemblyHelper helper = new AssemblyHelper();
+
+        ApplicationAssemblyImpl applicationAssembly = (ApplicationAssemblyImpl) assembly;
+        ActivatorsModel<Application> applicationActivators = new ActivatorsModel<>( applicationAssembly.activators() );
+        List<LayerModel> layerModels = new ArrayList<>();
+        final ApplicationModel applicationModel = new ApplicationModel( applicationAssembly.name(),
+                                                                        applicationAssembly.version(),
+                                                                        applicationAssembly.mode(),
+                                                                        applicationAssembly.metaInfo(),
+                                                                        applicationActivators,
+                                                                        layerModels );
+        Map<LayerAssembly, LayerModel> mapAssemblyModel = new HashMap<>();
+        Map<LayerAssembly, List<LayerModel>> mapUsedLayers = new HashMap<>();
+
+        // Build all layers
+        List<LayerAssemblyImpl> layerAssemblies = new ArrayList<>( applicationAssembly.layerAssemblies() );
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+        {
+            List<LayerModel> usedLayers = new ArrayList<>();
+            mapUsedLayers.put( layerAssembly, usedLayers );
+
+            UsedLayersModel usedLayersModel = new UsedLayersModel( usedLayers );
+            List<ModuleModel> moduleModels = new ArrayList<>();
+            String name = layerAssembly.name();
+            if( name == null )
+            {
+                throw new AssemblyException( "Layer must have name set" );
+            }
+            ActivatorsModel<Layer> layerActivators = new ActivatorsModel<>( layerAssembly.activators() );
+            LayerModel layerModel = new LayerModel( name, layerAssembly.metaInfo(), usedLayersModel, layerActivators, moduleModels );
+
+            for( ModuleAssemblyImpl moduleAssembly : layerAssembly.moduleAssemblies() )
+            {
+                moduleModels.add( moduleAssembly.assembleModule( helper ) );
+            }
+            mapAssemblyModel.put( layerAssembly, layerModel );
+            layerModels.add( layerModel );
+        }
+
+        // Populate used layer lists
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+        {
+            Set<LayerAssembly> usesLayers = layerAssembly.uses();
+            List<LayerModel> usedLayers = mapUsedLayers.get( layerAssembly );
+            for( LayerAssembly usesLayer : usesLayers )
+            {
+                LayerModel layerModel = mapAssemblyModel.get( usesLayer );
+                usedLayers.add( layerModel );
+            }
+        }
+
+        // Bind model
+        // This will resolve all dependencies
+        try
+        {
+//            applicationModel.bind();
+            applicationModel.accept( new BindingVisitor( applicationModel ) );
+        }
+        catch( BindingException e )
+        {
+            throw new AssemblyException( "Unable to bind: " + applicationModel, e );
+        }
+
+        return applicationModel;
+    }
+
+    private static class BindingVisitor
+        implements HierarchicalVisitor<Object, Object, BindingException>
+    {
+        private LayerModel layer;
+        private ModuleModel module;
+        private ModelDescriptor objectDescriptor;
+        private CompositeMethodModel compositeMethodModel;
+
+        private Resolution resolution;
+        private final ApplicationModel applicationModel;
+
+        private BindingVisitor( ApplicationModel applicationModel )
+        {
+            this.applicationModel = applicationModel;
+        }
+
+        @Override
+        public boolean visitEnter( Object visited )
+            throws BindingException
+        {
+            if( visited instanceof Binder )
+            {
+                Binder binder = (Binder) visited;
+                binder.bind( resolution );
+
+                return false;
+            }
+            else if( visited instanceof CompositeMethodModel )
+            {
+                compositeMethodModel = (CompositeMethodModel) visited;
+                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, compositeMethodModel, null );
+            }
+            else if( visited instanceof ModelDescriptor )
+            {
+                objectDescriptor = (ModelDescriptor) visited;
+                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, null, null );
+            }
+            else if( visited instanceof InjectedFieldModel )
+            {
+                InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
+                fieldModel.bind( new Resolution( applicationModel, layer, module,
+                                                 objectDescriptor, compositeMethodModel, fieldModel.field() ) );
+            }
+            else if( visited instanceof ModuleModel )
+            {
+                module = (ModuleModel) visited;
+            }
+            else if( visited instanceof LayerModel )
+            {
+                layer = (LayerModel) visited;
+            }
+
+            return true;
+        }
+
+        @Override
+        public boolean visitLeave( Object visited )
+            throws BindingException
+        {
+            return true;
+        }
+
+        @Override
+        public boolean visit( Object visited )
+            throws BindingException
+        {
+            if( visited instanceof Binder )
+            {
+                ( (Binder) visited ).bind( resolution );
+            }
+            return true;
+        }
+    }
+}
\ No newline at end of file


Mime
View raw message