org.qi4j.api.unitofwork

## Interface UnitOfWork

- All Superinterfaces:
    AutoCloseable, MetaInfoHolder

      public interface UnitOfWork
      extends MetaInfoHolder, AutoCloseable

  All operations on entities goes through an UnitOfWork.

  A UnitOfWork allows you to access Entities and work with them. All modifications to Entities are recorded by the UnitOfWork, and at the end they may be sent to the underlying EntityStore by calling complete(). If the UoW was read-only you may instead simply discard() it.

  A UoW differs from a traditional Transaction in the sense that it is not tied at all to the underlying storage resource. Because of this there is no timeout on a UoW. It can be very short or very long. Another difference is that if a call to complete() fails, and the cause is validation errors in the Entities of the UoW, then these can be corrected and the UoW retried. By contrast, when a Transaction commit fails, then the whole transaction has to be done from the beginning again.

  A UoW can be associated with a Usecase. A Usecase describes the metainformation about the process to be performed by the UoW.

  If a code block that uses a UoW throws an exception you need to ensure that this is handled properly, and that the UoW is closed before returning. Because discard() is a no-op if the UoW is closed, we therefore recommend the following template to be used:

           UnitOfWork uow = module.newUnitOfWork();
           try
           {
               ...
               uow.complete();
           }
           finally
           {
               uow.discard();
           }

  This ensures that in the happy case the UoW is completed, and if any exception is thrown the UoW is discarded. After the UoW has completed the discard() method doesn't do anything, and so has no effect. You can choose to either add catch blocks for any exceptions, including exceptions from complete(), or skip them.

  Since 2.1 you can leverage Java 7 Automatic Resource Management (ie. Try With Resources) and use the following template instead:

           try( UnitOfWork uow = module.newUnitOfWork() )
           {
               ...
               uow.complete();
           }

  It has the very same effect than the template above but is shorter.

- - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `addUnitOfWorkCallback(UnitOfWorkCallback callback)` Register a callback.
    `void` | `close()` Discard this UnitOfWork.
    `void` | `complete()` Complete this UnitOfWork.
    `long` | `currentTime()`
    `void` | `discard()` Discard this UnitOfWork.
    `<T> T` | `get(Class<T> type, String identity)` Find an Entity of the given mixin type with the give identity.
    `<T> T` | `get(T entity)` If you have a reference to an Entity from another UnitOfWork and want to create a reference to it in this UnitOfWork, then call this method.
    `boolean` | `isOpen()` Check if the UnitOfWork is open.
    `boolean` | `isPaused()` Check if the UnitOfWork is paused.
    `<T> T` | `newEntity(Class<T> type)` Create a new Entity which implements the given mixin type.
    `<T> T` | `newEntity(Class<T> type, String identity)` Create a new Entity which implements the given mixin type.
    `<T> EntityBuilder<T>` | `newEntityBuilder(Class<T> type)` Create a new EntityBuilder for an EntityComposite which implements the given mixin type.
    `<T> EntityBuilder<T>` | `newEntityBuilder(Class<T> type, String identity)` Create a new EntityBuilder for an EntityComposite which implements the given mixin 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)` Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given state.
    `<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)` Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given state.
    `<T> Query<T>` | `newQuery(QueryBuilder<T> queryBuilder)`
    `void` | `pause()` Pauses this UnitOfWork.
    `void` | `remove(Object entity)` Remove the given Entity.
    `void` | `removeUnitOfWorkCallback(UnitOfWorkCallback callback)` Unregister a callback.
    `void` | `resume()` Resumes this UnitOfWork to again become the current UnitOfWork.
    `void` | `setMetaInfo(Object metaInfo)`
    `<T extends Identity> T` | `toEntity(Class<T> primaryType, T valueComposite)` Converts the provided Value to an Entity of the same type.
    `<T extends Identity> T` | `toValue(Class<T> primaryType, T entityComposite)` Converts the provided Entity to a Value of the same type.
    `UnitOfWorkFactory` | `unitOfWorkFactory()` Get the UnitOfWorkFactory that this UnitOfWork was created from.
    `Usecase` | `usecase()` Get the Usecase for this UnitOfWork

    - ### Methods inherited from interface org.qi4j.api.structure.MetaInfoHolder

      `metaInfo`

- - ### Method Detail

    - #### unitOfWorkFactory

          UnitOfWorkFactory unitOfWorkFactory()

      Get the UnitOfWorkFactory that this UnitOfWork was created from.
      Returns:
        The UnitOfWorkFactory instance that was used to create this UnitOfWork.

    - #### currentTime

          long currentTime()

    - #### usecase

          Usecase usecase()

      Get the Usecase for this UnitOfWork
      Returns:
        the Usecase

    - #### setMetaInfo

          void setMetaInfo(Object metaInfo)

    - #### newQuery

          <T> Query<T> newQuery(QueryBuilder<T> queryBuilder)

    - #### newEntity

          <T> T newEntity(Class<T> type)
                      throws EntityTypeNotFoundException,
                             AmbiguousTypeException,
                             LifecycleException

      Create a new Entity which implements the given mixin type.

      An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered. If several EntityComposites implement the type then an AmbiguousTypeException will be thrown.

      The identity of the Entity will be generated by the IdentityGenerator of the Module of the EntityComposite.

      Parameters:
        `type` - the mixin type that the EntityComposite must implement
      Returns:
        a new Entity
      Throws:
        `EntityTypeNotFoundException` - if no EntityComposite type of the given mixin type has been registered
        `AmbiguousTypeException` - If several mixins implement the given type
        `LifecycleException` - if the entity cannot be created

    - #### newEntity

          <T> T newEntity(Class<T> type,
                        String identity)
                      throws EntityTypeNotFoundException,
                             AmbiguousTypeException,
                             LifecycleException

      Create a new Entity which implements the given mixin type. An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered. If several EntityComposites implement the type then an AmbiguousTypeException will be thrown.
      Parameters:
        `type` - the mixin type that the EntityComposite must implement
        `identity` - the identity of the new Entity
      Returns:
        a new Entity
      Throws:
        `EntityTypeNotFoundException` - if no EntityComposite type of the given mixin type has been registered
        `AmbiguousTypeException` - If several mixins implement the given type
        `LifecycleException` - if the entity cannot be created

    - #### newEntityBuilder

          <T> EntityBuilder<T> newEntityBuilder(Class<T> type)
                                            throws EntityTypeNotFoundException,
                                                   AmbiguousTypeException

      Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered. If several EntityComposites implement the type then an AmbiguousTypeException will be thrown.
      Parameters:
        `type` - the mixin type that the EntityComposite must implement
      Returns:
        a new EntityBuilder
      Throws:
        `EntityTypeNotFoundException` - if no EntityComposite type of the given mixin type has been registered
        `AmbiguousTypeException` - If several mixins implement the given type

    - #### newEntityBuilder

          <T> EntityBuilder<T> newEntityBuilder(Class<T> type,
                                              String identity)
                                            throws EntityTypeNotFoundException,
                                                   AmbiguousTypeException

      Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered. If several mixins implement the type then an AmbiguousTypeException will be thrown.
      Parameters:
        `type` - the mixin type that the EntityComposite must implement
        `identity` - the identity of the new Entity
      Returns:
        a new EntityBuilder
      Throws:
        `EntityTypeNotFoundException` - if no EntityComposite type of the given mixin type has been registered
        `AmbiguousTypeException` - If several mixins implement the given type

    - #### newEntityBuilderWithState

          <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.

      An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered.

      Type Parameters:
        `T` - Entity type
      Parameters:
        `type` - Entity type
        `propertyFunction` - a function providing the state of properties
        `associationFunction` - a function providing the state of associations
        `manyAssociationFunction` - a function providing the state of many associations
        `namedAssociationFunction` - a function providing the state of named associations
      Returns:
        a new EntityBuilder starting with the given state
      Throws:
        `EntityTypeNotFoundException` - if no EntityComposite type of the given mixin type has been registered
        `AmbiguousTypeException` - If several mixins implement the given type

    - #### newEntityBuilderWithState

          <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

      Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given state.

      An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and Layers will be considered.

      Type Parameters:
        `T` - Entity type
      Parameters:
        `type` - Entity type
        `identity` - the identity of the new Entity
        `propertyFunction` - a function providing the state of properties
        `associationFunction` - a function providing the state of associations
        `manyAssociationFunction` - a function providing the state of many associations
        `namedAssociationFunction` - a function providing the state of named associations
      Returns:
        a new EntityBuilder starting with the given state
      Throws:
        `EntityTypeNotFoundException` - If no mixins implements the given type
        `AmbiguousTypeException` - If several mixins implement the given type

    - #### get

          <T> T get(Class<T> type,
                  String identity)
                throws EntityTypeNotFoundException,
                       NoSuchEntityException

      Find an Entity of the given mixin type with the give identity. This method verifies that it exists by asking the underlying EntityStore.
      Parameters:
        `type` - of the entity
        `identity` - of the entity
      Returns:
        the entity
      Throws:
        `EntityTypeNotFoundException` - if no entity type could be found
        `NoSuchEntityException` - if the entity could not be found

    - #### get

          <T> T get(T entity)
                throws EntityTypeNotFoundException

      If you have a reference to an Entity from another UnitOfWork and want to create a reference to it in this UnitOfWork, then call this method.
      Parameters:
        `entity` - the Entity to be dereferenced
      Returns:
        an Entity from this UnitOfWork
      Throws:
        `EntityTypeNotFoundException` - if no entity type could be found

    - #### remove

          void remove(Object entity)
                      throws LifecycleException

      Remove the given Entity.
      Parameters:
        `entity` - the Entity to be removed.
      Throws:
        `LifecycleException` - if the entity could not be removed

    - #### complete

          void complete()
                        throws UnitOfWorkCompletionException,
                               ConcurrentEntityModificationException

      Complete this UnitOfWork. This will send all the changes down to the underlying EntityStore's.
      Throws:
        `UnitOfWorkCompletionException` - if the UnitOfWork could not be completed
        `ConcurrentEntityModificationException` - if entities have been modified by others

    - #### discard

          void discard()

      Discard this UnitOfWork. Use this if a failure occurs that you cannot handle, or if the usecase was of a read-only character. This is a no-op of the UnitOfWork is already closed.

    - #### close

          void close()

      Discard this UnitOfWork. Use this if a failure occurs that you cannot handle, or if the usecase was of a read-only character. This is a no-op of the UnitOfWork is already closed. This simply call the `discard()` method and is an implementation of the `AutoCloseable` interface providing Try With Resources support for UnitOfWork.
      Specified by:
        `close` in interface `AutoCloseable`

    - #### isOpen

          boolean isOpen()

      Check if the UnitOfWork is open. It is closed after either complete() or discard() methods have been called successfully.
      Returns:
        true if the UnitOfWork is open.

    - #### isPaused

          boolean isPaused()

      Check if the UnitOfWork is paused. It is not paused after it has been create through the UnitOfWorkFactory, and it can be paused by calling `pause()` and then resumed by calling `resume()`.
      Returns:
        true if this UnitOfWork has been paused.

    - #### pause

          void pause()

      Pauses this UnitOfWork.

      Calling this method will cause the underlying UnitOfWork to become the current UnitOfWork until the the resume() method is called. It is the client's responsibility not to drop the reference to this UnitOfWork while being paused.

    - #### resume

          void resume()

      Resumes this UnitOfWork to again become the current UnitOfWork.

    - #### addUnitOfWorkCallback

          void addUnitOfWorkCallback(UnitOfWorkCallback callback)

      Register a callback. Callbacks are invoked when the UnitOfWork is completed or discarded.
      Parameters:
        `callback` - a callback to be registered with this UnitOfWork

    - #### removeUnitOfWorkCallback

          void removeUnitOfWorkCallback(UnitOfWorkCallback callback)

      Unregister a callback. Callbacks are invoked when the UnitOfWork is completed or discarded.
      Parameters:
        `callback` - a callback to be unregistered with this UnitOfWork

    - #### toValue

          <T extends Identity> T toValue(Class<T> primaryType,
                                       T entityComposite)

      Converts the provided Entity to a Value of the same type. This is a convenience method to convert an EntityComposite to a ValueComposite.

      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.

      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;

               public interface Person extends Identity { ... };
               public class MyAssembler
               {
                   public void assemble( ModuleAssembly module )
                   {
                       module.values( Person.class );
                       module.entities( Person.class );
                   }
               }

      Parameters:
        `primaryType` - The shared type for which the properties and associations will be converted. Properties outside this type will be ignored.
        `entityComposite` - The entity to be convered.

    - #### toEntity

          <T extends Identity> T toEntity(Class<T> primaryType,
                                        T valueComposite)

      Converts the provided Value to an Entity of the same type. This is a convenience method to convert a ValueComposite to an EntityComposite.

      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.

      This method MUST be called within a UnitOfWork.

      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.

      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;

               public interface Person extends Identity { ... };
               public class MyAssembler
               {
                   public void assemble( ModuleAssembly module )
                   {
                       module.values( Person.class );
                       module.entities( Person.class );
                   }
               }

      Parameters:
        `primaryType` - The shared type for which the properties and associations will be converted. Properties outside this type will be ignored.
        `valueComposite` - The Value to be convered into an Entity.