package com.treelight.krnl;

/**
 * The fundamental type for a node that is capable of having
 * multiple versions. Distinguished from (@link StructureNode}
 * in that the latter has multiple versions -- one for each
 * sublist it contains.
 *
 * @version 0.1
 * @author Eric Armstrong
 * @see ../NodesAndLists.html
 */
abstract public class AbstractVersionedEntity extends AbstractEntity {

  /**
   * A pointer to the previous version of this node.
   */
  private AbstractEntity previousVersion; 
  public AbstractEntity getPreviousVersion() { return previousVersion; }

  /**
   * A pointer to the original version of this node. This pointer
   * is motivated by performance. The original author needs to be
   * identified frequently, and we don't want to have to traverse
   * the entire list of versions to find him/her.
   * <p>
   * When created, a new node is initialized with a pointer to 
   * itself. This value therefore points to the original version
   * in every copy of the node.
   */
  private AbstractNode originalVersion; 

  /**
   * Returns the original version of the node. IT's version
   * stamp identifies the original author, as well as
   * the time it was created and the system it was created on.
   * Preserved when new versions of the node are produced.
   */
  public AbstractNode getOriginalVersion() { return originalVersion; }  

  /**
   * Returns the original author of the node.
   * (A convenience method, since that information os accessed so much.)
   */
  public UserID getOriginalAuthor() { 
    VersionStamp stamp = originalVersion.getVersionStamp();
    return stamp.getUserID();
  }  

  /**
   * Identifies the author of <i>this version</i> of the node, along
   * with the time the version was created, and the system it
   * was created on.
   */
  private VersionStamp versionStamp;

  /**
   * Returns the author of this version of the node, along
   * with the time the version was created, and the system it
   * was created on.
   */
  public VersionStamp getVersionStamp() { return this.versionStamp; } 
 
  /**
   * Specifies the author of this version of the node, along
   * with the time the version was created, and the system it
   * was created on.
   */
  protected void setVersionStamp(VersionStamp versionStamp) { 
    this.versionStamp = versionStamp; 
  }  

  /** 
   * Creates a new version of the current node, with the
   * original version stamp unchanged, and latest version
   * stamp initialized with a new version. Adds the node
   * to the unstamped versions list (which forces the
   * using system to have initialized the list, and be 
   * prepared to use it.) 
   * <blockquote><b>Note:</b><br>
   *    Since a node always points to the most recent
   *    version, it only exists once on the unstamped
   *    versions list.
   * </blockquote>
   * <p>
   * Uses Object.clone(), which produces a shallow copy of
   * the object. Puts a shallow copy of the current node
   * on the version list. Changes the version stamp for this
   * node, making it the new version. (Note that this method
   * must be called by add, chg, del methods BEFORE making
   * their respective changes.)
   */
  public void newVersion() {
    AbstractNode copy = this.clone();
    VersionStamp versionStamp = new VersionStamp(this);
    VersionControl.addUnstampedNode(this);
    this.setLatestVersion(versionStamp);
    //___TODO: 
  }

}//AbstractVersionedNode
