001/* A parameter that contains FSM transition attributes.
002
003   Copyright (c) 2014-2015 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   PT_COPYRIGHT_VERSION_2
024   COPYRIGHTENDKEY
025
026 */
027
028package ptolemy.domains.modal.kernel;
029
030import java.util.Collection;
031import java.util.List;
032
033import ptolemy.data.BooleanToken;
034import ptolemy.data.StringToken;
035import ptolemy.data.expr.Parameter;
036import ptolemy.data.expr.SingletonParameter;
037import ptolemy.domains.modal.modal.ModalController;
038import ptolemy.kernel.util.AbstractSettableAttribute;
039import ptolemy.kernel.util.IllegalActionException;
040import ptolemy.kernel.util.InternalErrorException;
041import ptolemy.kernel.util.Location;
042import ptolemy.kernel.util.NameDuplicationException;
043import ptolemy.kernel.util.NamedObj;
044import ptolemy.kernel.util.Settable;
045import ptolemy.kernel.util.ValueListener;
046import ptolemy.kernel.util.Workspace;
047
048/** A parameter that contains FSM transition attributes. In large FSMs
049 *  with long strings in actions, the graphical representation can be
050 *  challenging. This parameter can be used represent configuration of
051 *  transitions in a parameter that can be moved independent from the
052 *  transition in vergil.
053 *  @author Patricia Derler
054 *  @version $Id$
055 *  @since Ptolemy II 10.0
056 *
057 *  @Pt.ProposedRating Red (derler)
058 *  @Pt.AcceptedRating Red (derler)
059 */
060public class FSMTransitionParameter extends AbstractSettableAttribute {
061
062    /** Construct an attribute with the given name contained by the specified
063     *  entity. The container argument must not be null, or a
064     *  NullPointerException will be thrown.  This attribute will use the
065     *  workspace of the container for synchronization and version counts.
066     *  If the name argument is null, then the name is set to the empty string.
067     *  Increment the version of the workspace.
068     *  @param container The container.
069     *  @param name The name of this attribute.
070     *  @exception IllegalActionException If the attribute is not of an
071     *   acceptable class for the container, or if the name contains a period.
072     *  @exception NameDuplicationException If the name coincides with
073     *   an attribute already in the container.
074     */
075    public FSMTransitionParameter(NamedObj container, String name)
076            throws IllegalActionException, NameDuplicationException {
077        super(container, name);
078        _init();
079    }
080
081    /** Add value listener. Nothing to do.
082     *  @param listener Ignored in this base class.
083     *  @see #removeValueListener(ValueListener)
084     */
085    @Override
086    public void addValueListener(ValueListener listener) {
087        // nothing to do.
088    }
089
090    /** Clone the transition into the specified workspace. This calls the
091     *  base class and then sets the attribute public members to refer to
092     *  the attributes of the new transition.
093     *  @param workspace The workspace for the new transition.
094     *  @return A new transition.
095     *  @exception CloneNotSupportedException If a derived class contains
096     *   an attribute that cannot be cloned.
097     */
098    @Override
099    public Object clone(Workspace workspace) throws CloneNotSupportedException {
100        FSMTransitionParameter newObject = (FSMTransitionParameter) super.clone(
101                workspace);
102        newObject._transition = null;
103        return newObject;
104    }
105
106    /** Return the name of the parameter.
107     *  @return The name.
108     */
109    @Override
110    public String getExpression() {
111        if (_transition != null) {
112            return _transition.getFullLabel();
113        }
114        return "";
115    }
116
117    /** Set the transition that corresponds to the parameters.
118     *  @return The transition.
119     *  @see #setTransition(Transition)
120     */
121    public Transition getTransition() {
122        return _transition;
123    }
124
125    /** Get visibility. Nothing to do.
126     *  @return Always return NOT_EDITABLE.
127     *  @see #setVisibility(Visibility)
128     */
129    @Override
130    public Visibility getVisibility() {
131        return NOT_EDITABLE;
132    }
133
134    /** If hide is true, hide the parameter and display transition parameters next
135     * to the transition.
136     * FIXME this should probably be done in setVisibility.
137     * @param hide True if the parameter should be hidden.
138     * @exception IllegalActionException If thrown while creating
139     * the _hide parameter, while validating the location or while
140     * creating a location.
141     */
142    public void hide(boolean hide) throws IllegalActionException {
143        Parameter _hide = (Parameter) getAttribute("_hide");
144        if (_hide == null) {
145            try {
146                _hide = new Parameter(this, "_hide");
147            } catch (NameDuplicationException e) {
148                // not going to happen
149                e.printStackTrace();
150            }
151        }
152        if (_hide == null) {
153            throw new InternalErrorException(this, null,
154                    "Could not create _hide parameter?");
155        }
156        _hide.setExpression("" + hide);
157        Location location = (Location) getAttribute("_location");
158        if (location != null) {
159            location.validate();
160        } else {
161            // FindBugs: "Redundant nullcheck of value known to be
162            // null" location is known to be null here.
163            if (!hide /*&& (location == null || (location.getLocation()[0] == 0 && location.getLocation()[1] == 0))*/) {
164                if (_transition != null && _transition.sourceState() != null) {
165                    Location sourceStateLocation = (Location) _transition
166                            .sourceState().getAttribute("_location");
167                    Location destinationStateLocation = (Location) _transition
168                            .destinationState().getAttribute("_location");
169                    try {
170                        new Location(this, "_location").setLocation(
171                                new double[] { destinationStateLocation
172                                        .getLocation()[0]
173                                        + (sourceStateLocation.getLocation()[0]
174                                                - destinationStateLocation
175                                                        .getLocation()[0])
176                                                / 2,
177                                        destinationStateLocation
178                                                .getLocation()[1]
179                                                + (sourceStateLocation
180                                                        .getLocation()[1]
181                                                        - destinationStateLocation
182                                                                .getLocation()[1])
183                                                        / 2 });
184                    } catch (NameDuplicationException ex) {
185                        throw new IllegalActionException(_transition, ex,
186                                "Could not add _location?");
187                    }
188                }
189            }
190        }
191    }
192
193    /** Upon setting the name of this parameter change the corresponding
194     *  attribute in the transition.
195     */
196    @Override
197    public void setName(String name)
198            throws IllegalActionException, NameDuplicationException {
199        super.setName(name);
200        if (_transition != null) {
201            _transition.fsmTransitionParameterName.setExpression(name);
202            _transition.fsmTransitionParameterName.setPersistent(true);
203        }
204    }
205
206    /** Remove value listener. Nothing to do.
207     *  @param listener Ignored.
208     *  @see #addValueListener(ValueListener)
209     */
210    @Override
211    public void removeValueListener(ValueListener listener) {
212        // Nothing to do.
213    }
214
215    @Override
216    public void setContainer(NamedObj container)
217            throws IllegalActionException, NameDuplicationException {
218        super.setContainer(container);
219        if (container == null && _transition != null) {
220            _transition.setFsmTransitionParameter(null);
221            _transition.showFSMTransitionParameter
222                    .setToken(new BooleanToken(false));
223        }
224    }
225
226    /** Set the transition that corresponds to the parameters.
227     * @param transition The transition.
228     * @exception IllegalActionException Can happen during initialization.
229     * @exception NameDuplicationException Can happen during initialization.
230     * @see #getTransition()
231     */
232    public void setTransition(Transition transition)
233            throws IllegalActionException, NameDuplicationException {
234        _transition = transition;
235        _init();
236    }
237
238    /** Set visibility. Nothing to do.
239     *  @param visibility Ignored.
240     *  @see #getVisibility()
241     */
242    @Override
243    public void setVisibility(Visibility visibility) {
244        // Nothing to do, visibility is always not-editable.
245    }
246
247    /** Validate. Nothing to do.
248     * @return null
249     * @exception IllegalActionException Not thrown.
250     */
251    @Override
252    public Collection validate() throws IllegalActionException {
253        return null;
254    }
255
256    ///////////////////////////////////////////////////////////////////
257    ////                         private methods                   ////
258
259    private void _init()
260            throws IllegalActionException, NameDuplicationException {
261        if (getAttribute("_hideName") == null) {
262            SingletonParameter hide = new SingletonParameter(this, "_hideName");
263            hide.setToken(BooleanToken.TRUE);
264            hide.setVisibility(Settable.EXPERT);
265        }
266
267        hide(false);
268        setPersistent(true);
269
270        List<Transition> transitions = ((ModalController) getContainer())
271                .relationList();
272        for (Transition transition : transitions) {
273            if (((StringToken) transition.fsmTransitionParameterName.getToken())
274                    .stringValue().equals(this.getName())) {
275                _transition = transition;
276                _transition.setFsmTransitionParameter(this);
277                break;
278            }
279        }
280    }
281
282    private Transition _transition;
283
284}