method register
Contract
Return typewob
Parameter keyDefault valueType
instancereq
registryopt
assign_nbrtrueboolean
Water Contract
<method register
  instance  =req
  registry  =opt
  assign_nbr=true/>

See also: class, registry, make, to_cxs

In normal programming, a class does not know what instances of it have been created. Applications which want to keep track of individual instances, for debugging, display or other purposes, need to explicitly store the object in a variable, field, or table.

Water's register method provides a versatile way for classes to automatically track their instances, allowing them to be distinguished and identified based on both program logic (when they were created) and business logic (their individual attributes). register is typically called at the end of the 'make' method for a class with an argument of the instance being created.

register provides two kinds of instance recording: serial_id registration and unique_id registration. serial_id registration assigns a unique serial number to each instance when it is created and allows the instances of a class to be easily retrieved by serial number. unique_id registration ensures that a particular combination of fields uniquely identify instances of a class and makes it possible to retrieve an instance based on a particular combination.

serial_id registration stores the serial number of an instance in the '_serial_id' field of the instances and maintains a field '_with_serial_id' on the class which is a vector of created instances. The serial number can then be used to select the particular instance from this vector. An instance of the 'boat' class with a serial number of 1138 can be referenced by the expression boat._with_serial_id.1138.

uniquekey registration provides both a way to find instances based on a particular combination of fields and ensures that there is only one instance with each particular combination. This uniqueness can be very important to the business logic of an application as well as providing for potential performance improvements. On the business logic side, many applications create instances which correspond to single business objects (for instance, real world individuals (people, boats, cars, computers, etc) or virtual objects (bank accounts, access or distribution lists, inventories, etc). In nearly all of these cases, it is important that changes to representations of business objects be consistent: that changes to an account balance in one part of the program be immediately visible to other parts of the program. The easiest and safest way to do this is by having them be the same Water object, which is what register ensures.

On the performance side, it can be much faster to compare or lookup registered instances than to compare or lookup regular objects.

Both kinds of registration can be overriden by setting the '_dont_register' field on an instance.

register takes a two optional arguments: 'serial_id' and 'registry'. The 'serial_id' argument is a boolean, defaulting to true, which determines whether to do serial_id registration for the object. When provided, 'registry' points to a registry object to be used for uniquekey registration; when it isn't provided, register uses (and creates if neccessary) a registry on the instance's parent. This registry is created using two fields of the class being instantiated:

'_unique_key' specifies the key around which the registry is built and '_merge_method' (optional) specifies the method used to merge instances in the registry.

'_unique_key' is either a field name or a vector of field names. It indicates the field or combination of fields which uniquely identifies instances of the class. Whenever register is invoked and the _unique_key field is defined, register checks if there are any instances of the class that have the same unique id values as the instance being created. If no such instance exists, the instance being created is stored so that it can be found by future calls to register.

'_merge_method' controls what happens when an instance with the same unique id does exist. It is a method called on the existing instance and the new instance and returns a value which will both be stored under the given unique id and returned by register. The merge method is also called the first time an instance is registered, with a first argument of false.

The default merge method, registry.merge_overlay, keeps the older instance but overwrites any conflicting fields with values from the new instance. Other merge methods are:

registry.merge_overwrite which uses the older instance but makes its field values identical to the new instance, removing fields if necessary;

registry.merge_replace which uses the new instance and replaces the stored value (this may break business logic identity);

registry.merge_ignore which simply returns the new instance, but doesn't store it, setting the '_unregistered' field instead.

Here is an example of serial_id registration:

<class boat>
  <method make> .<register/> </method>
</class>
<set myboat=<boat/>/>
<v myboat._serial_id boat._with_serial_id.0.<is myboat/>/>
<v 0 true/>

Here is an example of unique_id registration, where the 'name' field provides the unique id:

<class boat name=req color='blue' _unique_key='name'>
  <method make> .<register/> </method>
</class>
<set myboat=<boat name="bluebelle" color='blue'/>/>
<set stillmyboat=<boat name="bluebelle"/>/>
stillmyboat.<set color='green'/>
myboat.color
"green"

Since myboat and stillmyboat are the same object, as guaranteed by register, changing the color of stillmyboat changes the color of myboat.

a wob
Parameter keyDefault valueType
serial_idfalse

This determines whether all instances of the class are registered with a unique serial number (serial_id registration). Objects with serial numbers are not normally reclaimed by garbage collection as normal objects are. The serial_serial_id parameter may be set to false to avoid this problem or to simply save the space need to keep track of serial numbers.

Needs to be fixed The formatting method to_cxs has special support for serial_id instances. boat.<to_cxs only_print_instances=true/> turns off the printing of the call to class and the printing of all its attributes. It does however leave on the printing of the of field and all the of fields of all the subclasses of the class you are printing. Use only_print_instances=true when you want to save the instances of a class in a file but not the classes that they came from since you probably load them as part of the loading of your application.

a wob
Parameter keyDefault valueType
_unique_keyfalse

When register is called, the value of this field (if not false) determines the fields of an instance used to uniquely identify it and guarantee the absolute identity of equivalent instances.

In practice, the fields specified in the key field should be read-only and not subject to change (since that would corrupt the registry), but registries do not currently check that this is so.

a wob
Parameter keyDefault valueType
_merge_methodmerge_overlay

When register is called, the value of _merge_method is used to merge distinct but logically equivalent instances of the class. The default behaviour, implemented by registry.merge_overlay, simply uses the existing object, overwriting any fields from the new instance being registered. This method is also called when a new object is registered for the first time, in which case the first argument is simplfy false.

a wob
Parameter keyDefault valueType
_dont_registerfalse

When this field is set to true on an instance, register leaves it alone, neither registering or merging it. This can be used to make distinct instances which would otherwise be identical, e.g.

<class boat name=req color='blue' _unique_key='name' _other_keyed=opt>
  <method make> <register _subject/> </method>
</class>
<set myboat=<boat name="bluebelle" color='blue'/>/>
<set notmyboat=<boat name="bluebelle" _dont_register=true/>/>
notmyboat.<set color='green'/>
myboat.color
"blue"

a wob
Parameter keyDefault valueType
_with_unique_keyfalse

On classes with registered instances, this field contains a mapping from each instance's unique key to the corresponding instance.

<class boat name=req color='blue' _unique_key='name' _other_keyed=opt>
  <method make> <register _subject/> </method>
</class>
<set myboat=<boat name="bluebelle" color='blue'/>/>
boat._with_unique_key."bluebelle".color
"blue"

a wob
Parameter keyDefault valueType
_with_serial_idfalse

On classes with serial_id registered instances, this field contains a mapping from each instance's serial_id to the corresponding instance.