001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: brooks $'
006 * '$Date: 2012-06-18 00:36:48 +0000 (Mon, 18 Jun 2012) $' 
007 * '$Revision: 29975 $'
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
030package org.sdm.spa.gui;
031
032import java.util.Set;
033
034import ptolemy.actor.gui.Effigy;
035import ptolemy.actor.gui.Tableau;
036import ptolemy.actor.gui.TableauFactory;
037import ptolemy.data.Token;
038import ptolemy.data.expr.ASTPtAssignmentNode;
039import ptolemy.data.expr.ASTPtRootNode;
040import ptolemy.data.expr.ModelScope;
041import ptolemy.data.expr.Parameter;
042import ptolemy.data.expr.ParseTreeEvaluator;
043import ptolemy.data.expr.ParserScope;
044import ptolemy.data.expr.PtParser;
045import ptolemy.data.expr.Variable;
046import ptolemy.gui.ShellInterpreter;
047import ptolemy.kernel.util.Attribute;
048import ptolemy.kernel.util.IllegalActionException;
049import ptolemy.kernel.util.NameDuplicationException;
050import ptolemy.kernel.util.NamedObj;
051
052//////////////////////////////////////////////////////////////////////////
053//// DoubleShellTAPTableau
054/**
055 * Based on the Ptolemy II v.3.0.2 code ExpressionShellTableau.java A tableau
056 * that provides an interactive shell for evaluating expressions.
057 * 
058 * @author Ilkay Altintas
059 * @version $Id: DoubleShellTAPTableau.java 29975 2012-06-18 00:36:48Z brooks $
060 */
061public class DoubleShellTAPTableau extends Tableau implements ShellInterpreter {
062
063        /**
064         * Create a new tableau. The tableau is itself an entity contained by the
065         * effigy and having the specified name. The frame is not made visible
066         * automatically. You must call show() to make it visible.
067         * 
068         * @param container
069         *            The containing effigy.
070         * @param name
071         *            The name of this tableau within the specified effigy.
072         * @exception IllegalActionException
073         *                If the tableau is not acceptable to the specified
074         *                container.
075         * @exception NameDuplicationException
076         *                If the container already contains an entity with the
077         *                specified name.
078         */
079        public DoubleShellTAPTableau(DoubleShellTAPEffigy container, String name)
080                        throws IllegalActionException, NameDuplicationException {
081                super(container, name);
082                frame = new DoubleShellTAPTableauFrame(this);
083                setFrame(frame);
084                frame.setTableau(this);
085                _evaluator = new ParseTreeEvaluator();
086        }
087
088        // /////////////////////////////////////////////////////////////////
089        // // public methods ////
090
091        /**
092         * Evaluate the specified command.
093         * 
094         * @param command
095         *            The command.
096         * @return The return value of the command, or null if there is none.
097         * @exception Exception
098         *                If something goes wrong processing the command.
099         */
100        public String evaluateCommand(String command) throws Exception {
101                if (command.trim().equals("")) {
102                        return "";
103                }
104                PtParser parser = new PtParser();
105                ASTPtRootNode node = parser.generateSimpleAssignmentParseTree(command);
106                String targetName = null;
107
108                // Figure out if we got an assignment... if so, then get the
109                // identifier name and only evaluated the expression part.
110                if (node instanceof ASTPtAssignmentNode) {
111                        ASTPtAssignmentNode assignmentNode = (ASTPtAssignmentNode) node;
112                        targetName = assignmentNode.getIdentifier();
113                        node = assignmentNode.getExpressionTree();
114                }
115
116                final NamedObj model = ((DoubleShellTAPEffigy) getContainer())
117                                .getModel();
118                ParserScope scope = new ModelScope() {
119                        public ptolemy.data.Token get(String name)
120                                        throws IllegalActionException {
121                                Variable result = getScopedVariable(null, model, name);
122                                if (result != null) {
123                                        return result.getToken();
124                                } else {
125                                        return null;
126                                }
127                        }
128
129                        public ptolemy.data.type.Type getType(String name)
130                                        throws IllegalActionException {
131                                Variable result = getScopedVariable(null, model, name);
132                                if (result != null) {
133                                        return result.getType();
134                                } else {
135                                        return null;
136                                }
137                        }
138
139                        public ptolemy.graph.InequalityTerm getTypeTerm(String name)
140                                        throws IllegalActionException {
141                                Variable result = getScopedVariable(null, model, name);
142                                if (result != null) {
143                                        return result.getTypeTerm();
144                                } else {
145                                        return null;
146                                }
147                        }
148
149                        public Set identifierSet() {
150                                return getAllScopedVariableNames(null, model);
151                        }
152                };
153
154                Token result = _evaluator.evaluateParseTree(node, scope);
155
156                // If a target was specified, instantiate a new token.
157                if (targetName != null) {
158                        Attribute attribute = model.getAttribute(targetName);
159                        if (attribute != null && !(attribute instanceof Parameter)) {
160                                attribute.setContainer(null);
161                                attribute = null;
162                        }
163                        if (attribute == null) {
164                                attribute = new Parameter(model, targetName);
165                        }
166                        ((Parameter) attribute).setToken(result);
167                }
168
169                if (result == null) {
170                        return "";
171                } else {
172                        return result.toString();
173                }
174        }
175
176        /**
177         * Return true if the specified command is complete (ready to be
178         * interpreted).
179         * 
180         * @param command
181         *            The command.
182         * @return True.
183         */
184        public boolean isCommandComplete(String command) {
185                return true;
186        }
187
188        // /////////////////////////////////////////////////////////////////
189        // // public variables ////
190
191        /** The associated frame. */
192        public DoubleShellTAPTableauFrame frame;
193
194        /** The contained shell. */
195        public DoubleShellTextAreaPanel shellPanel;
196
197        // /////////////////////////////////////////////////////////////////
198        // // private variables ////
199
200        // The parameter used for evaluation.
201        private ParseTreeEvaluator _evaluator;
202
203        // /////////////////////////////////////////////////////////////////
204        // // inner classes ////
205
206        /**
207         * A factory that creates a control panel to display a Tcl Shell
208         */
209        public static class Factory extends TableauFactory {
210
211                /**
212                 * Create a factory with the given name and container.
213                 * 
214                 * @param container
215                 *            The container.
216                 * @param name
217                 *            The name.
218                 * @exception IllegalActionException
219                 *                If the container is incompatible with this attribute.
220                 * @exception NameDuplicationException
221                 *                If the name coincides with an attribute already in the
222                 *                container.
223                 */
224                public Factory(NamedObj container, String name)
225                                throws IllegalActionException, NameDuplicationException {
226                        super(container, name);
227                }
228
229                // /////////////////////////////////////////////////////////////////
230                // // public methods ////
231
232                /**
233                 * Create a new instance of ExpressionShellTableau in the specified
234                 * effigy. It is the responsibility of callers of this method to check
235                 * the return value and call show().
236                 * 
237                 * @param effigy
238                 *            The model effigy.
239                 * @return A new control panel tableau if the effigy is a PtolemyEffigy,
240                 *         or null otherwise.
241                 * @exception Exception
242                 *                If the factory should be able to create a tableau for
243                 *                the effigy, but something goes wrong.
244                 */
245                public Tableau createTableau(Effigy effigy) throws Exception {
246                        // NOTE: Can create any number of tableaux within the same
247                        // effigy. Is this what we want?
248                        if (effigy instanceof DoubleShellTAPEffigy) {
249                                return new DoubleShellTAPTableau((DoubleShellTAPEffigy) effigy,
250                                                "DoubleShellTAPTableau");
251                        } else {
252                                return null;
253                        }
254                }
255        }
256}