001/* A representative of a plot file.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026 */
027package ptolemy.actor.gui;
028
029import java.io.File;
030import java.io.FileOutputStream;
031import java.io.IOException;
032import java.net.URL;
033
034import ptolemy.kernel.CompositeEntity;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.NameDuplicationException;
037import ptolemy.kernel.util.Workspace;
038import ptolemy.plot.PlotBoxInterface;
039
040///////////////////////////////////////////////////////////////////
041//// PlotEffigy
042
043/**
044 An effigy for a plot file.
045
046 @author Edward A. Lee
047 @version $Id$
048 @since Ptolemy II 2.1
049 @Pt.ProposedRating Red (neuendor)
050 @Pt.AcceptedRating Red (neuendor)
051 */
052public class PlotEffigy extends PtolemyEffigy {
053    // FIXME: Why does this extend PtolemyEffigy?  It means that everywhere
054    // we check for PtolemyEffigy, we need to make sure the graph is not a
055    // PlotEffigy.  See vergil.actor.ActorGraphTableau
056
057    /** Create a new effigy in the specified workspace with an empty string
058     *  for its name.
059     *  @param workspace The workspace for this effigy.
060     */
061    public PlotEffigy(Workspace workspace) {
062        super(workspace);
063    }
064
065    /** Create a new effigy in the given directory with the given name.
066     *  @param container The directory that contains this effigy.
067     *  @param name The name of this effigy.
068     *  @exception IllegalActionException If the entity cannot be contained
069     *   by the proposed container.
070     *  @exception NameDuplicationException If the name coincides with
071     *   an entity already in the container.
072     */
073    public PlotEffigy(CompositeEntity container, String name)
074            throws IllegalActionException, NameDuplicationException {
075        super(container, name);
076    }
077
078    ///////////////////////////////////////////////////////////////////
079    ////                         public methods                    ////
080
081    /** Return the plot that this is an effigy of.
082     *  @return The plot or null if none has been set.
083     *  @see #setPlot(PlotBoxInterface)
084     */
085    public PlotBoxInterface getPlot() {
086        return _plot;
087    }
088
089    /** Set the plot that this is an effigy of.
090     *  @param plot The plot.
091     *  @see #getPlot()
092     */
093    public void setPlot(PlotBoxInterface plot) {
094        _plot = plot;
095    }
096
097    /** Write the text of the plot to the specified file.
098     *  If no plot has been specified, then no write occurs.
099     *  @param file The file to write to.
100     *  @exception IOException If the write fails.
101     */
102    @Override
103    public void writeFile(File file) throws IOException {
104        if (_plot != null) {
105            FileOutputStream stream = null;
106
107            try {
108                stream = new FileOutputStream(file);
109                _plot.write(stream);
110            } finally {
111                if (stream != null) {
112                    try {
113                        stream.close();
114                    } catch (Throwable throwable) {
115                        System.out.println("Ignoring failure to close stream "
116                                + "on " + file);
117                        throwable.printStackTrace();
118                    }
119                }
120            }
121        }
122    }
123
124    ///////////////////////////////////////////////////////////////////
125    ////                         private members                   ////
126    // The plot associated with this effigy.
127    private PlotBoxInterface _plot;
128
129    ///////////////////////////////////////////////////////////////////
130    ////                         inner classes                     ////
131
132    /** A factory for creating new effigies.
133     */
134    public static class Factory extends EffigyFactory {
135        /** Create a factory with the given name and container.
136         *  @param container The container.
137         *  @param name The name.
138         *  @exception IllegalActionException If the container is incompatible
139         *   with this entity.
140         *  @exception NameDuplicationException If the name coincides with
141         *   an entity already in the container.
142         */
143        public Factory(CompositeEntity container, String name)
144                throws IllegalActionException, NameDuplicationException {
145            super(container, name);
146        }
147
148        ///////////////////////////////////////////////////////////////
149        ////                     public methods                    ////
150
151        /** Return false, indicating that this effigy factory is not
152         *  capable of creating an effigy without a URL being specified.
153         *  @return False.
154         */
155        @Override
156        public boolean canCreateBlankEffigy() {
157            return false;
158        }
159
160        /** Create a new effigy in the given container by reading the
161         *  specified URL. If the specified URL is null, or
162         *  if the URL does not end with extension ".plt", ".plot", or
163         *  ".xml", then return null.  If the extension is ".xml",
164         *  then read the file and return null if it does not contain
165         *  a line that starts with the string
166         *  <code>&gt;!DOCTYPE plot PUBLIC "-//UC Berkeley//DTD PlotML</code>
167         *  within the first five lines.
168         *  Note that as of this writing, the plotter
169         *  parses any file you give it without complaint, so we cannot
170         *  rely on the plotter to report that this file is not a plot
171         *  file.  Thus, we assume that if the extension matches,
172         *  then it is.
173         *  @param container The container for the effigy.
174         *  @param base The base for relative file references, or null if
175         *   there are no relative file references.  This is ignored in this
176         *   class.
177         *  @param input The input URL.
178         *  @return A new instance of PlotEffigy, or null if the URL
179         *   does not have a recognized extension.
180         *  @exception Exception If the URL cannot be read.
181         */
182        @Override
183        public Effigy createEffigy(CompositeEntity container, URL base,
184                URL input) throws Exception {
185            if (input != null) {
186                String extension = getExtension(input);
187
188                if (extension.equals("xml")) {
189                    if (checkForDTD(input,
190                            "<!DOCTYPE plot PUBLIC \"-//UC Berkeley//DTD PlotML",
191                            null)) {
192                        // This is a plot file.
193                        PlotEffigy effigy = new PlotEffigy(container,
194                                container.uniqueName("effigy"));
195                        effigy.uri.setURL(input);
196                        return effigy;
197                    }
198                } else if (extension.equals("plt")
199                        || extension.equals("plot")) {
200                    PlotEffigy effigy = new PlotEffigy(container,
201                            container.uniqueName("effigy"));
202                    effigy.uri.setURL(input);
203                    return effigy;
204                }
205            }
206
207            return null;
208        }
209    }
210}