ptolemy.actor
Class IORelation

java.lang.Object
  extended by ptolemy.kernel.util.NamedObj
      extended by ptolemy.kernel.Relation
          extended by ptolemy.kernel.ComponentRelation
              extended by ptolemy.actor.IORelation
All Implemented Interfaces:
java.io.Serializable, java.lang.Cloneable, Changeable, Debuggable, DebugListener, Derivable, ModelErrorHandler, MoMLExportable, Moveable, Nameable
Direct Known Subclasses:
TypedIORelation

public class IORelation
extends ComponentRelation

This class mediates connections between ports that can send data to one another via message passing. One purpose of this relation is to ensure that IOPorts are only connected to IOPorts. A second purpose is to support the notion of a width to represent something like a bus. By default an IORelation is a bus for which the width will be inferred, which corresponds to a width equal to Auto. In Vergil you can change the width from Auto to a specific value, to explicitly specify the width of a relation. Specifying a width equal to zero will disable the relation. A width equal equal to -1 is equivalent to a width equal to Auto, in which case the width will be inferred (if possible) from the context. In particular, if this relation is linked on the inside to a port with some width, then the width of this relation will be inferred to be the enough so that the widths of all inside linked relations adds up to the outside width of the port. If this IORelation is linked to another instance of IORelation, then the width of the two IORelations is constrained to be the same.

Instances of IORelation can only be linked to instances of IOPort or instances of IORelation. Derived classes may further constrain this to subclasses of IOPort of IORelation. Such derived classes should override the protected methods _checkPort() and _checkRelation() to throw an exception.

To link a IOPort to an IORelation, use the link() or liberalLink() method in the IOPort class. To remove a link, use the unlink() method. To link (unlink) an IORelation to an IORelation, use the link() (unlink()) method of IORelation.

The container for instances of this class can only be instances of CompositeActor. Derived classes may wish to further constrain the container to subclasses of ComponentEntity. To do this, they should override the _checkContainer() method.

Since:
Ptolemy II 0.2
Version:
$Id: IORelation.java 57040 2010-01-27 20:52:32Z cxh $
Author:
Edward A. Lee, Jie Liu, Contributor: Bert Rodiers
See Also:
Serialized Form
Accepted Rating:
Green (acataldo)
Proposed Rating:
Green (eal)

Nested Class Summary
 
Nested classes/interfaces inherited from class ptolemy.kernel.util.NamedObj
NamedObj.ContainedObjectsIterator
 
Field Summary
private  Parameter _auto
          A parameter to be able to set the width to Auto to automatically infer widths.
private  int _cachedWidth
           
private  int _inferredWidth
           
private  long _inferredWidthVersion
           
private  boolean _suppressWidthPropagation
           
static boolean _USE_NEW_WIDTH_INFERENCE_ALGO
          Indicate whether the new or the old width inference algo should be used This is a packaged field.
static int CONFIGURATION
          Indicate that the description(int) method should describe the width of the relation, and whether it has been fixed.
 Parameter width
          The width of this relation.
static int WIDTH_TO_INFER
          The value of the width we should infer.
 
Fields inherited from class ptolemy.kernel.Relation
_linkList
 
Fields inherited from class ptolemy.kernel.util.NamedObj
_changeListeners, _changeLock, _changeRequests, _debugging, _debugListeners, _elementName, _isPersistent, _verbose, _workspace, ATTRIBUTES, CLASSNAME, COMPLETE, CONTENTS, DEEP, FULLNAME, LINKS
 
Constructor Summary
IORelation()
          Construct a relation in the default workspace with an empty string as its name.
IORelation(CompositeEntity container, java.lang.String name)
          Construct a relation with the given name contained by the specified entity.
IORelation(Workspace workspace)
          Construct a relation in the specified workspace with an empty string as a name.
 
Method Summary
private  Receiver[][] _cascade(Receiver[][] array1, Receiver[][] array2)
          Cascade two Receiver arrays to form a new array.
