package gsingh.learnkirtan; import gsingh.learnkirtan.listener.FileEventListener; import gsingh.learnkirtan.listener.FileEventListener.FileEvent; import gsingh.learnkirtan.shabad.Shabad; import gsingh.learnkirtan.ui.shabadeditor.ShabadEditor; import gsingh.learnkirtan.utility.DialogUtility; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.LinkedList; import java.util.List; import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; /** * Responsible for managing the opening and saving of files * * @author Gulshan * */ public class FileManager { public enum SaveResult { NOT_SAVED_CANCELLED, NOT_SAVED, SAVEDEXISTING, SAVED_NEW, OVERWRITE, NOT_SAVED_INVALID_SHABAD } private List<FileEventListener> listeners = new LinkedList<FileEventListener>(); private static final int VERSION = 2; /** The file extension of Shabad files */ private static final String EXTENSION = ".sbd"; /** The path to the settings files */ private static final String SETTINGS_FILE = "config"; /** The filechooser used for opening and saving files */ private final JFileChooser fc; { fc = new JFileChooser(); FileFilter filter = new FileNameExtensionFilter("SBD (Shabad) File", "sbd"); fc.setFileFilter(filter); } /** * The file in which your shabad will be saved or was opened from. When the * program is first started, it has the value of {@code null}. */ private File curFile; public void addFileEventListener(FileEventListener l) { listeners.add(l); } /** * Writes a DOM to the settings file * * @param dom * The DOM to persist * @throws TransformerFactoryConfigurationError * @throws TransformerException */ public void saveSettings(Document dom) throws TransformerFactoryConfigurationError, TransformerException { // Prepare the DOM document for writing Source source = new DOMSource(dom); // Prepare the output file File file = new File(SETTINGS_FILE); Result result = new StreamResult(file); // Write the DOM document to the file Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.transform(source, result); } /** * Sets the invariants for a new file */ public void newFile() { curFile = null; for (FileEventListener l : listeners) { FileEvent e = FileEvent.CREATE; e.setFileName(""); l.onFileEvent(e); } } /** * Saves the text in the shabadEditor to the file specified. If no file is * specified, the user is prompted to specify one. * * @throws IOException */ public SaveResult saveShabad(Shabad shabad) throws IOException { // If no file is currently opened if (!isFileOpened()) { int returnVal = fc.showSaveDialog(null); if (returnVal == JFileChooser.APPROVE_OPTION) { curFile = fc.getSelectedFile(); curFile = appendFileExtension(curFile); // If the selected file exists and we're about to overwrite it if (curFile.exists()) { int result = DialogUtility.showOverwriteDialog(); // If the user is OK with overwriting it if (DialogUtility.isOK(result)) { write(shabad); return SaveResult.OVERWRITE; } else { return SaveResult.NOT_SAVED_CANCELLED; } } else { write(shabad); return SaveResult.SAVED_NEW; } } else { return SaveResult.NOT_SAVED_CANCELLED; } } else { write(shabad); return SaveResult.SAVEDEXISTING; } } /** * Returns true if a file is currently opened, false otherwise * */ public boolean isFileOpened() { if (curFile == null) return false; else return true; } /** * Append the file extension if not present * * @param file * The file to append the extension to */ private File appendFileExtension(File file) { String filename = file.getName(); if (isMissingExtension(filename)) { curFile = new File(curFile.getAbsolutePath() + EXTENSION); } return curFile; } /** * @param filename * the filename to check * @return true if filename does not end in the file extension */ private boolean isMissingExtension(String filename) { if (filename.length() <= 4 || !filename.substring(filename.length() - 4).equals(EXTENSION)) return true; else return false; } /** * Writes a {@link Shabad} to a file * * @throws IOException */ private void write(Shabad shabad) throws IOException { FileOutputStream fileOut = new FileOutputStream(curFile); ObjectOutputStream out = new ObjectOutputStream(fileOut); try { out.writeInt(VERSION); out.writeObject(shabad); } finally { out.close(); fileOut.close(); } for (FileEventListener l : listeners) { FileEvent e = FileEvent.SAVE; e.setFileName(curFile.getName()); l.onFileEvent(e); } } /** * Prompts the user for a file to open and opens the selected file. * * @return true if a file was opened, false otherwise * * @throws IOException */ public boolean openFile(ShabadEditor shabadEditor) throws IOException { int returnVal = fc.showOpenDialog(null); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); if (file.exists()) { FileInputStream fileIn = new FileInputStream(file); ObjectInputStream in = new ObjectInputStream(fileIn); Shabad shabad = null; try { int version = in.readInt(); shabad = (Shabad) in.readObject(); } catch (ClassNotFoundException e) { // Programmer error: should never happen e.printStackTrace(); } finally { in.close(); fileIn.close(); } shabadEditor.setShabad(shabad); curFile = file; for (FileEventListener l : listeners) { FileEvent e = FileEvent.OPEN; e.setFileName(curFile.getName()); l.onFileEvent(e); } return true; } else { DialogUtility.showFileDoesntExistDialog(); } } return false; } /** * Gets the name of the currently opened file * * @return The name of the opened file. If no file is opened, returns the * empty string */ public String getFileName() { if (isFileOpened()) { return curFile.getName(); } else { return ""; } } }