You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/04/24 08:36:55 UTC

[42/50] [abbrv] zest-qi4j git commit: QI-413 UnitOfWork::newEntityBuilderWithState()

QI-413 UnitOfWork::newEntityBuilderWithState()


Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/355ea47d
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/355ea47d
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/355ea47d

Branch: refs/heads/master
Commit: 355ea47da44f7d4e22133f06cd742f1fe4a12f39
Parents: 118928a
Author: Paul Merlin <pa...@nosphere.org>
Authored: Wed Mar 25 16:02:13 2015 +0100
Committer: Paul Merlin <pa...@nosphere.org>
Committed: Wed Mar 25 16:02:13 2015 +0100

----------------------------------------------------------------------
 .../org/qi4j/api/unitofwork/UnitOfWork.java     |  60 +++++++-
 .../composite/FunctionStateResolver.java        |  71 +++++++++
 .../qi4j/runtime/composite/StateResolver.java   |  36 +++++
 .../qi4j/runtime/entity/EntityStateModel.java   |   2 +-
 .../qi4j/runtime/structure/ModuleInstance.java  |  87 ++++-------
 .../runtime/structure/ModuleUnitOfWork.java     | 109 ++++++++++++--
 .../unitofwork/EntityBuilderInstance.java       |  50 ++++++-
 .../runtime/value/ValueBuilderInstance.java     |   3 +-
 .../runtime/value/ValueBuilderWithState.java    |  19 ++-
 .../qi4j/runtime/value/ValueStateInstance.java  |   4 +-
 .../org/qi4j/runtime/value/ValueStateModel.java |  21 +--
 .../entity/EntityBuilderWithStateTest.java      | 148 +++++++++++++++++++
 12 files changed, 510 insertions(+), 100 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
index a0ea959..e17bc07 100644
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
+++ b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
  * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013-2014, Paul Merlin. All Rights Reserved.
+ * Copyright (c) 2013-2015, 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.
@@ -15,13 +15,18 @@
  */
 package org.qi4j.api.unitofwork;
 
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
 import org.qi4j.api.composite.AmbiguousTypeException;
 import org.qi4j.api.entity.EntityBuilder;
+import org.qi4j.api.entity.EntityReference;
 import org.qi4j.api.entity.LifecycleException;
+import org.qi4j.api.property.PropertyDescriptor;
 import org.qi4j.api.query.Query;
 import org.qi4j.api.query.QueryBuilder;
 import org.qi4j.api.structure.MetaInfoHolder;
 import org.qi4j.api.usecase.Usecase;
