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/06/10 01:58:06 UTC
[08/14] zest-qi4j git commit: Fix for ZEST-23. + Putting the
toValue() and toEntity() into the UnitOfWork instead f the SPI. + Adding
access to the EntityReference in Associations.
Fix for ZEST-23.
+ Putting the toValue() and toEntity() into the UnitOfWork instead f the SPI.
+ Adding access to the EntityReference in Associations.
Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/568fa2ff
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/568fa2ff
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/568fa2ff
Branch: refs/heads/develop
Commit: 568fa2ff3fe8abb4ff66c286e8675ed7ad285e64
Parents: e6d2d6b
Author: Niclas Hedhman <ni...@hedhman.org>
Authored: Wed Jun 3 12:22:31 2015 +0800
Committer: Niclas Hedhman <ni...@hedhman.org>
Committed: Wed Jun 3 12:22:31 2015 +0800
----------------------------------------------------------------------
core/api/src/main/java/org/qi4j/api/Qi4j.java | 71 ------
.../org/qi4j/api/association/Association.java | 7 +
.../api/association/AssociationWrapper.java | 8 +
.../qi4j/api/association/ManyAssociation.java | 11 +
.../api/association/ManyAssociationWrapper.java | 7 +
.../qi4j/api/association/NamedAssociation.java | 6 +
.../association/NamedAssociationWrapper.java | 7 +
.../org/qi4j/api/entity/EntityReference.java | 7 +
.../org/qi4j/api/unitofwork/UnitOfWork.java | 74 ++++++
.../java/org/qi4j/runtime/Qi4jRuntimeImpl.java | 213 -----------------
.../AbstractAssociationInstance.java | 31 +--
.../association/AssociationInstance.java | 13 +-
.../association/ManyAssociationInstance.java | 33 ++-
.../association/NamedAssociationInstance.java | 35 ++-
.../runtime/structure/ModuleUnitOfWork.java | 235 ++++++++++++++++++-
.../unitofwork/EntityBuilderInstance.java | 11 +-
.../runtime/value/ValueWithAssociationTest.java | 53 ++++-
.../qi4j/spi/value/ValueSerializerAdapter.java | 129 +++++-----
.../binding/internal/BoundAssociation.java | 7 +
.../binding/internal/BoundManyAssociation.java | 7 +
.../binding/internal/BoundNamedAssociation.java | 7 +
.../swing/binding/internal/BoundProperty.java | 11 +-
22 files changed, 557 insertions(+), 426 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/Qi4j.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/Qi4j.java b/core/api/src/main/java/org/qi4j/api/Qi4j.java
index d8f2d29..0b40c4a 100644
--- a/core/api/src/main/java/org/qi4j/api/Qi4j.java
+++ b/core/api/src/main/java/org/qi4j/api/Qi4j.java
@@ -135,77 +135,6 @@ public interface Qi4j
AssociationDescriptor associationDescriptorFor( AbstractAssociation association );
/**
- * Converts the provided Entity to a Value of the same type.
- * This is a convenience method to convert an EntityComposite to a ValueComposite.
- * <p/>
- * All Property values are transferred across as-is, and the Association, ManyAssociation
- * and NamedAssociatino values are kept in the ValueComposite as EntityReferences
- * until they are dereferenced (get() and other methods), and IF a UnitOfWork is
- * present at dereferencing the corresponding EntityCompoiste is retrieved from the
- * EntityStore. If there is not an UnitOfWork present, an exception is thrown.
- * <p/>
- * For this to work, the Composites (both Entity and Value) must not declare the
- * EntityComposite and ValueComposite super types, but rely on the declaration in
- * the assembly, and also extend the Identity supertype.
- *
- * Example;
- * <pre><code>
- * public interface Person extends Identity { ... };
- * public class MyAssembler
- * {
- * public void assemble( ModuleAssembly module )
- * {
- * module.values( Person.class );
- * module.entities( Person.class );
- * }
- * }
- * </code></pre>
- *
- * @param primaryType The shared type for which the properties and associations will
- * be converted. Properties outside this type will be ignored.
- * @param entityComposite The entity to be convered.
- */
- <T extends Identity> T toValue( Class<T> primaryType, T entityComposite );
-
- /**
- * Converts the provided Value to an Entity of the same type.
- * This is a convenience method to convert a ValueComposite to an EntityComposite.
- * <p/>
- * All Property values are transferred across as-is (no deep copy in case mutable
- * types (DISCOURAGED!) are used), and the Association, ManyAssociation
- * and NamedAssociatino that were in the ValueComposite as EntityReferences are
- * transferred into the EntityComposite correctly, and can be dereferenced.
- * <p/>
- * This method MUST be called within a UnitOfWork.
- * <p/>
- * If an Entity with the Identity in the ValueComposite already exists, then that
- * Entity is updated with the values from the ValueComposite. If an Entity of
- * that Identity doesn't exist and new one is created.
- * <p/>
- * For this to work, the Composites (both Entity and Value) must not declare the
- * EntityComposite and ValueComposite super types, but rely on the declaration in
- * the assembly, and also extend the Identity supertype.
- *
- * Example;
- * <pre><code>
- * public interface Person extends Identity { ... };
- * public class MyAssembler
- * {
- * public void assemble( ModuleAssembly module )
- * {
- * module.values( Person.class );
- * module.entities( Person.class );
- * }
- * }
- * </code></pre>
- *
- * @param primaryType The shared type for which the properties and associations will
- * be converted. Properties outside this type will be ignored.
- * @param valueComposite The Value to be convered into an Entity.
- */
- <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite );
-
- /**
* Function that returns the CompositeDescriptor of a Composite.
*/
Function<Composite, CompositeDescriptor> FUNCTION_DESCRIPTOR_FOR = new Function<Composite, CompositeDescriptor>()
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/Association.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/Association.java b/core/api/src/main/java/org/qi4j/api/association/Association.java
index f262a8c..acd406f 100644
--- a/core/api/src/main/java/org/qi4j/api/association/Association.java
+++ b/core/api/src/main/java/org/qi4j/api/association/Association.java
@@ -14,6 +14,8 @@
package org.qi4j.api.association;
+import org.qi4j.api.entity.EntityReference;
+
/**
* Association to a single EntityComposite.
*/
@@ -36,4 +38,9 @@ public interface Association<T> extends AbstractAssociation
*/
void set( T associated )
throws IllegalArgumentException, IllegalStateException;
+
+ /**
+ * @return the the reference of the associated entity.
+ */
+ EntityReference reference();
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
index 4e907de..fd5af6f 100644
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
+++ b/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
@@ -1,5 +1,7 @@
package org.qi4j.api.association;
+import org.qi4j.api.entity.EntityReference;
+
/**
* If you want to catch getting and setting association, then create a GenericConcern
* that wraps the Qi4j-supplied Association instance with AssociationWrappers. Override
@@ -34,6 +36,12 @@ public class AssociationWrapper
}
@Override
+ public EntityReference reference()
+ {
+ return next.reference();
+ }
+
+ @Override
public int hashCode()
{
return next.hashCode();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
index 707d53a..37d7211 100644
--- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
+++ b/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
@@ -16,12 +16,17 @@ package org.qi4j.api.association;
import java.util.List;
import java.util.Set;
+import org.qi4j.api.entity.EntityReference;
/**
* Association to a collection of entities.
*/
public interface ManyAssociation<T> extends Iterable<T>, AbstractAssociation
{
+ /**
+ * Returns the number of references in this association.
+ * @return the number of references in this association.
+ */
int count();
boolean contains( T entity );
@@ -37,4 +42,10 @@ public interface ManyAssociation<T> extends Iterable<T>, AbstractAssociation
List<T> toList();
Set<T> toSet();
+
+ /**
+ * Returns an unmodifiable Iterable of the references to the associated entities.
+ * @return the references to the associated entities.
+ */
+ Iterable<EntityReference> references();
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
index 748af83..c844f0b 100644
--- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
+++ b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
@@ -3,6 +3,7 @@ package org.qi4j.api.association;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.qi4j.api.entity.EntityReference;
/**
* If you want to catch calls to ManyAssociations, then create a GenericConcern
@@ -73,6 +74,12 @@ public class ManyAssociationWrapper
}
@Override
+ public Iterable<EntityReference> references()
+ {
+ return next.references();
+ }
+
+ @Override
public Iterator<Object> iterator()
{
return next.iterator();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
index e8abe32..9464eed 100644
--- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
+++ b/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
@@ -19,6 +19,7 @@
package org.qi4j.api.association;
import java.util.Map;
+import org.qi4j.api.entity.EntityReference;
/**
* Association to named Entities.
@@ -75,4 +76,9 @@ public interface NamedAssociation<T>
*/
Map<String, T> toMap();
+ /**
+ * Returns an unmodifiable Iterable of the references to the associated entities.
+ * @return the references to the associated entities.
+ */
+ Iterable<EntityReference> references();
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
index 581948e..7d0640e 100644
--- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
+++ b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
@@ -20,6 +20,7 @@ package org.qi4j.api.association;
import java.util.Iterator;
import java.util.Map;
+import org.qi4j.api.entity.EntityReference;
/**
* If you want to catch calls to NamedAssociations, then create a GenericConcern
@@ -90,6 +91,12 @@ public class NamedAssociationWrapper
}
@Override
+ public Iterable<EntityReference> references()
+ {
+ return next.references();
+ }
+
+ @Override
public int hashCode()
{
return next.hashCode();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java b/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
index 60c4d1b..967647c 100644
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
+++ b/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
@@ -55,6 +55,13 @@ public final class EntityReference
return new EntityReference( (EntityComposite) object );
}
+ public static EntityReference create( Identity identity )
+ {
+ if( identity == null )
+ return null;
+ return new EntityReference( identity.identity().get() );
+ }
+
private static final long serialVersionUID = 1L;
private String identity;
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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 e17bc07..7721265 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
@@ -20,6 +20,7 @@ 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.Identity;
import org.qi4j.api.entity.LifecycleException;
import org.qi4j.api.property.PropertyDescriptor;
import org.qi4j.api.query.Query;
@@ -348,4 +349,77 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
* @param callback a callback to be unregistered with this UnitOfWork
*/
void removeUnitOfWorkCallback( UnitOfWorkCallback callback );
+
+ /**
+ * Converts the provided Entity to a Value of the same type.
+ * This is a convenience method to convert an EntityComposite to a ValueComposite.
+ * <p/>
+ * All Property values are transferred across as-is, and the Association, ManyAssociation
+ * and NamedAssociatino values are kept in the ValueComposite as EntityReferences
+ * until they are dereferenced (get() and other methods), and IF a UnitOfWork is
+ * present at dereferencing the corresponding EntityCompoiste is retrieved from the
+ * EntityStore. If there is not an UnitOfWork present, an exception is thrown.
+ * <p/>
+ * For this to work, the Composites (both Entity and Value) must not declare the
+ * EntityComposite and ValueComposite super types, but rely on the declaration in
+ * the assembly, and also extend the Identity supertype.
+ *
+ * Example;
+ * <pre><code>
+ * public interface Person extends Identity { ... };
+ * public class MyAssembler
+ * {
+ * public void assemble( ModuleAssembly module )
+ * {
+ * module.values( Person.class );
+ * module.entities( Person.class );
+ * }
+ * }
+ * </code></pre>
+ *
+ * @param primaryType The shared type for which the properties and associations will
+ * be converted. Properties outside this type will be ignored.
+ * @param entityComposite The entity to be convered.
+ */
+ <T extends Identity> T toValue( Class<T> primaryType, T entityComposite );
+
+ /**
+ * Converts the provided Value to an Entity of the same type.
+ * This is a convenience method to convert a ValueComposite to an EntityComposite.
+ * <p/>
+ * All Property values are transferred across as-is (no deep copy in case mutable
+ * types (DISCOURAGED!) are used), and the Association, ManyAssociation
+ * and NamedAssociatino that were in the ValueComposite as EntityReferences are
+ * transferred into the EntityComposite correctly, and can be dereferenced.
+ * <p/>
+ * This method MUST be called within a UnitOfWork.
+ * <p/>
+ * If an Entity with the Identity in the ValueComposite already exists, then that
+ * Entity is updated with the values from the ValueComposite. If an Entity of
+ * that Identity doesn't exist and new one is created.
+ * <p/>
+ * For this to work, the Composites (both Entity and Value) must not declare the
+ * EntityComposite and ValueComposite super types, but rely on the declaration in
+ * the assembly, and also extend the Identity supertype.
+ *
+ * Example;
+ * <pre><code>
+ * public interface Person extends Identity { ... };
+ * public class MyAssembler
+ * {
+ * public void assemble( ModuleAssembly module )
+ * {
+ * module.values( Person.class );
+ * module.entities( Person.class );
+ * }
+ * }
+ * </code></pre>
+ *
+ * @param primaryType The shared type for which the properties and associations will
+ * be converted. Properties outside this type will be ignored.
+ * @param valueComposite The Value to be convered into an Entity.
+ */
+ <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite );
+
+
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
index 9b5dce7..23ba27b 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
@@ -338,57 +338,6 @@ public final class Qi4jRuntimeImpl
return (AssociationDescriptor) ( (AbstractAssociationInstance) association ).associationInfo();
}
- @Override
- public <T extends Identity> T toValue( Class<T> primaryType, T entityComposite )
- {
- EntityDescriptor entityDescriptor = entityDescriptorFor( entityComposite );
- Function<PropertyDescriptor, Object> propertyFunction = new ToValuePropertyMappingFunction<T>( entityComposite );
- Function<AssociationDescriptor, EntityReference> assocationFunction = new ToValueAssociationMappingFunction<T>( entityComposite );
- Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToValueManyAssociationMappingFunction<T>( entityComposite );
- Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToValueNameAssociationMappingFunction<T>( entityComposite );
-
- @SuppressWarnings( "unchecked" )
- ValueBuilder<T> builder = moduleOf( entityComposite ).newValueBuilderWithState(
- (Class<T>) entityDescriptor.primaryType(), propertyFunction, assocationFunction, manyAssocFunction, namedAssocFunction );
- return builder.newInstance();
- }
-
- @Override
- public <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite )
- {
- Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<T>( valueComposite );
- Function<AssociationDescriptor, EntityReference> assocationFunction = new ToEntityAssociationMappingFunction<T>( valueComposite );
- Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToEntityManyAssociationMappingFunction<T>( valueComposite );
- Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToEntityNameAssociationMappingFunction<T>( valueComposite );
-
- UnitOfWork uow = moduleOf( valueComposite ).currentUnitOfWork();
- String identity = valueComposite.identity().get();
- try
- {
- T entity = uow.get( primaryType, identity );
- // If successful, then this entity is to by modified.
- EntityInstance instance = EntityInstance.entityInstanceOf( (EntityComposite) entity );
- EntityState state = instance.entityState();
- FunctionStateResolver stateResolver = new FunctionStateResolver( propertyFunction,
- assocationFunction,
- manyAssocFunction,
- namedAssocFunction );
- EntityModel model = (EntityModel) EntityInstance.entityInstanceOf( (EntityComposite) entity ).descriptor();
- stateResolver.populateState( model, state );
- return entity;
- }
- catch( NoSuchEntityException e )
- {
- EntityBuilder<T> entityBuilder = uow.newEntityBuilderWithState( primaryType,
- identity,
- propertyFunction,
- assocationFunction,
- manyAssocFunction,
- namedAssocFunction );
- return entityBuilder.newInstance();
- }
- }
-
// SPI
@Override
public EntityState entityStateOf( EntityComposite composite )
@@ -416,166 +365,4 @@ public final class Qi4jRuntimeImpl
return ( (NamedAssociationInstance) assoc ).getEntityReferences();
}
- private class ToValuePropertyMappingFunction<T>
- implements Function<PropertyDescriptor, Object>
- {
- private Object entity;
-
- public ToValuePropertyMappingFunction( Object entity )
- {
- this.entity = entity;
- }
-
- @Override
- public Object map( PropertyDescriptor propertyDescriptor )
- {
- EntityState entityState = entityStateOf( (EntityComposite) entity );
- return entityState.propertyValueOf( propertyDescriptor.qualifiedName() );
- }
- }
-
- private class ToValueAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, EntityReference>
- {
- private final T entity;
-
- public ToValueAssociationMappingFunction( T entity )
- {
- this.entity = entity;
- }
-
- @Override
- public EntityReference map( AssociationDescriptor associationDescriptor )
- {
- EntityState entityState = entityStateOf( (EntityComposite) entity );
- return entityState.associationValueOf( associationDescriptor.qualifiedName() );
- }
- }
-
- private class ToValueManyAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, Iterable<EntityReference>>
- {
- private final T entity;
-
- public ToValueManyAssociationMappingFunction( T entity )
- {
- this.entity = entity;
- }
-
- @Override
- public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
- {
- EntityState entityState = entityStateOf( (EntityComposite) entity );
- return entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
- }
- }
-
- private class ToValueNameAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, Map<String, EntityReference>>
- {
- private final T entity;
-
- public ToValueNameAssociationMappingFunction( T entity )
- {
- this.entity = entity;
- }
-
- @Override
- public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
- {
- Map<String, EntityReference> result = new HashMap<>();
- EntityState entityState = entityStateOf( (EntityComposite) entity );
- final NamedAssociationState state = entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
- for( String name : state )
- {
- result.put( name, state.get( name ) );
- }
- return result;
- }
- }
-
- private class ToEntityPropertyMappingFunction<T>
- implements Function<PropertyDescriptor, Object>
- {
- private final T value;
-
- public ToEntityPropertyMappingFunction( T value )
- {
- this.value = value;
- }
-
- @Override
- public Object map( PropertyDescriptor propertyDescriptor )
- {
- StateHolder state = stateOf( (ValueComposite) value );
- Property<Object> property = state.propertyFor( propertyDescriptor.accessor() );
- return property.get();
- }
- }
-
- private class ToEntityAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, EntityReference>
- {
-
- private final T value;
-
- public ToEntityAssociationMappingFunction( T value )
- {
- this.value = value;
- }
-
- @Override
- public EntityReference map( AssociationDescriptor associationDescriptor )
- {
- AssociationStateHolder state = stateOf( (ValueComposite) value );
- AssociationInstance<T> association = (AssociationInstance<T>) state.associationFor( associationDescriptor.accessor() );
- return association.getAssociationState().get();
- }
- }
-
- private class ToEntityManyAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, Iterable<EntityReference>>
- {
-
- private final T value;
-
- public ToEntityManyAssociationMappingFunction( T value )
- {
- this.value = value;
- }
-
- @Override
- public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
- {
- AssociationStateHolder state = stateOf( (ValueComposite) value );
- ManyAssociationInstance<T> association = (ManyAssociationInstance<T>) state.manyAssociationFor( associationDescriptor
- .accessor() );
- return association.getManyAssociationState();
- }
- }
-
- private class ToEntityNameAssociationMappingFunction<T>
- implements Function<AssociationDescriptor, Map<String, EntityReference>>
- {
- private final T value;
-
- public ToEntityNameAssociationMappingFunction( T value )
- {
- this.value = value;
- }
-
- @Override
- public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
- {
- AssociationStateHolder state = stateOf( (ValueComposite) value );
- NamedAssociationInstance<T> association = (NamedAssociationInstance<T>) state.namedAssociationFor( associationDescriptor
- .accessor() );
- HashMap<String, EntityReference> result = new HashMap<>();
- for( Map.Entry<String, EntityReference> entry : association.getEntityReferences() )
- {
- result.put( entry.getKey(), entry.getValue() );
- }
- return result;
- }
- }
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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
index e42b2c5..e8de5c1 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
@@ -1,14 +1,10 @@
package org.qi4j.runtime.association;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.entity.EntityComposite;
import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.entity.Identity;
import org.qi4j.functional.Function2;
-import org.qi4j.runtime.composite.ProxyReferenceInvocationHandler;
-import org.qi4j.runtime.entity.EntityInstance;
/**
* Implementation of AbstractAssociation. Includes helper methods for subclasses
@@ -55,32 +51,17 @@ public abstract class AbstractAssociationInstance<T>
return null;
}
- InvocationHandler handler = Proxy.getInvocationHandler( composite );
- if( handler instanceof ProxyReferenceInvocationHandler )
- {
- handler = Proxy.getInvocationHandler( ( (ProxyReferenceInvocationHandler) handler ).proxy() );
- }
- EntityInstance instance = (EntityInstance) handler;
- return instance.identity();
+ return new EntityReference( ( (Identity) composite ).identity().get() );
}
protected void checkType( Object instance )
{
- if( instance != null )
- {
- if( !( instance instanceof EntityComposite ) )
- {
- if( instance instanceof Proxy )
- {
- if( Proxy.getInvocationHandler( instance ) instanceof EntityInstance )
- {
- return; // It's fine
- }
- }
- throw new IllegalArgumentException( "Object must be an EntityComposite" );
- }
+ if( instance instanceof Identity || instance == null )
+ {
+ return;
}
+ throw new IllegalArgumentException( "Object must be a subtype of org.qi4j.api.identity.Identity" );
}
protected void checkImmutable()
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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
index d5babcd..e42d8eb 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
@@ -19,6 +19,7 @@ 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;
@@ -57,7 +58,13 @@ public final class AssociationInstance<T>
associationInfo.checkConstraints( newValue );
// Change association
- associationState.set( getEntityReference( newValue ) );
+ associationState.set( EntityReference.create( (Identity) newValue ));
+ }
+
+ @Override
+ public EntityReference reference()
+ {
+ return associationState.get();
}
public Property<EntityReference> getAssociationState()
@@ -81,10 +88,10 @@ public final class AssociationInstance<T>
@Override
public int hashCode()
{
- int hash = associationInfo.hashCode() * 61; // Descriptor
+ int hash = associationInfo.hashCode() * 39; // Descriptor
if( associationState.get() != null )
{
- hash += associationState.get().hashCode() * 3; // State
+ hash = hash * 997 + associationState.get().hashCode(); // State
}
return hash;
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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
index a946862..eafda9a 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
@@ -10,8 +10,10 @@ 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.runtime.composite.ConstraintsCheck;
+import org.qi4j.functional.Iterables;
import org.qi4j.spi.entity.ManyAssociationState;
/**
@@ -47,10 +49,11 @@ public class ManyAssociationInstance<T>
@Override
public boolean add( int i, T entity )
{
+ NullArgumentException.validateNotNull( "entity", entity );
checkImmutable();
checkType( entity );
- ( (ConstraintsCheck) associationInfo ).checkConstraints( entity );
- return manyAssociationState.add( i, getEntityReference( entity ) );
+ associationInfo.checkConstraints( entity );
+ return manyAssociationState.add( i, new EntityReference( ( (Identity) entity ).identity().get() ) );
}
@Override
@@ -62,10 +65,11 @@ public class ManyAssociationInstance<T>
@Override
public boolean remove( T entity )
{
+ NullArgumentException.validateNotNull( "entity", entity );
checkImmutable();
checkType( entity );
- return manyAssociationState.remove( getEntityReference( entity ) );
+ return manyAssociationState.remove( new EntityReference( ( (Identity) entity ).identity().get() ) );
}
@Override
@@ -77,7 +81,7 @@ public class ManyAssociationInstance<T>
@Override
public List<T> toList()
{
- ArrayList<T> list = new ArrayList<T>();
+ ArrayList<T> list = new ArrayList<>();
for( EntityReference entityReference : manyAssociationState )
{
list.add( getEntity( entityReference ) );
@@ -89,7 +93,7 @@ public class ManyAssociationInstance<T>
@Override
public Set<T> toSet()
{
- Set<T> set = new HashSet<T>();
+ Set<T> set = new HashSet<>();
for( EntityReference entityReference : manyAssociationState )
{
set.add( getEntity( entityReference ) );
@@ -99,6 +103,12 @@ public class ManyAssociationInstance<T>
}
@Override
+ public Iterable<EntityReference> references()
+ {
+ return Iterables.toList( manyAssociationState );
+ }
+
+ @Override
public String toString()
{
return manyAssociationState.toString();
@@ -194,15 +204,4 @@ public class ManyAssociationInstance<T>
idIterator.remove();
}
}
-
- @Override
- protected void checkType( Object instance )
- {
- if( instance == null )
- {
- throw new NullPointerException( "Associated object may not be null" );
- }
-
- super.checkType( instance );
- }
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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
index 284de5d..7bffb4b 100644
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
+++ b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
@@ -24,12 +24,15 @@ import java.util.Iterator;
import java.util.Map;
import org.qi4j.api.association.NamedAssociation;
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.runtime.composite.ConstraintsCheck;
import org.qi4j.spi.entity.NamedAssociationState;
+import static org.qi4j.functional.Iterables.map;
+
public class NamedAssociationInstance<T>
extends AbstractAssociationInstance<T>
implements NamedAssociation<T>
@@ -39,7 +42,8 @@ public class NamedAssociationInstance<T>
public NamedAssociationInstance( AssociationInfo associationInfo,
Function2<EntityReference, Type, Object> associationFunction,
- NamedAssociationState namedAssociationState )
+ NamedAssociationState namedAssociationState
+ )
{
super( associationInfo, associationFunction );
this.namedAssociationState = namedAssociationState;
@@ -66,10 +70,11 @@ public class NamedAssociationInstance<T>
@Override
public boolean put( String name, T entity )
{
+ NullArgumentException.validateNotNull( "entity", entity );
checkImmutable();
checkType( entity );
- ( (ConstraintsCheck) associationInfo ).checkConstraints( entity );
- return namedAssociationState.put( name, getEntityReference( entity ) );
+ associationInfo.checkConstraints( entity );
+ return namedAssociationState.put( name, new EntityReference( ( (Identity) entity ).identity().get() ) );
}
@Override
@@ -102,9 +107,22 @@ public class NamedAssociationInstance<T>
return map;
}
- public Iterable<Map.Entry<String,EntityReference>> getEntityReferences()
+ @Override
+ public Iterable<EntityReference> references()
{
- return Iterables.map( new Function<String, Map.Entry<String,EntityReference>>()
+ return map( new Function<String, EntityReference>()
+ {
+ @Override
+ public EntityReference map( String name )
+ {
+ return namedAssociationState.get( name );
+ }
+ }, namedAssociationState );
+ }
+
+ 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 )
@@ -133,10 +151,10 @@ public class NamedAssociationInstance<T>
@Override
public boolean equals( Object o )
{
- if( o instanceof Map.Entry)
+ if( o instanceof Map.Entry )
{
Map.Entry other = (Map.Entry) o;
- return key.equals(other.getKey());
+ return key.equals( other.getKey() );
}
return false;
}
@@ -150,5 +168,4 @@ public class NamedAssociationInstance<T>
}
}, namedAssociationState );
}
-
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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 dd1a830..9f63d2c 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,6 +1,6 @@
/*
* Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2013-2015, Niclas Hedhman. All Rights Reserved.
* Copyright (c) 2013-2015, Paul Merlin. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,9 +16,11 @@
package org.qi4j.runtime.structure;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.association.AssociationStateHolder;
import org.qi4j.api.common.QualifiedName;
import org.qi4j.api.composite.Composite;
import org.qi4j.api.entity.EntityBuilder;
@@ -27,7 +29,9 @@ 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.Property;
import org.qi4j.api.property.PropertyDescriptor;
+import org.qi4j.api.property.StateHolder;
import org.qi4j.api.query.Query;
import org.qi4j.api.query.QueryBuilder;
import org.qi4j.api.query.QueryExecutionException;
@@ -42,18 +46,24 @@ 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.api.value.ValueBuilder;
+import org.qi4j.api.value.ValueComposite;
import org.qi4j.functional.Function;
import org.qi4j.functional.Iterables;
import org.qi4j.functional.Specification;
+import org.qi4j.runtime.association.AssociationInstance;
+import org.qi4j.runtime.association.ManyAssociationInstance;
+import org.qi4j.runtime.association.NamedAssociationInstance;
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.runtime.value.ValueInstance;
+import org.qi4j.spi.entity.EntityState;
import org.qi4j.spi.entity.EntityStatus;
+import org.qi4j.spi.entity.NamedAssociationState;
import org.qi4j.spi.entitystore.EntityStore;
import org.qi4j.spi.query.EntityFinder;
import org.qi4j.spi.query.EntityFinderException;
@@ -133,7 +143,7 @@ public class ModuleUnitOfWork
}
@Override
- @SuppressWarnings( {"raw", "unchecked"} )
+ @SuppressWarnings( { "raw", "unchecked" } )
public <T> Query<T> newQuery( QueryBuilder<T> queryBuilder )
{
QueryBuilderSPI queryBuilderSPI = (QueryBuilderSPI) queryBuilder;
@@ -235,7 +245,7 @@ public class ModuleUnitOfWork
EntityStore entityStore = model.module().entityStore();
- StateResolver stateResolver = new FunctionStateResolver(
+ FunctionStateResolver stateResolver = new FunctionStateResolver(
propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
);
@@ -314,6 +324,7 @@ public class ModuleUnitOfWork
}
}
+ @SuppressWarnings( "DuplicateThrows" )
@Override
public void complete()
throws UnitOfWorkCompletionException, ConcurrentEntityModificationException
@@ -332,7 +343,7 @@ public class ModuleUnitOfWork
{
discard();
}
-
+
@Override
public boolean isOpen()
{
@@ -403,6 +414,55 @@ public class ModuleUnitOfWork
uow.addEntity( instance );
}
+ @Override
+ public <T extends Identity> T toValue( Class<T> primaryType, T entityComposite )
+ {
+ Function<PropertyDescriptor, Object> propertyFunction = new ToValuePropertyMappingFunction( entityComposite );
+ Function<AssociationDescriptor, EntityReference> assocationFunction = new ToValueAssociationMappingFunction<>( entityComposite );
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToValueManyAssociationMappingFunction<>( entityComposite );
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToValueNameAssociationMappingFunction<>( entityComposite );
+
+ @SuppressWarnings( "unchecked" )
+ ValueBuilder<T> builder = module().newValueBuilderWithState(
+ primaryType, propertyFunction, assocationFunction, manyAssocFunction, namedAssocFunction );
+ return builder.newInstance();
+ }
+
+ @Override
+ public <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite )
+ {
+ Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, EntityReference> assocationFunction = new ToEntityAssociationMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToEntityManyAssociationMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToEntityNameAssociationMappingFunction<>( valueComposite );
+
+ String identity = valueComposite.identity().get();
+ try
+ {
+ T entity = get( primaryType, identity );
+ // If successful, then this entity is to by modified.
+ EntityInstance instance = EntityInstance.entityInstanceOf( (EntityComposite) entity );
+ EntityState state = instance.entityState();
+ FunctionStateResolver stateResolver = new FunctionStateResolver( propertyFunction,
+ assocationFunction,
+ manyAssocFunction,
+ namedAssocFunction );
+ EntityModel model = (EntityModel) EntityInstance.entityInstanceOf( (EntityComposite) entity ).descriptor();
+ stateResolver.populateState( model, state );
+ return entity;
+ }
+ catch( NoSuchEntityException e )
+ {
+ EntityBuilder<T> entityBuilder = newEntityBuilderWithState( primaryType,
+ identity,
+ propertyFunction,
+ assocationFunction,
+ manyAssocFunction,
+ namedAssocFunction );
+ return entityBuilder.newInstance();
+ }
+ }
+
private static class UoWQuerySource implements QuerySource
{
private final ModuleUnitOfWork moduleUnitOfWork;
@@ -533,4 +593,167 @@ public class ModuleUnitOfWork
return "UnitOfWork( " + moduleUnitOfWork.usecase().name() + " )";
}
}
+
+ private class ToValuePropertyMappingFunction
+ implements Function<PropertyDescriptor, Object>
+ {
+ private Object entity;
+
+ public ToValuePropertyMappingFunction( Object entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Object map( PropertyDescriptor propertyDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.propertyValueOf( propertyDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, EntityReference>
+ {
+ private final T entity;
+
+ public ToValueAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public EntityReference map( AssociationDescriptor associationDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.associationValueOf( associationDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueManyAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Iterable<EntityReference>>
+ {
+ private final T entity;
+
+ public ToValueManyAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueNameAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Map<String, EntityReference>>
+ {
+ private final T entity;
+
+ public ToValueNameAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ Map<String, EntityReference> result = new HashMap<>();
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ final NamedAssociationState state = entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
+ for( String name : state )
+ {
+ result.put( name, state.get( name ) );
+ }
+ return result;
+ }
+ }
+
+ private class ToEntityPropertyMappingFunction<T>
+ implements Function<PropertyDescriptor, Object>
+ {
+ private final T value;
+
+ public ToEntityPropertyMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Object map( PropertyDescriptor propertyDescriptor )
+ {
+ StateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ Property<Object> property = state.propertyFor( propertyDescriptor.accessor() );
+ return property.get();
+ }
+ }
+
+ private class ToEntityAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, EntityReference>
+ {
+
+ private final T value;
+
+ public ToEntityAssociationMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public EntityReference map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ AssociationInstance<T> association = (AssociationInstance<T>) state.associationFor( associationDescriptor.accessor() );
+ return association.getAssociationState().get();
+ }
+ }
+
+ private class ToEntityManyAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Iterable<EntityReference>>
+ {
+
+ private final T value;
+
+ public ToEntityManyAssociationMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ ManyAssociationInstance<T> association =
+ (ManyAssociationInstance<T>) state.manyAssociationFor( associationDescriptor.accessor() );
+ return association.getManyAssociationState();
+ }
+ }
+
+ private class ToEntityNameAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Map<String, EntityReference>>
+ {
+ private final T value;
+
+ public ToEntityNameAssociationMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ NamedAssociationInstance<T> association =
+ (NamedAssociationInstance<T>) state.namedAssociationFor( associationDescriptor.accessor() );
+ HashMap<String, EntityReference> result = new HashMap<>();
+ for( Map.Entry<String, EntityReference> entry : association.getEntityReferences() )
+ {
+ result.put( entry.getKey(), entry.getValue() );
+ }
+ return result;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/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 95c2e92..eae69b1 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
@@ -16,23 +16,16 @@
*/
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.composite.FunctionStateResolver;
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;
@@ -80,7 +73,7 @@ public final class EntityBuilderInstance<T>
ModuleUnitOfWork uow,
EntityStoreUnitOfWork store,
String identity,
- StateResolver stateResolver
+ FunctionStateResolver stateResolver
)
{
this.model = model;
@@ -92,7 +85,7 @@ public final class EntityBuilderInstance<T>
model.model().initState( model.module(), entityState );
if( stateResolver != null )
{
- (( FunctionStateResolver) stateResolver).populateState( model.model(), entityState );
+ stateResolver.populateState( model.model(), entityState );
}
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/568fa2ff/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
index 5d699d5..4f6b375 100644
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
+++ b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
@@ -33,6 +33,7 @@ public class ValueWithAssociationTest extends AbstractQi4jTest
{
module.entities( SimpleName.class );
module.entities( DualFaced.class );
+ module.values( SimpleName.class );
module.values( DualFaced.class );
module.services( MemoryEntityStoreService.class );
module.services( UuidIdentityGeneratorService.class );
@@ -61,7 +62,7 @@ public class ValueWithAssociationTest extends AbstractQi4jTest
proto.namedSimples().put( "niclas", simpleEntity );
DualFaced faced = builder2.newInstance();
identity2 = faced.identity().get();
- value = spi.toValue( DualFaced.class, faced );
+ value = uow.toValue( DualFaced.class, faced );
assertThat( value.identity().get(), equalTo( identity2 ) );
uow.complete();
}
@@ -83,7 +84,7 @@ public class ValueWithAssociationTest extends AbstractQi4jTest
.next()
.getValue(), equalTo( EntityReference.parseEntityReference( identity1 ) ) );
- DualFaced resurrected = spi.toEntity( DualFaced.class, value );
+ DualFaced resurrected = uow.toEntity( DualFaced.class, value );
assertThat( resurrected.simple(), equalTo( entity.simple() ) );
assertThat( resurrected.simples(), equalTo( entity.simples() ) );
assertThat( resurrected.namedSimples(), equalTo( entity.namedSimples() ) );
@@ -101,7 +102,7 @@ public class ValueWithAssociationTest extends AbstractQi4jTest
try (UnitOfWork uow = module.newUnitOfWork())
{
- spi.toEntity( DualFaced.class, value );
+ uow.toEntity( DualFaced.class, value );
uow.complete();
}
@@ -114,6 +115,52 @@ public class ValueWithAssociationTest extends AbstractQi4jTest
}
}
+ @Test
+ public void givenValueWithIdentityAlreadyInStoreWhenConvertingToEntityExpectExistingEntityToBeUpdated()
+ throws UnitOfWorkCompletionException
+ {
+ String identity1;
+ String identity2;
+ DualFaced value;
+ try (UnitOfWork uow = module.newUnitOfWork())
+ {
+ EntityBuilder<SimpleName> builder1 = uow.newEntityBuilder( SimpleName.class );
+ builder1.instance().name().set( "Niclas" );
+ SimpleName simpleEntity = builder1.newInstance();
+ identity1 = simpleEntity.identity().get();
+
+ EntityBuilder<DualFaced> builder2 = uow.newEntityBuilder( DualFaced.class );
+ DualFaced proto = builder2.instance();
+ proto.name().set( "Hedhman" );
+ proto.simple().set( simpleEntity );
+ proto.simples().add( simpleEntity );
+ proto.namedSimples().put( "niclas", simpleEntity );
+ DualFaced faced = builder2.newInstance();
+ identity2 = faced.identity().get();
+ uow.complete();
+ }
+ ValueBuilder<SimpleName> vb1 = module.newValueBuilder( SimpleName.class );
+ vb1.prototype().identity().set( identity1 );
+ vb1.prototype().name().set( "Paul" );
+ SimpleName simpleValue = vb1.newInstance();
+
+ ValueBuilder<DualFaced> vb2 = module.newValueBuilder( DualFaced.class );
+ vb2.prototype().identity().set(identity2);
+ vb2.prototype().name().set("Merlin");
+ vb2.prototype().simple().set( simpleValue );
+ vb2.prototype().simples().add( simpleValue );
+ vb2.prototype().namedSimples().put( "paul", simpleValue );
+ DualFaced dualValue = vb2.newInstance();
+
+ try (UnitOfWork uow = module.newUnitOfWork())
+ {
+ DualFaced dualEntity = uow.toEntity( DualFaced.class, dualValue );
+ assertThat( dualEntity.name().get(), equalTo( "Merlin"));
+ assertThat( dualEntity.simple().get().name().get(), equalTo( "Niclas"));
+ assertThat( dualEntity.simple().get().name().get(), equalTo( "Paul"));
+ }
+ }
+
public interface SimpleName extends Identity
{
Property<String> name();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
index 8b6246f..5345414 100644
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
+++ b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
@@ -48,6 +48,7 @@ import org.qi4j.api.value.ValueSerializationException;
import org.qi4j.api.value.ValueSerializer;
import org.qi4j.functional.Function;
import org.qi4j.functional.Function2;
+import org.qi4j.spi.Qi4jSPI;
import static org.qi4j.functional.Iterables.first;
@@ -55,29 +56,29 @@ import static org.qi4j.functional.Iterables.first;
* Adapter for pull-parsing capable ValueSerializers.
*
* <p>
- * Among Plain values (see {@link ValueSerializer}) some are considered primitives to underlying serialization
- * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
+ * Among Plain values (see {@link ValueSerializer}) some are considered primitives to underlying serialization
+ * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
* </p>
* <ul>
- * <li>String,</li>
- * <li>Character or char,</li>
- * <li>Boolean or boolean,</li>
- * <li>Integer or int,</li>
- * <li>Long or long,</li>
- * <li>Short or short,</li>
- * <li>Byte or byte,</li>
- * <li>Float or float,</li>
- * <li>Double or double.</li>
+ * <li>String,</li>
+ * <li>Character or char,</li>
+ * <li>Boolean or boolean,</li>
+ * <li>Integer or int,</li>
+ * <li>Long or long,</li>
+ * <li>Short or short,</li>
+ * <li>Byte or byte,</li>
+ * <li>Float or float,</li>
+ * <li>Double or double.</li>
* </ul>
* <p>
- * Some other Plain values are transformed before being handed to implementations:
+ * Some other Plain values are transformed before being handed to implementations:
* </p>
* <ul>
- * <li>BigInteger and BigDecimal depends on ValueSerializer.{@link Options};</li>
- * <li>Date as a ISO-8601 UTC String;</li>
- * <li>DateTime (JodaTime) as a ISO-8601 String with timezone offset or Z for UTC;</li>
- * <li>LocalDateTime (JodaTime) as a ISO-8601 String with no timezone offset;</li>
- * <li>LocalDate (JodaTime) as a ISO-8601 String with no time info;</li>
+ * <li>BigInteger and BigDecimal depends on ValueSerializer.{@link Options};</li>
+ * <li>Date as a ISO-8601 UTC String;</li>
+ * <li>DateTime (JodaTime) as a ISO-8601 String with timezone offset or Z for UTC;</li>
+ * <li>LocalDateTime (JodaTime) as a ISO-8601 String with no timezone offset;</li>
+ * <li>LocalDate (JodaTime) as a ISO-8601 String with no time info;</li>
* </ul>
*
* @param <OutputType> Implementor output type
@@ -112,8 +113,8 @@ public abstract class ValueSerializerAdapter<OutputType>
/**
* Register a Plain Value type serialization Function.
*
- * @param <T> Plain Value parametrized Type
- * @param type Plain Value Type
+ * @param <T> Plain Value parametrized Type
+ * @param type Plain Value Type
* @param serializer Serialization Function
*/
@SuppressWarnings( "unchecked" )
@@ -125,8 +126,8 @@ public abstract class ValueSerializerAdapter<OutputType>
/**
* Register a Complex Value type serialization Function.
*
- * @param <T> Complex Value parametrized Type
- * @param type Complex Value Type
+ * @param <T> Complex Value parametrized Type
+ * @param type Complex Value Type
* @param serializer Serialization Function
*/
@SuppressWarnings( "unchecked" )
@@ -364,48 +365,48 @@ public abstract class ValueSerializerAdapter<OutputType>
onValue( output, null );
}
else // Registered serializer
- if( serializers.get( object.getClass() ) != null )
- {
- onValue( output, serializers.get( object.getClass() ).map( options, object ) );
- }
- else if( complexSerializers.get( object.getClass() ) != null )
- {
- complexSerializers.get( object.getClass() ).serialize( options, object, output );
- }
- else // ValueComposite
- if( ValueComposite.class.isAssignableFrom( object.getClass() ) )
- {
- serializeValueComposite( options, object, output, rootPass );
- }
- else // EntityComposite
- if( EntityComposite.class.isAssignableFrom( object.getClass() ) )
- {
- serializeEntityComposite( object, output );
- }
- else // Collection - Iterable
- if( Iterable.class.isAssignableFrom( object.getClass() ) )
- {
- serializeIterable( options, object, output );
- }
- else // Array - QUID Remove this and use java serialization for arrays?
- if( object.getClass().isArray() )
- {
- serializeBase64Serializable( object, output );
- }
- else // Map
- if( Map.class.isAssignableFrom( object.getClass() ) )
- {
- serializeMap( options, object, output );
- }
- else // Enum
- if( object.getClass().isEnum() )
- {
- onValue( output, object.toString() );
- }
- else // Fallback to Base64 encoded Java Serialization
- {
- serializeBase64Serializable( object, output );
- }
+ if( serializers.get( object.getClass() ) != null )
+ {
+ onValue( output, serializers.get( object.getClass() ).map( options, object ) );
+ }
+ else if( complexSerializers.get( object.getClass() ) != null )
+ {
+ complexSerializers.get( object.getClass() ).serialize( options, object, output );
+ }
+ else // ValueComposite
+ if( ValueComposite.class.isAssignableFrom( object.getClass() ) )
+ {
+ serializeValueComposite( options, object, output, rootPass );
+ }
+ else // EntityComposite
+ if( EntityComposite.class.isAssignableFrom( object.getClass() ) )
+ {
+ serializeEntityComposite( object, output );
+ }
+ else // Collection - Iterable
+ if( Iterable.class.isAssignableFrom( object.getClass() ) )
+ {
+ serializeIterable( options, object, output );
+ }
+ else // Array - QUID Remove this and use java serialization for arrays?
+ if( object.getClass().isArray() )
+ {
+ serializeBase64Serializable( object, output );
+ }
+ else // Map
+ if( Map.class.isAssignableFrom( object.getClass() ) )
+ {
+ serializeMap( options, object, output );
+ }
+ else // Enum
+ if( object.getClass().isEnum() )
+ {
+ onValue( output, object.toString() );
+ }
+ else // Fallback to Base64 encoded Java Serialization
+ {
+ serializeBase64Serializable( object, output );
+ }
}
private void serializeValueComposite( Options options, Object object, OutputType output, boolean rootPass )
@@ -548,7 +549,7 @@ public abstract class ValueSerializerAdapter<OutputType>
throws Exception
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
- try( ObjectOutputStream out = new ObjectOutputStream( bout ) )
+ try (ObjectOutputStream out = new ObjectOutputStream( bout ))
{
out.writeUnshared( object );
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
----------------------------------------------------------------------
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
index 5c0daf0..b927cc3 100644
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
+++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
@@ -18,6 +18,7 @@
package org.qi4j.lib.swing.binding.internal;
import org.qi4j.api.association.Association;
+import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
@@ -82,4 +83,10 @@ public final class BoundAssociation<T> extends AbstractBinding<T>
{
//To change body of implemented methods use File | Settings | File Templates.
}
+
+ @Override
+ public EntityReference reference()
+ {
+ return actual.reference();
+ }
}
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
----------------------------------------------------------------------
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
index a7dcb0f..892a3d5 100644
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
+++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
@@ -5,6 +5,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.qi4j.api.association.ManyAssociation;
+import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
@@ -59,6 +60,12 @@ public class BoundManyAssociation<T> extends AbstractBinding<T>
}
@Override
+ public Iterable<EntityReference> references()
+ {
+ return actualAssociations.references();
+ }
+
+ @Override
public int count()
{
return actualAssociations.count();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java
----------------------------------------------------------------------
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java
index 8e9f187..7becd24 100644
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java
+++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java
@@ -4,6 +4,7 @@ import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import org.qi4j.api.association.NamedAssociation;
+import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
@@ -75,6 +76,12 @@ public class BoundNamedAssociation<T>
}
@Override
+ public Iterable<EntityReference> references()
+ {
+ return actualAssociations.references();
+ }
+
+ @Override
public Iterator<String> iterator()
{
return actualAssociations.iterator();
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/568fa2ff/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
----------------------------------------------------------------------
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
index 30a88d6..7d22b44 100644
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
+++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
@@ -17,19 +17,17 @@
*/
package org.qi4j.lib.swing.binding.internal;
+import java.awt.event.FocusListener;
+import java.lang.reflect.Method;
+import javax.swing.JComponent;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.property.GenericPropertyInfo;
import org.qi4j.api.property.Property;
import org.qi4j.lib.swing.binding.Binding;
import org.qi4j.lib.swing.binding.SwingAdapter;
-import javax.swing.*;
-import java.awt.event.FocusListener;
-import java.lang.reflect.Method;
-
public final class BoundProperty<T> extends AbstractBinding<T>
implements Property<T>, Binding
{
@@ -44,7 +42,8 @@ public final class BoundProperty<T> extends AbstractBinding<T>
* @throws IllegalArgumentException Thrown if the specified {@code aMethod} is {@code null}.
*/
public BoundProperty( @Uses Method propertyMethod, @Structure ObjectFactory objectBuilderFactory,
- @Service Iterable<SwingAdapter> allAdapters )
+ @Service Iterable<SwingAdapter> allAdapters
+ )
throws IllegalArgumentException
{
super( propertyMethod, objectBuilderFactory, allAdapters );