com.h3c.util.dao

## Class AbstractBidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>

- java.lang.Object
- - com.h3c.util.dao.AbstractBaseDao<I,P,T,F,S>
  - - com.h3c.util.dao.AbstractBidirectionalDependentDao<I,P,T,Q,F,S,E,W,R>

- Type Parameters:
    `I` - type of the persistent object and transport object id. This type should be immutable. It is critical this type implements equals() and hashCode() correctly.
    `P` - type of the persistent object.
    `T` - type of the transport object with a reference to the owner.
    `Q` - type of the transport object with a reference to the owner's id.
    `F` - type of the associated filter.
    `S` - type of the associated sort specification type.
    `E` - type of the owner persistent object and owner transport object id. This type should be immutable. It is critical this type implements equals() and hashCode() correctly.
    `W` - type of the owner persistent object.
    `R` - type of the owner transport object.
  All Implemented Interfaces:
    Converter<P,Q>, BaseDao<I,P,T,F,S>, BidirectionalDependentDao<I,P,T,Q,F,S,E,W,R>

      public abstract class AbstractBidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
      extends AbstractBaseDao<I,P,T,F,S>
      implements BidirectionalDependentDao<I,P,T,Q,F,S,E,W,R>

  JPA Data Access Object for a storable that is the dependent object in a one-to-many bidirectional relation.

  One to Many Relations with Dependent Entities

  Note that any other type of relation (One to many or many to many with independent entities) could be implemented using `Dao`s.

  - Let `Item` be a model object.
  - Let `Image` be a model object.
  - One item may have several images (One-to-Many relation). So `Item` has a collection of `Image`. Dependent classes are modeled as value type (Collection of value type).
  - Let `ItemEntity` be a storable.
  - Let `ItemImageEntity` be the dependent storable. The dependent object has no life outside of the collection; it's dependent on an `Item` entity.
  - A regular `Dao` may be used to access `ItemEntity`.
  - If the association from `Item` to `Image` is unidirectional then the same regular `Dao` that access `ItemEntity` could also access `ItemImageEntity`. No need of a separated DAO for `ItemImageEntity` since JPA will propagate updates when the collection of dependent entities is modified. The `Dao` will just need to create an `ItemImageEntity` from `Image` and vice-verza. With an unidirectional relation you can navigate to the images by accessing the collection through an item instance. This is the only way you can get the images objects; no other entity holds a reference to them (dependent entity value type).
  - If the association from `Item` to `Image` is bidirectional a `BidirectionalDependentDao` should be used to access `ItemImageEntity`. In a bidirectional relation it is possible to navigate from an `Image` back to an `Item`. Note this type of navigation does not make much sense and should be avoided if possible. The JPA provider (Like Hibernate) can fill in this property for you if you annotate your entity accordingly. True bidirectional navigation is impossible with JPA, however. You can't retrieve an `ItemImageEntity` independently and then navigate back to its parent `ItemEntity`. This is an important issue: You can load `ImageEntity` instances by querying for them. But these images won't have a reference to their owner (the property is null). For this reason this implementation introduces `Dependable` to keep a reference of the owner's id so it can be manually retrieved (Since JPA provider won't fill the owner if the dependent object is queried by itself).

  Annotations Examples:

  One to many association in the independent object

        @OneToMany(cascade=CascadeType.ALL, mappedBy="owner", orphanRemoval=true)
        private Collection<ItemImageEntity> images = new ArrayList<ItemImageEntity>();

  One to many association in the dependent object

       @ManyToOne
       @JoinColumn(name = "owner_fk")
       private ItemEntity owner;

       // Needed to implement true bidirectional navigation. See Dependable note above.
       @Column(name = "owner_id")
       private Long ownerId;

