001package jmri.jmrit;
002
003import java.awt.Component;
004import java.awt.event.ActionEvent;
005import java.io.File;
006
007import javax.swing.JFileChooser;
008import javax.swing.JTextArea;
009
010import jmri.util.swing.JmriPanel;
011import jmri.util.swing.JmriJOptionPane;
012import jmri.util.swing.WindowInterface;
013
014/**
015 * Make sure an XML file is readable, and validates OK against its schema and DTD.
016 * <p>
017 * Can also be run from the command line as apps.jmrit.XmlFileValidationAction
018 * (e.g. ./runtest.csh apps/jmrit/XmlFileValidateAction foo.xml) in which case
019 * if there's a filename argument, it checks that directly, otherwise it pops a
020 * file selection dialog. (The dialog form has to be manually canceled when
021 * done)
022 *
023 * @author Bob Jacobsen Copyright (C) 2005, 2007
024 * @see jmri.jmrit.XmlFile
025 * @see jmri.jmrit.XmlFileCheckAction
026 */
027public class XmlFileValidateAction extends jmri.util.swing.JmriAbstractAction {
028
029    public XmlFileValidateAction(String s, Component who) {
030        super(s);
031        _who = who;
032    }
033
034    public XmlFileValidateAction(String s, WindowInterface wi) {
035        this(s, wi != null ? wi.getFrame() : null);
036    }
037
038    public XmlFileValidateAction() {
039        super(Bundle.getMessage("XmlFileValidateAction")); // NOI18N
040    }
041
042    private JFileChooser fci;
043
044    private Component _who;
045
046    private final XmlFile xmlfile = new XmlFile() {};   // odd syntax is due to XmlFile being abstract
047    
048    @Override
049    public void actionPerformed(ActionEvent e) {
050        if (fci == null) {
051            fci = jmri.jmrit.XmlFile.userFileChooser("XML files", "xml");
052        }
053        // request the filename from an open dialog
054        fci.rescanCurrentDirectory();
055        int retVal = fci.showOpenDialog(_who);
056        // handle selection or cancel
057        if (retVal == JFileChooser.APPROVE_OPTION) {
058            processFile(fci.getSelectedFile());
059        } else {
060            log.debug("XmlFileValidateAction cancelled in open dialog");
061        }
062    }
063
064    protected void processFile(File file) {
065        log.debug("located file \"{}\" for XML processing", file);
066        // handle the file (TODO should be outside this thread?)
067        try {
068            xmlfile.setValidate(XmlFile.Validate.CheckDtdThenSchema);
069            readFile(file);
070        } catch (Exception ex) {
071            showFailResults(_who, file.getName(), ex.getMessage());
072            return;
073        }
074        showOkResults(_who, Bundle.getMessage("ValidatedOk", file.getName()));
075        log.debug("parsing xml complete");
076    }
077
078    protected void showOkResults(Component who, String text) {
079        JmriJOptionPane.showMessageDialog(who, text);
080    }
081
082    protected void showFailResults(Component who, String fileName, String text) {
083        // non-editable line-wrapped JTextArea 30 columns wide so user can copy text
084        JTextArea jta = new JTextArea((int) Math.ceil((double)text.length() / 30),30);
085        jta.setLineWrap(true);
086        jta.setWrapStyleWord(true);
087        jta.setEditable(false);
088        jta.setText(text);
089        JmriJOptionPane.showMessageDialog(who, jta, 
090            Bundle.getMessage("ValidationErrorInFile", fileName), JmriJOptionPane.ERROR_MESSAGE);
091    }
092
093    /**
094     * Read and verify a file is schema valid XML.
095     *
096     * @param file the file to read
097     * @throws org.jdom2.JDOMException if file is not schema valid XML
098     * @throws java.io.IOException     if unable to read file
099     */
100    void readFile(File file) throws org.jdom2.JDOMException, java.io.IOException {
101        xmlfile.rootFromFile(file);
102
103    }
104
105    // never invoked, because we overrode actionPerformed above
106    @Override
107    public JmriPanel makePanel() {
108        throw new IllegalArgumentException("Should not be invoked");
109    }
110
111    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(XmlFileValidateAction.class);
112
113}