001/* Plotter application that is capable of reading PlotML files.
002
003 @Author: Edward A. Lee
004
005 @Version: $Id$
006
007 @Copyright (c) 1997-2016 The Regents of the University of California.
008 All rights reserved.
009
010 Permission is hereby granted, without written agreement and without
011 license or royalty fees, to use, copy, modify, and distribute this
012 software and its documentation for any purpose, provided that the
013 above copyright notice and the following two paragraphs appear in all
014 copies of this software.
015
016 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
017 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
018 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
019 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
020 SUCH DAMAGE.
021
022 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
023 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
024 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
025 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
026 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
027 ENHANCEMENTS, OR MODIFICATIONS.
028
029 PT_COPYRIGHT_VERSION_2
030 COPYRIGHTENDKEY
031 */
032package ptolemy.plot.plotml;
033
034import java.io.BufferedInputStream;
035import java.io.IOException;
036import java.io.InputStream;
037import java.net.URL;
038
039import javax.swing.JOptionPane;
040import javax.swing.SwingUtilities;
041
042import com.microstar.xml.XmlException;
043
044import ptolemy.plot.Plot;
045import ptolemy.plot.PlotApplication;
046import ptolemy.plot.PlotBox;
047import ptolemy.util.StringUtilities;
048
049///////////////////////////////////////////////////////////////////
050//// PlotMLApplication
051
052/**
053 An application that can plot data in PlotML format from a URL or
054 from files specified on the command line.
055 To compile and run this application, do the following:
056 <pre>
057 javac -classpath ../.. PlotMLApplication.java
058 java -classpath ../.. ptolemy.plot.plotml.PlotMLApplication
059 </pre>
060
061 @author Edward A. Lee
062 @version $Id$
063 @since Ptolemy II 0.4
064 @Pt.ProposedRating red (eal)
065 @Pt.AcceptedRating red (cxh)
066 @see PlotBox
067 @see Plot
068 */
069@SuppressWarnings("serial")
070public class PlotMLApplication extends PlotApplication {
071    /** Construct a plot with no command-line arguments.
072     *  It initially displays a sample plot.
073     *  @exception Exception If command line arguments have problems.
074     */
075    public PlotMLApplication() throws Exception {
076        this(null);
077    }
078
079    /** Construct a plot with the specified command-line arguments.
080     *  @param args The command-line arguments.
081     *  @exception Exception If command line arguments have problems.
082     */
083    public PlotMLApplication(String[] args) throws Exception {
084        this(new Plot(), args);
085    }
086
087    /** Construct a plot with the specified command-line arguments
088     *  and instance of plot.
089     *  @param plot The instance of Plot to use.
090     *  @param args The command-line arguments.
091     *  @exception Exception If command line arguments have problems.
092     */
093    public PlotMLApplication(PlotBox plot, String[] args) throws Exception {
094        super(plot, args);
095    }
096
097    ///////////////////////////////////////////////////////////////////
098    ////                         public methods                    ////
099
100    /** Create a new plot window and map it to the screen.
101     *  The command to run would be:
102     *  <pre>
103     *  java -classpath $PTII ptolemy.plot.plotml.PlotMLApplication
104     *  </pre>
105     *  @param args Arguments suitable for the
106     *  {@link ptolemy.plot.Plot} class.
107     */
108    public static void main(final String[] args) {
109        try {
110            Runnable doActions = new Runnable() {
111                @Override
112                public void run() {
113                    try {
114                        new PlotMLApplication(new Plot(), args);
115                    } catch (Exception ex) {
116                        System.err.println(ex.toString());
117                        ex.printStackTrace();
118                    }
119                }
120            };
121
122            // NOTE: Using invokeAndWait() here risks causing
123            // deadlock.  However, the Sun Tutorial recommends calling
124            // invokeAndWait so that the work finishes before returning.
125            // if we call invokeLater() then demo/PlotFourierSeries.java
126            // has problems.
127            SwingUtilities.invokeAndWait(doActions);
128        } catch (Exception ex) {
129            System.err.println(ex.toString());
130            ex.printStackTrace();
131        }
132
133        // If the -test arg was set, then exit after 2 seconds.
134        if (_test) {
135            try {
136                Thread.sleep(2000);
137            } catch (InterruptedException e) {
138            }
139
140            StringUtilities.exit(0);
141        }
142    }
143
144    ///////////////////////////////////////////////////////////////////
145    ////                         protected methods                 ////
146    @Override
147    protected void _about() {
148        JOptionPane.showMessageDialog(this,
149                "PlotMLApplication class\n" + "By: Edward A. Lee "
150                        + "and Christopher Hylands\n" + "Version "
151                        + PlotBox.PTPLOT_RELEASE + ", Build: $Id$\n\n"
152                        + "For more information, see\n"
153                        + "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n"
154                        + "Copyright (c) 1997-2016, "
155                        + "The Regents of the University of California.",
156                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
157    }
158
159    /** Display more detailed information than given by _about().
160     */
161    @Override
162    protected void _help() {
163        JOptionPane.showMessageDialog(this,
164                "PlotMLApplication is a standalone plot " + " application.\n"
165                        + "  File formats understood: PlotML and Ptplot ASCII.\n"
166                        + "  Left mouse button: Zooming.\n\n" + _usage(),
167                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
168    }
169
170    /** Read the specified stream.  This method checks to see whether
171     *  the data is PlotML data, and if so, creates a parser to read it.
172     *  If not, it defers to the parent class to read it.
173     *  @param base The base for relative file references, or null if
174     *   there are not relative file references.
175     *  @param in The input stream.
176     *  @exception IOException If the stream cannot be read.
177     */
178    @Override
179    protected void _read(URL base, InputStream in) throws IOException {
180        // Create a buffered input stream so that mark and reset
181        // are supported.
182        BufferedInputStream bin = new BufferedInputStream(in);
183
184        // Peek at the file...
185        bin.mark(9);
186
187        // Read 8 bytes in case 16-bit encoding is being used.
188        byte[] peek = new byte[8];
189        int bytesRead = bin.read(peek);
190        if (bytesRead != peek.length) {
191            throw new IOException("Read only " + bytesRead + "bytes, expecting "
192                    + peek.length);
193        }
194        bin.reset();
195
196        if (new String(peek).startsWith("<?xm")) {
197            // file is an XML file.
198            PlotBoxMLParser parser = _newParser();
199
200            try {
201                parser.parse(base, bin);
202            } catch (Exception ex) {
203                String msg;
204
205                if (ex instanceof XmlException) {
206                    XmlException xmlex = (XmlException) ex;
207                    msg = "PlotMLApplication: failed to parse PlotML data:\n"
208                            + "line: " + xmlex.getLine() + ", column: "
209                            + xmlex.getColumn() + "\nIn entity: "
210                            + xmlex.getSystemId() + "\n";
211                } else {
212                    msg = "PlotMLApplication: failed to parse PlotML data:\n";
213                }
214
215                System.err.println(msg + ex.toString());
216                ex.printStackTrace();
217            }
218        } else {
219            super._read(base, bin);
220        }
221    }
222
223    /** Create a new parser object for the application.  Derived classes can
224     *  redefine this method to return a different type of parser.
225     *  @return A new parser.
226     */
227    protected PlotBoxMLParser _newParser() {
228        if (plot instanceof Plot) {
229            return new PlotMLParser((Plot) plot);
230        } else {
231            return new PlotBoxMLParser(plot);
232        }
233    }
234}