001: /*
002: * Enhydra Java Application Server
003: * The Initial Developer of the Original Code is Lutris Technologies Inc.
004: * Portions created by Lutris are Copyright (C) 1997-2000 Lutris Technologies
005: * Inc.
006: * All Rights Reserved.
007: *
008: * The contents of this file are subject to the Enhydra Public License Version
009: * 1.0 (the "License"); you may not use this file except in compliance with the
010: * License. You may obtain a copy of the License at
011: * http://www.enhydra.org/software/license/epl.html
012: *
013: * Software distributed under the License is distributed on an "AS IS" basis,
014: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
015: * License for the specific language governing rights and limitations under the
016: * License.
017: *
018: *
019: */
020:
021: package golfShop.business.cart;
022:
023: import java.util.Stack;
024: import java.util.Hashtable;
025: import java.util.Enumeration;
026: import golfShop.business.cart.CartItemPairImpl;
027:
028: /*
029: Only the cart object needs to use this.
030: */
031: public class UndoRedoStack implements java.io.Serializable {
032:
033: private Hashtable currentVersion;
034: private Stack undoStack;
035: private Stack redoStack;
036:
037: /**
038: * Create a new UndoRedoStack. To avoid uninitialized states, you
039: * must pass in the initial version of the hashtable you want to track.
040: * Every time you change this object, call StoreNewVersion().
041: * If you want to undo, call UndoToPreviousVersion(). This returns
042: * the previous version of the hashtable; you should use this in your
043: * program as the new value of the hashtable. If you want to redo,
044: * call RedoToNewerVersion(). This returns a newer version of the
045: * hashtable.
046: *
047: * @author Andrew John
048: * @param initialVersion The starting version of the hashtable to be
049: * tracked.
050: * @version $Revision: 1.1
051: */
052: protected UndoRedoStack(Hashtable initialVersion) {
053: undoStack = new Stack();
054: redoStack = new Stack();
055: currentVersion = copyHT(initialVersion);
056: }
057:
058: /**
059: * After you make a change to your object, call this function to
060: * remember the current version. The previous version is saved for
061: * so that you can do an undo.
062: *
063: * @param newVersion The current version of the object to
064: * be tracked.
065: */
066: protected void storeNewVersion(Hashtable newVersion) {
067: // Save the current version for later.
068: undoStack.push(currentVersion);
069: // Throw out the whole redo stack.
070: redoStack = new Stack();
071: // This is now the current version.
072: currentVersion = copyHT(newVersion);
073: }
074:
075: protected boolean canUndo() {
076: return !undoStack.empty();
077: }
078:
079: protected Hashtable undoToPreviousVersion() {
080: if (undoStack.empty())
081: // Error condition.
082: return copyHT(currentVersion);
083: else {
084: // Save the current version in case they redo.
085: redoStack.push(currentVersion);
086: // Go back to the previous version.
087: currentVersion = (Hashtable) undoStack.pop();
088: return copyHT(currentVersion);
089: }
090: }
091:
092: protected boolean canRedo() {
093: return !redoStack.empty();
094: }
095:
096: protected Hashtable redoToNewerVersion() {
097: if (redoStack.empty())
098: return copyHT(currentVersion);
099: else {
100: undoStack.push(currentVersion);
101: currentVersion = (Hashtable) redoStack.pop();
102: return copyHT(currentVersion);
103: }
104: }
105:
106: protected Object getCurrentVersion() {
107: return copyHT(currentVersion);
108: }
109:
110: /*
111: Make a copy of the hashtable. If you call clone() on a hashtable
112: it gives you a new hashtable, but it contains pointers to the
113: same key objects and value objects. If you change the
114: value objects, they will be changed in both coppies of the
115: hashtable. This is not what we want for undo functionality.
116: So this function creates a new hashtable and populates it
117: with clones of the value objects. The key objects are not cloned.
118:
119: All the versions stored in this object must be insulated from
120: being modified by the rest of the program. So make coppies of the
121: input, and only give out coppies.
122: */
123: private Hashtable copyHT(Hashtable ht) {
124: Hashtable newHT = new Hashtable();
125: Enumeration e = ht.keys();
126: while (e.hasMoreElements()) {
127: Object key = e.nextElement();
128: CartItemPairImpl value = (CartItemPairImpl) ht.get(key);
129: CartItemPairImpl valueCopy = value.copy();
130: newHT.put(key, valueCopy);
131: }
132: return newHT;
133: }
134:
135: // For debugging only.
136: private void printHT(Hashtable ht) {
137: Enumeration e = ht.keys();
138: System.out.println("Hashtable contents:");
139: while (e.hasMoreElements()) {
140: Object key = e.nextElement();
141: CartItemPairImpl value = (CartItemPairImpl) ht.get(key);
142: System.out.println("ObjectId "
143: + value.getItem().getObjectId() + " x "
144: + value.getQuantity());
145: }
146: System.out.println("\n");
147: }
148: }
|