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 <inputPort> 061 _isPresent, 062 where <inputPort> 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 <outputPort>=true, where <outputPort> is the output port 067 corresponding to this transition; for internal transition, the action is set 068 to <parameter>=true, where <parameter> 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}