Index: trunk/gli/src/org/greenstone/gatherer/collection/ExportCollectionPrompt.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/collection/ExportCollectionPrompt.java	(revision 5843)
+++ trunk/gli/src/org/greenstone/gatherer/collection/ExportCollectionPrompt.java	(revision 5843)
@@ -0,0 +1,434 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.collection;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.GSDLSiteConfig;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides the functionality to export current collections from the GSDLHOME/collect/ directory to CDROM. The user chooses the collection from a list, where each entry also displays details about itself, confirms the delete of a collection by checking a checkbox then presses the ok button to actually delete the collection.
+    Copied from DeleteCollectionPrompt
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ExportCollectionPrompt
+    extends ModalDialog 
+    implements GShellListener {
+    /** The currently selected collection for deletion. */
+    private CollectionEntry collection = null;
+    /** The model behind the list. */
+    private DefaultListModel list_model = null;
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private ExportCollectionPrompt prompt = null;
+    /** The close button, which exits the prompt without deleting anything. */
+    private JButton cancel_button = null;
+    /** The ok button which causes the selected collection to be deleted. */
+    private JButton ok_button = null;
+    /** The label above details. */
+    private JLabel details_label = null;
+    /** The label above the list. */
+    private JLabel list_label = null;
+    /** The list of available collections. */
+    private JList list = null;
+    /** The text area used to display details about the collection selected. */
+    private JTextArea details_textarea = null;
+    /** The text area used to display instructions for the export */
+    private JTextArea instructions_textarea;
+    /** A string array used to pass arguments to the phrase retrieval method. */
+    private String args[] = null;
+    
+    /** whether the exporting was successful or not */
+    private boolean successful = false;
+    /** whether we are trying to export or not */
+    private boolean exporting = false;
+    /** the error message if any */
+    private StringBuffer error_message = null;
+    /** The size of the export prompt screen. */
+    public static final Dimension SIZE = new Dimension(500, 500);
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.collection.ExportCollectionPrompt.CancelButtonListener
+     * @see org.greenstone.gatherer.collection.ExportCollectionPrompt.CollectionListListener
+     * @see org.greenstone.gatherer.collection.ExportCollectionPrompt.OKButtonListener
+     */
+    public ExportCollectionPrompt() {
+	super(Gatherer.g_man);
+	cancel_button = new JButton();
+	cancel_button.setMnemonic(KeyEvent.VK_C);
+	Dictionary.setBoth(cancel_button, "General.Close", "General.Close_Tooltip");
+	details_textarea = new JTextArea();
+	details_textarea.setEditable(false);
+	details_textarea.setFont(Gatherer.config.getFont("general.tooltip_font", false));
+	Dictionary.setText(details_textarea, "DeleteCollectionPrompt.No_Collection");
+	details_label = new JLabel();
+	Dictionary.setText(details_label, "DeleteCollectionPrompt.Collection_Details");
+
+	instructions_textarea = new JTextArea();
+	instructions_textarea.setCaretPosition(0);
+	instructions_textarea.setEditable(false);
+	instructions_textarea.setLineWrap(true);
+	instructions_textarea.setRows(4);
+	instructions_textarea.setWrapStyleWord(true);
+	Dictionary.registerText(instructions_textarea, "ExportCollectionPrompt.Instructions");
+
+	list = new JList();
+	list_label = new JLabel();
+	Dictionary.setText(list_label, "DeleteCollectionPrompt.Collection_List");
+	list_model = new DefaultListModel();
+	ok_button = new JButton();
+	ok_button.setMnemonic(KeyEvent.VK_D);
+	Dictionary.setBoth(ok_button, "ExportCollectionPrompt.Export", "ExportCollectionPrompt.Export_Tooltip");
+	prompt = this;
+	setModal(true);
+	setSize(SIZE);
+	Dictionary.setText(this, "ExportCollectionPrompt.Title");
+
+	setJMenuBar(new SimpleMenuBar("0")); // need to find an appropriate help page to open at
+	cancel_button.addActionListener(new CancelButtonListener());
+	list.addListSelectionListener(new CollectionListListener());
+	list.clearSelection();
+	list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	list.setModel(list_model);
+	ok_button.addActionListener(new OKButtonListener());
+	ok_button.setEnabled(false);
+	scanForCollections();
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	list_model.clear();
+	list_model = null;
+	cancel_button = null;
+	details_textarea = null;
+	details_label = null;
+	list = null;
+	ok_button = null;
+	prompt = null;
+    }
+
+    /** This method causes the modal prompt to be displayed. 
+     * returns true if it has deleted the collection that is currently open */
+    public boolean display() {
+	// Top pane
+	JPanel instructions_pane = new JPanel(new BorderLayout());
+	instructions_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	instructions_pane.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER);
+	
+	// Central pane
+	JPanel list_pane = new JPanel(new BorderLayout());
+	list_pane.add(list_label, BorderLayout.NORTH);
+	list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+	list_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
+
+	JPanel details_pane = new JPanel(new BorderLayout());
+	details_pane.add(details_label, BorderLayout.NORTH);
+	details_pane.add(new JScrollPane(details_textarea), BorderLayout.CENTER);
+	details_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel central_pane = new JPanel(new GridLayout(2, 1));
+	central_pane.add(list_pane);
+	central_pane.add(details_pane);
+	central_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+	// Lower pane
+	JPanel button_pane = new JPanel(new GridLayout(1, 2));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+	button_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel lower_pane = new JPanel(new BorderLayout());
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
+
+	// Final.
+	JPanel content_pane = (JPanel)this.getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(instructions_pane, BorderLayout.NORTH);
+	content_pane.add(central_pane, BorderLayout.CENTER);
+	content_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	// Center and display.
+	Dimension screen_size = Gatherer.config.screen_size;
+	this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	this.setVisible(true); // blocks until the dialog is killed
+	return true;
+	
+    }
+
+    
+    /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.Message
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.shell.GShell
+     * @see org.greenstone.gatherer.shell.GShellListener
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void exportCollection() {
+	Gatherer.println("ExportCollectionPrompt.exportCollection()");
+
+	String args[];
+	if(Utility.isWindows()) {
+	    args = new String[4];
+	    args[0] = Gatherer.config.perl_path;
+	    args[1] = "-S";
+	    args[2] = Gatherer.config.getScriptPath() + "exportcol.pl";
+	    args[3] = collection.getName();
+	}
+	else {
+	    args = new String[2];
+	    args[0] = Gatherer.config.getScriptPath() + "exportcol.pl";
+	    args[1] = collection.getName();
+	}
+	
+	GShell process = new GShell(args, GShell.EXPORT, 3, this, null, GShell.GSHELL_EXPORT);
+	//process.addGShellListener(this);
+	process.run(); // Don't bother threading this... yet
+	Gatherer.println("ExportCollectionPrompt.exportCollection().return");
+    }
+
+    /** Shows an export complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    public void resultPrompt(boolean success, String extra) {
+	args = new String[2];
+	args[0] = collection.getName();
+	args[1] = "export_"+collection.getName();
+	if (success) {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("ExportCollectionPrompt.Successful_Export", args)+"\n"+extra, Dictionary.get("ExportCollectionPrompt.Successful_Title"),JOptionPane.INFORMATION_MESSAGE);
+	}
+	else {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("ExportCollectionPrompt.Failed_Export", args)+"\n"+extra, Dictionary.get("ExportCollectionPrompt.Failed_Title"),JOptionPane.WARNING_MESSAGE);
+	}
+    }
+
+    /** Method to scan the collect directory retrieving and reloading each collection it finds, while building the list of known collections.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.util.ArrayTools
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private void scanForCollections() {
+	// Start at the collect dir.
+	String collect_directory_name = Utility.getCollectionDir(Gatherer.config.gsdl_path);
+	File collect_directory = new File(collect_directory_name);
+	if(collect_directory.exists()) {
+	    // Now for each child directory see if it contains a .col file and
+	    // if so try to load it..
+	    File collections[] = collect_directory.listFiles();
+	    ArrayTools.sort(collections);
+	    for(int i = 0; collections != null && i < collections.length; i++) {
+		if(!collections[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+		    File config_file = Utility.findConfigFile(collections[i]);
+		    if (config_file != null) {
+			CollectionConfiguration config = new CollectionConfiguration(config_file);
+			if (config != null) {
+			    CollectionEntry col = new CollectionEntry(collections[i].getName(), config);
+			    list_model.addElement(col);
+			}    
+		    }
+		}
+	    }
+	}
+	// Otherwise the collect directory doesn't actually exist, so there ain't much we can do.
+    }
+
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+	// Ignore the messages from RecPlug with 'show_progress' set (used for progress bars)
+	String message = event.getMessage();
+	if (message.startsWith("exportcol.pl>")) {
+	    message = message.substring(13);
+	    System.err.println("message = "+event.getMessage());
+	    error_message.append(message);
+	    error_message.append("\n");
+	}
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	// We don't care. 
+    }
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	if(event.getStatus() == GShell.OK) {
+	    if(event.getType() == GShell.EXPORT) {
+		successful = true;
+	    }
+	}
+	else {
+	    successful = false;
+	}
+    }
+
+    /** A button listener implementation, which listens for actions on the close button and disposes of the dialog when detected. */
+    private class CancelButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    prompt.dispose();
+	}
+    }
+
+    /** This private class listens for selection events in from the list and then displays the appropriate details for that collection.
+     */
+    private class CollectionListListener 
+	implements ListSelectionListener {
+	/** Any implementation of ListSelectionListener must include this method so we can be informed when the list selection changes.
+	 * @param  event a <strong>ListSelectionEvent</strong> containing all the relevant information garnered from the event itself
+	 */
+	public void valueChanged(ListSelectionEvent event) {
+	    ok_button.setEnabled(false);
+	    if(!list.isSelectionEmpty()) {
+		collection = (CollectionEntry) list.getSelectedValue();
+		args = new String[5];
+		args[0] = collection.getTitle();
+		args[1] = collection.getName();
+		args[2] = collection.getCreator();
+		args[3] = collection.getMaintainer();
+		args[4] = collection.getDescription();
+		Dictionary.setText(details_textarea, "DeleteCollectionPrompt.Details", args);
+		details_textarea.setCaretPosition(0);
+		ok_button.setEnabled(true);
+	    }
+	    else {
+		Dictionary.setText(details_textarea, "DeleteCollectionPrompt.No_Collection");
+		ok_button.setEnabled(false);
+	    }
+	}
+    }
+    
+   /** The OK button listener implementation. */
+    private class OKButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 * @see org.greenstone.gatherer.Configuration
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    error_message = new StringBuffer();
+	    
+	    // set the cursor to hourglass
+	    Component glass_pane = getGlassPane();
+	    MouseListener mouse_blocker_listener = new MouseAdapter() {};
+	    glass_pane.addMouseListener(mouse_blocker_listener);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+
+	    // Export the selected collection.
+	    exportCollection();
+	    
+	    // unset the cursor
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	    glass_pane.removeMouseListener(mouse_blocker_listener);
+	    glass_pane = null;
+	    mouse_blocker_listener= null;
+
+	    if (successful) {
+		resultPrompt(true, "");
+	    } else {
+		resultPrompt(false, error_message.toString());
+	    }
+	    error_message = null;
+	}
+    }
+
+    private class CollectionEntry {
+
+	private String name = null;
+	private CollectionConfiguration config = null;
+
+	public CollectionEntry(String name, CollectionConfiguration config) {
+	    this.name = name;
+	    this.config = config;
+	}
+
+	public String getName() {
+	    return name;
+	}
+
+	public String getTitle() {
+	    return config.getName();
+	}
+
+	public String getCreator() {
+	    return config.getCreator();
+	}
+
+	public String getDescription() {
+	    return config.getDescription();
+	}
+	
+	public String getMaintainer() {
+	    return config.getMaintainer();
+	}
+
+	public String toString() {
+	    return name + " - \"" + config.getName() + "\"";	    
+	}
+    }
+}