protected  void _checkPort(Port port)
          Throw an exception if the specified port cannot be linked to this relation (is not of class IOPort).
protected  void _checkRelation(Relation relation, boolean symmetric)
          Throw an exception if the specified relation is not an instance of IORelation or if it does not have the same width as this relation.
protected  java.lang.String _description(int detail, int indent, int bracket)
          Return a description of the object.
private  int _getUserWidth()
          Return the width set by the user
private  boolean _inferringWidths()
          Determine whether widths are currently being inferred or not.
private  int _inferWidth()
          Infer the width of the port from how it is connected.
private  void _init()
          Create an initialize the width parameter.
(package private)  void _setInferredWidth(int width)
          Set the inferred width of this relation.
private  void _setWidth(int width)
          Set the width of this relation and all relations in its relation group.
protected  boolean _skipWidthInference()
          Determines whether width inference should be skipped or not.
 void attributeChanged(Attribute attribute)
          React to a change in an attribute.
 java.lang.Object clone(Workspace workspace)
          Clone the object into the specified workspace.
 Receiver[][] deepReceivers(IOPort except)
          Return the receivers of all input ports linked to this relation, directly or indirectly through a relation group, except those in the port given as an argument.
 int getWidth()
          Return the width of the IORelation, which is always at least one.
 boolean isWidthFixed()
          Return true if the relation has a definite width (i.e., setWidth() has not been called with a value equal to WIDTH_TO_INFER.
 java.util.List<IOPort> linkedDestinationPortList()
          List the input ports that this relation connects to from the outside, and the output ports that it connects to from the inside.
 java.util.List<IOPort> linkedDestinationPortList(IOPort except)
          List the input ports that this relation connects to from the outside and the output ports that it connects to from the inside, except the port given as an argument.
 java.util.Enumeration linkedDestinationPorts()
          Deprecated. Use linkedDestinationPortList() instead.
 java.util.Enumeration linkedDestinationPorts(IOPort except)
          Deprecated. Use linkDestinationPortList(IOPort) instead.
 java.util.List<IOPort> linkedSourcePortList()
          List the output ports that this relation connects to from the outside and the input ports that it connects to from the inside.
 java.util.List<IOPort> linkedSourcePortList(IOPort except)
          List the output ports that this relation connects to from the outside and the input ports that it connects to from the inside, except the port given as an argument.
 java.util.Enumeration linkedSourcePorts()
          Deprecated. Use linkedSourcePortList() instead.
 java.util.Enumeration linkedSourcePorts(IOPort except)
          Deprecated. Use linkedSourcePortList(IOPort) instead.
 boolean needsWidthInference()
          Determine whether for this relation width inference needs to be performed.
 void setContainer(CompositeEntity container)
          Specify the container, adding the relation to the list of relations in the container.
 void setWidth(int widthValue)
          Set the width of this relation and all relations in its relation group.
 
Methods inherited from class ptolemy.kernel.ComponentRelation
_checkContainer, _propagateExistence, deepLinkedPortList, deepLinkedPorts, getContainer, moveDown, moveToFirst, moveToIndex, moveToLast, moveUp, setName, unlinkAll
 
Methods inherited from class ptolemy.kernel.Relation
_getContainedObject, link, linkedObjectsList, linkedPortList, linkedPortList, linkedPorts, linkedPorts, numLinks, relationGroupList, unlink
 
Methods inherited from class ptolemy.kernel.util.NamedObj
_addAttribute, _adjustOverride, _attachText, _cloneFixAttributeFields, _debug, _debug, _debug, _debug, _debug, _exportMoMLContents, _getIndentPrefix, _isMoMLSuppressed, _markContentsDerived, _propagateValue, _recordDecoratedAttributes, _removeAttribute, _splitName, _stripNumericSuffix, _validateSettables, addChangeListener, addDebugListener, attributeList, attributeList, attributeTypeChanged, clone, containedObjectsIterator, 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, propagateExistence, propagateValue, propagateValues, removeChangeListener, removeDebugListener, requestChange, setClassName, setDeferringChangeRequests, setDerivedLevel, setDisplayName, setModelErrorHandler, setPersistent, setSource, sortContainedObjects, toplevel, toString, uniqueName, validateSettables, workspace
 
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

width

public Parameter width
The width of this relation. This is an integer that defaults to WIDTH_TO_INFER, which means that the width will be inferred.


CONFIGURATION

public static final int CONFIGURATION
Indicate that the description(int) method should describe the width of the relation, and whether it has been fixed.

See Also:
Constant Field Values

WIDTH_TO_INFER

public static final int WIDTH_TO_INFER
The value of the width we should infer.

See Also:
Constant Field Values

_auto

private Parameter _auto
A parameter to be able to set the width to Auto to automatically infer widths. This is an integer that equals WIDTH_TO_INFER.


_USE_NEW_WIDTH_INFERENCE_ALGO

public static final boolean _USE_NEW_WIDTH_INFERENCE_ALGO
Indicate whether the new or the old width inference algo should be used This is a packaged field.

See Also:
Constant Field Values

_inferredWidth

private transient int _inferredWidth

_inferredWidthVersion

private transient long _inferredWidthVersion

_suppressWidthPropagation

private boolean _suppressWidthPropagation

_cachedWidth

private int _cachedWidth
Constructor Detail

IORelation

public IORelation()
Construct a relation in the default workspace with an empty string as its name. Add the relation to the directory of the workspace.


IORelation

public IORelation(Workspace workspace)
Construct a relation in the specified workspace with an empty string as a name. You can then change the name with setName(). If the workspace argument is null, then use the default workspace. Add the relation to the workspace directory.

Parameters:
workspace - The workspace that will list the relation.

IORelation

public IORelation(CompositeEntity container,
                  java.lang.String name)
           throws IllegalActionException,
                  NameDuplicationException
Construct a relation with the given name contained by the specified entity. The container argument must not be null, or a NullPointerException will be thrown. This relation will use the workspace of the container for synchronization and version counts. If the name argument is null, then the name is set to the empty string. This constructor write-synchronizes on the workspace.

Parameters:
container - The container.
name - The name of the relation.
Throws:
IllegalActionException - If the container is incompatible with this relation.
NameDuplicationException - If the name coincides with a relation already in the container.
Method Detail

attributeChanged

public void attributeChanged(Attribute attribute)
                      throws IllegalActionException
React to a change in an attribute. This method is called by a contained attribute when its value changes. This overrides the base class so that if the attribute is an instance of Parameter and the name is "width", then the width of the Relation is set.

Overrides:
attributeChanged in class NamedObj
Parameters:
attribute - The attribute that changed.
Throws:
IllegalActionException - If the change is not acceptable to this container.

clone

public java.lang.Object clone(Workspace workspace)
                       throws java.lang.CloneNotSupportedException
Clone the object into the specified workspace. The new object is not added to the directory of that workspace (you must do this yourself if you want it there). The result is a new relation with no links and no container, but with the same width as the original.

Overrides:
clone in class ComponentRelation
Parameters:
workspace - The workspace for the cloned object.
Returns:
A new ComponentRelation.
Throws:
java.lang.CloneNotSupportedException - If one or more of the attributes cannot be cloned.
See Also:
NamedObj.exportMoML(Writer, int, String), NamedObj.setDeferringChangeRequests(boolean)

deepReceivers

public Receiver[][] deepReceivers(IOPort except)
                           throws InvalidStateException,
                                  IllegalActionException
Return the receivers of all input ports linked to this relation, directly or indirectly through a relation group, except those in the port given as an argument. The returned value is an array of arrays. The first index (the row) specifies the group, where a group receives the same data from a channel. Each channel normally receives distinct data. The second index (the column) specifies the receiver number within the group of receivers that get copies from the same channel.

The number of groups (rows) is less than or equal to the width of the relation, which is always at least one. If there are no receivers then return null.

For each channel, there may be any number of receivers in the group. The individual receivers are selected using the second index of the returned array of arrays. If there are no receivers in the group, then the channel is represented by null. I.e., if the returned array of arrays is x and the channel number is c, then x[c] is null. Otherwise, it is an array, where the size of the array is the number of receivers in the group.

NOTE: This method may have the effect of creating new receivers in the remote input ports and losing the previous receivers in those ports, together with any data they may contain. This occurs only if the topology has changed since the receivers were created, and that change resulting in one of those ports not having the right number of receivers.

This method read-synchronizes on the workspace.

Parameters:
except - The port to exclude, or null to not exclude any ports.
Returns:
The receivers associated with this relation.
Throws:
IllegalActionException
InvalidStateException
See Also:
IOPort.getRemoteReceivers()

getWidth

public int getWidth()
             throws IllegalActionException
Return the width of the IORelation, which is always at least one. If the width has been set to the value of WIDTH_TO_INFER, then the relation is a bus with unspecified width, and the width needs to be inferred from the way the relation is connected. This is done by checking the ports that this relation is linked to from the inside and setting the width to the maximum of those port widths, minus the widths of other relations linked to those ports on the inside. Each such port is allowed to have at most one inside relation with an unspecified width, or an exception is thrown. If this inference yields a width of zero, then return one.

Returns:
The width, which is at least zero.
Throws:
IllegalActionException
See Also:
setWidth(int)

isWidthFixed

public boolean isWidthFixed()
                     throws IllegalActionException
Return true if the relation has a definite width (i.e., setWidth() has not been called with a value equal to WIDTH_TO_INFER.

Returns:
True if the width has been set to a positive value.
Throws:
IllegalActionException - If the expression for the width 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.

linkedDestinationPortList

public java.util.List<IOPort> linkedDestinationPortList()
List the input ports that this relation connects to from the outside, and the output ports that it connects to from the inside. I.e., list the ports through or to which we could send data. Two ports are connected if they are linked to relations in the same relation group. This method read-synchronizes on the workspace.

Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts()

linkedDestinationPortList

public java.util.List<IOPort> linkedDestinationPortList(IOPort except)
List the input ports that this relation connects to from the outside and the output ports that it connects to from the inside, except the port given as an argument. I.e., list the ports through or to which we could send data. Two ports are connected if they are linked to relations in the same relation group. This method read-synchronizes on the workspace.

Parameters:
except - The port not included in the returned list, or null to not exclude any ports.
Returns:
A list of IOPort objects.
See Also:
Relation.linkedPortList(ptolemy.kernel.Port)

linkedDestinationPorts

public java.util.Enumeration linkedDestinationPorts()
Deprecated. Use linkedDestinationPortList() instead.

Enumerate the input ports that we are linked to from the outside, and the output ports that we are linked to from the inside. I.e., enumerate the ports through or to which we could send data. This method is deprecated and calls linkedDestinationPortList(). This method read-synchronizes on the workspace.

Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts()

linkedDestinationPorts

public java.util.Enumeration linkedDestinationPorts(IOPort except)
Deprecated. Use linkDestinationPortList(IOPort) instead.

Enumerate the input ports that we are linked to from the outside, and the output ports that we are linked to from the inside, except the port given as an argument. I.e., enumerate the ports through or to which we could send data. This method is deprecated and calls linkedDestinationPortList(IOPort). This method read-synchronizes on the workspace.

Parameters:
except - The port not included in the returned Enumeration.
Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts(ptolemy.kernel.Port)

linkedSourcePortList

public java.util.List<IOPort> linkedSourcePortList()
List the output ports that this relation connects to from the outside and the input ports that it connects to from the inside. I.e., list the ports through or from which we could receive data. Two ports are connected if they are linked to relations in the same relation group. This method read-synchronizes on the workspace.

Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts()

linkedSourcePortList

public java.util.List<IOPort> linkedSourcePortList(IOPort except)
List the output ports that this relation connects to from the outside and the input ports that it connects to from the inside, except the port given as an argument. I.e., list the ports through or from which we could receive data. Two ports are connected if they are linked to relations in the same relation group. This method read-synchronizes on the workspace.

Parameters:
except - The port not included in the returned list.
Returns:
A list of IOPort objects.
See Also:
Relation.linkedPortList(ptolemy.kernel.Port)

linkedSourcePorts

public java.util.Enumeration linkedSourcePorts()
Deprecated. Use linkedSourcePortList() instead.

Enumerate the output ports that we are linked to from the outside and the input ports that we are linked to from the inside. I.e. enumerate the ports from or through which we might receive data. This method is deprecated and calls linkedSourcePortList(). This method read-synchronizes on the workspace.

Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts()

linkedSourcePorts

public java.util.Enumeration linkedSourcePorts(IOPort except)
Deprecated. Use linkedSourcePortList(IOPort) instead.

Enumerate the output ports that we are linked to from the outside and the input ports that we are linked to from the inside. I.e. enumerate the ports from or through which we might receive This method is deprecated and calls linkedSourcePortList(IOPort). This method read-synchronizes on the workspace.

Parameters:
except - The port not included in the returned Enumeration.
Returns:
An enumeration of IOPort objects.
See Also:
Relation.linkedPorts(ptolemy.kernel.Port)

needsWidthInference

public boolean needsWidthInference()
                            throws IllegalActionException
Determine whether for this relation width inference needs to be performed.

Returns:
True when width inference needs to be performed.
Throws:
IllegalActionException - If the expression for the width 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.

setContainer

public void setContainer(CompositeEntity container)
                  throws IllegalActionException,
                         NameDuplicationException
Specify the container, adding the relation to the list of relations in the container. If this relation already has a container, remove it from that container first. Otherwise, remove it from the list of objects in the workspace. If the argument is null, then unlink the ports from the relation, remove it from its container, and add it to the list of objects in the workspace. If the relation is already contained by the container, do nothing.

The container must be an instance of CompositeActor or null, otherwise an exception is thrown. Derived classes may further constrain the class of the container to a subclass of CompositeActor.

This method invalidates the schedule and resolved types of the director of the container, if there is one.

This method is write-synchronized on the workspace.

Overrides:
setContainer in class ComponentRelation
Parameters:
container - The proposed container.
Throws:
IllegalActionException - If the container is not a CompositeActor or null, or this entity and the container are not in the same workspace.
NameDuplicationException - If the name collides with a name already on the relations list of the container.
See Also:
ComponentRelation.getContainer()

setWidth

public void setWidth(int widthValue)
              throws IllegalActionException
Set the width of this relation and all relations in its relation group. The width is the number of channels that the relation represents. If the argument is equal to WIDTH_TO_INFER, then the relation becomes a bus with unspecified width, and the width will be inferred from the way the relation is used (but will never be less than zero). This method invalidates the resolved types on the director of the container, if there is one, and notifies each connected actor that its connections have changed. This method write-synchronizes on the workspace.

Parameters:
widthValue - The width of the relation.
Throws:
IllegalActionException - If the argument is not zero, one, or equal to WIDTH_TO_INFER and the relation is linked to a non-multiport. Or when the argument is less than zero and different from WIDTH_TO_INFER.
See Also:
Workspace.getWriteAccess(), getWidth()

_checkPort

protected void _checkPort(Port port)
                   throws IllegalActionException
Throw an exception if the specified port cannot be linked to this relation (is not of class IOPort).

Overrides:
_checkPort in class ComponentRelation
Parameters:
port - The candidate port to link to.
Throws:
IllegalActionException - If the port is not an IOPort.

_checkRelation

protected void _checkRelation(Relation relation,
                              boolean symmetric)
                       throws IllegalActionException
Throw an exception if the specified relation is not an instance of IORelation or if it does not have the same width as this relation.

Overrides:
_checkRelation in class ComponentRelation
Parameters:
relation - The relation to link to.
symmetric - If true, the call _checkRelation() on the specified relation with this as an argument.
Throws:
IllegalActionException - If this relation has no container, or if this relation is not an acceptable relation for the specified relation, or if this relation and the specified relation do not have the same width.

_description

protected java.lang.String _description(int detail,
                                        int indent,
                                        int bracket)
                                 throws IllegalActionException
Return a description of the object. The level of detail depends on the argument, which is an or-ing of the static final constants defined in the NamedObj class and in this class. Lines are indented according to to the level argument using the protected method _getIndentPrefix(). Zero, one or two brackets can be specified to surround the returned description. If one is specified it is the the leading bracket. This is used by derived classes that will append to the description. Those derived classes are responsible for the closing bracket. An argument other than 0, 1, or 2 is taken to be equivalent to 0.

If the detail argument sets the bit defined by the constant CONFIGURATION, then append to the description is a field of the form "configuration {width integer ?fixed?}", where the word "fixed" is present if the relation has fixed width, and is absent if the relation is a bus with inferred width (isWidthFixed() returns false). This method is read-synchronized on the workspace.

Overrides:
_description in class Relation
Parameters:
detail - The level of detail.
indent - The amount of indenting.
bracket - The number of surrounding brackets (0, 1, or 2).
Returns:
A description of the object.
Throws:
IllegalActionException

_skipWidthInference

protected boolean _skipWidthInference()
Determines whether width inference should be skipped or not.

Returns:
True when width inference needs to be skipped.

_setInferredWidth

void _setInferredWidth(int width)
                 throws IllegalActionException
Set the inferred width of this relation. The width is the number of channels that the relation represents. This method is not synchronized on the workspace. This packaged method is only meant for the width inference algorithm. It should not be used in other circumstances. Precondition: you should only infer the width in case it is not set by the user.

Parameters:
width - The inferred width of the relation.
Throws:
IllegalActionException - If the expression for the width 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.

_cascade

private Receiver[][] _cascade(Receiver[][] array1,
                              Receiver[][] array2)
                       throws InvalidStateException,
                              IllegalActionException
Cascade two Receiver arrays to form a new array. For each row, each element of the second array is appended behind the elements of the first array. This method is solely for deepReceivers. The two input arrays must have the same number of rows.

Throws:
IllegalActionException
InvalidStateException

_getUserWidth

private int _getUserWidth()
                   throws IllegalActionException
Return the width set by the user

Returns:
The width set by the user.
Throws:
IllegalActionException - If the expression for the width 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.

_inferringWidths

private boolean _inferringWidths()
                          throws IllegalActionException
Determine whether widths are currently being inferred or not.

Returns:
True When widths are currently being inferred.
Throws:
IllegalActionException - If toplevel not a CompositeActor.

_inferWidth

private int _inferWidth()
                 throws IllegalActionException
Infer the width of the port from how it is connected. Throw a runtime exception if this cannot be done (normally, the methods that construct a topology ensure that it can be be done). The returned value is always at least one. This method is not read-synchronized on the workspace, so the caller should be.

Returns:
The inferred width.
Throws:
IllegalActionException

_init

private void _init()
Create an initialize the width parameter.


_setWidth

private void _setWidth(int width)
                throws IllegalActionException
Set the width of this relation and all relations in its relation group. The width is the number of channels that the relation represents. If the argument is equal to the value of WIDTH_TO_INFER, then the relation becomes a bus with unspecified width, and the width will be inferred from the way the relation is used (but will never be less than zero). This method invalidates the resolved types on the director of the container, if there is one, and notifies each connected actor that its connections have changed. This method write-synchronizes on the workspace.

Parameters:
width - The width of the relation.
Throws:
IllegalActionException - If the argument is not zero, one, or equal to WIDTH_TO_INFER and the relation is linked to a non-multiport. Or when the argument is less than zero and different from WIDTH_TO_INFER.
See Also:
Workspace.getWriteAccess(), getWidth()