source: main/trunk/gli/src/org/greenstone/gatherer/gui/ConfigFileEditor.java@ 31831

Last change on this file since 31831 was 31582, checked in by ak19, 7 years ago

In place of the Input- and OutputStreamGobbler classes, am now shifting GLI code to use SafeProcess too, copied across from GS3 src code. Class SafeProcess includes the two streamgobblers as static inner classes and some more functionality with safely running an external process from Java.

File size: 9.8 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 * Copyright (C) 1999 New Zealand Digital Library Project
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *########################################################################
24 */
25
26package org.greenstone.gatherer.gui;
27
28import org.greenstone.gatherer.Configuration;
29import org.greenstone.gatherer.Dictionary;
30import org.greenstone.gatherer.Gatherer;
31import org.greenstone.gatherer.util.StaticStrings;
32import org.greenstone.gatherer.util.Utility;
33import org.greenstone.gatherer.util.XMLTools;
34
35import org.w3c.dom.*;
36
37
38import java.io.File;
39import java.io.IOException;
40
41import java.awt.*;
42import java.awt.event.*;
43import java.util.*;
44import javax.swing.*;
45import javax.swing.border.*;
46import javax.swing.event.*;
47
48
49public class ConfigFileEditor extends ModalDialog
50 implements ActionListener, DocumentListener
51{
52 public final File config_file;
53
54 private GLIButton cancel_button = null;
55 private GLIButton save_button = null;
56 private NumberedJTextArea editor = null;
57 private JTextArea editor_msgarea;
58
59 //private final String DEFAULT_PROCESSING_INSTRUCTION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
60
61 private static final Dimension SIZE = new Dimension(850,550);
62
63 public ConfigFileEditor() {
64
65 super(Gatherer.g_man, true);
66 setModal(true);
67 setSize(SIZE);
68
69 String collection_folder_path = Gatherer.getCollectDirectoryPath();
70 String collectionName = Gatherer.c_man.getCollection().getName(); // we won't be in this constructor if collection is null.
71 this.config_file = new File(collection_folder_path + File.separator + collectionName, Utility.CONFIG_GS3_FILE); // col config editing is a GS3 feature
72
73
74 // Most of the validation_msg_panel code is from Format4gs3Manager.java
75 JPanel validation_msg_panel = new JPanel();
76 JLabel validation_label = new JLabel(Dictionary.get("CDM.FormatManager.MessageBox"));
77 validation_label.setBorder(new EmptyBorder(10,10,10,10)); // add some margin
78 editor_msgarea = new JTextArea();
79
80 editor_msgarea.setCaretPosition(0);
81 editor_msgarea.setLineWrap(true);
82 editor_msgarea.setRows(3);
83 editor_msgarea.setWrapStyleWord(false);
84 editor_msgarea.setEditable(false);
85 editor_msgarea.setToolTipText(Dictionary.get("CDM.FormatManager.MessageBox_Tooltip"));
86 validation_msg_panel.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
87 validation_msg_panel.setLayout(new BorderLayout(5, 0));
88 validation_msg_panel.add(validation_label, BorderLayout.WEST);
89 validation_msg_panel.add(new JScrollPane(editor_msgarea), BorderLayout.CENTER);
90
91 // the all important XML editor
92 editor = new NumberedJTextArea(Dictionary.get("ConfigFileEditor.Tooltip"));
93 editor.getDocument().addDocumentListener(this);
94
95 save_button = new GLIButton(Dictionary.get("General.Save"), Dictionary.get("ConfigFileEditor.Save_Tooltip"));
96 cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("ConfigFileEditor.Cancel_Tooltip")); // tooltip is the same
97 cancel_button.addActionListener(this);
98 save_button.addActionListener(this);
99
100 // LAYOUT
101 JPanel button_panel = new JPanel(new FlowLayout());
102 button_panel.setComponentOrientation(Dictionary.getOrientation());
103 button_panel.add(editor.undoButton);
104 button_panel.add(editor.redoButton);
105 button_panel.add(cancel_button);
106 button_panel.add(save_button);
107
108 JPanel content_pane = (JPanel) getContentPane();
109 content_pane.setComponentOrientation(Dictionary.getOrientation());
110 content_pane.setLayout(new BorderLayout());
111 content_pane.add(validation_msg_panel, BorderLayout.NORTH);
112 content_pane.add(new JScrollPane(editor), BorderLayout.CENTER); // make editor scrollable
113 content_pane.add(button_panel, BorderLayout.SOUTH);
114
115
116 // NOW WE CAN PREPARE THE ACTUAL CONTENT TO GO INTO THE XML EDITOR TEXTAREA
117 Document xmlDoc = null;
118 xmlDoc = XMLTools.parseXMLFile(config_file);
119
120 if(xmlDoc != null) {
121
122 // Save the collectionConfig.xml before loading it.
123 String[] nonEscapingTagNames = { StaticStrings.FORMAT_STR, StaticStrings.DISPLAYITEM_STR };
124 XMLTools.writeXMLFile(this.config_file, xmlDoc, nonEscapingTagNames); //prepends proc instruction
125
126 // now load the contents
127 editor_msgarea.setBackground(Color.white);
128 StringBuffer sb = new StringBuffer();
129 XMLTools.xmlNodeToString(sb, xmlDoc.getDocumentElement(), true, " ", 0);
130 editor.setText(sb.toString());
131 //editor.setText(elementToString(xmlDoc.getDocumentElement(), true)); // reading in file this way adds processing instruction, which the parser doesn't like.
132
133 } else { // parsing failed
134 // so read in file as text and display as text and show the validation box in red
135
136 // Won't re-save file that is already invalid before it's even been edited through this Editor
137 System.err.println("*** Warning: Parsing error in file " + config_file + ".");
138 System.err.println("*** Not saving ahead of editing.");
139
140 String xml_str = Utility.readFile(config_file);
141
142 // re-parse to get error msg to display in validation field
143
144 // but first get rid of the preprocessing instruction, as this will fail parsing
145 String processingInstruction = getProcessingInstruction(xml_str);
146 xml_str = xml_str.replace(processingInstruction, "").trim(); // also trim newline at start
147
148 if(!xml_str.equals("")) {
149
150 String msg = XMLTools.parse(xml_str); // re-parse
151 editor_msgarea.setBackground(Color.red);
152 editor_msgarea.setText(msg); // display the parsing error
153 save_button.setEnabled(false);
154
155 editor.setText(xml_str); // display the xml contents with error and all
156
157 } else {
158 editor.setText("");
159 editor_msgarea.setText("Empty collection config file");
160 }
161 }
162
163 // Final dialog setup & positioning.
164 setDefaultCloseOperation(DISPOSE_ON_CLOSE); // get rid of this dialog when it's closed (on dispose())
165 getRootPane().setDefaultButton(save_button);
166 Dimension screen_size = Configuration.screen_size;
167 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
168 }
169
170 public void actionPerformed(ActionEvent e) {
171
172 if(e.getSource() == cancel_button) {
173 this.dispose(); // get rid of this dialog, we're done
174 }
175 else if(e.getSource() == save_button) {
176 // write out the XML to the collectionConfig.xml file and we're done.
177
178 // already know the xml in the textarea is valid, else the save_button would have been inactive
179 Document xml_file_doc = XMLTools.getDOM(editor.getText());
180 // This code from FormatConversionDialog.dispose()
181 // saves the XML, prepending the processing instruction (<?xml ... ?>)
182 String[] nonEscapingTagNames = { StaticStrings.FORMAT_STR, StaticStrings.DISPLAYITEM_STR };
183 XMLTools.writeXMLFile(this.config_file, xml_file_doc, nonEscapingTagNames);
184
185 this.dispose(); // get rid of this dialog, we're done
186
187 // close and reopen the collection in GLI
188 String current_collection_filepath = Gatherer.c_man.getCollection().getCollectionPath();
189 Gatherer.c_man.closeCollection();
190 Gatherer.c_man.loadCollection(current_collection_filepath);
191 }
192 }
193
194
195
196 // This method returns a proper processing instruction (starts with <?xml and ends with ?>)
197 // else the empty string is returned
198 public String getProcessingInstruction(String xmlStr) {
199 String processingInstruction = "";
200
201 xmlStr = xmlStr.trim();
202 if(xmlStr.startsWith("<?xml")) {
203 int endIndex = xmlStr.indexOf("?>"); // end of processing instruction
204
205 if(endIndex != -1) {
206 endIndex += 2;
207 processingInstruction = xmlStr.substring(0, endIndex);
208 }
209 }
210 return processingInstruction;
211 }
212
213
214 // THE FOLLOWING FUNCTIONS ARE LARGELY FROM Format4gs3Manager.java.EditorListener
215 public void changedUpdate(DocumentEvent e)
216 {
217 update();
218 }
219
220 public void insertUpdate(DocumentEvent e)
221 {
222 update();
223 updateUndo("insert");
224
225 }
226
227 public void removeUpdate(DocumentEvent e)
228 {
229 update();
230 updateUndo("remove");
231
232 }
233
234 private void updateUndo(String from)
235 {
236
237 editor.undoButton.setEnabled(true);
238 }
239
240 public void update()
241 {
242
243 String xml_str = editor.getText();
244
245 // Processing instructions "<?xml...?>" are no longer displayed in the editor (but
246 // they are written out to the file on save) so we don't need to deal with them here.
247
248 // can't parse with processing instruction <?xml...?>, so remove that
249 ///String processingInstruction = getProcessingInstruction(xml_str);
250 ///xml_str = xml_str.replace(processingInstruction, "");
251 // now can parse the XML portion without the processing instruction,
252 // while the original XML remains unchanged in the editor area
253 // If the processing instruction was incomplete, then xml_str would still
254 // include the incomplete processing instruction, and parsing below will catch the error.
255
256 String msg = XMLTools.parse(xml_str);
257 editor_msgarea.setText(msg);
258
259 if (msg.startsWith(XMLTools.WELLFORMED))
260 {
261 editor_msgarea.setBackground(Color.white);
262 save_button.setEnabled(true);
263 }
264 else
265 {
266 editor_msgarea.setBackground(Color.red);
267 save_button.setEnabled(false);
268 }
269 }
270
271}
Note: See TracBrowser for help on using the repository browser.