001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2015-06-18 22:21:04 +0000 (Thu, 18 Jun 2015) $' 
007 * '$Revision: 33484 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030
031package org.kepler.provenance;
032
033import java.io.BufferedWriter;
034import java.io.FileWriter;
035import java.io.IOException;
036import java.io.StringWriter;
037import java.text.SimpleDateFormat;
038import java.util.Date;
039
040import javax.xml.parsers.DocumentBuilder;
041import javax.xml.parsers.DocumentBuilderFactory;
042import javax.xml.transform.OutputKeys;
043import javax.xml.transform.Transformer;
044import javax.xml.transform.TransformerConfigurationException;
045import javax.xml.transform.TransformerException;
046import javax.xml.transform.TransformerFactory;
047import javax.xml.transform.dom.DOMSource;
048import javax.xml.transform.stream.StreamResult;
049
050import org.w3c.dom.Comment;
051import org.w3c.dom.Document;
052import org.w3c.dom.Element;
053
054import ptolemy.actor.Actor;
055import ptolemy.actor.Director;
056import ptolemy.actor.FiringEvent;
057import ptolemy.actor.IOPortEvent;
058import ptolemy.actor.IORelation;
059import ptolemy.actor.TypedIOPort;
060import ptolemy.data.StringToken;
061import ptolemy.data.expr.FileParameter;
062import ptolemy.data.expr.Parameter;
063import ptolemy.kernel.util.AbstractSettableAttribute;
064import ptolemy.kernel.util.IllegalActionException;
065import ptolemy.kernel.util.NameDuplicationException;
066import ptolemy.kernel.util.NamedObj;
067
068/** Provenance recording that outputs to an XML file.
069 *  
070 *  @author Faraaz Sareshwala
071 *  @version $Id: XMLRecording.java 33484 2015-06-18 22:21:04Z crawl $
072 *  @deprecated This no longer works. For XML output, use ProvRecording.
073 */
074@Deprecated
075public class XMLRecording extends Recording
076{
077        public XMLRecording() throws RecordingException
078        {
079                super();
080
081                try
082                {
083                        // We need a Document
084                        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
085                        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
086                        xmldoc = docBuilder.newDocument();
087
088                        // create the root element and add it to the document
089                        xmlroot = xmldoc.createElement("run");
090                        Comment comment = xmldoc.createComment("Parameters and ports are given in their display name form only."
091                                        + " Constructing the full name is simply the entity full name + \".\" + displayname");
092                        xmlroot.appendChild(comment);
093                        xmldoc.appendChild(xmlroot);
094                }
095                catch(Exception e)
096                {
097                        e.printStackTrace();
098                }
099        }
100
101        public boolean regActor(Actor actor) throws RecordingException
102        {
103                xmlactor = xmldoc.createElement("actor");
104                xmlactor.setAttribute("name", actor.getFullName());
105                xmlroot.appendChild(xmlactor);
106
107                return true;
108        }
109
110        public boolean regDirector(Director director) throws RecordingException
111        {
112                // create director child element, add an attribute, and add to root
113                xmldirector = xmldoc.createElement("director");
114                xmldirector.setAttribute("name", director.getFullName());
115                xmlroot.appendChild(xmldirector);
116
117                return true;
118        }
119
120        /** Register a link between two endpoints. */
121        public boolean regLink(NamedObj endPoint1, NamedObj endPoint2) throws RecordingException
122        {
123                // TODO: Monitor this.
124
125                return true;
126        }
127
128        /** Register a port or portparameter. */
129        public boolean regPort(TypedIOPort port) throws RecordingException
130        {
131                xmlport = xmldoc.createElement("port");
132                xmlport.setAttribute("name", port.getFullName());
133                xmlactor.appendChild(xmlport);
134
135                return true;
136        }
137
138        /** Register a relation. */
139        public boolean regRelation(IORelation relation) throws RecordingException
140        {
141                // TODO: Monitor this.
142
143                return true;
144        }
145
146        public boolean regParameter(NamedObj parameter) throws RecordingException
147        {
148                Element xmlparameter = xmldoc.createElement("parameter");
149                xmlparameter.setAttribute("name", parameter.getDisplayName());
150                xmlparameter.setAttribute("class", parameter.getClassName());
151
152                if(parameter instanceof AbstractSettableAttribute)
153                        xmlparameter.setTextContent(((AbstractSettableAttribute) parameter).getValueAsString());
154
155                if(xmldirector != null && parameter.getContainer().getFullName().equals(xmldirector.getAttribute("name")))
156                        xmldirector.appendChild(xmlparameter); // are we working with a director?
157                else if(xmlactor != null && parameter.getContainer().getFullName().equals(xmlactor.getAttribute("name")))
158                        xmlactor.appendChild(xmlparameter); // are we working with an actor?
159                else if(xmlport != null && parameter.getContainer().getFullName().equals(xmlport.getAttribute("name")))
160                        xmlport.appendChild(xmlparameter); // are we working with a port?
161
162                return true;
163        }
164
165        /**
166         * Record the stopping of workflow execution.
167         */
168        public void executionStop() throws RecordingException
169        {
170                try
171                {
172                        FileParameter fp = _params.getFileParameter();
173                        String name = ((StringToken) fp.getToken()).stringValue();
174
175                        // remove possible "file:" prefix
176                        if(name.startsWith("file:"))
177                                name = name.substring("file:".length());
178
179                        // save the name
180                        _outputName = name;
181
182                        TransformerFactory transfac = TransformerFactory.newInstance();
183                        Transformer trans = transfac.newTransformer();
184                        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
185                        trans.setOutputProperty(OutputKeys.INDENT, "yes");
186
187                        // create string from xml tree
188                        StringWriter sw = new StringWriter();
189                        StreamResult result = new StreamResult(sw);
190                        DOMSource source = new DOMSource(xmldoc);
191                        trans.transform(source, result);
192                        String xmlString = sw.toString();
193
194                        BufferedWriter output = new BufferedWriter(new FileWriter(name));
195
196                        output.write(xmlString);
197                        output.close();
198                }
199                catch(TransformerConfigurationException e)
200                {
201                        e.printStackTrace();
202                }
203                catch(TransformerException e)
204                {
205                        e.printStackTrace();
206                }
207                catch(IllegalActionException e)
208                {
209                        e.printStackTrace();
210                }
211                catch(IOException e)
212                {
213                        e.printStackTrace();
214                }
215        }
216
217        /** Record starting an actor fire event. */
218        public void actorFire(FiringEvent event) throws RecordingException
219        {
220
221                if(event.getType() == event.AFTER_FIRE)
222                {
223                        // create actor event element, add an attribute, and add to root
224                        Element xmlevent = xmldoc.createElement("event");
225                        xmlevent.setAttribute("timestamp", Long.toString(new Date().getTime()));
226                        xmlevent.setAttribute("type", "actorFire");
227                        xmlevent.setAttribute("entity", event.getActor().getFullName());
228                        xmlroot.appendChild(xmlevent);
229                }
230        }
231
232        /** Record a port event. */
233        public void portEvent(IOPortEvent event) throws RecordingException
234        {
235                // create port event element, add an attribute, and add to root
236                Element xmlevent = xmldoc.createElement("event");
237                xmlevent.setAttribute("timestamp", Long.toString(new Date().getTime()));
238                xmlevent.setAttribute("type", "portEvent");
239                xmlevent.setAttribute("entity", event.getPort().getFullName());
240
241                Element xmltoken = xmldoc.createElement("token");
242                xmltoken.setTextContent(event.getToken().toString());
243                xmlevent.appendChild(xmltoken);
244
245                xmlroot.appendChild(xmlevent);
246        }
247
248        /** Add Parameters for ProvenanceListener. */
249        public RecordingParameters generateParameters(NamedObj no) throws IllegalActionException, NameDuplicationException
250        {
251                _params = new XMLRecordingParameters(no);
252                return _params;
253        }
254
255        /* Adapted from TextFileRecording to perform the same actions.
256         * Can be extended later.
257         * Configuration Parameters for TextFileRecording. */
258        protected class XMLRecordingParameters extends RecordingParameters
259        {
260                XMLRecordingParameters(NamedObj no) throws IllegalActionException, NameDuplicationException
261                {
262                        super(no);
263                        addBooleanParameter(_recordSpecStr, _recordSpecVal);
264                        addFileParameter(_filenameStr, "System.out");
265                }
266
267                /** Get the "Record Specification" check-box value. */
268                boolean getRecordSpecValue() throws IllegalActionException
269                {
270                        return getBooleanValue(_recordSpecStr);
271                }
272
273                /** Get the output FileParameter. */
274                FileParameter getFileParameter() throws IllegalActionException
275                {
276                        return (FileParameter) _params.get(_filenameStr);
277                }
278
279                /** Replace a Parameter. */
280                public void replaceParameter(String name, Parameter parameter) throws IllegalActionException
281                {
282                        // if replacing the filename, close the file.
283                        if(name.equals(_filenameStr))
284                        {
285                                FileParameter p = (FileParameter) _params.get(_filenameStr);
286                                p.close();
287                        }
288
289                        super.replaceParameter(name, parameter);
290                }
291
292                private static final String _recordSpecStr = "Record Specification";
293                private static final String _filenameStr = "Filename";
294        }
295
296        // //////////////////////////////////////////////////////////////////////
297        // // protected variables ////
298
299        /** Whether to record workflow specification. */
300        protected boolean _recordSpecVal = true;
301
302        /** Whether to always flush after writing to output. */
303        protected boolean _alwaysFlushVal = false;
304
305        /** Format timestamps. */
306        protected SimpleDateFormat _dFormat = null;
307
308        /** Parameters for TextFileRecording */
309        protected XMLRecordingParameters _params = null;
310
311        /** Output name. */
312        protected String _outputName = null;
313
314        /** XML Document **/
315        Document xmldoc = null;
316
317        /** XML Root **/
318        Element xmlroot = null;
319
320        /** XML Actor currently being edited **/
321        Element xmlactor = null;
322
323        /** XML Director currently being edited **/
324        Element xmldirector = null;
325
326        /** XML Port currently being edited **/
327        Element xmlport = null;
328}