001/* A transition in an Interface Automaton.
002
003 Copyright (c) 1999-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.domains.modal.kernel.ia;
028
029import ptolemy.data.expr.Parameter;
030import ptolemy.domains.modal.kernel.Transition;
031import ptolemy.kernel.CompositeEntity;
032import ptolemy.kernel.util.Attribute;
033import ptolemy.kernel.util.IllegalActionException;
034import ptolemy.kernel.util.InternalErrorException;
035import ptolemy.kernel.util.NameDuplicationException;
036import ptolemy.kernel.util.Settable;
037import ptolemy.kernel.util.StringAttribute;
038
039///////////////////////////////////////////////////////////////////
040//// InterfaceAutomatonTransition
041
042/**
043 A Transition for Interface Automaton. In the Interface Automata paper
044 written by Luca de Alfaro and Henzinger, transitions are called actions.
045 However, the name action conflicts with the Action class in this package,
046 so this class uses the name transition.  There are three types of transitions:
047 input, output, and internal. Each transition has a label. The labels for
048 input, output, and internal transitions end with "?", "!", and ";",
049 respectively. The type of transition is determined by the ending character
050 of the label this way. Each input transition corresponds to an input port of
051 the InterfaceAutomaton that contains it, and its label, excluding the
052 ending "?", must be the same as the input port name; Similarly, each output
053 transition corresponds to an output port, and its label, excluding the
054 ending "!", must be the same as the output port name;  Each internal
055 transitions corresponds to a parameter of the InterfaceAutomaton that
056 contains it, and its label, excluding the ending ";", must be the same as
057 the parameter name.
058 <p>
059 The guard of each transition is set automatically. Users should not set
060 the guard. For an input transition, the guard is set to &lt;inputPort&gt;
061 _isPresent,
062 where &lt;inputPort&gt; is the port corresponding to this transition; For output
063 and internal transitions, the guard is set to true. Each of the output
064 and internal transitions contain an Action. The expression of the Action
065 is also set automatically. For output transition, the action is set to
066 &lt;outputPort&gt;=true, where &lt;outputPort&gt; is the output port
067 corresponding to this transition; for internal transition, the action is set
068 to &lt;parameter&gt;=true, where &lt;parameter&gt; is the parameter
069 corresponding to this transition.
070
071 @author Yuhong Xiong, Xiaojun Liu and Edward A. Lee
072 @version $Id$
073 @since Ptolemy II 8.0
074 @Pt.ProposedRating Red (yuhong)
075 @Pt.AcceptedRating Red (yuhong)
076 @see InterfaceAutomaton
077 @see ptolemy.domains.modal.kernel.Action
078 */
079public class InterfaceAutomatonTransition extends Transition {
080    /** Construct a transition with the specified container and name.
081     *  The container argument must not be null, or a NullPointerException
082     *  will be thrown. This transition will use the workspace of the
083     *  container for synchronization and version counts.
084     *  If the name argument is null, then the name is set to the empty string.
085     *  @param container An interface automaton.
086     *  @param name The name of this transition.
087     *  @exception IllegalActionException If the container is incompatible
088     *   with this transition.
089     *  @exception NameDuplicationException If the name coincides with
090     *   any relation already in the container.
091     */
092    public InterfaceAutomatonTransition(InterfaceAutomaton container,
093            String name)
094            throws IllegalActionException, NameDuplicationException {
095        super(container, name);
096        label = new StringAttribute(this, "label");
097        outputActions.setVisibility(Settable.NONE);
098        setActions.setVisibility(Settable.NONE);
099        preemptive.setVisibility(Settable.NONE);
100        history.setVisibility(Settable.NONE);
101        guardExpression.setVisibility(Settable.NONE);
102    }
103
104    ///////////////////////////////////////////////////////////////////
105    ////                         public variables                  ////
106
107    /** The label of this transition. Must ends with "?" or "!" or ";"
108     */
109    public StringAttribute label = null;
110
111    ///////////////////////////////////////////////////////////////////
112    ////                         public methods                    ////
113
114    /** React to a change in an attribute. If the changed attribute is
115     *  <i>label</i>, use the ending character of the label to determine
116     *  the transition type, and set the guard and output action of this
117     *  transition. For internal transition, also create the parameter
118     *  corresponding to the transition.
119     *  Increment the version number of the workspace.
120     *  @param attribute The attribute that changed.
121     *  @exception IllegalActionException If thrown by the superclass
122     *   attributeChanged() method, or the changed attribute is
123     *   <i>label</i> and it does not ends with "?" or "!" or ";".
124     */
125    @Override
126    public void attributeChanged(Attribute attribute)
127            throws IllegalActionException {
128        super.attributeChanged(attribute);
129
130        if (attribute == label) {
131            String labelString = label.getExpression();
132            String name = labelString.substring(0, labelString.length() - 1);
133
134            if (labelString.endsWith("?")) {
135                setGuardExpression(name + "_isPresent");
136                outputActions.setExpression("");
137            } else if (labelString.endsWith("!")) {
138                setGuardExpression("true");
139                outputActions.setExpression(name + "=true");
140            } else if (labelString.endsWith(";")) {
141                // create a parameter if it is not created yet.
142                // Note that if this transition is removed, or changed to
143                // an input or output transition, the parameter is still
144                // in the Interface Automaton.
145                InterfaceAutomaton container = (InterfaceAutomaton) getContainer();
146
147                if (container.getAttribute(name) == null) {
148                    try {
149                        new Parameter(container, name);
150                    } catch (NameDuplicationException exception) {
151                        // should not happen
152                        throw new InternalErrorException(
153                                "InterfaceAutomatonTransition."
154                                        + "attributeChanged:\n"
155                                        + "Cannot create Parameter for internal "
156                                        + "transition:\n"
157                                        + exception.getMessage());
158                    }
159                }
160
161                setGuardExpression("true");
162                outputActions.setExpression(name + "=true");
163            } else {
164                throw new IllegalActionException(
165                        "InterfaceAutomatonTransition.attributeChanged: "
166                                + "The argument " + label
167                                + " does not end with ? " + "or ! or ;");
168            }
169        }
170    }
171
172    /** Return the label of this transition. If the label has not been set,
173     *  return an empty string.
174     *  @return The label of this transition.
175     */
176    @Override
177    public String getLabel() {
178        String labelStr = label.getExpression();
179
180        if (labelStr == null) {
181            labelStr = "";
182        }
183
184        return labelStr;
185    }
186
187    /** Return the transition type. The transition type is one of
188     *  _INPUT_TRANSITION, _OUTPUT_TRANSITION, or _INTERNAL_TRANSITION.
189     *  @return the transition type.
190     */
191    public int getType() {
192        String labelString = label.getExpression();
193
194        if (labelString.endsWith("?")) {
195            return _INPUT_TRANSITION;
196        } else if (labelString.endsWith("!")) {
197            return _OUTPUT_TRANSITION;
198        } else if (labelString.endsWith(";")) {
199            return _INTERNAL_TRANSITION;
200        } else {
201            throw new InternalErrorException(
202                    "InterfaceAutomatonTransition.getType: "
203                            + "The label does not end with ? or ! or ;");
204        }
205    }
206
207    /** Override the base class to ensure that the proposed container
208     *  is an instance of InterfaceAutomaton or null. If it is, call the
209     *  base class setContainer() method. A null argument will remove
210     *  this transition from its container.
211     *
212     *  @param container The proposed container.
213     *  @exception IllegalActionException If setting the container would
214     *   result in a recursive containment structure, or if
215     *   this transition and container are not in the same workspace, or
216     *   if the argument is not an InterfaceAutomaton or null.
217     *  @exception NameDuplicationException If the container already has
218     *   an relation with the name of this transition.
219     */
220    @Override
221    public void setContainer(CompositeEntity container)
222            throws IllegalActionException, NameDuplicationException {
223        if (!(container instanceof InterfaceAutomaton) && container != null) {
224            throw new IllegalActionException(container, this,
225                    "Transition can only be contained by instances of "
226                            + "InterfaceAutomaton.");
227        }
228
229        super.setContainer(container);
230    }
231
232    /** Throw an exception. Trigger expression is not used in
233     *  InterfaceAutomaton, so this method should not be called in this class.
234     *  @param expression The trigger expression.
235     *  @exception UnsupportedOperationException Always thrown.
236     */
237    public void setTriggerExpression(String expression) {
238        throw new UnsupportedOperationException(
239                "InterfaceAutomatonTransition.setTriggerExpression: "
240                        + "The trigger expression is not used in InterfaceAutomaton, "
241                        + "so this method should not be called.");
242    }
243
244    ///////////////////////////////////////////////////////////////////
245    ////                         protected variables               ////
246
247    /** The input transition type. */
248    protected static final int _INPUT_TRANSITION = 0;
249
250    /** The output transition type. */
251    protected static final int _OUTPUT_TRANSITION = 1;
252
253    /** The internal transition type. */
254    protected static final int _INTERNAL_TRANSITION = 2;
255}