Repository: zest-java Updated Branches: refs/heads/develop 78e20260e -> bbeb6d514
ZEST-173 - Adding toValueList, toValueSet and toValueMap into UnitOfWork, for greater convenience. Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/bbeb6d51 Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/bbeb6d51 Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/bbeb6d51 Branch: refs/heads/develop Commit: bbeb6d51473790a28d0c99b804114a0ed78d3ea4 Parents: 78e2026 Author: Niclas Hedhman <[email protected]> Authored: Sat Sep 3 09:46:00 2016 +0800 Committer: Niclas Hedhman <[email protected]> Committed: Sat Sep 3 09:46:00 2016 +0800 ---------------------------------------------------------------------- .../apache/zest/api/unitofwork/UnitOfWork.java | 89 ++++++++++++++++++-- .../runtime/unitofwork/ModuleUnitOfWork.java | 48 +++++++++++ 2 files changed, 128 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/bbeb6d51/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java index 884d000..15b3b84 100644 --- a/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java +++ b/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java @@ -19,9 +19,13 @@ */ package org.apache.zest.api.unitofwork; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import org.apache.zest.api.association.AssociationDescriptor; +import org.apache.zest.api.association.ManyAssociation; +import org.apache.zest.api.association.NamedAssociation; import org.apache.zest.api.common.Optional; import org.apache.zest.api.composite.AmbiguousTypeException; import org.apache.zest.api.entity.EntityBuilder; @@ -132,8 +136,8 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new Entity * * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered - * @throws AmbiguousTypeException If several mixins implement the given type - * @throws LifecycleException if the entity cannot be created + * @throws AmbiguousTypeException If several mixins implement the given type + * @throws LifecycleException if the entity cannot be created */ <T> T newEntity( Class<T> type ) throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException; @@ -150,8 +154,8 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new Entity * * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered - * @throws AmbiguousTypeException If several mixins implement the given type - * @throws LifecycleException if the entity cannot be created + * @throws AmbiguousTypeException If several mixins implement the given type + * @throws LifecycleException if the entity cannot be created */ <T> T newEntity( Class<T> type, @Optional String identity ) throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException; @@ -167,7 +171,7 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new EntityBuilder * * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered - * @throws AmbiguousTypeException If several mixins implement the given type + * @throws AmbiguousTypeException If several mixins implement the given type */ <T> EntityBuilder<T> newEntityBuilder( Class<T> type ) throws NoSuchEntityTypeException, AmbiguousTypeException; @@ -184,7 +188,7 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new EntityBuilder * * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered - * @throws AmbiguousTypeException If several mixins implement the given type + * @throws AmbiguousTypeException If several mixins implement the given type */ <T> EntityBuilder<T> newEntityBuilder( Class<T> type, @Optional String identity ) throws NoSuchEntityTypeException, AmbiguousTypeException; @@ -206,7 +210,7 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new EntityBuilder starting with the given state * * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered - * @throws AmbiguousTypeException If several mixins implement the given type + * @throws AmbiguousTypeException If several mixins implement the given type */ <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, Function<PropertyDescriptor, Object> propertyFunction, @@ -234,7 +238,7 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return a new EntityBuilder starting with the given state * * @throws NoSuchEntityTypeException If no mixins implements the given type - * @throws AmbiguousTypeException If several mixins implement the given type + * @throws AmbiguousTypeException If several mixins implement the given type */ <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, @Optional String identity, Function<PropertyDescriptor, Object> propertyFunction, @@ -254,7 +258,7 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable * @return the entity * * @throws NoSuchEntityTypeException if no entity type could be found - * @throws NoSuchEntityException if the entity could not be found + * @throws NoSuchEntityException if the entity could not be found */ <T> T get( Class<T> type, String identity ) throws NoSuchEntityTypeException, NoSuchEntityException; @@ -396,6 +400,73 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable <T extends Identity> T toValue( Class<T> primaryType, T entityComposite ); /** + * Converts all the entities referenced in the ManyAssociation into a List of values of the same type. + * + * <p> + * All the referenced entities inside the association will be fetched from the underlying entity store, + * which is potentially very expensive operation. + * </p> + * + * <p> + * For this to work, the type <T> must be registered at bootstrap as both an Entity and a Value, and + * as seen in the method signature, also be sub-type of {@link Identity}. + * </p> + + * + * @param association The association of entities to be converted into values. + * @param <T> The primary type of the association. + * + * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations. + * + * @see #toValue(Class, Identity) + */ + <T extends Identity> List<T> toValueList( ManyAssociation<T> association ); + + /** + * Converts all the entities referenced in the ManyAssociation into a Set of values of the same type. + * + * <p> + * All the referenced entities inside the association will be fetched from the underlying entity store, + * which is potentially very expensive operation. However, any duplicate EntityReferences in the association + * will be dropped before the fetch occurs. + * </p> + * + * <p> + * For this to work, the type <T> must be registered at bootstrap as both an Entity and a Value, and + * as seen in the method signature, also be sub-type of {@link Identity}. + * </p> + * + * @param association The association of entities to be converted into values. + * @param <T> The primary type of the association. + * + * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations. + * + * @see #toValue(Class, Identity) + */ + <T extends Identity> Set<T> toValueSet( ManyAssociation<T> association ); + + /** + * Converts the {@link NamedAssociation} into a Map with a String key and a ValueComposite as the value. + * + * <p> + * A {@link NamedAssociation} is effectively a Map with a String key and an EntityReference as the value. The + * EntityReference is fetched from the entity store and converted into a value of the same type. + * </p> + * <p> + * For this to work, the type <T> must be registered at bootstrap as both an Entity and a Value, and + * as seen in the method signature, also be sub-type of {@link Identity}. + * </p> + * + * @param association The association of entities to be converted into values. + * @param <T> The primary type of the association. + * + * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations. + * + * @see #toValue(Class, Identity) + */ + <T extends Identity> Map<String, T> toValueMap( NamedAssociation<T> association ); + + /** * Converts the provided Value to an Entity of the same type. * This is a convenience method to convert a ValueComposite to an EntityComposite. * <p> http://git-wip-us.apache.org/repos/asf/zest-java/blob/bbeb6d51/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java index a67cd50..d9a2d8a 100755 --- a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java +++ b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java @@ -23,11 +23,17 @@ package org.apache.zest.runtime.unitofwork; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; +import org.apache.zest.api.ZestAPI; import org.apache.zest.api.association.AssociationDescriptor; import org.apache.zest.api.association.AssociationStateHolder; +import org.apache.zest.api.association.ManyAssociation; +import org.apache.zest.api.association.NamedAssociation; import org.apache.zest.api.common.QualifiedName; import org.apache.zest.api.composite.Composite; import org.apache.zest.api.entity.EntityBuilder; @@ -105,6 +111,9 @@ public class ModuleUnitOfWork private UnitOfWorkInstance uow; @Structure + private ZestAPI api; + + @Structure private ModuleDescriptor module; @Service @@ -444,6 +453,45 @@ public class ModuleUnitOfWork } @Override + public <T extends Identity> Map<String, T> toValueMap( NamedAssociation<T> association ) + { + @SuppressWarnings( "unchecked" ) + Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type(); + + return association + .toMap() + .entrySet() + .stream() + .collect( Collectors.toMap( Map.Entry::getKey, entry -> toValue( primaryType, entry.getValue()) ) ); + } + + @Override + public <T extends Identity> List<T> toValueList( ManyAssociation<T> association ) + { + @SuppressWarnings( "unchecked" ) + Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type(); + + return association + .toList() + .stream() + .map( entity -> toValue( primaryType, entity ) ) + .collect( Collectors.toList() ); + } + + @Override + public <T extends Identity> Set<T> toValueSet( ManyAssociation<T> association ) + { + @SuppressWarnings( "unchecked" ) + Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type(); + + return association + .toSet() + .stream() + .map( entity -> toValue( primaryType, entity ) ) + .collect( Collectors.toSet() ); + } + + @Override public <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite ) { Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<>( valueComposite );
