Frames and FrameSets
Overview: The Cougaar Frame infrastructure provides a lightweight and
efficiently distributed form of knowledge representation supporting
two independent inheritance hierarchies, path following, and code
generation. Frames are simultaneously Blackboard objects and Jess
Shadow Facts and can therefore be used both by Plugins and by Jess
rules.
Frames and FrameSets
A {@link org.cougaar.core.qos.frame.DataFrame} is a unit of
knowledge, consisting of a type specification (what kind of entity or
relationship itr represents) and a set of name-value pairs
representing its current state. The of any given DataFrame is fixed
for the lifetime of the Frame. The pairs, also known as slots,
can change dynamically at runtime. Types are organized as a (single
inheritance) hierarchy in which each type inherits the slots defined
by its parent. A second form of read-only inheritance is described below.
DataFrames can be treated as beans, more or less, with the standard
form of accessor methods and with support for property-change
notifications. This allows DataFrames to be shadowed in Jess, which
in turn means that rules can use slot values of DataFrames.
A DataFrame can represent either an entity or a binary
relationship between other DataFrames. In the latter case, each of
two parts of the binary relation are specified by a type/slot/value
triple which is expected to match at most one DataFrame (i.e., at most
one frame of the given type should have the given value in the given
slot). NB: In the current release we assume that slots used in
relationship matching are immutable.
The meta-data in the Cougaar frame system is derived from
prototypes described in xml. These prototypes correspond to
the types of the DataFrames, and are organized as a single-inheritance
hierarchy. Prototypes include declarations of the slots they include,
with optional default values.
Prototype meta-data is used for several purposes. First, it's used
to generate Java classes for the types. DataFrame instances at run
time will be instances of one of these generated classes. In
addition, the prototypes are also accessible at runtime as frames
themselves, in particular as {@link
org.cougaar.core.qos.frame.PrototypeFrame} instances.
A {@link org.cougaar.core.qos.frame.FrameSet} is simply an
organized collection of PrototypeFrames and
DataFrames. PrototypeFrames are associated with the FrameSet when it's
made and are fixed for the life of the FrameSet. DateFrames, on the
other hand, come and go dynamically. The main jobs of a FrameSet are
to provide a well-defined subspace for a collection of Frames, and to
cache relationships.
FrameSets can be created and populated via xml using the {@link
org.cougaar.core.qos.frame.FrameSetService}, which can also be
used to find existing FrameSets. [more?]
One of the novel features of the
Cougaar frame system is that it supports two independent
hierarchies. In addition to the prototype hierarchy, the Cougaar frame
system a second single-inheritance hierarchy known as
containment. Containment is a special relationship used to
augment slot value lookup at runtime. As one might expect, DataFrames
can include a frame-specific value for any given slot. If it does, no
further work is required. If it doesn't, the prototype hierarchy is
searched for a default value or for a path specification (see below for more on paths). If this fails as well,
the containment hierarchy can then be searched. This allows a
DataFrame to have virtual access to slots defined by its logical
container. The containment relation is defined as part of FrameSet
and fixed when the FrameSet is created. This relation is an example
of caching handled by the FrameSet.
Another novel features of the Cougaar frame
system is the {@link org.cougaar.core.qos.frame.Path}
specification. The description of any given slot in a prototype can
indicate that the value of that slot for some frame F is determined by
following a particular path from F a runtime. A Path represents a
kind of encapsulated visitor pattern. It consists of an ordered
series of Forks and a slot. Each Fork refers to a relation and
a role. This allows any given frame to follow a path, one
relationship at a time, to any related frame, arbitrarily far away.
When the final frame in the path is reached, the given slot value is
returned as the value of the original slot reference. NB: Although
DataFrames generally act like beans, including property-change
support, Path-valued slots are an exception at the moment: if the
value of Path-valued slot changes, listeners will not be notified. We
hope to deal with this in a future release.
XML Specification
FrameSets and Frames can be loaded into Cougaar via xml files.
This section describes the XML elements and attributes for
PrototypeFrames. The formal description is in framesets.dtd. The
DTD format for the DataFrames of any particular domain is generated
from the PrototypeFrames. Those are not described in detail here,
but in general each Prototype has a corresponding element that can
contains elements for the slots in that Prototype. Slot elements
have only PCDATA for the value of the slot. For an example, see
cougaar-topology.dtd and test-frames.xml.
- frameset
- A
frameset element is used to describe a FrameSet.
It has four required attributes. The
frame-inheritance describes the prototype inheritance
structure. The only supported value right now is "single" (i.e.,
single inheritance). The container-relation
attribute specifies which relation prototype defines the
containment hierarchy. Any defined relation prototype can be
specified here. The package attribute is used by the
code generator: the classes generated for this frameset's
prototypes will be put in the given package and the files will be
written to the corresponding directory stucture, following
standard Java conventions. Finally, the domain
attribute specifies a name for whatever logical domain the
framset's prototypes are describing. This name should be the root
element in xml data files for this domain.
- prototypes
- A
prototypes element can be used to group
prototype elements. It has no attributes and is
not required. Ordinarily a prototypes element would
be within a frameset element in an XML file. But it
can also be at the top level if the file is being read in to an
existing FrameSet.
- prototype
- A
prototype element defines a PrototypeFrame. It
has one required attribute, name , which is the name of
the prototype. It also supports three optional attributes:
prototype , which specifies the "super" of this one;
container , which specifies the prototype of frames that
can act as containers for frames of this prototype; and
doc , which will be used as javadoc in the generated
class. The remaining structure of a prototype is specified by
the slot elements it contains.
- relation-prototype
- A
relation-prototype element defines a
PrototypeFrame representing a relationship. The attributes
are a superset of the attributes of prototype
elements. The additional attributes, all optional, are
parent-prototype , parent-slot ,
child-prototype and child-slot
- path
- A
path element defines a Path.
It has one required attribute, name . The elements it
contains are any number of forks (order is
significant) followed by an optional slot-reference .
- fork
- A
fork element defines a "hop" in its enclosing
path , where a hop consists of a relation prototype and
a role the next object on the path should play in that
relationshoip. Correspondingly, a element has two required
attributes: relation (the relation prototype name) and
role ("parent" or "child").
- slot
- A
slot element is used within
prototype element to define one of the prototype's
named fields. It has one required attribute, name , which
is the name of the slot, and a range of optional attributes:
doc
- This attribute provides optional
documentation for the slot and is used as javadoc for the
public accessor. It's included in the slot metadata.
immutable
- This boolean valued attribute indicates whether or not
the value of the slot in any given DataFrame can be chaged
after initialization. The default is "false" (ie, values
can be changed after initialization).
member
- This boolean valued attribute indicates whether or not the
generated code for this slot treats it as a data member or
as a property. The former is more efficient for slots whose
value is usually frame-specific, the latter is more
efficient for slots whose value is usually defaulted. The
default for this attribute is "true".
Other slot attributes can render this one irrelevant. In
particular, if a slot has a path , it will never
be a data member, regardless of the setting of this
attribute. Conversely, if the slot is declared to have a
simple type , or if it's declared to be
transient , it will always be a data member,
regardless of the setting of this attribute.
notify-blackboard
- This attribute specifies whether or not a change should be
published on the Blackboard when the slot value changes. The
default is "true".
notify-listeners
- This attribute specifies whether or not PropertyChange
listeners should be notified when the slot value changes. The
default is "true".
path
- The presence of this attribute indicates that the default
value for this slot is computed by following a path. The
value of the attribute is the name of path. If a
path attribute is present, the slot cannot be a
member .
transient
- This boolean valued attribute indicates whether or not the
corresponding data member in the generated class will be
declared transient. The default is "false". Transient
slots are always
members .
type
- This attribute is used to specify the Java type of values
of this slot. The default is "String". Other possible values
are "int", "long", "float", "double", "boolean", "Integer",
"Long", "Float", "Double", "Boolean" and "Metric". Slots with
simple types must be
members . See below for more
on slot types.
units
- This attribute provides optional units for the slot. It's
included in the slot metadata but currently isn't used for
anything else.
default-value
- This attribute gives a default value of the slot. The
value can be any string. If a slot has neither a value nor
a path attribute, then the slot has no default value. In
this case, the generated accessor code will issue a warning
if it has no frame-specific value for this slot.
warn
- This boolean valued attribute indicates whether or not a
warning is generated at runtime if the slot has no
value. The default for this attribute is "true".
- slot-reference
- A
slot-reference element can only be used within a
path element, and if present, must be the last element
in the path . It simply names a slot. As such it has
one required attribute, name .
Code Generation
TO BE DONE
|