Disable and enable context handlers
In order to disable context functions completely, one may set the contextEnabled property in a DataSource definition to false . before opening the data source or passing false in bContextEnabled parameter when opening a database. Disabling context when opening a database or data source disables context behavior completely. i.e. context rules cannot be enabled from within the application while the database is opened.
When context behavior is enabled for the opened database (default), it might be disabled partially. In order to disable a certain context (e.g. the type or property context for a property handle), the appropriate context can be disabled(enabled by setting the BaseContext ::enable property.
Since the type context for a property depends on the type of the currently selected property, disabling the type context becomes more difficult, when reading e.g. instances for a weak-typed collection. Since reading an instance in a weak-typed collection may change the current type of the selected instance, disabling the context before reading the instance will not have any effect, when the new instance has got another type. Hence, Property ::setType() has to be called before reading the instance in order to disable the proper context. This becomes difficult, when the type of the instance to be read is not known. A possible solution is disabling the property context and checking the property context state in critical context functions.
Since the type context for a property depends on the type of the currently selected property, disabling the type context becomes more difficult, when reading e.g. instances for a weak-typed collection. Since reading an instance in a weak-typed collection may change the current type of the selected instance, disabling the context before reading the instance will not have any effect, when the new instance has got another type. Hence, Property ::setType() has to be called before reading the instance in order to disable the proper context. This becomes difficult, when the type of the instance to be read is not known. A possible solution is disabling the property context and checking the property context state in critical context functions.
Similar situation happens when inserting instances to weak-typed or untyped collections. In order to disable the proper context, i.e. the context of the instance to be inserted, the type has to be set before disabling the context. In case of calling Property ::insertReference() , the type to be set should be extracted from the property handle passed to the function.
// read handler for Empoyee (fragment)
int tEmployee::doAfterRead () {
BaseContext &prop_ctx = highContext();
if ( prop_ctx.enabled() { // execute, when property context enabled
// do something
}
}
// fragment:
// members is a weak.typed Person collection
members.propertyContext().enabled(false);
members.next();
members.propertyContext().enabled(true);
Enabling or disabling property context for operation nodes is an important feature, since the property context often is responsible for evaluating the result for a transient property or operation. After evaluating an operation result, the result will be returned internally in a result property, which can be retrieved by calling Property ::resultProperty() . It is possible to disable property context for the result property by providing the context for the result property and disabling it. Disabling context for the result property, however, should be avoided, since it may produce unexpected side effects.
Usually, an operation or transient property does not have got an own instance, and thus, no own type context. When a property handle refers to an operation path or has been evaluated by the application, instances are provided in a result property. When selecting an instance in a transient property handle, the instance is passed from the result to the transient property handle. When disabling the type context after selecting an instance, this works fine, but the instance owner is the result property, i.e. practically, the type context for the result property has been disabled. Similar to the property context for the result property, this may lead to unexpected side effects and should be avoided.
// read handler for Empoyee (fragment)
int tEmployee::doAfterRead () {
Property &person = property();
// local clients will execute both blocks
if ( !isClient() ) { // run on server side, only
// do something
}
if ( !isServer() ) { // run on client side, only
// do something
}
}
The property handle provides a property ( Property ::contextEnabled ), which allows disabling or enabling the context for a property handle. Since disabling context sometimes becomes difficult (weak-typed collections, operations, transient properties), this property allows controlling all context instances associated with the property.
Disabling the context for a property handle includes disabling following context class instances associated with the property:
- property context for the property
- type context for all instance types (weak-typed or untyped)
- property context for result property (operation and transient properties)
- type contexts for instance types for the result property
When a result property of a transient or operation property changes, the contexts for the result node are automatically enabled and contexts of the new result property are disabled.
When running an object server application, context functionality may be executed on the server, on the client or on both. The object server is the only server type, which is able to run context functions.
In order to avoid running context function on client or server, the context function have to check, whether they are running on a server or client. In order to run context functions on client, only, !isServer() should be checked. !isClient() can be checked in order to execute a context function on server side, only.
Since all clients, which are not object server clients, are considered as client, but also as server, this works properly in each client server configuration.