Index: /gli/trunk/src/org/greenstone/gatherer/gui/ReplaceSrcDocWithHtmlPrompt.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/gui/ReplaceSrcDocWithHtmlPrompt.java	(revision 15122)
+++ /gli/trunk/src/org/greenstone/gatherer/gui/ReplaceSrcDocWithHtmlPrompt.java	(revision 15122)
@@ -0,0 +1,384 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *
+ * Author: Anupama Krishnan, Greenstone Digital Library, University of Waikato
+ * Code based entirely on Katherine Don's ExplodeMetadataDatabasePrompt.java
+ * (part of the Greenstone Digital Library)
+ *
+ * Copyright (C) 2008 Greenstone Digital Library Project
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import java.io.*;
+import java.util.ArrayList;
+
+import org.w3c.dom.Document;
+
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentControl;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.Plugin;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.collection.ScriptOptions;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+
+public class ReplaceSrcDocWithHtmlPrompt	
+    extends ModalDialog
+    implements GShellListener
+{
+    /** The size of this new collection dialog box. */
+    static private Dimension SIZE = new Dimension(675, 250);
+    private JDialog self;
+    
+    /** the source document files we wil be replacing with their GS3-generated html equivalent */
+    private File[] srcdoc_files = null;
+     /** the names of the srcdoc_files that could not be replaced with their GS3-generated html equivalent */
+    private java.util.Vector failedFiles = null;
+
+    /** the list of potential plugins to be used */
+    private Argument plugin_arg = null;
+    /** holds all the available options for the src-replacing script */
+    private ScriptOptions options = null;
+    /** the pane containing the options */
+    private JPanel options_pane = null;
+    /** the error message if any */
+    private StringBuffer error_message = null;
+    /** whether we were successful or not */
+    private boolean successful;
+
+
+    public ReplaceSrcDocWithHtmlPrompt(File[] source_files) {
+	super(Gatherer.g_man, true);
+	this.self = this;
+	this.srcdoc_files = source_files;
+	failedFiles = new java.util.Vector(source_files.length); // number of failures will never be more than num source docs
+
+	// check that we actually have a src doc file which can be replaced with its GS3-generated html
+	// since all the files here have the same extension, the first file can be used to work out 
+	// the necessary plugin
+	ArrayList replacer_plugins = CollectionDesignManager.plugin_manager.getSrcReplacerPlugins(source_files[0]);
+	if (replacer_plugins.size() == 0) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("ReplaceSrcWithHTMLPrompt.NotSrcReplaceable"), Dictionary.get("ReplaceSrcWithHTMLPrompt.Title"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+	plugin_arg = createPluginArgument(replacer_plugins);
+	setJMenuBar(new SimpleMenuBar("replacingSourceDoc"));
+	setSize(SIZE);
+	setTitle(Dictionary.get("ReplaceSrcWithHTMLPrompt.Title"));
+	
+	// set up the script options
+	// we have empty initial values
+	String dom_string = "<Options/>";
+	Document doc = XMLTools.parseXML(new StringReader(dom_string));
+	options = new ScriptOptions(doc.getDocumentElement(), "replace_srcdoc_with_html.pl");
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setOpaque(true);
+	
+	options_pane = new JPanel();
+	addScriptOptions(options_pane);
+	JScrollPane middle_pane = new JScrollPane(options_pane);
+
+	JTextArea instructions_area = new JTextArea(Dictionary.get("ReplaceSrcWithHTMLPrompt.Instructions"));
+	instructions_area.setEditable(false);
+	instructions_area.setLineWrap(true);
+	instructions_area.setRows(5);
+	instructions_area.setWrapStyleWord(true);
+	
+	JPanel button_pane = new JPanel();
+	JButton srcreplace_button = new GLIButton(Dictionary.get("ReplaceSrcWithHTMLPrompt.ReplaceSrc"), Dictionary.get("ReplaceSrcWithHTMLPrompt.ReplaceSrc_Tooltip"));
+	JButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(new CancelListener());
+	srcreplace_button.addActionListener(new SrcReplaceListener());
+
+	// Layout
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(srcreplace_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(instructions_area, BorderLayout.NORTH);
+	content_pane.add(middle_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Final dialog setup & positioning.
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+
+    public void destroy() 
+    {
+       	
+    }
+
+    /** 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) {
+	String message = event.getMessage();
+	if (message.startsWith("replace_srcdoc_with_html.pl>")) {
+	    message = message.substring(28); // length of "replace_srcdoc_with_html.pl>"?
+	    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) {
+	successful = false;
+	if(event.getStatus() == GShell.OK) {
+	    successful = true;
+	}
+    }
+
+    private Argument createPluginArgument(ArrayList plugin_list) {
+	Argument arg = new Argument();
+	arg.setName("plugin");
+	arg.setDescription(Dictionary.get("ReplaceSrcWithHTMLPrompt.Plugin"));
+	arg.setRequired(true);
+	arg.setType(Argument.ENUM);
+	for (int i=0; i<plugin_list.size(); i++) {
+	    Plugin p = (Plugin)plugin_list.get(i);
+	    arg.addOption(p.getName(), p.getName());
+	}
+	return arg;
+    }
+    private void addScriptOptions(JPanel options_pane) {
+
+	options_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	options_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	options_pane.setLayout(new BoxLayout(options_pane, BoxLayout.Y_AXIS));
+
+	int current_mode = Configuration.getMode();
+	int total_argument_count = options.getArgumentCount();
+       
+	// first we add the plugin arg
+	ArgumentControl argument_control = new ArgumentControl(plugin_arg, true, null);
+	argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	options_pane.add((JComponent)argument_control);
+	for(int i = 0; i < total_argument_count; i++) {
+	    // Retrieve the argument so we know how to format the control.
+	    Argument argument = options.getArgument(i);
+	    if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
+		// by default, all args are disabled, and no value
+		argument_control = new ArgumentControl(argument, false, null);
+	
+		// make sure they are coloured the way we want - this is not the standard arg control coloring
+		argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+		options_pane.add((JComponent)argument_control);
+	    }
+	}
+    }
+
+    private void updateScriptOptions() {
+	for(int i = 0; i < options_pane.getComponentCount(); i++) {
+	    Component component = options_pane.getComponent(i);
+	    if(component instanceof ArgumentControl) {
+		ArgumentControl ac = (ArgumentControl)component;
+		String name = ac.getArgumentName();
+		String value = ac.getValue();
+		boolean enabled = ac.isEnabled();
+		if (!enabled && value==null) {
+		    // flag type, remove from options altogether
+		    options.removeValue(name);
+		} else {
+		    if (value.equals("")) {
+			// if the value is empty, we don't want it to be passed to the script
+			options.setValue(name, false, value);
+		    } else {
+			options.setValue(name, enabled, value);
+		    }
+		}
+
+	    }
+	}
+    }
+  
+    private int replaceSrcDoc(int fileNum)
+    {
+	// Generate the replace_srcdoc_with_html.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if (Utility.isWindows() && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "replace_srcdoc_with_html.pl");
+	
+	// Add in all the options from the user
+	String[] src_replace_options = options.getValues();
+	for (int i = 0; i < src_replace_options.length; i++) {
+	    command_parts_list.add(src_replace_options[i]);
+	}
+
+	// Local case
+	if (!Gatherer.isGsdlRemote) {    
+	    // Add in the filename
+	    command_parts_list.add(this.srcdoc_files[fileNum].getPath());
+	}
+	// Remote case
+	else {
+	    // Add in the filename, relative to the collection directory
+	    String collection_name = CollectionManager.getLoadedCollectionName();
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String srcdoc_file_relative_path = RemoteGreenstoneServer.getPathRelativeToDirectory(
+		   this.srcdoc_files[fileNum], collection_directory_path);
+	    command_parts_list.add("-file");
+	    command_parts_list.add(srcdoc_file_relative_path);
+	    	    
+	    // When running remotely we also need the collection name as the last argument
+	    command_parts_list.add(collection_name);
+	}
+
+	// Run the replace_srcdoc_with_html.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	this.error_message = new StringBuffer();
+
+	GShell process = new GShell(command_parts, GShell.SRCREPLACE, 3, this, null, GShell.GSHELL_SRCREPLACE);
+	//process.start();
+	process.run();
+	
+	if (successful) {
+	    return 0;
+	} 
+	return -1;
+    }	
+
+    private void resultPrompt(boolean success, String message)
+    {
+	if (success) {
+	    // !!! TO DO: Get replace_srcdoc_with_html.pl strings translated and use SimpleResultDialog below
+	    JOptionPane.showMessageDialog(null, Dictionary.get("ReplaceSrcWithHTMLPrompt.Successful_ReplaceSrc"), Dictionary.get("ReplaceSrcWithHTMLPrompt.Successful_Title"), JOptionPane.INFORMATION_MESSAGE);
+	}
+	else {
+	    String title = Dictionary.get("ReplaceSrcWithHTMLPrompt.Failed_Title");
+	    
+	    // comma separated list of all the names of the files that could not be replaced
+	    String failedFilenames = failedFiles.size() > 0 ? failedFiles.get(0).toString() : "";
+	    for(int i = 1; i < failedFiles.size(); i++) {
+		failedFilenames = failedFilenames + ", " + failedFiles.get(i);
+	    }
+
+	    String label = Dictionary.get("ReplaceSrcWithHTMLPrompt.Failed_ReplaceSrc", failedFilenames);//srcdoc_file.getName());
+	    SimpleResultDialog result_dialog = new SimpleResultDialog(title, label, message);
+	    result_dialog.setVisible(true); // Blocks
+	    result_dialog.dispose();
+	    result_dialog = null;
+	}
+    }
+
+    private class CancelListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    self.dispose();
+	}
+    }
+    
+    private class SrcReplaceListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    Gatherer.g_man.wait(true);
+	    // update the options
+	    updateScriptOptions();
+	    self.dispose();  
+	    (new ReplaceSrcDocWithHtmlTask()).start();
+	}
+    }
+
+
+    private class ReplaceSrcDocWithHtmlTask
+	extends Thread
+    {
+	public ReplaceSrcDocWithHtmlTask()
+	{
+	}
+
+	public void run()
+	{
+	    int exit_value = 0;
+	    // first run the replace process for all src files, and accumulate error exit values (0 means it's fine)
+	    for(int i = 0; i < srcdoc_files.length; i++) {
+		int exit_value_this_time =  replaceSrcDoc(i);
+		exit_value += exit_value_this_time; // should remain at 0 if this file successfully replaced
+		if(exit_value_this_time != 0) {
+		    failedFiles.add(srcdoc_files[i].getName()); // add this file to list of failures
+		}
+	    }
+
+	    if (exit_value == 0) { // success on all files
+		// Clear out the old source document file and download the updated (collect?) directory
+		if (Gatherer.isGsdlRemote) {
+		    System.err.println("*****ReplaceSrcDocWithHtmlPrompt.java - ReplaceSrcDocWithHtmlTask.run() - gsdl remote case");
+		    // not sure what the new file is renamed to, so at present still delete entire
+		    // containing directory and get the updated copy of this directory from remote server
+		    Utility.delete(srcdoc_files[0].getParentFile()); // remove the local copy of containing dir
+		    RemoteGreenstoneServer.downloadCollectionFile(
+		         CollectionManager.getLoadedCollectionName(), srcdoc_files[0].getParentFile()); 
+		    //downloads the same folder from remote server - which should include 
+		    // the replaced srcdoc file's html and any associated img _files folder
+		}
+
+		// Replace the srcdoc file in the GLI filemanager system with its html equivalent
+                Collection collection = Gatherer.c_man.getCollection();
+		// this works: refreshes content view to what's in the collection
+		Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
+		resultPrompt(true, error_message.toString());
+	    } else { // failure
+		resultPrompt(false, error_message.toString());
+	    }
+	    error_message = null;
+	    Gatherer.g_man.wait(false);
+	}
+    }    
+}
