package com.treelight.krnl;
import java.util.*;
/**
* A node that encapsulates version-identification information.
*
* @version 0.1
* @author Eric Armstrong
* @see ../NodesAndLists.html
*/
public class VersionStamp implements NodeTypes, Comparable {
// Note that these three values together define a globally unique node ID
private UserID userID; // Identifies the author of the current version
private SystemID systemID; // Identifies the system the version was created on
private long timeStamp;
public String getUserID() { return userID; }
public String getSystemID() { return systemID; }
/** Returns time stamp -- MAY BE NULL. */
public String getTimeStamp() { return timeStamp; }
/** Sets time stamp. */
public void setTime(Long timeStamp) {
this.timeStamp = timeStamp;
}
/**
* A link to the node that this version identifies. Used when
* the using system is processing a list of changes in order to
* "undo" them.
*/
private AbstractNode node;
/**
* Tests for node equality. This test will usually occur after
* nodes created on one system are delivered to another. The
* test therefore proceeds in the order most likely to produce
* a difference: the systemID, then timesStamp, then userID.
*/
public boolean equals(Object obj)
throws ClassCastException, UnstampedVersionException {
VersionStamp targetStamp = (VersionStamp) obj;
if (!this.systemID.equals(target.getSystemID())) return false;
if (!this.timeStamp.equals(target.getTimeStamp())) return false;
if (!this.userID.equals(target.getUserID())) return false;
return true;
}
/**
* The comparable interface is used in by the java.util
* list sorting mechanisms. Generally, the matter is
* decided by the timestamp. When the timestamps happen
* to be equal, we can do one of two things:
*
* - Identify the versions as equal, for the purposes
* of comparison. That defines a partial ordering that
* has a different definition for "equals" than the
* one above. That can be problematic. (See the
* java.util.Comparable interface.)
*
* - Return an ordering based on userID and systemID.
* That means that different systems will always have
* the same ordering of version lists (which could
* be handy), and that the equality operation is
* identical to the one defined in equals().
*
* Of the two possiblities, the latter makes the most
* sense for compare(). For timeStamp-only comparisons,
* use {@link #timeStampCompare}.
*/
public boolean compare(Object obj)
throws ClassCastException, UnstampedVersionException {
VersionStamp targetStamp = (VersionStamp) obj;
int result = this.timeStamp.compare(target.getTimeStamp());
if (result == -1) return -1; // less
if (result == 1) return 1; // more
// result = 0, so the timeStamps are equal
if (!this.systemID.equals(target.getSystemID())) return false;
if (!this.userID.equals(target.getUserID())) return false;
return true;
}
/**
* Returns -1 if this node's timeStamp is earlier than the
* target node, +1 if later, and 0 if equal.
*/
public int timeStampCompare(VersionStamp targetStamp)
throws UnstampedVersionException {
TimeStamp targetTime = targetStamp.getTimeStamp();
return this.timeStamp.compare(targetTime);
}
public long getTimeStamp()
throws UnstampedVersionException {
if (time == null) throw new UnstampedVersionException()
return timeStamp;
}
/**
* Create a new version stamp that identifies the author of the
* the new version. After creating the stamp, call (@link #setTime()}
* to get the time value from the currently configured time server.
*
* Node: The node argument exists, so that a list of
* unstamped versions can be processed serially, as a way of implementing
* UNDO in the outer system. (For versioning, the KRNL needs a list of
* nodes that have changed, where the set of changes constitutes the
* new version. But for undo, the outer system needs a chronological
* list of changes.
*/
public void VersionStamp(AbstractNode node) {
this.userID = VersionControl.getUserID;
this.systemID = VersionControl.getSystemID;
this.node = node;
}
}//VersionStamp