package data.ooimpl;

import data.*;

import log.*;

import java.io.Serializable;

/**
  * Basic simple implementation of the DataBasketEntry interface.
  * DataBasketEntries may be coalesced, meaning that two separate operations may
  * be expressed by one DataBasketEntry, if this is possible. Applications that
  * inspect DataBasketEntries directly should not make assumptions about whether
  * or not they have been coalesced.
  *
  * @author Steffen Zschaler
  * @version 14/06/1999
  * @since v2.0
  */
public class DataBasketEntryImpl extends Object implements DataBasketEntry,
                                                           Loggable,
                                                           Serializable {

  /**
    * The source of the operation.
    *
    * @serial
    */
  protected DataBasketEntrySource m_dbesSource;

  /**
    * The destination of the operation.
    *
    * @serial
    */
  protected DataBasketEntryDestination m_dbedDest;

  /**
    * The object moved by the operation.
    *
    * @serial
    */
  protected Object m_oValue;

  /**
    * The entry's main key.
    *
    * @serial
    */
  protected String m_sMainKey;

  /**
    * The entry's secondary key.
    *
    * @serial
    */
  protected String m_sSecondaryKey;

  /**
    * true if the entry was commited or rolled back completely.
    *
    * @serial
    */
  protected boolean m_fHandled = false;

  /**
    * The DataBasket owning this entry..
    *
    * @serial
    */
  protected DataBasketImpl m_dbiOwner;

  /**
    * Create a new DataBasketEntryImpl.
    *
    * @param sMainKey the entry's main key.
    * @param sSecondaryKey the entry's secondary key.
    * @param dbesSource the operation's source. Assumed to be a {@link SelfManagingDBESource}.
    * @param dbedDest the operation's destination.  Assumed to be a {@link SelfManagingDBEDestination}.
    * @param oValue the object moved by the operation.
    */
  public DataBasketEntryImpl (String sMainKey,
                              String sSecondaryKey,
                              DataBasketEntrySource dbesSource,
                              DataBasketEntryDestination dbedDest,
                              Object oValue) {
    super();

    m_sMainKey = sMainKey;
    m_sSecondaryKey = sSecondaryKey;
    m_dbesSource = dbesSource;
    m_dbedDest = dbedDest;
    m_oValue = oValue;
  }

  /**
    * Rollback the operation. This is done by first calling {@link SelfManagingDBEDestination#rollbackAdd} in
    * the destination and then {@link SelfManagingDBESource#rollbackRemove} in the source of the entry.
    *
    * @override Never
    */
  public void rollback() {
    if (!isHandled()) {
      m_fHandled = true;

      m_dbiOwner.log (DataBasketImpl.ROLLBACK_ACTION, this);

      SelfManagingDBEDestination smdbedDest = (SelfManagingDBEDestination) getDestination();
      if (smdbedDest != null) {
        smdbedDest.rollbackAdd (m_dbiOwner, this);
      }

      SelfManagingDBESource smdbesSource = (SelfManagingDBESource) getSource();
      if (smdbesSource != null) {
        smdbesSource.rollbackRemove (m_dbiOwner, this);
      }
    }
  }

  /**
    * Commit the operation. This is done by first calling {@link SelfManagingDBESource#commitRemove} in the
    * source and then {@link SelfManagingDBEDestination#commitAdd} in the destination of the entry.
    *
    * @override Never
    */
  public void commit() {
    if (!isHandled()) {
      m_fHandled = true;

      m_dbiOwner.log (DataBasketImpl.COMMIT_ACTION, this);

      SelfManagingDBESource smdbesSource = (SelfManagingDBESource) getSource();
      if (smdbesSource != null) {
        smdbesSource.commitRemove (m_dbiOwner, this);
      }

      SelfManagingDBEDestination smdbedDest = (SelfManagingDBEDestination) getDestination();
      if (smdbedDest != null) {
        smdbedDest.commitAdd (m_dbiOwner, this);
      }
    }
  }

  /**
    * Set the DataBasket owning this DataBasketEntry.
    *
    * <p>This method is public as an implementation detail and must not be called directly.</p>
    *
    * @override Never
    */
  public void setOwner (DataBasket dbOwner) {
    m_dbiOwner = (DataBasketImpl) dbOwner;
  }

  /**
    * Return the DataBasket containing this DataBasketEntry. Initially <code>null</code>. Once
    * {@link #setOwner} has been called, always returns the last value of the <code>dbOwner</code>
    * parameter passed to <code>setOwner</code>.
    *
    * @return the DataBasket containing this DataBasketEntry.
    */
  public DataBasket getOwner() {
    return m_dbiOwner;
  }

  /**
    * Get the entry's source.
    *
    * @override Never
    */
  public DataBasketEntrySource getSource() {
    return m_dbesSource;
  }

  /**
    * Get the entry's destination.
    *
    * @override Never
    */
  public DataBasketEntryDestination getDestination() {
    return m_dbedDest;
  }

  /**
    * Get the entry's value, i.e. the object that was moved by the operation.
    *
    * @override Never
    */
  public Object getValue() {
    return m_oValue;
  }

  /**
    * Get the entry's main key.
    *
    * @override Never
    */
  public String getMainKey() {
    return m_sMainKey;
  }

  /**
    * Get the entry's secondary key.
    *
    * @override Never
    */
  public String getSecondaryKey() {
    return m_sSecondaryKey;
  }

  /**
    * Return true, if the entry has been either completely commited or rolled back.
    *
    * @override Never
    */
  public boolean isHandled() {
    return m_fHandled;
  }

  // Loggable interface method
  /**
    * Return a LogEntry that describes this DataBasketEntry.
    *
    * @override Always The default implementation is generic and therefore usually not optimal for a subclass
    * implementation.
    */
  public LogEntry getLogData() {
    final String sMainKey = getMainKey();
    final String sSecondaryKey = getSecondaryKey();
    final String sSource = "" + getSource();
    final String sDest = "" + getDestination();
    final String sValue = "" + getValue();

    return new LogEntry() {
      public String toString() {
        return "DataBasketEntry: \"" + sMainKey + "\"/\"" + sSecondaryKey + "\": " +
               "\"" + sValue + "\" (\"" + sSource + "\" -> \"" + sDest + "\")";
      }
    };
  }
}