/** *######################################################################### * * 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. * * Copyright (C) 1999 New Zealand 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 org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.cdm.CollectionConfigXMLReadWrite; import org.greenstone.gatherer.util.Codec; import org.greenstone.gatherer.util.InputStreamGobbler; import org.greenstone.gatherer.util.OutputStreamGobbler; import org.greenstone.gatherer.util.StaticStrings; import org.greenstone.gatherer.util.Utility; import org.greenstone.gatherer.util.XMLTools; import org.w3c.dom.*; import java.io.File; import java.io.IOException; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; public class ConfigFileEditor extends ModalDialog implements ActionListener, DocumentListener { public final File config_file; private GLIButton cancel_button = null; private GLIButton save_button = null; private NumberedJTextArea editor = null; private JTextArea editor_msgarea; //private final String DEFAULT_PROCESSING_INSTRUCTION = ""; private static final Dimension SIZE = new Dimension(640,480); public ConfigFileEditor() { String collection_folder_path = Gatherer.getCollectDirectoryPath(); String collectionName = Gatherer.c_man.getCollection().getName(); // we won't be in this constructor if collection is null. this.config_file = new File(collection_folder_path + File.separator + collectionName, Utility.CONFIG_GS3_FILE); // col config editing is a GS3 feature // Most of the validation_msg_panel code is from Format4gs3Manager.java JPanel validation_msg_panel = new JPanel(); JLabel validation_label = new JLabel(Dictionary.get("CDM.FormatManager.MessageBox")); validation_label.setBorder(new EmptyBorder(10,10,10,10)); // add some margin editor_msgarea = new JTextArea(); editor_msgarea.setCaretPosition(0); editor_msgarea.setLineWrap(true); editor_msgarea.setRows(3); editor_msgarea.setWrapStyleWord(false); editor_msgarea.setEditable(false); editor_msgarea.setToolTipText(Dictionary.get("CDM.FormatManager.MessageBox_Tooltip")); validation_msg_panel.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); validation_msg_panel.setLayout(new BorderLayout(5, 0)); validation_msg_panel.add(validation_label, BorderLayout.WEST); validation_msg_panel.add(new JScrollPane(editor_msgarea), BorderLayout.CENTER); // the all important XML editor editor = new NumberedJTextArea(Dictionary.get("ConfigFileEditor.Tooltip")); editor.getDocument().addDocumentListener(this); save_button = new GLIButton(Dictionary.get("General.Save"), Dictionary.get("ConfigFileEditor.Save_Tooltip")); cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("ConfigFileEditor.Cancel_Tooltip")); // tooltip is the same cancel_button.addActionListener(this); save_button.addActionListener(this); // LAYOUT JPanel button_panel = new JPanel(new FlowLayout()); button_panel.setComponentOrientation(Dictionary.getOrientation()); button_panel.add(editor.undoButton); button_panel.add(editor.redoButton); button_panel.add(cancel_button); button_panel.add(save_button); JPanel content_pane = (JPanel) getContentPane(); content_pane.setComponentOrientation(Dictionary.getOrientation()); content_pane.setLayout(new BorderLayout()); content_pane.add(validation_msg_panel, BorderLayout.NORTH); content_pane.add(new JScrollPane(editor), BorderLayout.CENTER); // make editor scrollable content_pane.add(button_panel, BorderLayout.SOUTH); // NOW WE CAN PREPARE THE ACTUAL CONTENT TO GO INTO THE XML EDITOR TEXTAREA Document xmlDoc = null; xmlDoc = XMLTools.parseXMLFile(config_file); if(xmlDoc != null) { // Save the collectionConfig.xml before loading it. String[] nonEscapingTagNames = { StaticStrings.FORMAT_STR, StaticStrings.DISPLAYITEM_STR }; XMLTools.writeXMLFile(this.config_file, xmlDoc, nonEscapingTagNames); //prepends proc instruction // now load the contents editor_msgarea.setBackground(Color.white); StringBuffer sb = new StringBuffer(); XMLTools.xmlNodeToString(sb, xmlDoc.getDocumentElement(), true, " ", 0); editor.setText(sb.toString()); //editor.setText(elementToString(xmlDoc.getDocumentElement(), true)); // reading in file this way adds processing instruction, which the parser doesn't like. } else { // parsing failed // so read in file as text and display as text and show the validation box in red // Won't re-save file that is already invalid before it's even been edited through this Editor System.err.println("*** Warning: Parsing error in file " + config_file + "."); System.err.println("*** Not saving ahead of editing."); String xml_str = Utility.readFile(config_file); // re-parse to get error msg to display in validation field // but first get rid of the preprocessing instruction, as this will fail parsing String processingInstruction = getProcessingInstruction(xml_str); xml_str = xml_str.replace(processingInstruction, "").trim(); // also trim newline at start if(!xml_str.equals("")) { String msg = XMLTools.parse(xml_str); // re-parse editor_msgarea.setBackground(Color.red); editor_msgarea.setText(msg); // display the parsing error save_button.setEnabled(false); editor.setText(xml_str); // display the xml contents with error and all } else { editor.setText(""); editor_msgarea.setText("Empty collection config file"); } } // Final dialog setup & positioning. setDefaultCloseOperation(DISPOSE_ON_CLOSE); // get rid of this dialog when it's closed (on dispose()) getRootPane().setDefaultButton(save_button); Dimension screen_size = Configuration.screen_size; setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); } public void actionPerformed(ActionEvent e) { if(e.getSource() == cancel_button) { this.dispose(); // get rid of this dialog, we're done } else if(e.getSource() == save_button) { // write out the XML to the collectionConfig.xml file and we're done. // already know the xml in the textarea is valid, else the save_button would have been inactive Document xml_file_doc = XMLTools.getDOM(editor.getText()); // This code from FormatConversionDialog.dispose() // saves the XML, prepending the processing instruction () String[] nonEscapingTagNames = { StaticStrings.FORMAT_STR, StaticStrings.DISPLAYITEM_STR }; XMLTools.writeXMLFile(this.config_file, xml_file_doc, nonEscapingTagNames); this.dispose(); // get rid of this dialog, we're done } } // This method returns a proper processing instruction (starts with ) // else the empty string is returned public String getProcessingInstruction(String xmlStr) { String processingInstruction = ""; xmlStr = xmlStr.trim(); if(xmlStr.startsWith(""); // end of processing instruction if(endIndex != -1) { endIndex += 2; processingInstruction = xmlStr.substring(0, endIndex); } } return processingInstruction; } // THE FOLLOWING FUNCTIONS ARE LARGELY FROM Format4gs3Manager.java.EditorListener public void changedUpdate(DocumentEvent e) { update(); } public void insertUpdate(DocumentEvent e) { update(); updateUndo("insert"); } public void removeUpdate(DocumentEvent e) { update(); updateUndo("remove"); } private void updateUndo(String from) { editor.undoButton.setEnabled(true); } public void update() { String xml_str = editor.getText(); // Processing instructions "" are no longer displayed in the editor (but // they are written out to the file on save) so we don't need to deal with them here. // can't parse with processing instruction , so remove that ///String processingInstruction = getProcessingInstruction(xml_str); ///xml_str = xml_str.replace(processingInstruction, ""); // now can parse the XML portion without the processing instruction, // while the original XML remains unchanged in the editor area // If the processing instruction was incomplete, then xml_str would still // include the incomplete processing instruction, and parsing below will catch the error. String msg = XMLTools.parse(xml_str); editor_msgarea.setText(msg); if (msg.startsWith(XMLTools.WELLFORMED)) { editor_msgarea.setBackground(Color.white); save_button.setEnabled(true); } else { editor_msgarea.setBackground(Color.red); save_button.setEnabled(false); } } }