public class Variable extends AbstractSettableAttribute implements Typeable, ValueListener
A variable can be given a token or an expression as its value. To create a variable with a token, either call the appropriate constructor, or create the variable with the appropriate container and name, and then call setToken(). To set the value from an expression, call setExpression(). The expression is not actually evaluated until you call getToken(), getType(). By default, it is also evaluated when you call validate(), unless you have called setLazy(true), in which case it will only be evaluated if there are other variables that depend on it and those have not had setLazy(true) called.
Consider for example the sequence:
Variable v3 = new Variable(container,"v3"); Variable v2 = new Variable(container,"v2"); Variable v1 = new Variable(container,"v1"); v3.setExpression("v1 + v2"); v2.setExpression("1.0"); v1.setExpression("2.0"); v3.getToken();Notice that the expression for
v3
cannot be evaluated
when it is set because v2
and v1
do not
yet have values. But there is no problem because the expression
is not evaluated until getToken() is called. Equivalently, we
could have called, for example,
v3.validate();This will force
v3
to be evaluated,
and also v1
and v2
to be evaluated.
There is a potentially confusing subtlety. In the above code,
before the last line is executed, the expression for v3
has not been evaluated, so the dependence that v3
has
on v1
and v2
has not been recorded.
Thus, if we call
v1.validate();before
v3
has ever been evaluated, then it will not
trigger an evaluation of v3
. Because of this, we recommend
that user code call validate() immediately after calling
setExpression().
If the expression string is null or empty, or if no value has been specified, then getToken() will return null.
The expression can reference variables that are in scope before the expression is evaluated (i.e., before getToken() or validate() is called). Otherwise, getToken() will throw an exception. All variables contained by the same container, and those contained by the container's container, are in the scope of this variable. Thus, in the above, all three variables are in each other's scope because they belong to the same container. If there are variables in the scope with the same name, then those lower in the hierarchy shadow those that are higher. An instance of ScopeExtendingAttribute can also be used to aggregate a set of variables and add them to the scope.
If a variable is referred to by expressions of other variables, then the name of the variable must be a valid identifier as defined by the Ptolemy II expression language syntax. A valid identifier starts with a letter or underscore, and contains letters, underscores, numerals, dollar signs ($), at signs (@), or pound signs (#).
A variable is a Typeable object. Constraints on its type can be specified relative to other Typeable objects (as inequalities on the types), or relative to specific types. The former are called dynamic type constraints, and the latter are called static type constraints. Static type constraints are specified by the methods:
The dynamic type constraints are not enforced in this class, but merely reported by the typeConstraints() method. They must be enforced at a higher level (by a type system) since they involve a network of variables and other typeable objects. In fact, if the variable does not yet have a value, then a type system may use these constraints to infer what the type of the variable needs to be, and then call setTypeEquals().
The token returned by getToken() is always an instance of the class given by the getType() method. This is not necessarily the same as the class of the token that was inserted via setToken(). It might be a distinct type if the token given by setToken() can be converted losslessly into one of the type given by setTypeEquals().
A variable by default has no MoML description (MoML is an XML modeling markup language). Thus, a variable contained by a named object is not persistent, in that if the object is exported to a MoML file, the variable will not be represented. If you prefer that the variable be represented, then you should use the derived class Parameter instead.
A variable is also normally not settable by casual users from the user interface. This is because, by default, getVisibility() returns EXPERT. The derived class Parameter is fully visible by default.
In addition, this class provides as a convenience a "string mode." If the variable is in string mode, then when setting the value of this variable, the string that you pass to setExpression(String) is taken to be literally the value of the instance of StringToken that represents the value of this parameter. It is not necessary to enclose it in quotation marks (and indeed, if you do, the quotation marks will become part of the value of the string). In addition, the type of this parameter will be set to string. In addition, getToken() will never return null; if the value of the string has never been set, then an instance of StringToken is returned that has an empty string as its value. A parameter is in string mode if either setStringMode(true) has been called or it contains an attribute named "_stringMode".
In string mode, the value passed to setExpression(String) may contain
references to other variables in scope using the syntax $id,
${id} or $(id). The first case only works if the id consists
only of alphanumeric characters and/or underscore, and if the
character immediately following the id is not one of these.
To get a simple dollar sign, use $$. In string mode, to set the
value to be the empty string, create a Parameter in the container
that has the value ""
and then set the string mode
parameter to the $nameOfTheParameter
. For example,
the parameter might be named myEmptyParameter
and have
a value ""
; the value for the string mode parameter would
be $myEmptyParameter
.
Token
,
PtParser
,
Parameter
,
ScopeExtendingAttribute
,
NamedObj.setPersistent(boolean)
Modifier and Type | Class and Description |
---|---|
static class |
Variable.CircularDependencyError
Subclass of IllegalActionException for use in reporting
circular dependency errors.
|
protected class |
Variable.VariableScope
Scope implementation with local caching.
|
NamedObj.ContainedObjectsIterator
Settable.Visibility
Modifier and Type | Field and Description |
---|---|
protected java.lang.String |
_currentExpression
Stores the expression used to set this variable.
|
protected boolean |
_needsEvaluation
Flags that the expression needs to be evaluated when the value of this
variable is queried.
|
protected ParserScope |
_parserScope
The instance of VariableScope.
|
protected boolean |
_parseTreeValid
Indicator that the parse tree is valid.
|
protected boolean |
_suppressVariableSubstitution
True to suppress variable substitution in string mode.
|
protected java.util.List<ValueListener> |
_valueListeners
Listeners for changes in value.
|
_changeListeners, _changeLock, _changeRequests, _debugging, _debugListeners, _deferChangeRequests, _elementName, _isPersistent, _verbose, _workspace, ATTRIBUTES, CLASSNAME, COMPLETE, CONTENTS, DEEP, FULLNAME, LINKS
EXPERT, FULL, NONE, NOT_EDITABLE
Modifier | Constructor and Description |
---|---|
|
Variable()
Construct a variable in the default workspace with an empty string
as its name.
|
|
Variable(NamedObj container,
java.lang.String name)
Construct a variable with the given name as an attribute of the
given container.
|
|
Variable(NamedObj container,
java.lang.String name,
Token token)
Construct a variable with the given container, name, and token.
|
protected |
Variable(NamedObj container,
java.lang.String name,
Token token,
boolean incrementWorkspaceVersion)
Construct a variable with the given container, name, and token.
|
|
Variable(Workspace workspace)
Construct a variable in the specified workspace with an empty
string as its name.
|
Modifier and Type | Method and Description |
---|---|
protected java.lang.String |
_description(int detail,
int indent,
int bracket)
Return a description of this variable.
|
protected void |
_evaluate()
Evaluate the current expression to a token.
|
protected java.lang.String |
_getCurrentExpression()
Get the current expression as a string, to be used to export to MoML.
|
protected void |
_notifyValueListeners()
Notify the value listeners of this variable that this variable
changed.
|
protected void |
_parseIfNecessary()
Parse the expression, if the current parse tree is not valid.
|
protected java.util.List<IllegalActionException> |
_propagate()
Force evaluation of this variable, unless it is lazy,
and call _propagate() on its value dependents.
|
protected java.util.List<IllegalActionException> |
_propagateToValueListeners()
Call propagate() on all value listeners.
|
protected void |
_propagateValue(NamedObj destination)
Propagate the value of this object to the
specified object.
|
protected void |
_setToken(Token newToken)
Set the token value and type of the variable.
|
protected void |
_setTokenAndNotify(Token newToken)
Set the token value and type of the variable, and notify the
container that the value (and type, if appropriate) has changed.
|
void |
addValueListener(ValueListener listener)
Add a listener to be notified when the value of this variable changes.
|
void |
attributeChanged(Attribute attribute)
React to a change in an attribute.
|
java.lang.Object |
clone(Workspace workspace)
Clone the variable.
|
Type |
getDeclaredType()
If setTypeEquals() has been called, then return the type specified
there.
|
java.lang.String |
getExpression()
Get the expression currently used by this variable.
|
java.util.Set |
getFreeIdentifiers()
Return the list of identifiers referenced by the current expression.
|
ParserScope |
getParserScope()
Return the parser scope for this variable.
|
NamedList |
getScope()
Return a NamedList of the variables that the value of this
variable can depend on.
|
static NamedList |
getScope(NamedObj object)
Return a NamedList of the variables that the value of the specified
variable can depend on.
|
Token |
getToken()
Get the token contained by this variable.
|
Type |
getType()
Get the type of this variable.
|
InequalityTerm |
getTypeTerm()
Return an InequalityTerm whose value is the type of this variable.
|
java.lang.String |
getValueAsString()
Get the value of the attribute, which is the evaluated expression.
|
Variable |
getVariable(java.lang.String name)
Look up and return the attribute with the specified name in the
scope.
|
Settable.Visibility |
getVisibility()
Get the visibility of this variable, as set by setVisibility().
|
void |
invalidate()
Mark this variable, and all variables that depend on it, as
needing to be evaluated.
|
boolean |
isKnown()
Return true if the value of this variable is known, and
false otherwise.
|
boolean |
isLazy()
Return true if this variable is lazy.
|
boolean |
isStringMode()
Return true if this parameter is in string mode.
|
boolean |
isSuppressVariableSubstitution()
Return true if this variable is suppressing
variable substitution.
|
boolean |
isTypeAcceptable()
Check whether the current type of this variable is acceptable.
|
void |
removeValueListener(ValueListener listener)
Remove a listener from the list of listeners that is
notified when the value of this variable changes.
|
void |
reset()
Deprecated.
This capability may be removed to simplify this class.
It is not currently used in Ptolemy II, as of version 2.0.
|
void |
setContainer(NamedObj container)
Specify the container, and add this variable to the list
of attributes in the container.
|
void |
setExpression(java.lang.String expr)
Set the expression of this variable.
|
void |
setLazy(boolean lazy)
Specify whether this variable is to be lazy.
|
void |
setName(java.lang.String name)
Override the base class to throw an exception if renaming this
variable results in an error evaluating some variable that depends
on it.
|
void |
setParseTreeEvaluator(ParseTreeEvaluator parseTreeEvaluator)
Set a new parseTreeEvaluator.
|
void |
setStringMode(boolean stringMode)
Specify whether this parameter should be in string mode.
|
void |
setSuppressVariableSubstitution(boolean suppress)
If the argument is true, then for a string mode parameter,
suppress variable substitution.
|
void |
setToken(java.lang.String expression)
Set the expression for this variable by calling
setExpression(), and then evaluate it by calling
validate().
|
void |
setToken(Token token)
Put a new token in this variable and notify the container and
and value listeners.
|
void |
setTypeAtLeast(InequalityTerm typeTerm)
Constrain the type of this variable to be equal to or
greater than the type represented by the specified InequalityTerm.
|
void |
setTypeAtLeast(Typeable lesser)
Constrain the type of this variable to be equal to or
greater than the type of the specified object.
|
void |
setTypeAtMost(Type type)
Set a type constraint that the type of this object be less than
or equal to the specified class in the type lattice.
|
void |
setTypeEquals(Type type)
Set a type constraint that the type of this object equal
the specified value.
|
void |
setTypeSameAs(Typeable equal)
Constrain the type of this variable to be the same as the
type of the specified object.
|
void |
setUnknown(boolean value)
Mark the value of this variable to be unknown if the argument is
true, or known if the argument is false.
|
void |
setValueListenerAsWeakDependency(ValueListener listener)
Set a value listener as a weak dependency.
|
void |
setVisibility(Settable.Visibility visibility)
Set the visibility of this variable.
|
java.lang.String |
stringRepresentation()
Deprecated.
|
java.lang.String |
toString()
Return a string representation of the current evaluated variable value.
|
java.util.List |
typeConstraintList()
Deprecated.
Use typeConstraints().
|
java.util.Set<Inequality> |
typeConstraints()
Return the type constraints of this variable.
|
java.util.Collection |
validate()
If this variable is not lazy (the default) then evaluate
the expression contained in this variable, and notify any
value dependents.
|
void |
valueChanged(Settable settable)
React to the change in the specified instance of Settable.
|
getDefaultExpression
_checkContainer, _getContainedObject, _propagateExistence, getContainer, moveDown, moveToFirst, moveToIndex, moveToLast, moveUp, updateContent
_addAttribute, _adjustOverride, _attachText, _cloneFixAttributeFields, _containedDecorators, _copyChangeRequestList, _debug, _debug, _debug, _debug, _debug, _executeChangeRequests, _exportMoMLContents, _getIndentPrefix, _isMoMLSuppressed, _markContentsDerived, _notifyHierarchyListenersAfterChange, _notifyHierarchyListenersBeforeChange, _removeAttribute, _splitName, _stripNumericSuffix, _validateSettables, addChangeListener, addDebugListener, addHierarchyListener, attributeDeleted, attributeList, attributeList, attributeTypeChanged, clone, containedObjectsIterator, decorators, deepContains, depthInHierarchy, description, description, event, executeChangeRequests, exportMoML, exportMoML, exportMoML, exportMoML, exportMoML, exportMoMLPlain, getAttribute, getAttribute, getAttributes, getChangeListeners, getClassName, getDecoratorAttribute, getDecoratorAttributes, getDerivedLevel, getDerivedList, getDisplayName, getElementName, getFullName, getModelErrorHandler, getName, getName, getPrototypeList, getSource, handleModelError, isDeferringChangeRequests, isOverridden, isPersistent, lazyContainedObjectsIterator, message, notifyOfNameChange, propagateExistence, propagateValue, propagateValues, removeAttribute, removeChangeListener, removeDebugListener, removeHierarchyListener, requestChange, setClassName, setDeferringChangeRequests, setDerivedLevel, setDisplayName, setModelErrorHandler, setPersistent, setSource, sortContainedObjects, toplevel, uniqueName, validateSettables, workspace
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
getDisplayName
description, getContainer, getFullName, getName, getName
protected java.lang.String _currentExpression
protected boolean _needsEvaluation
protected boolean _parseTreeValid
protected ParserScope _parserScope
protected boolean _suppressVariableSubstitution
protected java.util.List<ValueListener> _valueListeners
public Variable()
public Variable(NamedObj container, java.lang.String name) throws IllegalActionException, NameDuplicationException
container
- The container.name
- The name of the variable.IllegalActionException
- If the container does not accept
a variable as its attribute.NameDuplicationException
- If the name coincides with a
variable already in the container.public Variable(NamedObj container, java.lang.String name, Token token) throws IllegalActionException, NameDuplicationException
container
- The container.name
- The name.token
- The token contained by this variable.IllegalActionException
- If the container does not accept
a variable as its attribute.NameDuplicationException
- If the name coincides with a
variable already in the container.public Variable(Workspace workspace)
workspace
- The workspace that will list the variable.protected Variable(NamedObj container, java.lang.String name, Token token, boolean incrementWorkspaceVersion) throws IllegalActionException, NameDuplicationException
container
- The container.name
- The name.token
- The token contained by this variable.incrementWorkspaceVersion
- False to not add this to the workspace
or do anything else that might change the workspace version number.IllegalActionException
- If the container does not accept
a variable as its attribute.NameDuplicationException
- If the name coincides with a
variable already in the container.public void addValueListener(ValueListener listener)
addValueListener
in interface Settable
listener
- The listener to add.removeValueListener(ValueListener)
public void attributeChanged(Attribute attribute) throws IllegalActionException
attributeChanged
in class NamedObj
attribute
- The attribute that changed.IllegalActionException
- If the change is not acceptable
to this container.public java.lang.Object clone(Workspace workspace) throws java.lang.CloneNotSupportedException
public Type getDeclaredType()
setTypeEquals(Type)
,
BaseType
public java.lang.String getExpression()
getExpression
in interface Settable
setExpression(String)
public java.util.Set getFreeIdentifiers() throws IllegalActionException
IllegalActionException
- If the expression cannot be parsed.public ParserScope getParserScope()
public NamedList getScope()
Note that this method is an extremely inefficient to refer to the scope of a variable because it constructs a list containing every variable in the scope. It is best to avoid calling it and instead just use the get() method of the VariableScope inner class.
This method is read-synchronized on the workspace.
public static NamedList getScope(NamedObj object)
Note that this method is an extremely inefficient way to refer to the scope of a variable because it constructs a list containing every variable in the scope. It is best to avoid calling it and instead just use the get() method of the VariableScope inner class.
This method is read-synchronized on the workspace.
object
- The NamedObj variablepublic Token getToken() throws IllegalActionException
IllegalActionException
- If the expression cannot
be parsed or cannot be evaluated, or if the result of evaluation
violates type constraints, or if the result of evaluation is null
and there are variables that depend on this one.setToken(String)
,
setToken(ptolemy.data.Token)
public Type getType()
public InequalityTerm getTypeTerm()
getTypeTerm
in interface Typeable
public java.lang.String getValueAsString()
getValueAsString
in interface Settable
getValueAsString
in class AbstractSettableAttribute
getExpression()
public Variable getVariable(java.lang.String name) throws IllegalActionException
name
- The name of the variable to be looked up.IllegalActionException
- If a value in the scope
exists with the given name, but cannot be evaluated.public Settable.Visibility getVisibility()
getVisibility
in interface Settable
setVisibility(Settable.Visibility)
public void invalidate()
public boolean isKnown() throws IllegalActionException
IllegalActionException
- If the expression cannot
be parsed or cannot be evaluated, or if the result of evaluation
violates type constraints, or if the result of evaluation is null
and there are variables that depend on this one.setUnknown(boolean)
public boolean isLazy()
setLazy(boolean)
public boolean isStringMode()
setStringMode(boolean)
public boolean isSuppressVariableSubstitution()
isStringMode()
,
setSuppressVariableSubstitution(boolean)
public boolean isTypeAcceptable()
isTypeAcceptable
in interface Typeable
public void removeValueListener(ValueListener listener)
removeValueListener
in interface Settable
listener
- The listener to remove.addValueListener(ValueListener)
@Deprecated public void reset()
public void setContainer(NamedObj container) throws IllegalActionException, NameDuplicationException
If this method results in a change of container (which it usually does), then remove this variable from the scope of any scope dependent of this variable.
This method is write-synchronized on the workspace and increments its version number.
setContainer
in class Attribute
container
- The proposed container of this variable.IllegalActionException
- If the container will not accept
a variable as its attribute, or this variable and the container
are not in the same workspace, or the proposed container would
result in recursive containment.NameDuplicationException
- If the container already has
an attribute with the name of this variable.Attribute.getContainer()
public void setExpression(java.lang.String expr)
setExpression
in interface Settable
setExpression
in class AbstractSettableAttribute
expr
- The expression for this variable.getExpression()
public void setLazy(boolean lazy)
A lazy variable may be used whenever its value will be actively accessed via getToken() when it is needed, and its type will be actively accessed via getType(). In particular, the container does not rely on a call to attributeChanged() or attributeTypeChanged() to notify it that the variable value has changed. Those methods will not be called when the value of the variable changes due to some other variable value that it depends on changing because the new value will not be immediately evaluated.
lazy
- True to make the variable lazy.validate()
,
NamedObj.attributeChanged(Attribute)
,
NamedObj.attributeTypeChanged(Attribute)
public void setName(java.lang.String name) throws IllegalActionException, NameDuplicationException
setName
in interface Nameable
setName
in class Attribute
name
- The new name.IllegalActionException
- If the name contains a period
or if this variable is referenced in some other expression.NameDuplicationException
- If there is already an
attribute with the same name in the container.NamedObj.getName()
,
NamedObj.getName(NamedObj)
public void setParseTreeEvaluator(ParseTreeEvaluator parseTreeEvaluator)
parseTreeEvaluator
- The new parseTreeEvaluator used by
this variable.public void setStringMode(boolean stringMode) throws IllegalActionException
setSuppressVariableSubstitution(boolean)
.stringMode
- True to put the parameter in string mode.IllegalActionException
- If the current value of this
parameter is incompatible with the resulting type.isStringMode()
public void setSuppressVariableSubstitution(boolean suppress)
suppress
- True to suppress variable substitution.setStringMode(boolean)
,
isSuppressVariableSubstitution()
public void setToken(java.lang.String expression) throws IllegalActionException
expression
- The expression.IllegalActionException
- If this variable or a
variable dependent on this variable cannot be evaluated (and is
not lazy) and the model error handler throws an exception.
Also thrown if the change is not acceptable to the container.getToken()
,
setExpression(String)
,
validate()
public void setToken(Token token) throws IllegalActionException
token
- The new token to be stored in this variable.IllegalActionException
- If the token type is not
compatible with specified constraints, or if you are attempting
to set to null a variable that has value dependents, or if the
container rejects the change.getToken()
public void setTypeAtLeast(InequalityTerm typeTerm)
setTypeAtLeast
in interface Typeable
typeTerm
- An InequalityTerm object.public void setTypeAtLeast(Typeable lesser)
setTypeAtLeast
in interface Typeable
lesser
- A Typeable object.public void setTypeAtMost(Type type) throws IllegalActionException
setTypeAtMost
in interface Typeable
type
- An instance of Type.IllegalActionException
- If the type of this object
already violates this constraint, or if the argument is not
an instantiable type in the type lattice.public void setTypeEquals(Type type) throws IllegalActionException
setTypeEquals
in interface Typeable
type
- A Type.IllegalActionException
- If the type of this object
already violates this constraint, in that the currently contained
token cannot be converted losslessly to the specified type.public void setTypeSameAs(Typeable equal)
setTypeSameAs
in interface Typeable
equal
- A Typeable object.public void setUnknown(boolean value)
value
- True to change mark this variable unknown.isKnown()
public void setValueListenerAsWeakDependency(ValueListener listener)
setContainer(NamedObj)
public void setVisibility(Settable.Visibility visibility)
setVisibility
in interface Settable
visibility
- The visibility of this variable.getVisibility()
@Deprecated public java.lang.String stringRepresentation()
public java.lang.String toString()
public java.util.Set<Inequality> typeConstraints()
typeConstraints
in interface HasTypeConstraints
Inequality
@Deprecated public java.util.List typeConstraintList()
Inequality
public java.util.Collection validate() throws IllegalActionException
If this variable is lazy, then mark this variable and any of its value dependents as needing evaluation and for any value dependents that are not lazy, evaluate them. Note that if there are no value dependents, or if they are all lazy, then this will not result in evaluation of this variable, and hence will not ensure that the expression giving its value is valid. Call getToken() or getType() to accomplish that.
validate
in interface Settable
IllegalActionException
- If this variable or a
variable dependent on this variable cannot be evaluated (and is
not lazy) and the model error handler throws an exception.
Also thrown if the change is not acceptable to the container.public void valueChanged(Settable settable)
valueChanged
in interface ValueListener
settable
- The object that has changed value.protected java.lang.String _description(int detail, int indent, int bracket)
_description
in class NamedObj
detail
- The level of detail.indent
- The amount of indenting.bracket
- The number of surrounding brackets (0, 1, or 2).protected void _evaluate() throws IllegalActionException
If evaluation results in a token that is not of the same type as the current type of the variable, then the type of the variable is changed, unless the new type is incompatible with statically specified types (setTypeEquals() and setTypeAtMost()). If the type is changed, the attributeTypeChanged() method of the container is called. The container can reject the change by throwing an exception.
This method may trigger a model error, which is delegated up the container hierarchy until an error handler is found, and is ignored if no error handler is found. A model error occurs if the expression cannot be parsed or cannot be evaluated.
Part of this method is read-synchronized on the workspace.
IllegalActionException
- If the expression cannot
be parsed or cannot be evaluated, or if a dependency loop is found.protected java.lang.String _getCurrentExpression()
protected void _notifyValueListeners()
protected final void _parseIfNecessary() throws IllegalActionException
IllegalActionException
- If the exception cannot be parsed.protected java.util.List<IllegalActionException> _propagate()
protected java.util.List<IllegalActionException> _propagateToValueListeners()
protected void _propagateValue(NamedObj destination) throws IllegalActionException
_propagateValue
in class NamedObj
destination
- Object to which to propagate the
value.IllegalActionException
- If the value cannot
be propagated.protected void _setToken(Token newToken) throws IllegalActionException
newToken
- The new value of the variable.IllegalActionException
- If the token type is not
compatible with specified constraints, or if you are attempting
to set to null a variable that has value dependents.protected void _setTokenAndNotify(Token newToken) throws IllegalActionException
newToken
- The new value of the variable.IllegalActionException
- If the token type is not
compatible with specified constraints, or if you are attempting
to set to null a variable that has value dependents.