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}