001: /*
002: * Author: Chris Seguin
003: *
004: * This software has been developed under the copyleft
005: * rules of the GNU General Public License. Please
006: * consult the GNU General Public License for more
007: * details about use and distribution of this software.
008: */
009: package org.acm.seguin.refactor.undo;
010:
011: import java.io.File;
012: import java.io.ObjectOutputStream;
013: import java.io.FileOutputStream;
014: import java.io.ObjectInputStream;
015: import java.io.FileInputStream;
016: import java.io.FileNotFoundException;
017: import java.io.IOException;
018: import java.util.Iterator;
019: import java.util.Stack;
020: import org.acm.seguin.refactor.Refactoring;
021: import net.sourceforge.jrefactory.uml.loader.ReloaderSingleton;
022: import org.acm.seguin.util.FileSettings;
023:
024: /**
025: * The stack of refactorings that we can undo. This stack holds all the
026: * refactorings that have occurred in the system. <P>
027: *
028: * This object is a singleton object because we only want one object
029: * responsible for storing the refactorings that can be undone.
030: *
031: *@author Chris Seguin
032: *@author <a href="mailto:JRefactory@ladyshot.demon.co.uk">Mike Atkinson</a>
033: *@version $Id: UndoStack.java,v 1.6 2003/12/02 23:39:40 mikeatkinson Exp $
034: */
035: public class UndoStack {
036: /**
037: * The stack that contains the actual elements
038: */
039: private Stack stack;
040: private Class undoer = DefaultUndoAction.class;
041:
042: private static UndoStack singleton;
043:
044: /**
045: * Constructor for the UndoStack object
046: */
047: public UndoStack() {
048: if (!load()) {
049: stack = new Stack();
050: }
051: }
052:
053: /**
054: * This sets the class that holds undo actions.
055: *
056: * If not called the org.acm.seguin.refactor.undo.DefaultUndoAction class
057: * is used. This creates file backups with extensions of incrementing integers.
058: *
059: * @param undoer a class that implements org.acm.seguin.refactor.undo.UndoAction
060: * @throws IllegalArgumentException if the class cannot be instantiated or does not implement UndoAction
061: */
062: public void setUndoAction(Class undoer)
063: throws IllegalArgumentException {
064: try {
065: if (!(undoer.newInstance() instanceof UndoAction)) {
066: throw new IllegalArgumentException(
067: "the undo class must implement org.acm.seguin.refactor.undo.UndoAction");
068: }
069: } catch (IllegalAccessException ex) {
070: IllegalArgumentException e = new IllegalArgumentException(
071: "your UndoAction class cannot be accessed");
072: e.initCause(ex);
073: } catch (InstantiationException ex) {
074: IllegalArgumentException e = new IllegalArgumentException(
075: "your UndoAction class must have a zero argument constructor");
076: e.initCause(ex);
077: }
078: this .undoer = undoer;
079: }
080:
081: /**
082: * Gets the StackEmpty attribute of the UndoStack object
083: *
084: *@return The StackEmpty value
085: */
086: public boolean isStackEmpty() {
087: return stack.isEmpty();
088: }
089:
090: /**
091: * Adds a refactoring to the undo stack. You provide the refactoring, this
092: * method provides the undo action.
093: *
094: *@param ref the refactoring about to be performed
095: *@return an undo action
096: */
097: public UndoAction add(Refactoring ref) {
098: //UndoAction action = new UndoAction(ref.getDescription());
099: try {
100: UndoAction action = (UndoAction) undoer.newInstance();
101: action.setDescription(ref.getDescription());
102:
103: stack.push(action);
104: return action;
105: } catch (IllegalAccessException ex) {
106: // this should not occur as we checked we could instantiate in setUndoAction().
107: } catch (InstantiationException ex) {
108: // this should not occur as we checked we could instantiate in setUndoAction().
109: }
110: return null;
111: }
112:
113: /**
114: * Return the top option without removing it from the stack
115: *
116: *@return the top object
117: */
118: public UndoAction peek() {
119: return (UndoAction) stack.peek();
120: }
121:
122: /**
123: * Lists the undo actions in the stack
124: *
125: *@return an iterator of undo actions
126: */
127: public Iterator list() {
128: return stack.iterator();
129: }
130:
131: /**
132: * Performs an undo of the top action
133: */
134: public void undo() {
135: UndoAction action = (UndoAction) stack.pop();
136: action.undo();
137: ReloaderSingleton.reload();
138: }
139:
140: /**
141: * Description of the Method
142: */
143: public void done() {
144: save();
145: }
146:
147: /**
148: * Deletes the undo stack
149: */
150: public void delete() {
151: File file = getFile();
152: file.delete();
153: stack = new Stack();
154: }
155:
156: /**
157: * Gets the stack file
158: *
159: *@return The File value
160: */
161: private File getFile() {
162: return new File(FileSettings.getRefactorySettingsRoot(),
163: "undo.stk");
164: }
165:
166: /**
167: * Saves the undo stack to the disk
168: */
169: private void save() {
170: try {
171: File file = getFile();
172: ObjectOutputStream output = new ObjectOutputStream(
173: new FileOutputStream(file));
174: output.writeObject(stack);
175: output.flush();
176: output.close();
177: } catch (IOException ioe) {
178: ioe.printStackTrace(System.out);
179: }
180: }
181:
182: /**
183: * Loads the undo stack from the disk
184: *
185: *@return Description of the Returned Value
186: */
187: private boolean load() {
188: try {
189: File file = getFile();
190: ObjectInputStream input = new ObjectInputStream(
191: new FileInputStream(file));
192: stack = (Stack) input.readObject();
193: input.close();
194:
195: return true;
196: } catch (FileNotFoundException fnfe) {
197: // Expected - this is normal the first time
198: } catch (IOException ioe) {
199: ioe.printStackTrace(System.out);
200: } catch (ClassNotFoundException cnfe) {
201: cnfe.printStackTrace(System.out);
202: }
203:
204: return false;
205: }
206:
207: /**
208: * Gets the singleton undo operation
209: *
210: *@return the undo stack for the system
211: */
212: public static UndoStack get() {
213: if (singleton == null) {
214: singleton = new UndoStack();
215: }
216:
217: return singleton;
218: }
219: }
|