+import org.qi4j.functional.Function;
 
 /**
  * All operations on entities goes through an UnitOfWork.
@@ -178,6 +183,59 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
         throws EntityTypeNotFoundException, AmbiguousTypeException;
 
     /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @param propertyFunction         a function providing the state of properties
+     * @param associationFunction      a function providing the state of associations
+     * @param manyAssociationFunction  a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     *
+     * @return a new EntityBuilder starting with the given state
+     *
+     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException      If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
+        throws EntityTypeNotFoundException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @param identity                 the identity of the new Entity
+     * @param propertyFunction         a function providing the state of properties
+     * @param associationFunction      a function providing the state of associations
+     * @param manyAssociationFunction  a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     *
+     * @return a new EntityBuilder starting with the given state
+     *
+     * @throws EntityTypeNotFoundException If no mixins implements the given type
+     * @throws AmbiguousTypeException      If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, String identity,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
+        throws EntityTypeNotFoundException, AmbiguousTypeException;
+
+    /**
      * Find an Entity of the given mixin type with the give identity. This
      * method verifies that it exists by asking the underlying EntityStore.
      *

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java
new file mode 100644
index 0000000..284929d
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, Kent Sølvsten.
+ *
+ * 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.composite;
+
+import java.util.List;
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.property.PropertyDescriptor;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Iterables;
+
+/**
+ * Function based StateResolver.
+ */
+public class FunctionStateResolver
+    implements StateResolver
+{
+    final Function<PropertyDescriptor, Object> propertyFunction;
+    final Function<AssociationDescriptor, EntityReference> associationFunction;
+    final Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction;
+    final Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction;
+
+    public FunctionStateResolver( Function<PropertyDescriptor, Object> propertyFunction,
+                                  Function<AssociationDescriptor, EntityReference> associationFunction,
+                                  Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+                                  Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
+    {
+        this.propertyFunction = propertyFunction;
+        this.associationFunction = associationFunction;
+        this.manyAssociationFunction = manyAssociationFunction;
+        this.namedAssociationFunction = namedAssociationFunction;
+    }
+
+    @Override
+    public Object getPropertyState( PropertyDescriptor propertyDescriptor )
+    {
+        return propertyFunction.map( propertyDescriptor );
+    }
+
+    @Override
+    public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
+    {
+        return associationFunction.map( associationDescriptor );
+    }
+
+    @Override
+    public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
+    {
+        return Iterables.toList( manyAssociationFunction.map( associationDescriptor ) );
+    }
+
+    @Override
+    public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor )
+    {
+        return namedAssociationFunction.map( associationDescriptor );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java
new file mode 100644
index 0000000..1f7072a
--- /dev/null
+++ b/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Kent Sølvsten.
+ *
+ * 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.composite;
+
+import java.util.List;
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.property.PropertyDescriptor;
+
+/**
+ * StateResolver.
+ */
+public interface StateResolver
+{
+    Object getPropertyState( PropertyDescriptor propertyDescriptor );
+
+    EntityReference getAssociationState( AssociationDescriptor associationDescriptor );
+
+    List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor );
+
+    Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor );
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
index 20d397e..5fae1a2 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
@@ -129,7 +129,7 @@ public final class EntityStateModel
     }
 
     @Override
-    public Iterable<? extends AssociationDescriptor> namedAssociations()
+    public Iterable<NamedAssociationModel> namedAssociations()
     {
         return namedAssociationsModel.namedAssociations();
     }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
