Cadena Property Specification (CPS) Files

CPS files specify various aspects of component behavior, such as intracomponent dependencies between ports and simple behavioral descriptions of a component's event handlers and other methods. The examples presented below describe the structure of these files and illustrate the different aspects of the language. The formal grammar can be found here

Example 1 : A basic CPS file

module common { component BMClosedED { dependencydefault == none; } component BMOpenED { dependencydefault == all; } }

As this first example shows, the contents of CPS files are enclosed within module blocks. The module keyword is followed by an identifier that names the module. This identifier must match the name of the CPS file. In Example 1, since the name of this module is "common", the file must be named "common.cps". In addition to this requirement, there must also be an IDL module with the same name as this CPS module. So for this example, the IDL3 file must contain a module named "common", too.

As seen in Example 1, component blocks constitute the body of a module block. The component keyword is followed by the name of the component, which MUST correspond to a component defined within the IDL3 file. For Example 1, there must be a component named "common :: BMClosedED" in "common.idl3" since there is a component "BMClosedED" in this CPS file.

The two components in Example 1 both use dependencydefault, which may be set to either all or none. A setting of none allows new dependencies to be added to an empty dependency relation. Dependencies do not exist unless they are explicitly declared. A setting of all allows all possible dependencies between ports. The dependencies can still be pruned, though. Once a port is mentioned on the left-hand-side (such as inDataAvailable in Example 2), then only declared dependencies apply for that port.

Example 2 : Explicitly defined dependencies

module common { component BMClosedED { dependencydefault == none; dependencies { inDataAvailable -> dataIn.data[get],outDataAvailable; } } }

Example 2 shows how to explicitly declare dependencies between ports. The dependence declarations take the form trigger-port-action -> response-port-action. The trigger-port-action should be either a facet or an event sink. The response-port-action should either be a receptacle or an event source. Example 2 shows that when an event is received by the "inDataAvailable" event sink, it may trigger the "ReadData" interface of another component, and it may publish a "DataAvailable" event on it's "outDataAvailable" event source (the interfaces are defined in the IDL3 file).

Example 3 : Components with modes

component BMModal { mode common.OnOffMode; dependencydefault == none; dependencies { case OnOffMode of { enabled: inDataAvailable -> dataIn.data[get], outDataAvailable; disabled: inDataAvailable ->; } } }

Components may have different dependencies for different modes of operation. Example 3 shows how the "BMModal" component's dependencies will change when its mode changes. The identifier following the mode keyword specifies the IDL attribute that determines what mode the component is in. The attribute should refer to an IDL enum. The "common.OnOffMode" enum has two values: "enabled" and "disabled".

Inside the dependencies block, the identifier for the case keyword specifies the IDL enum type that determines the mode. The available modes are then located inside the case block, each with its own set of dependencies. As seen in Example 3, "OnOffMode" has values of "enabled" and "disabled", and each of these modes has different dependencies for "inDataAvailable".

Last modified: 07/17/2003 1:02pm