The GlobalModel InterfaceAs promised earlier in this chapter in the section entitled "Keeping Code in the Model, Not the View," Listing 2-1 contains a snapshot of the GlobalModel interface as it exists today. Listing 2-1: DrJava's GlobalModel Provides an Interface that Maintains Limited Connections between the View and the Model
package edu.rice.cs.drjava.model; import javax.swing.text.*; import javax.swing.ListModel; import java.io.*; import java.util.*; import edu.rice.cs.util.swing.FindReplaceMachine; import edu.rice.cs.drjava.DrJava; import edu.rice.cs.util.UnexpectedException; import edu.rice.cs.drjava.model.definitions.*; import edu.rice.cs.drjava.model.repl.*; import edu.rice.cs.drjava.model.compiler.*; /** * Handles the bulk of DrJava's program logic. * The UI components interface with the GlobalModel through its public * methods, and GlobalModel responds via the GlobalModelListener interface. * This removes the dependency on the UI for the logical flow of the program's * features. With the current implementation, we can finally test the compile * functionality of DrJava, along with many other things. * * @version $Id: GlobalModel.java,v 1.30 2002/02/25 22:52:14 thepropsman Exp $ */ public interface GlobalModel { /** * Add a listener to this global model. * @param listener a listener that reacts on events generated by the GlobalModel */ public void addListener(GlobalModelListener listener); /** * Remove a listener from this global model. * @param listener a listener that reacts on events generated by the GlobalModel */ public void removeListener(GlobalModelListener listener); /** * Fetches the {@link javax.swing.EditorKit} implementation for use * in the definitions pane. */ public DefinitionsEditorKit getEditorKit(); /** * Gets a ListModel of the open definitions documents. */ public ListModel getDefinitionsDocuments(); /** * Gets the interactions document. */ public StyledDocument getInteractionsDocument(); /** * Gets the console document. */ public StyledDocument getConsoleDocument(); /** * Gets the array of all compile errors without Files. */ public CompilerError[] getCompilerErrorsWithoutFiles(); /** * Gets the total number of current errors. */ public int getNumErrors(); /** * Creates a new document in the definitions pane and * adds it to the list of open documents. * @return The new open document */ public OpenDefinitionsDocument newFile(); /** * Open a file and read it into the definitions. * The provided file selector chooses a file, and on a successful * open, the fileOpened() event is fired. * @param com a command pattern command that selects what file * to open * @return The open document, or null if unsuccessful * @exception IOException * @exception OperationCanceledException if the open was canceled * @exception AlreadyOpenException if the file is already open */ public OpenDefinitionsDocument openFile(FileOpenSelector com) throws IOException, OperationCanceledException, AlreadyOpenException; /** * Closes an open definitions document, prompting to save if * the document has been changed. Returns whether the file * was successfully closed. * @return true if the document was closed */ public boolean closeFile(OpenDefinitionsDocument doc); /** * Attempts to close all open documents. * @return true if all documents were closed */ public boolean closeAllFiles(); /** * Saves all open documents, prompting when necessary. */ public void saveAllFiles(FileSaveSelector com) throws IOException; /** * Saves all open documents, used for testing */ public void saveAllFiles(FileSaveSelector com[]) throws IOException; /** * Exits the program. * Only quits if all documents are successfully closed. */ public void quit(); /** * Returns the OpenDefinitionsDocument for the specified * File, opening a new copy if one is not already open. * @param file File contained by the document to be returned * @return OpenDefinitionsDocument containing file */ public OpenDefinitionsDocument getDocumentForFile(File file) throws IOException, OperationCanceledException; /** * Clears and resets the interactions pane. * First it makes sure it's in the right package given the * package specified by the definitions. If it can't, * the package for the interactions becomes the default * top level. In either case, this method calls a helper * which fires the interactionsReset() event. */ public void resetInteractions(); /** * Resets the console. * Fires consoleReset() event. */ public void resetConsole(); /** * Clears the current interaction text and then moves * to the end of the command history. */ public void clearCurrentInteraction(); /** * Forwarding method to remove logical dependency of InteractionsPane on * the InteractionsDocument. Gets the previous interaction in the * InteractionsDocument's history and replaces whatever is on the current * interactions input line with this interaction. */ public void recallPreviousInteractionInHistory(Runnable failed); /** * Forwarding method to remove logical dependency of InteractionsPane on * the InteractionsDocument. Gets the next interaction in the * InteractionsDocument's history and replaces whatever is on the current * interactions input line with this interaction. */ public void recallNextInteractionInHistory(Runnable failed); /** * Interprets the current given text at the prompt in the interactions * pane. */ public void interpretCurrentInteraction(); /** Returns the first location in the document where editing is allowed. */ public int getInteractionsFrozenPos(); /** * Aborts the currently running interaction. */ public void abortCurrentInteraction(); /** Called when the repl prints to System.out. */ public void replSystemOutPrint(String s); /** Called when the repl prints to System.err. */ public void replSystemErrPrint(String s); /** * Signifies that the most recent interpretation completed successfully, * returning no value. */ public void replReturnedVoid(); /** * Signifies that the most recent interpretation completed successfully, * returning a value. * * @param result The .toString-ed version of the value that was returned * by the interpretation. We must return the String form * because returning the Object directly would require the * data type to be serializable. */ public void replReturnedResult(String result); /** * Signifies that the most recent interpretation was ended * due to an exception being thrown. * * @param exceptionClass The name of the class of the thrown exception * @param message The exception's message * @param stackTrace The stack trace of the exception */ public void replThrewException(String exceptionClass, String message, String stackTrace); /** * Signifies that the most recent interpretation contained a call to * System.exit. * * @param status The exit status that will be returned. */ public void replCalledSystemExit(int status); /** * Returns all registered compilers that are actually available. * That is, for all elements in the returned array, .isAvailable() * is true. * This method will never return null or a zero-length array. * * @see CompilerRegistry#getAvailableCompilers */ public CompilerInterface[] getAvailableCompilers(); /** * Sets which compiler is the "active" compiler. * * @param compiler Compiler to set active. * * @see #getActiveCompiler * @see CompilerRegistry#setActiveCompiler */ public void setActiveCompiler(CompilerInterface compiler); /** * Gets the compiler is the "active" compiler. * * @see #setActiveCompiler * @see CompilerRegistry#getActiveCompiler */ public CompilerInterface getActiveCompiler(); /** * Gets an array of all sourceRoots for the open definitions * documents, without duplicates. * @throws InvalidPackageException if the package statement in one * of the open documents is invalid. */ public File[] getSourceRootSet(); } The DrJava IDE example (in the Building Cost-Effective Specifications with Stories") provides a good example of how much functionality can be put into a model. The only contact that the view has with the model is through a specially designed interface we call the GlobalModel, shown in the following listing. This interface includes methods for every functional modification a user can make while using DrJava. In essence, it provides a handle that our tests can use to interact with DrJava in any way that a user can, except that the tests don't have to interact through the view. |