index 551999e..c009c75 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
@@ -1,7 +1,8 @@
 /*
  * Copyright (c) 2008-2012, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Kent Sølvsten. All Rights Reserved.
  * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ * Copyright (c) 2012-2015, 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.
@@ -67,6 +68,7 @@ import org.qi4j.functional.Function2;
 import org.qi4j.functional.Specification;
 import org.qi4j.functional.Specifications;
 import org.qi4j.runtime.activation.ActivationDelegate;
+import org.qi4j.runtime.composite.FunctionStateResolver;
 import org.qi4j.runtime.composite.TransientBuilderInstance;
 import org.qi4j.runtime.composite.TransientModel;
 import org.qi4j.runtime.composite.TransientStateInstance;
@@ -86,12 +88,12 @@ import org.qi4j.runtime.service.ImportedServicesModel;
 import org.qi4j.runtime.service.ServicesInstance;
 import org.qi4j.runtime.service.ServicesModel;
 import org.qi4j.runtime.unitofwork.UnitOfWorkInstance;
+import org.qi4j.runtime.composite.StateResolver;
 import org.qi4j.runtime.value.ValueBuilderInstance;
 import org.qi4j.runtime.value.ValueBuilderWithPrototype;
 import org.qi4j.runtime.value.ValueBuilderWithState;
 import org.qi4j.runtime.value.ValueInstance;
 import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.runtime.value.ValueStateModel;
 import org.qi4j.runtime.value.ValuesModel;
 import org.qi4j.spi.entitystore.EntityStore;
 import org.qi4j.spi.metrics.MetricsProviderAdapter;
@@ -113,7 +115,6 @@ import static org.qi4j.functional.Iterables.toList;
 public class ModuleInstance
     implements Module, Activation
 {
-
     // Constructor parameters
     private final ModuleModel model;
     private final LayerInstance layer;
@@ -350,7 +351,7 @@ public class ModuleInstance
             throw new NoSuchValueException( mixinType.getName(), name() );
         }
 
-        ValueStateModel.StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
+        StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
         return new ValueBuilderInstance<>( compositeModelModule, this, stateResolver );
     }
 
@@ -373,14 +374,15 @@ public class ModuleInstance
             throw new NoSuchValueException( mixinType.getName(), name() );
         }
 
-        ValueStateModel.StateResolver stateResolver = new FunctionStateResolver( propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction );
+        StateResolver stateResolver = new FunctionStateResolver(
+            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+        );
         return new ValueBuilderWithState<>( compositeModelModule, this, stateResolver );
     }
 
     private static class InitialStateResolver
-        implements ValueStateModel.StateResolver
+        implements StateResolver
     {
-
         private final ModuleInstance module;
 
         private InitialStateResolver( ModuleInstance module )
@@ -411,53 +413,6 @@ public class ModuleInstance
         {
             return new HashMap<>();
         }
-        
-    }
-
-    private static class FunctionStateResolver
-        implements ValueStateModel.StateResolver
-    {
-
-        private final Function<PropertyDescriptor, Object> propertyFunction;
-        private final Function<AssociationDescriptor, EntityReference> associationFunction;
-        private final Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction;
-        private final Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction;
-
-        private FunctionStateResolver( Function<PropertyDescriptor, Object> propertyFunction,
-                                       Function<AssociationDescriptor, EntityReference> associationFunction,
-                                       Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                       Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
-        {
-            this.propertyFunction = propertyFunction;
-            this.associationFunction = associationFunction;
-            this.manyAssociationFunction = manyAssociationFunction;
-            this.namedAssociationFunction = namedAssociationFunction;
-        }
-
-        @Override
-        public Object getPropertyState( PropertyDescriptor propertyDescriptor )
-        {
-            return propertyFunction.map( propertyDescriptor );
-        }
-
-        @Override
-        public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return associationFunction.map( associationDescriptor );
-        }
-
-        @Override
-        public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return toList( manyAssociationFunction.map( associationDescriptor ) );
-        }
-
-        @Override
-        public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return namedAssociationFunction.map( associationDescriptor );
-        }
-
     }
 
     @Override
@@ -792,8 +747,12 @@ public class ModuleInstance
                         if( iter.hasNext() )
                         {
                             // Ambiguous exception
-                            throw new ClassNotFoundException( name, new AmbiguousTypeException(
-                                "More than one model matches the classname " + name + ":" + toList( moduleModels ) ) );
+                            throw new ClassNotFoundException(
+                                name,
+                                new AmbiguousTypeException(
+                                    "More than one model matches the classname " + name + ":" + toList( moduleModels )
+                                )
+                            );
                         }
                     }
                 }
@@ -819,8 +778,11 @@ public class ModuleInstance
                         if( iter.hasNext() )
                         {
                             // Ambiguous exception
-                            throw new ClassNotFoundException( name, new AmbiguousTypeException(
-                                "More than one model matches the classname " + name + ":" + toList( layerModels ) ) );
+                            throw new ClassNotFoundException(
+                                name,
+                                new AmbiguousTypeException(
+                                    "More than one model matches the classname " + name + ":" + toList( layerModels ) )
+                            );
                         }
                     }
                 }
@@ -842,8 +804,12 @@ public class ModuleInstance
                         if( iter.hasNext() )
                         {
                             // Ambiguous exception
-                            throw new ClassNotFoundException( name, new AmbiguousTypeException(
-                                "More than one model matches the classname " + name + ":" + toList( usedLayersModels ) ) );
+                            throw new ClassNotFoundException(
+                                name,
+                                new AmbiguousTypeException(
+                                    "More than one model matches the classname " + name + ":" + toList( usedLayersModels )
+                                )
+                            );
                         }
                     }
                 }
@@ -858,5 +824,4 @@ public class ModuleInstance
             return clazz;
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
index bdadb75..dd1a830 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
  * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
+ * Copyright (c) 2013-2015, 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.
@@ -18,12 +18,16 @@ package org.qi4j.runtime.structure;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.common.QualifiedName;
 import org.qi4j.api.composite.Composite;
 import org.qi4j.api.entity.EntityBuilder;
 import org.qi4j.api.entity.EntityComposite;
 import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
 import org.qi4j.api.entity.IdentityGenerator;
 import org.qi4j.api.entity.LifecycleException;
+import org.qi4j.api.property.PropertyDescriptor;
 import org.qi4j.api.query.Query;
 import org.qi4j.api.query.QueryBuilder;
 import org.qi4j.api.query.QueryExecutionException;
@@ -37,12 +41,18 @@ import org.qi4j.api.unitofwork.UnitOfWorkCallback;
 import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
 import org.qi4j.api.unitofwork.UnitOfWorkFactory;
 import org.qi4j.api.usecase.Usecase;
+import org.qi4j.api.util.NullArgumentException;
+import org.qi4j.functional.Function;
 import org.qi4j.functional.Iterables;
 import org.qi4j.functional.Specification;
+import org.qi4j.runtime.composite.FunctionStateResolver;
 import org.qi4j.runtime.entity.EntityInstance;
 import org.qi4j.runtime.entity.EntityModel;
+import org.qi4j.runtime.property.PropertyModel;
 import org.qi4j.runtime.unitofwork.EntityBuilderInstance;
 import org.qi4j.runtime.unitofwork.UnitOfWorkInstance;
+import org.qi4j.runtime.composite.StateResolver;
+import org.qi4j.runtime.value.ValueStateModel;
 import org.qi4j.spi.entity.EntityStatus;
 import org.qi4j.spi.entitystore.EntityStore;
 import org.qi4j.spi.query.EntityFinder;
@@ -59,20 +69,20 @@ import static org.qi4j.functional.Iterables.first;
 public class ModuleUnitOfWork
     implements UnitOfWork
 {
-//    private static final QualifiedName IDENTITY_STATE_NAME;
-//
-//    static
-//    {
-//        try
-//        {
-//            IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
-//        }
-//        catch( NoSuchMethodException e )
-//        {
-//            throw new InternalError( "Qi4j Core Runtime codebase is corrupted. Contact Qi4j team: ModuleUnitOfWork" );
-//        }
-//    }
-//
+    private static final QualifiedName IDENTITY_STATE_NAME;
+
+    static
+    {
+        try
+        {
+            IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
+        }
+        catch( NoSuchMethodException e )
+        {
+            throw new InternalError( "Qi4j Core Runtime codebase is corrupted. Contact Qi4j team: ModuleUnitOfWork" );
+        }
+    }
+
     private final UnitOfWorkInstance uow;
     private final ModuleInstance moduleInstance;
 
@@ -185,6 +195,75 @@ public class ModuleUnitOfWork
     }
 
     @Override
+    public <T> EntityBuilder<T> newEntityBuilderWithState(
+        Class<T> type,
+        Function<PropertyDescriptor, Object> propertyFunction,
+        Function<AssociationDescriptor, EntityReference> associationFunction,
+        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
+    )
+        throws EntityTypeNotFoundException
+    {
+        return newEntityBuilderWithState( type, null,
+                                          propertyFunction,
+                                          associationFunction,
+                                          manyAssociationFunction,
+                                          namedAssociationFunction );
+    }
+
+    @Override
+    public <T> EntityBuilder<T> newEntityBuilderWithState(
+        Class<T> type, String identity,
+        Function<PropertyDescriptor, Object> propertyFunction,
+        Function<AssociationDescriptor, EntityReference> associationFunction,
+        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
+    )
+        throws EntityTypeNotFoundException
+    {
+        NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
+        NullArgumentException.validateNotNull( "associationFunction", associationFunction );
+        NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
+        NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
+
+        ModelModule<EntityModel> model = moduleInstance.typeLookup().lookupEntityModel( type );
+
+        if( model == null )
+        {
+            throw new EntityTypeNotFoundException( type.getName() );
+        }
+
+        EntityStore entityStore = model.module().entityStore();
+
+        StateResolver stateResolver = new FunctionStateResolver(
+            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+        );
+
+        if( identity == null )
+        {
+            // Use identity from StateResolver if available
+            PropertyModel identityModel = model.model().state().findPropertyModelByQualifiedName( IDENTITY_STATE_NAME );
+            identity = (String) stateResolver.getPropertyState( identityModel );
+            if( identity == null )
+            {
+                // Generate identity
+                IdentityGenerator idGen = model.module().identityGenerator();
+                if( idGen == null )
+                {
+                    throw new NoSuchServiceException( IdentityGenerator.class.getName(), model.module().name() );
+                }
+                identity = idGen.generate( first( model.model().types() ) );
+            }
+        }
+
+        return new EntityBuilderInstance<>( model,
+                                            this,
+                                            uow.getEntityStoreUnitOfWork( entityStore, moduleInstance ),
+                                            identity,
+                                            stateResolver );
+    }
+
+    @Override
     public <T> T get( Class<T> type, String identity )
         throws EntityTypeNotFoundException, NoSuchEntityException
     {

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
index 74d1cf2..8bb0ffd 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
@@ -1,5 +1,8 @@
 /*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2007-2009, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008, Alin Dreghiciu. All Rights Reserved.
+ * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
+ * Copyright (c) 2014-2015, 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.
@@ -13,15 +16,22 @@
  */
 package org.qi4j.runtime.unitofwork;
 
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
 import org.qi4j.api.common.QualifiedName;
 import org.qi4j.api.entity.EntityBuilder;
 import org.qi4j.api.entity.EntityReference;
 import org.qi4j.api.entity.Identity;
 import org.qi4j.api.entity.LifecycleException;
