ECT components are deployed into the ECT Java container in the form
of beans which have been packaged in jar files. Each component available
through a container is defined by a component class, and any number of
supporting classes. To methods are available to allow ECT to recognize
which classes are beans - either a developer must either provide a
BeanInfo
class per
component which is packaged into the same jar, or they must
specify this information through a manifest file included in
the jar. This JAR file is normally deployed via the download/java/components
directory. Any supporting JAR files or DLLs are deployed via the download/java/commondirectory.
Once components have been deployed into a container, they may be advertised in a capability browser ( equip.ect.apps.editor.grapheditor.CapabilityBrowser) , which is capable of making requests for instance of a component from a container, and instances of components may be manipulated in the graph editor ( equip.ect.apps.editor.grapheditor.GraphEditor).
How about using an XML file to create the BeanInfo...
Note that the Introspector will share BeanInfo classes, so each component will need to have its own unique BeanInfo class. However, this could just be a trivial (no code) extension of a common class, which based on its own name would read a resource and create appropriate Descriptors...
Furthermore, the resource could be autogenerated by a custom Doclet (or similar?!) processing the component source, so that the same information is included in the Javadocs for the component...
An alternative to providing a BeanInfo class for every component in a jar is to provide a manifest with the jar. This can be used to specify which classes in the jar represent components, and additional information about these components.
The manifest if present is typically called manifest.mf, and must be
specified in the component's ant jar task. The manifest - if present -
must identify all components in the jar, and can also specify the
classification(s) of those components (see BeanInfo, attribute
"classification", above). An example manifest is:
Manifest-Version: 1.0
Name: equip/ect/components/phidgets/PhidgetInterfaceKit.class
Java-Bean: True
classification: Hardware/Input & Output
The lower section ("Name:..." onwards) is repeated for each
component in the jar, with a blank line between each such section.
Both a short description and a longer html description can be specified in the manifest, and ECT uses these attributes in the same way as the shortDescription property and htmlDescription attribute that can be defined in a bean info class. For more information, see file Documenting components
If the bean makes use of resources that need to be released (e.g. COM ports), then it must implement a method with signature "public void stop()" which will be called by the container when the component is being stopped/destroyed, and which should release all resources.
Note that external problems, e.g. termporary loss of remote services, may cause the "same" component instance to be stopped and subsequently recreated within the same container. Therefore it is important that - if at all possible - stopping a component does return all resources to a state where a similar component can be created anew.
While unconfigured the various configuration-specific parameters should be set (and settable). Once fully configured the property "configured" (if present) should be set to true. The component should now respond to any other (non-configuration) properties.
NB to allow the container
persistence and configuration manager to correctly initialise such
components it is required that all properties that must be set before
the component is fully configured begin with the string prefix
"config". If the component needs to know when it has been configured
then it should provide a binary property called "configured". This will
be set after the other "config..." properties and before any other
writeable properties.
If a component wishes to interact directly with ECT or the
installation dataspace, or to be aware of property link requests
applied to it, then it can implement the interface equip.ect.IActiveComponent.
When created the initialise method will be calling, giving the
component a reference to the container installation dataspace client
and the container manager.
Additional methods are also called when the component is linked to
or is about to be updated because of a link. This is used e.g. in the
dictionaryarraymerge component to merge incoming values (this may
become default behaviour for array-type properties in the future).
At present, only property change events are supported by the container.
Note that the container relies on the name and value in the property change events to track changes to properties being set. Therefore the editor (and other external components) will only "see" the change made to a property if a corresponding property change event is fired by the component in each set method, with the correct property name (as specified in the component's BeanInfo, NOT its actual method name).
Simple properties should have simple types. In particular, the
system
has a number of standard (best effort) type coercions, e.g. between all
java primitive types, and also strings and arrays of any of these.
These types should be used wherever possible for simplicity and
interoperability. E.g. the graphical editor views and sets all property
values as strings, and the component's container uses this coercion to
get a value of the appropriate target type. Note: arrays are
stringified in the form "{el1,el2,el3}".
By default string values are quoted within stringified arrays.
It is now also possible to directly use subclasses of equip.runtime.ValueBase as
property types (the root serializable type in EQUIP); these will be
used directly.
There is now also a general-purpose structured type, equip.data.DictionaryImpl. This should be used to communicate structured information and information with associated metadata. This is equivalent to a hash table with keys restricted to being strings and value beings subtypes of equip.runtime.ValueBase. equip.ect.Coerce.toClass(Object,Class) can be used to coerce to/from ValueBase types. The default coercion to/from simple types maps from/to the property named "value". Java Serializable types should also be converted to/from DictionaryImpl types by introspection (untested :-). A Dictionary can also be coerced to/from a java.util.Hashtable. Note: dictionaries are stringified in the form "{prop1=value1,prop2=value2}". A dictionary with no properties is stringified as "{=}" (inspired by Lingo property lists :-) By default string values are quoted within stringified dictionaries.
Use of dictionary type is supported by the components dictionarymerge - which
combines two dictionary-type values into one (merging properties) - and
dictionaryarraymerge -
which combines any number of arrays of dictionary-type values into one.
Note that dictionary types are also used with the dataspaceinterface component, which allows linked values to be exposed directly as tuples and retrieved via the usual dataspace pattern matching.
If a property's type is a 1D array of a Serializable class then the
container will normally assume that these are sub-components of the
parent component, and will expose each element of the array to the
infrastructure as a sub-component with its own properties, etc. It will
add a synthetic "parent" property identifying the parent component. A
sub-component should also have a property of type string called
"persistentChild", which is used a key for sub-component persistence.
I.e. if a parent component is recreated by the persistence mechanism,
then the new child components will be matched to equivalent old child
components based on having the same value for their "persistentChild"
property. Therefore this must be consistent and meaningful (e.g. a X10
subcomponent corresponding to a particular lamp module should always
have a consistent persistentChild property value, typically the X10
address of that particular module).
Note: at some point in the future this may change to require a
particular interface to be implemented by sub-components.
Other properties which are not Serializable are currently assumed to
direct references to internal Java objects that should be passed
directly by reference between components. Currently, this will not work
between components in different JVMs. This is used by the video and
audio framework components to allow video consuming components to get
rapid access to individual video frames via a shared object without
each operation invocation being routed via the dataspace. Note that
this also means that such invocations are not logged and cannot be
replayed.
Components which implement the interface equip.ect.DynamicProperties
(typically implemented using equip.ect.DynamicPropertiesSupport)
can present dynamically (run-time) generated properties to the
framework. See for example the DynamicBeanShell component. The types
can be as for ordinary properties - see above.