- - ### Constructor Summary

    Constructors
    Modifier | Constructor and Description
    --- | ---
    `protected` | `AbstractBidirectionalDependentDao(Class<P> entityClass)` Construct DAO and initialize query predicate generator.
    `protected` | `AbstractBidirectionalDependentDao(Class<P> entityClass, UpdateStrategy<P,T> updateStrategyT, UpdateStrategy<P,Q> updateStrategyQ)` Construct DAO and initialize query predicate generator.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected abstract void` | `conformQ(P target, Q source)` Synchronizes the transport object and the persistent object state.
    `protected abstract void` | `conformT(P target, T source)` Synchronizes the transport object and the persistent object state.
    `Q` | `convert(P source)` Converts an instance of type S to an instance of type T
    `T` | `convert(P storable, BaseDao<E,W,R,?,?> ownerDao, Converter<W,R> ownerConverter, DataStoreContext context)` Converts the storable object to a transportable.
    `T` | `convert(P source, R owner)` Converts the storable object to a transportable.
    `P` | `create(T transportable, W owner, DataStoreContext context)` Creates a new persistent object with the data from the given transport object.
    `protected abstract P` | `createStorableInstance(T transportable, W owner)` Creates the instance of the persistent object (Entity).
    `protected abstract Q` | `doConvert(P source)` Converts the persistent object to a transport object.
    `protected abstract T` | `doConvert(P source, R owner)` Converts the persistent object to a transport object.
    `protected abstract T` | `findDependent(I dependentId, R owner)` Finds a dependent with the given id.
    `void` | `update(P target, T source, DataStoreContext context)` Updates the persistent object related to the given transport object.
    `P` | `update(Q transportable, DataStoreContext context)` Updates the persistent object related to the given transport object.

    - ### Methods inherited from class com.h3c.util.dao.AbstractBaseDao

      `count, find, find, findAll, get, getQueryPredicate, getQueryPredicateGenerator, getSingularAttribute, updateDependents`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

    - ### Methods inherited from interface com.h3c.util.dao.BaseDao

      `count, find, find, findAll, get`

- - ### Constructor Detail

    - #### AbstractBidirectionalDependentDao

          protected AbstractBidirectionalDependentDao(Class<P> entityClass)

      Construct DAO and initialize query predicate generator.
      Parameters:
        `entityClass` - persistent object class.

    - #### AbstractBidirectionalDependentDao

          protected AbstractBidirectionalDependentDao(Class<P> entityClass,
                                           UpdateStrategy<P,T> updateStrategyT,
                                           UpdateStrategy<P,Q> updateStrategyQ)

      Construct DAO and initialize query predicate generator.
      Parameters:
        `entityClass` - persistent object class.
        `updateStrategyT` - update strategy for the transport object with a reference to the owner.
        `updateStrategyQ` - update strategy for the transport object with a reference to the owner's id.

  - ### Method Detail

    - #### create

          public P create(T transportable,
                 W owner,
                 DataStoreContext context)

      Description copied from interface: `BidirectionalDependentDao`
      Creates a new persistent object with the data from the given transport object.
      Specified by:
        `create` in interface `BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>`
      Parameters:
        `transportable` - transport object to get the data from.
        `owner` - owner
        `context` - data store context
      Returns:
        the new created persistent object

    - #### update

          public void update(P target,
                    T source,
                    DataStoreContext context)

      Description copied from interface: `BidirectionalDependentDao`
      Updates the persistent object related to the given transport object. This method is meant to be called by the owner. No need to re-load the dependent storable since the owner already loads it.
      Specified by:
        `update` in interface `BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>`
      Parameters:
        `target` - object to update
        `source` - object to take the data from
        `context` - data store context

    - #### update

          public P update(Q transportable,
                 DataStoreContext context)

      Description copied from interface: `BidirectionalDependentDao`
      Updates the persistent object related to the given transport object.
      Specified by:
        `update` in interface `BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>`
      Parameters:
        `transportable` - transport object to get the data from
        `context` - data store context
      Returns:
        the updated persistent object

    - #### convert

          public Q convert(P source)

      Description copied from interface: `Converter`
      Converts an instance of type S to an instance of type T
      Specified by:
        `convert` in interface `Converter<P extends Storable<I> & Dependable<E>,Q extends Transportable<? super Q,I> & Dependent<E>>`
      Parameters:
        `source` - the source object to be converted
      Returns:
        an instance of the target type T converted from the source

    - #### convert

          public T convert(P source,
                  R owner)

      Description copied from interface: `BidirectionalDependentDao`
      Converts the storable object to a transportable.
      Specified by:
        `convert` in interface `BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>`
      Parameters:
        `source` - storable object to convert
        `owner` - the storable object's owner
      Returns:
        the transport object representing the state of the given storable

    - #### convert

          public T convert(P storable,
                  BaseDao<E,W,R,?,?> ownerDao,
                  Converter<W,R> ownerConverter,
                  DataStoreContext context)

      Description copied from interface: `BidirectionalDependentDao`
      Converts the storable object to a transportable. This call will load the owner from the database.

      Example when owner is a `Dao`

           Dao<E, W, R, ?, ?> ownerDao = ...;
           BidirectionalDependentDao<I, P, T, ?, ?, ?, E, W, R> dependentDao = ...;
           DataStoreContext context = ...;
           P storable = ...;
           T transportable = dependentDao.convert(storable, ownerDao, ownerDao, context);

      Example when owner is a `BidirectionalDependentDao`

           final Dao<H, M, N, ?, ?> rootOwnerDao = ...;
           final BidirectionalDependentDao<E, W, R, ?, ?, ?, H, M, N> dependentOwnerDao = ...;
           BidirectionalDependentDao<I, P, T, ?, ?, ?, E, W, R> dependentDao = ...;
           final DataStoreContext context = ...;

           Converter<W, R> dependentOwnerConverter = new Converter<W, R>() {
               @Override
               public R convert(W source) {
                   return dependentOwnerDao.convert(source, rootOwnerDao, rootOwnerDao, context);
               }
           };

           P storable = ...;
           T transportable = dependentDao.convert(storable, dependentOwnerDao, dependentOwnerConverter, context);

      Specified by:
        `convert` in interface `BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>`
      Parameters:
        `storable` - storable object to convert
        `ownerDao` - owner dao to load the owner from the database
        `ownerConverter` - converter to use to convert the owner persistent object to a transport object
        `context` - data store context
      Returns:
        the transport object representing the state of the given storable

    - #### createStorableInstance

          protected abstract P createStorableInstance(T transportable,
                                 W owner)

      Creates the instance of the persistent object (Entity).
      Parameters:
        `transportable` - transport object to get the data from.
        `owner` - owner.
      Returns:
        a new instance of the persistent object.

    - #### doConvert

          protected abstract Q doConvert(P source)

      Converts the persistent object to a transport object.
      Parameters:
        `source` - persistent object to convert.
      Returns:
        a transport object with the same data than `source`

    - #### doConvert

          protected abstract T doConvert(P source,
                    R owner)

      Converts the persistent object to a transport object.
      Parameters:
        `source` - persistent object to convert.
        `owner` - owner.
      Returns:
        a transport object with the same data than `source`

    - #### conformT

          protected abstract void conformT(P target,
                      T source)

      Synchronizes the transport object and the persistent object state. This method is called from `update(Transportable, DataStoreContext)`, thus if `update(Transportable, DataStoreContext)` is overwritten this method could have an empty implementation.
      Parameters:
        `target` - object to update.
        `source` - object to take the data from.

    - #### conformQ

          protected abstract void conformQ(P target,
                      Q source)

      Synchronizes the transport object and the persistent object state. This method is called from `update(Transportable, DataStoreContext)`, thus if `update(Transportable, DataStoreContext)` is overwritten this method could have an empty implementation.
      Parameters:
        `target` - object to update.
        `source` - object to take the data from.

    - #### findDependent

          protected abstract T findDependent(I dependentId,
                        R owner)

      Finds a dependent with the given id.
      Parameters:
        `dependentId` - id of the dependent to find.
        `owner` - owner to search into.
      Returns:
        the dependent with the given id if found, null otherwise.

Copyright © 2014. All Rights Reserved.