+import org.qi4j.api.property.PropertyDescriptor;
+import org.qi4j.runtime.association.ManyAssociationModel;
+import org.qi4j.runtime.association.NamedAssociationModel;
 import org.qi4j.runtime.entity.EntityInstance;
 import org.qi4j.runtime.entity.EntityModel;
 import org.qi4j.runtime.structure.ModelModule;
 import org.qi4j.runtime.structure.ModuleUnitOfWork;
+import org.qi4j.runtime.composite.StateResolver;
+import org.qi4j.runtime.value.ValueStateModel;
 import org.qi4j.spi.entity.EntityState;
 import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
 
@@ -61,6 +71,17 @@ public final class EntityBuilderInstance<T>
         String identity
     )
     {
+        this( model, uow, store, identity, null );
+    }
+
+    public EntityBuilderInstance(
+        ModelModule<EntityModel> model,
+        ModuleUnitOfWork uow,
+        EntityStoreUnitOfWork store,
+        String identity,
+        StateResolver stateResolver
+    )
+    {
         this.model = model;
         this.uow = uow;
         this.store = store;
@@ -68,6 +89,33 @@ public final class EntityBuilderInstance<T>
         EntityReference reference = new EntityReference( identity );
         entityState = new BuilderEntityState( model.model(), reference );
         model.model().initState( model.module(), entityState );
+        if( stateResolver != null )
+        {
+            for( PropertyDescriptor propDesc : model.model().state().properties() )
+            {
+                Object value = stateResolver.getPropertyState( propDesc );
+                entityState.setPropertyValue( propDesc.qualifiedName(), value );
+            }
+            for( AssociationDescriptor assDesc : model.model().state().associations() )
+            {
+                EntityReference ref = stateResolver.getAssociationState( assDesc );
+                entityState.setAssociationValue( assDesc.qualifiedName(), ref );
+            }
+            for( ManyAssociationModel manyAssDesc : model.model().state().manyAssociations() )
+            {
+                for( EntityReference ref : stateResolver.getManyAssociationState( manyAssDesc ) )
+                {
+                    entityState.manyAssociationValueOf( manyAssDesc.qualifiedName() ).add( 0, ref );
+                }
+            }
+            for( NamedAssociationModel namedAssDesc : model.model().state().namedAssociations() )
+            {
+                for( Map.Entry<String, EntityReference> entry : stateResolver.getNamedAssociationState( namedAssDesc ).entrySet() )
+                {
+                    entityState.namedAssociationValueOf( namedAssDesc.qualifiedName() ).put( entry.getKey(), entry.getValue() );
+                }
+            }
+        }
         entityState.setPropertyValue( IDENTITY_STATE_NAME, identity );
         prototypeInstance = model.model().newInstance( uow, model.module(), entityState );
     }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
