source: main/trunk/gli/src/org/greenstone/gatherer/gui/ReplaceSrcDocWithHtmlPrompt.java@ 32706

Last change on this file since 32706 was 20957, checked in by ak19, 14 years ago

When dealing with a remote Greenstone server, file separators need to be replaced with vertical bar since we don't know what operating system the remote GS server is (and hence what File separator it uses).

File size: 17.2 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: Anupama Krishnan, Greenstone Digital Library, University of Waikato
9 * Code based entirely on Katherine Don's ExplodeMetadataDatabasePrompt.java
10 * (part of the Greenstone Digital Library)
11 *
12 * Copyright (C) 2008 Greenstone Digital Library Project
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *########################################################################
28 */
29package org.greenstone.gatherer.gui;
30
31import java.awt.*;
32import java.awt.event.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.text.*;
36import java.io.*;
37import java.util.ArrayList;
38
39import org.w3c.dom.Document;
40
41import org.greenstone.gatherer.Dictionary;
42import org.greenstone.gatherer.Configuration;
43import org.greenstone.gatherer.Gatherer;
44import org.greenstone.gatherer.cdm.Argument;
45import org.greenstone.gatherer.cdm.ArgumentControl;
46import org.greenstone.gatherer.cdm.CollectionDesignManager;
47import org.greenstone.gatherer.cdm.Plugin;
48import org.greenstone.gatherer.collection.CollectionManager;
49import org.greenstone.gatherer.collection.ScriptOptions;
50import org.greenstone.gatherer.collection.Collection;
51import org.greenstone.gatherer.feedback.Base64;
52import org.greenstone.gatherer.greenstone.LocalGreenstone;
53import org.greenstone.gatherer.gui.tree.DragTree;
54import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
55import org.greenstone.gatherer.shell.GShell;
56import org.greenstone.gatherer.shell.GShellEvent;
57import org.greenstone.gatherer.shell.GShellListener;
58import org.greenstone.gatherer.util.Utility;
59import org.greenstone.gatherer.util.XMLTools;
60
61public class ReplaceSrcDocWithHtmlPrompt
62 extends ModalDialog
63 implements GShellListener
64{
65 /** The size of this new collection dialog box. */
66 static private Dimension SIZE = new Dimension(675, 250);
67 private JDialog self;
68
69 /** the source document files we wil be replacing with their GS3-generated html equivalent */
70 private File[] srcdoc_files = null;
71 /** the names of the srcdoc_files that could not be replaced with their GS3-generated html equivalent */
72 private java.util.Vector failedFiles = null;
73
74 /** the list of potential plugins to be used */
75 private Argument plugin_arg = null;
76 /** holds all the available options for the src-replacing script */
77 private ScriptOptions options = null;
78 /** the pane containing the options */
79 private JPanel options_pane = null;
80 /** the error message if any */
81 private StringBuffer error_message = null;
82 /** whether we were successful or not */
83 private boolean successful;
84 /** The command output of a successful execution of the replace script
85 * containing the generated tailname of the replacement file */
86 private String successfulOutput;
87
88 public ReplaceSrcDocWithHtmlPrompt(File[] source_files) {
89 super(Gatherer.g_man, true);
90 this.self = this;
91 this.srcdoc_files = source_files;
92 failedFiles = new java.util.Vector(source_files.length); // number of failures will never be more than num source docs
93
94 // check that we actually have a src doc file which can be replaced with its GS3-generated html
95 // since all the files here have the same extension, the first file can be used to work out
96 // the necessary plugin
97 ArrayList replacer_plugins = CollectionDesignManager.plugin_manager.getSrcReplacerPlugins(source_files[0]);
98 if (replacer_plugins.size() == 0) {
99 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("ReplaceSrcWithHTMLPrompt.NotSrcReplaceable"), Dictionary.get("ReplaceSrcWithHTMLPrompt.Title"), JOptionPane.ERROR_MESSAGE);
100 return;
101 }
102 plugin_arg = createPluginArgument(replacer_plugins);
103 setJMenuBar(new SimpleMenuBar("replacingSourceDoc"));
104 setSize(SIZE);
105 setTitle(Dictionary.get("ReplaceSrcWithHTMLPrompt.Title"));
106
107 // set up the script options
108 // we have empty initial values
109 String dom_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Options/>";
110 Document doc = XMLTools.parseXML(new StringReader(dom_string));
111 options = new ScriptOptions(doc.getDocumentElement(), "replace_srcdoc_with_html.pl");
112
113 // Creation
114 JPanel content_pane = (JPanel) getContentPane();
115 content_pane.setOpaque(true);
116 content_pane.setComponentOrientation(Dictionary.getOrientation());
117 options_pane = new JPanel();
118
119 addScriptOptions(options_pane);
120 JScrollPane middle_pane = new JScrollPane(options_pane);
121 middle_pane.setComponentOrientation(Dictionary.getOrientation());
122
123 JTextArea instructions_area = new JTextArea(Dictionary.get("ReplaceSrcWithHTMLPrompt.Instructions"));
124 instructions_area.setComponentOrientation(Dictionary.getOrientation());
125 instructions_area.setEditable(false);
126 instructions_area.setLineWrap(true);
127 instructions_area.setRows(5);
128 instructions_area.setWrapStyleWord(true);
129
130 JPanel button_pane = new JPanel();
131 button_pane.setComponentOrientation(Dictionary.getOrientation());
132 JButton srcreplace_button = new GLIButton(Dictionary.get("ReplaceSrcWithHTMLPrompt.ReplaceSrc"), Dictionary.get("ReplaceSrcWithHTMLPrompt.ReplaceSrc_Tooltip"));
133 JButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
134
135 // Connection
136 cancel_button.addActionListener(new CancelListener());
137 srcreplace_button.addActionListener(new SrcReplaceListener());
138
139 // Layout
140
141 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
142 button_pane.setLayout(new GridLayout(1,2));
143 button_pane.add(srcreplace_button);
144 button_pane.add(cancel_button);
145
146 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
147 content_pane.setLayout(new BorderLayout());
148 content_pane.add(instructions_area, BorderLayout.NORTH);
149 content_pane.add(middle_pane, BorderLayout.CENTER);
150 content_pane.add(button_pane, BorderLayout.SOUTH);
151
152 // Final dialog setup & positioning.
153 Dimension screen_size = Configuration.screen_size;
154 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
155 setVisible(true);
156 }
157
158 public void destroy()
159 {
160
161 }
162
163 /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
164 * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
165 */
166 public synchronized void message(GShellEvent event) {
167 String message = event.getMessage();
168 if (message.startsWith("replace_srcdoc_with_html.pl>")) {
169 message = message.substring(28); // length of "replace_srcdoc_with_html.pl>"?
170 error_message.append(message);
171 error_message.append("\n");
172 }
173 }
174
175 /** 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.
176 * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
177 */
178 public synchronized void processBegun(GShellEvent event) {
179 // We don't care.
180 }
181
182 /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
183 * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
184 */
185 public synchronized void processComplete(GShellEvent event) {
186 successful = false;
187 if(event.getStatus() == GShell.OK) {
188 successful = true;
189 GShell process = (GShell)event.getSource();
190 successfulOutput = process.getCommandOutput();
191 process.resetCommandOutput();
192 }
193 }
194
195 private Argument createPluginArgument(ArrayList plugin_list) {
196 Argument arg = new Argument();
197 arg.setName("plugin");
198 arg.setDescription(Dictionary.get("ReplaceSrcWithHTMLPrompt.Plugin"));
199 arg.setRequired(true);
200 arg.setType(Argument.ENUM);
201 for (int i=0; i<plugin_list.size(); i++) {
202 Plugin p = (Plugin)plugin_list.get(i);
203 arg.addOption(p.getName(), p.getName());
204 }
205 return arg;
206 }
207 private void addScriptOptions(JPanel options_pane) {
208
209 options_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
210 options_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
211 options_pane.setLayout(new BoxLayout(options_pane, BoxLayout.Y_AXIS));
212
213 int current_mode = Configuration.getMode();
214 int total_argument_count = options.getArgumentCount();
215
216 // first we add the plugin arg
217 ArgumentControl argument_control = new ArgumentControl(plugin_arg, true, null);
218 argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
219 options_pane.add((JComponent)argument_control);
220 for(int i = 0; i < total_argument_count; i++) {
221 // Retrieve the argument so we know how to format the control.
222 Argument argument = options.getArgument(i);
223 if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
224 // by default, all args are disabled, and no value
225 argument_control = new ArgumentControl(argument, false, null);
226
227 // make sure they are coloured the way we want - this is not the standard arg control coloring
228 argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
229 options_pane.add((JComponent)argument_control);
230 }
231 }
232 }
233
234 private void updateScriptOptions() {
235 for(int i = 0; i < options_pane.getComponentCount(); i++) {
236 Component component = options_pane.getComponent(i);
237 if(component instanceof ArgumentControl) {
238 ArgumentControl ac = (ArgumentControl)component;
239 String name = ac.getArgumentName();
240 String value = ac.getValue();
241 boolean enabled = ac.isEnabled();
242 if (!enabled && value==null) {
243 // flag type, remove from options altogether
244 options.removeValue(name);
245 } else {
246 if (value.equals("")) {
247 // if the value is empty, we don't want it to be passed to the script
248 options.setValue(name, false, value);
249 } else {
250 options.setValue(name, enabled, value);
251 }
252 }
253
254 }
255 }
256 }
257
258 private int replaceSrcDoc(int fileNum)
259 {
260 // Generate the replace_srcdoc_with_html.pl command
261 ArrayList command_parts_list = new ArrayList();
262 if (!Gatherer.isGsdlRemote) {
263 command_parts_list.add(Configuration.perl_path);
264 command_parts_list.add("-S");
265 }
266 command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "replace_srcdoc_with_html.pl");
267
268 // Add in all the options from the user
269 String[] src_replace_options = options.getValues();
270 for (int i = 0; i < src_replace_options.length; i++) {
271 command_parts_list.add(src_replace_options[i]);
272 }
273
274 // Local case
275 if (!Gatherer.isGsdlRemote) {
276 // Add in the filename
277 command_parts_list.add(this.srcdoc_files[fileNum].getPath());
278 }
279 // Remote case
280 else {
281 // Add in the filename, relative to the collection directory
282 String collection_name = CollectionManager.getLoadedCollectionName();
283 String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
284 String srcdoc_file_relative_path = Gatherer.remoteGreenstoneServer.getPathRelativeToDirectory(
285 this.srcdoc_files[fileNum], collection_directory_path); // preserves spaces in filename
286 srcdoc_file_relative_path = srcdoc_file_relative_path.replace(File.separatorChar, '|');
287
288 // base64 encode the relative filepath, so that special characters in the filename are preserved
289 command_parts_list.add("-file");
290 command_parts_list.add(Base64.encodeBytes(srcdoc_file_relative_path.getBytes()));
291
292 // When running remotely we also need the collection name as the last argument
293 command_parts_list.add(collection_name);
294 }
295
296 // Run the replace_srcdoc_with_html.pl command
297 String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
298 this.error_message = new StringBuffer();
299
300 GShell process = new GShell(command_parts, GShell.SRCREPLACE, 3, this, null, GShell.GSHELL_SRCREPLACE);
301 //process.start();
302 process.run();
303
304 if (successful) {
305 return 0;
306 }
307 return 1;
308 }
309
310 private void resultPrompt(boolean success, String message)
311 {
312 if (success) {
313 // !!! TO DO: Get replace_srcdoc_with_html.pl strings translated and use SimpleResultDialog below
314 JOptionPane.showMessageDialog(null, Dictionary.get("ReplaceSrcWithHTMLPrompt.Successful_ReplaceSrc"), Dictionary.get("ReplaceSrcWithHTMLPrompt.Successful_Title"), JOptionPane.INFORMATION_MESSAGE);
315 }
316 else {
317 String title = Dictionary.get("ReplaceSrcWithHTMLPrompt.Failed_Title");
318
319 // comma separated list of all the names of the files that could not be replaced
320 String failedFilenames = failedFiles.size() > 0 ? failedFiles.get(0).toString() : "";
321 for(int i = 1; i < failedFiles.size(); i++) {
322 failedFilenames = failedFilenames + ", " + failedFiles.get(i);
323 }
324
325 String label = Dictionary.get("ReplaceSrcWithHTMLPrompt.Failed_ReplaceSrc", failedFilenames);//srcdoc_file.getName());
326 SimpleResultDialog result_dialog = new SimpleResultDialog(title, label, message);
327 result_dialog.setVisible(true); // Blocks
328 result_dialog.dispose();
329 result_dialog = null;
330 }
331 }
332
333 private class CancelListener
334 implements ActionListener {
335 public void actionPerformed(ActionEvent event) {
336 self.dispose();
337 }
338 }
339
340 private class SrcReplaceListener
341 implements ActionListener {
342
343 public void actionPerformed(ActionEvent event) {
344 Gatherer.g_man.wait(true);
345 // update the options
346 updateScriptOptions();
347 self.dispose();
348 (new ReplaceSrcDocWithHtmlTask()).start();
349 }
350 }
351
352
353 private class ReplaceSrcDocWithHtmlTask
354 extends Thread
355 {
356 public ReplaceSrcDocWithHtmlTask()
357 {
358 }
359
360 public void run()
361 {
362 int exit_value = 0;
363 String errMsg = "";
364
365 // We're going to try replacing all selected documents and then
366 // display errormessages
367 // first run the replace process for all src files, and accumulate error exit values (0 means it's fine)
368 for(int i = 0; i < srcdoc_files.length; i++) {
369 int exit_value_this_time = replaceSrcDoc(i);
370 exit_value += exit_value_this_time; // if all files successfully replaced, exit_value will stay at 0
371
372 // accumulate all error and success msgs to display after processing all the files
373 // that are to be replaced
374 errMsg += error_message.toString();
375 error_message = null;
376
377 if(exit_value_this_time != 0) {
378 failedFiles.add(srcdoc_files[i].getName()); // add this file to list of failures
379 } else {
380 if (Gatherer.isGsdlRemote) {
381 //System.err.println("*****ReplaceSrcDocWithHtmlPrompt.java - run() - gsdl remote case");
382
383 // Conversion may have renamed the file by URL- or base64-encoding it.
384 // The new replacement file's tailname is the last line of the script output.
385 String[] lines = successfulOutput.split("\n");
386 String suffixlessFilename = lines[lines.length-1];
387 String htmlFile = suffixlessFilename+".html";
388
389 // Delete the local copy of the old source document file on the client side
390 // (it's already been replaced on the server side), and download the updated
391 // (html) file and any directory containing associated files
392 Utility.delete(srcdoc_files[i]); // remove the local copy of src doc
393
394 // download the generated html file from the server side to put it
395 // into the import directory on the client side
396 Gatherer.remoteGreenstoneServer.downloadCollectionFile(
397 CollectionManager.getLoadedCollectionName(),
398 new File(srcdoc_files[i].getParentFile(), htmlFile));
399
400 // download any assoc folder which is srcfilename+"_files"
401 File assoc_folder = new File(srcdoc_files[i].getParentFile(), suffixlessFilename+"_files");
402
403 // If an associated_folder by such a name exists, download it
404 if(Gatherer.remoteGreenstoneServer.exists(CollectionManager.getLoadedCollectionName(), assoc_folder)) {
405 Gatherer.remoteGreenstoneServer.downloadCollectionFile(
406 CollectionManager.getLoadedCollectionName(), assoc_folder);
407 }
408 }
409 // Whether remote or local case, need to refressh the GLI filemanager system to show
410 // what files are in the current collection space
411 Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED); // refreshes coll's content view
412 Gatherer.g_man.wait(false);
413 }
414 } // end for loop
415
416 // Display error messages now that we finished processing the multiple files
417 if(exit_value != 0) {
418 resultPrompt(false, errMsg);
419 } else {
420 resultPrompt(true, errMsg);
421 }
422 } // end run method
423
424 } //end Task class
425}
Note: See TracBrowser for help on using the repository browser.