001/* Parameter is a subclass of Variable with support for strings.
002
003 Copyright (c) 1998-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
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027
028 */
029package ptolemy.data.expr;
030
031import java.io.IOException;
032import java.io.Writer;
033import java.util.ArrayList;
034import java.util.List;
035
036import ptolemy.data.StringToken;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.NameDuplicationException;
039import ptolemy.kernel.util.NamedObj;
040import ptolemy.kernel.util.Settable;
041import ptolemy.kernel.util.Workspace;
042import ptolemy.util.StringUtilities;
043
044///////////////////////////////////////////////////////////////////
045//// Parameter
046
047/**
048 <p>Parameter extends Variable with additional support for string-valued
049 variables that makes these friendlier at the user interface level.
050 In particular, this class supports an annotation that specifies
051 choices for values.  A user interface can use this to present a
052 choice dialog that offers the specified values.  This is typically
053 used when a particular set of choices make sense.  The values can
054 be any expression, or if used in conjunction with string mode,
055 any string.</p>
056 <p>
057 By default, an instance of Parameter, unlike Variable, is persistent.</p>
058 <p>
059 By convention, an instance of NamedObj has a set of attributes,
060 some of which are visible to users and some of which are not.
061 When a user interface presents these attributes
062 for editing, it presents only those that are visible.
063 By default, an instance of Parameter is visible, as indicated by the fact
064 that it returns FULL in its getVisibility() method.  This can be overridden
065 by calling setVisibility().</p>
066
067 @author Neil Smyth, Edward A. Lee, Xiaojun Liu
068 @version $Id$
069 @since Ptolemy II 0.2
070 @Pt.ProposedRating Yellow (eal)
071 @Pt.AcceptedRating Red (cxh)
072
073 @see ptolemy.data.expr.PtParser
074 @see ptolemy.data.Token
075
076 */
077public class Parameter extends Variable {
078    /** Construct a parameter in the default workspace with an empty
079     *  string as its name. The parameter is added to the list of
080     *  objects in the workspace.
081     *  Increment the version number of the workspace.
082     */
083    public Parameter() {
084        super();
085        setVisibility(Settable.FULL);
086
087        // Override the base class setting persistence to false,
088        // making it once again unspecified.
089        _isPersistent = null;
090    }
091
092    /** Construct a parameter in the specified workspace with an empty
093     *  string as a name. You can then change the name with setName().
094     *  If the workspace argument is null, then use the default workspace.
095     *  The object is added to the list of objects in the workspace.
096     *  Increment the version number of the workspace.
097     *  @param workspace The workspace that will list the parameter.
098     */
099    public Parameter(Workspace workspace) {
100        super(workspace);
101        setVisibility(Settable.FULL);
102
103        // Override the base class setting persistence to false,
104        // making it once again unspecified.
105        _isPersistent = null;
106    }
107
108    /** Construct a parameter with the given name contained by the specified
109     *  entity. The container argument must not be null, or a
110     *  NullPointerException will be thrown.  This parameter will use the
111     *  workspace of the container for synchronization and version counts.
112     *  If the name argument is null, then the name is set to the empty string.
113     *  The object is not added to the list of objects in the workspace
114     *  unless the container is null.
115     *  Increment the version of the workspace.
116     *  @param container The container.
117     *  @param name The name of the parameter.
118     *  @exception IllegalActionException If the parameter is not of an
119     *   acceptable class for the container.
120     *  @exception NameDuplicationException If the name coincides with
121     *   a parameter already in the container.
122     */
123    public Parameter(NamedObj container, String name)
124            throws IllegalActionException, NameDuplicationException {
125        super(container, name);
126        setVisibility(Settable.FULL);
127
128        // Override the base class setting persistence to false,
129        // making it once again unspecified.
130        _isPersistent = null;
131    }
132
133    /** Construct a Parameter with the given container, name, and Token.
134     *  The container argument must not be null, or a
135     *  NullPointerException will be thrown.  This parameter will use the
136     *  workspace of the container for synchronization and version counts.
137     *  If the name argument is null, then the name is set to the empty string.
138     *  The object is not added to the list of objects in the workspace
139     *  unless the container is null.
140     *  Increment the version of the workspace.
141     *  If the name argument is null, then the name is set to the empty
142     *  string.
143     *  @param container The container.
144     *  @param name The name.
145     *  @param token The Token contained by this Parameter.
146     *  @exception IllegalActionException If the parameter is not of an
147     *   acceptable class for the container.
148     *  @exception NameDuplicationException If the name coincides with
149     *   an parameter already in the container.
150     */
151    public Parameter(NamedObj container, String name, ptolemy.data.Token token)
152            throws IllegalActionException, NameDuplicationException {
153        super(container, name, token);
154        setVisibility(Settable.FULL);
155
156        // Override the base class setting persistence to false,
157        // making it once again unspecified.
158        _isPersistent = null;
159    }
160
161    ///////////////////////////////////////////////////////////////////
162    ////                         public methods                    ////
163
164    /** Add a choice.
165     *  @param choice A choice to offer to the user.
166     *  @see #removeChoice(String)
167     */
168    public void addChoice(String choice) {
169        if (_choices == null) {
170            _choices = new ArrayList();
171        }
172        if (!_choices.contains(choice)) {
173            _choices.add(choice);
174        }
175    }
176
177    /** Clone the object into the specified workspace.
178     *  @param workspace The workspace for the new object.
179     *  @return A new NamedObj.
180     *  @exception CloneNotSupportedException If any of the attributes
181     *   cannot be cloned.
182     */
183    @Override
184    public Object clone(Workspace workspace) throws CloneNotSupportedException {
185        Parameter newObject = (Parameter) super.clone(workspace);
186        if (_choices != null) {
187            newObject._choices = new ArrayList(_choices);
188        }
189
190        return newObject;
191    }
192
193    /** Write a MoML description of this object, unless this object is
194     *  not persistent. MoML is an XML modeling markup language.
195     *  In this class, the object is identified by the "property"
196     *  element, with "name" and "class" (XML) attributes.
197     *  The body of the element, between the "&lt;property&gt;"
198     *  and "&lt;/property&gt;", is written using
199     *  the _exportMoMLContents() protected method, so that derived classes
200     *  can override that method alone to alter only how the contents
201     *  of this object are described.
202     *  The text that is written is indented according to the specified
203     *  depth, with each line (including the last one)
204     *  terminated with a newline.
205     *  @param output The output stream to write to.
206     *  @param depth The depth in the hierarchy, to determine indenting.
207     *  @param name The name to use instead of the current name.
208     *  @exception IOException If an I/O error occurs.
209     *  @see #isPersistent()
210     */
211    @Override
212    public void exportMoML(Writer output, int depth, String name)
213            throws IOException {
214        if (_isMoMLSuppressed(depth)) {
215            return;
216        }
217
218        // NOTE: This used to read as follows, but this is problematic
219        // because you may actually want a parameter value to be an
220        // empty string (e.g., in InteractiveShell for the prompt).
221        // Unfortunately, we can't use getExpression(), because it
222        // substitutes null with an empty string, which isn't what
223        // we want. So we have to duplicate the code of getExpression().
224        // EAL 8/8/06.
225        // String value = getExpression();
226        // if ((value != null) && !value.equals("")) {
227        String value = _getCurrentExpression();
228        if (value == null) {
229            ptolemy.data.Token token = null;
230            try {
231                token = getToken();
232            } catch (IllegalActionException ex) {
233                // token will remain null if the value is invalid.
234            }
235            if (token != null) {
236                if (isStringMode()) {
237                    value = ((StringToken) token).stringValue();
238                } else {
239                    value = token.toString();
240                }
241            }
242        }
243
244        String valueTerm = "";
245        if (value != null) {
246            valueTerm = " value=\"" + StringUtilities.escapeForXML(value)
247                    + "\"";
248        }
249
250        // escape any < character in name. unescapeForXML occurs in
251        // NamedObj.setName(String)
252        name = StringUtilities.escapeForXML(name);
253
254        output.write(_getIndentPrefix(depth) + "<" + _elementName + " name=\""
255                + name + "\" class=\"" + getClassName() + "\"" + valueTerm
256                + ">\n");
257        _exportMoMLContents(output, depth + 1);
258        output.write(_getIndentPrefix(depth) + "</" + _elementName + ">\n");
259    }
260
261    /** Get choices.
262     *  @return An array of choices, or null if there are none.
263     *  @see #addChoice(String)
264     */
265    public String[] getChoices() {
266        if (_choices == null || _choices.size() == 0) {
267            return null;
268        } else {
269            return (String[]) _choices.toArray(new String[_choices.size()]);
270        }
271    }
272
273    /** Remove all the choices.
274     *  @see #removeChoice(String)
275     */
276    public void removeAllChoices() {
277        _choices = null;
278    }
279
280    /** Remove a choice.
281     *  @param choice A choice to remove from the list offered to the user.
282     *  @see #addChoice(String)
283     *  @see #removeAllChoices()
284     */
285    public void removeChoice(String choice) {
286        if (_choices != null) {
287            _choices.remove(choice);
288        }
289    }
290
291    ///////////////////////////////////////////////////////////////////
292    ////                         private variables                 ////
293    // The List of choices.
294    private List _choices;
295}