001/* Utilities for accessing MoML.
002
003 Copyright (c) 2009-2013 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 OR RESEARCH IN MOTION
012 LIMITED BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
013 INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
014 SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
015 OR RESEARCH IN MOTION LIMITED HAVE BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION LIMITED
019 SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
021 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
022 BASIS, AND THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION
023 LIMITED HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
024 ENHANCEMENTS, OR MODIFICATIONS.
025
026
027 */
028package ptolemy.data.expr;
029
030import java.lang.reflect.Method;
031
032import ptolemy.data.ActorToken;
033import ptolemy.kernel.Entity;
034import ptolemy.kernel.util.IllegalActionException;
035import ptolemy.kernel.util.NamedObj;
036
037///////////////////////////////////////////////////////////////////
038//// MoMLUtilities
039
040/** This class provides access to the Ptolemy MoML parser
041 in ptolemy.moml by using reflection.
042
043 @author Christopher Brooks.  Based on ParseMoML by Edward A. Lee. Based on MatlabUtilities by Steve Neuendorffer and Zoltan Kemenczy (Research in Motion Ltd.)
044 @version $Id$
045 @since Ptolemy II 8.0
046 @Pt.ProposedRating Red (cxh)
047 @Pt.AcceptedRating Red (cxh)
048 @see ptolemy.data.expr.ParseTreeEvaluator
049 */
050public class MoMLUtilities {
051    /** Parse the string provided and return the result wrapped in a token.
052     *  @param moml The MoML string.
053     *  @return The result of parsing the MoML.
054     *  @exception Exception If the MoML is invalid or the results is not an
055     *   instance of Entity.
056     */
057    public static ActorToken parseMoML(String moml) throws Exception {
058        // This code is tested in ptolemy/moml/test/parseMoML.tcl
059        // because this code requires that ptolemy.moml be present
060        try {
061            if (_parserClass == null) {
062                _initialize();
063            }
064
065            // This is not static so that we avoid memory leaks.
066            Object parser = null;
067
068            try {
069                parser = _parserClass.newInstance();
070            } catch (InstantiationException ex) {
071                throw new IllegalActionException(null, ex,
072                        "Failed to instantiate ptolemy.moml.MoMLParser");
073            }
074
075            // We synchronize here because MatlabUtilities is synchronized.
076            synchronized (_parserClass) {
077                _parserResetAll.invoke(parser, new Object[0]);
078
079                NamedObj parseResult = (NamedObj) _parserParse.invoke(parser,
080                        new Object[] { moml });
081                return new ActorToken((Entity) parseResult);
082            }
083        } catch (Exception ex) {
084            throw new IllegalActionException(null, ex,
085                    "Problem invoking a method on ptolemy.moml.MoMLParser");
086        }
087    }
088
089    ///////////////////////////////////////////////////////////////////
090    ////                         private methods                   ////
091
092    // Initialize private variables.
093    private static void _initialize() throws IllegalActionException {
094        // These could be in the constructor, but since the evaluate()
095        // method is a static method, we break out the functionality into
096        // a separate method.
097        // Use reflection so that we can compile without
098        // ptolemy.moml and we check to see if is present at runtime.
099        try {
100            _parserClass = Class.forName("ptolemy.moml.MoMLParser");
101        } catch (Throwable throwable) {
102            // UnsatsifiedLinkError is an Error, not an Exception, so
103            // we catch Throwable
104            throw new IllegalActionException(null, throwable,
105                    "Failed to load ptolemy.moml.MoMLParser");
106        }
107
108        try {
109            // Methods of ptolemy.moml.MoMLParser, in alphabetical order.
110            _parserParse = _parserClass.getMethod("parse",
111                    new Class[] { String.class });
112
113            _parserResetAll = _parserClass.getMethod("resetAll", new Class[0]);
114        } catch (NoSuchMethodException ex) {
115            throw new IllegalActionException(null, ex,
116                    "Problem finding a method of " + "ptolemy.moml.MoMLParser");
117        }
118    }
119
120    ///////////////////////////////////////////////////////////////////
121    ////                         private variables                 ////
122
123    // The class of ptolemy.moml.MoMLParser
124    private static Class _parserClass;
125
126    // Methods of ptolemy.moml.MoMLParser, in alphabetical order.
127
128    // ptolemy.moml.MoMLParser.parse(String)
129    private static Method _parserParse;
130
131    // ptolemy.moml.MoMLParser.resetAll()
132    private static Method _parserResetAll;
133}