index f1f59de..0d70463 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
@@ -18,6 +18,7 @@ import org.qi4j.api.common.ConstructionException;
 import org.qi4j.api.composite.Composite;
 import org.qi4j.api.value.NoSuchValueException;
 import org.qi4j.api.value.ValueBuilder;
+import org.qi4j.runtime.composite.StateResolver;
 import org.qi4j.runtime.structure.ModelModule;
 import org.qi4j.runtime.structure.ModuleInstance;
 
@@ -33,7 +34,7 @@ public final class ValueBuilderInstance<T>
     private final ModuleInstance currentModule;
     private final ValueInstance prototypeInstance;
 
-    public ValueBuilderInstance( ModelModule<ValueModel> compositeModelModule, ModuleInstance currentModule, ValueStateModel.StateResolver stateResolver )
+    public ValueBuilderInstance( ModelModule<ValueModel> compositeModelModule, ModuleInstance currentModule, StateResolver stateResolver )
     {
         ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
         prototypeInstance = compositeModelModule.model().newValueInstance( compositeModelModule.module(), state );

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
index d5ed565..ec1f7b3 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
@@ -1,8 +1,22 @@
+/*
+ * Copyright (c) 2012, Kent Sølvsten. 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.value;
 
 import org.qi4j.api.association.AssociationStateHolder;
 import org.qi4j.api.common.ConstructionException;
 import org.qi4j.api.value.ValueBuilder;
+import org.qi4j.runtime.composite.StateResolver;
 import org.qi4j.runtime.structure.ModelModule;
 import org.qi4j.runtime.structure.ModuleInstance;
 
@@ -11,7 +25,10 @@ public class ValueBuilderWithState<T> implements ValueBuilder<T>
     private final ModelModule<ValueModel> model;
     private ValueInstance prototypeInstance;
 
-    public ValueBuilderWithState( ModelModule<ValueModel> compositeModelModule, ModuleInstance currentModule, ValueStateModel.StateResolver stateResolver ) {
+    public ValueBuilderWithState( ModelModule<ValueModel> compositeModelModule,
+                                  ModuleInstance currentModule,
+                                  StateResolver stateResolver )
+    {
         ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
         ValueInstance instance = compositeModelModule.model().newValueInstance( compositeModelModule.module(), state );
         instance.prepareToBuild();

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
index 660e2e2..68dd5c7 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
  * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012, Kent Sølvsten. 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.
@@ -34,6 +35,7 @@ import org.qi4j.runtime.association.ManyAssociationInstance;
 import org.qi4j.runtime.association.ManyAssociationModel;
 import org.qi4j.runtime.association.NamedAssociationInstance;
 import org.qi4j.runtime.association.NamedAssociationModel;
+import org.qi4j.runtime.composite.StateResolver;
 import org.qi4j.runtime.property.PropertyInfo;
 import org.qi4j.runtime.property.PropertyInstance;
 import org.qi4j.runtime.property.PropertyModel;
@@ -65,7 +67,7 @@ public final class ValueStateInstance
 
     public ValueStateInstance( ModelModule<ValueModel> compositeModelModule,
                                ModuleInstance currentModule,
-                               ValueStateModel.StateResolver stateResolver )
+                               StateResolver stateResolver )
     {
         ValueModel valueModel = compositeModelModule.model();
         this.properties = new LinkedHashMap<>();

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
index 8c5ecf7..d3f8060 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
@@ -1,5 +1,7 @@
 /*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2011, Rickard Öberg.
+ * Copyright (c) 2012, Kent Sølvsten.
+ * Copyright (c) 2014-2015, Paul Merlin.
  *
  * Licensed  under the  Apache License,  Version 2.0  (the "License");
  * you may not use  this file  except in  compliance with the License.
@@ -17,13 +19,9 @@
  */
 package org.qi4j.runtime.value;
 
-import java.util.List;
-import java.util.Map;
 import org.qi4j.api.association.AssociationDescriptor;
 import org.qi4j.api.association.AssociationStateDescriptor;
 import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
 import org.qi4j.functional.HierarchicalVisitor;
 import org.qi4j.functional.VisitableHierarchy;
 import org.qi4j.runtime.association.AssociationModel;
@@ -129,19 +127,6 @@ public final class ValueStateModel
                 }
             }
         }
-
         return visitor.visitLeave( this );
     }
-
-    public interface StateResolver
-    {
-        public Object getPropertyState( PropertyDescriptor propertyDescriptor );
-
-        public EntityReference getAssociationState( AssociationDescriptor associationDescriptor );
-
-        public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor );
-
-        public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor );
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/355ea47d/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java
new file mode 100644
index 0000000..a949419
--- /dev/null
+++ b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015 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.entity;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import org.junit.Test;
+import org.qi4j.api.association.Association;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.association.NamedAssociation;
+import org.qi4j.api.common.Optional;
+import org.qi4j.api.entity.EntityBuilder;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
+import org.qi4j.api.property.Property;
+import org.qi4j.api.property.PropertyDescriptor;
+import org.qi4j.api.unitofwork.UnitOfWork;
+import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.functional.Function;
+import org.qi4j.test.AbstractQi4jTest;
+import org.qi4j.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * EntityBuilder With State Test.
+ */
+public class EntityBuilderWithStateTest
+    extends AbstractQi4jTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeEntity.class );
+    }
+
+    @Test
+    public void test()
+        throws UnitOfWorkCompletionException
+    {
+        final String associatedIdentity;
+        try( UnitOfWork uow = module.newUnitOfWork() )
+        {
+            EntityBuilder<SomeEntity> builder = uow.newEntityBuilder( SomeEntity.class );
+            builder.instance().prop().set( "Associated" );
+            SomeEntity entity = builder.newInstance();
+            associatedIdentity = entity.identity().get();
+            uow.complete();
+        }
+        try( UnitOfWork uow = module.newUnitOfWork() )
+        {
+            SomeEntity entity = uow.newEntityBuilderWithState(
+                SomeEntity.class,
+                new Function<PropertyDescriptor, Object>()
+                {
+                    @Override
+                    public Object map( PropertyDescriptor descriptor )
+                    {
+                        if( "prop".equals( descriptor.qualifiedName().name() ) )
+                        {
+                            return "Foo";
+                        }
+                        return null;
+                    }
+                },
+                new Function<AssociationDescriptor, EntityReference>()
+                {
+                    @Override
+                    public EntityReference map( AssociationDescriptor descriptor )
+                    {
+                        if( "ass".equals( descriptor.qualifiedName().name() ) )
+                        {
+                            return EntityReference.parseEntityReference( associatedIdentity );
+                        }
+                        return null;
+                    }
+                },
+                new Function<AssociationDescriptor, Iterable<EntityReference>>()
+                {
+                    @Override
+                    public Iterable<EntityReference> map( AssociationDescriptor descriptor )
+                    {
+                        if( "manyAss".equals( descriptor.qualifiedName().name() ) )
+                        {
+                            return Arrays.asList( EntityReference.parseEntityReference( associatedIdentity ) );
+                        }
+                        return null;
+                    }
+                },
+                new Function<AssociationDescriptor, Map<String, EntityReference>>()
+                {
+                    @Override
+                    public Map<String, EntityReference> map( AssociationDescriptor descriptor )
+                    {
+                        if( "namedAss".equals( descriptor.qualifiedName().name() ) )
+                        {
+                            return Collections.singletonMap(
+                                "foo",
+                                EntityReference.parseEntityReference( associatedIdentity )
+                            );
+                        }
+                        return null;
+                    }
+                }
+            ).newInstance();
+            assertThat( entity.prop().get(), equalTo( "Foo" ) );
+            assertThat( entity.ass().get().identity().get(), equalTo( associatedIdentity ) );
+            assertThat( entity.manyAss().get( 0 ).identity().get(), equalTo( associatedIdentity ) );
+            assertThat( entity.namedAss().get( "foo" ).identity().get(), equalTo( associatedIdentity ) );
+            uow.complete();
+        }
+    }
+
+    public interface SomeEntity
+        extends Identity
+    {
+        Property<String> prop();
+
+        @Optional
+        Association<SomeEntity> ass();
+
+        @Optional
+        ManyAssociation<SomeEntity> manyAss();
+
+        @Optional
+        NamedAssociation<SomeEntity> namedAss();
+    }
+}