Copyright (c) Prolog
Developemnt Center SPb
Application Frame. Information exchange
between modules
All application core modules (both FE
and BE) are objects and, therefore, simple calls to them as class
modules cannot be used.
Applicaiton Frame uses a
single object registrar, which is a repository of named objects. An object is added to the
registrar programmatically by the user when this object is created. The object in the registrar
is stored until it is deleted from there by the user programmatically.
If you use a configuration
in which FrontEnd and BackEnd are separate applications and they are
connected via Http, then each of the applications has its own object
registrar, that is, FE and BE cannot "see" each other's object modules. However, in the
configuration of the mono-applications, FE and BE do not take advantage
of the opportunity to contact each other's module-objects through a
common object registrar.
Object Register Operations
The object registrar is an
integral part of the SpbVipTools\Packs\Logic\PzlSystem\OpenPzl\Packs\pzl.pack package. The
predicates for manipulating
object registration are (in the pzl.cl class ):
predicates % Object registration
register :( string ObjectName , object Object ).
registerMulti :( string ObjectName , object Object ).
getObjectByName_nd :( string ObjectName ) -> object Object nondeterm .
getNameByObject_nd :( object Object ) -> string ObjectNameLow nondeterm .
getNameAndObject_nd :( string ObjectName , object Object ) nondeterm ( o , o ).
unRegister :( string ObjectName , object Object ).
unRegisterByName :( string ObjectName ).
unRegisterAllByNamePrefix :( string EntityPrefix ). % unregister all entities
with the Prefixed names
unRegisterByObject :( object Object ).
unRegisterAll :().
Registration is simple by
assigning a name to the
pzl :: register object ( <object name>, <object>),
for example, like this:
...
Tasks = fe_CoreTasks :: new ( This ),
pzl :: register (fe_CoreTasks_C , Tasks ),
...
Wherefe_CoreTasks_C - the name
of the object by agreement.
Getting the registered
object for subsequent calls is also easy:
...
TasksObj = pzl :: getObjectByName_nd (fe_CoreTasks_C )),
the
Tasks = tryConvert ( fe_CoreTasks , TasksObj ) , ! ,
Tasks: foo
(),
...
Of course, one should pay
attention to the determinism of such a transformation. Removing an
object from the registrar is a simple operation
...
pzl::unRegisterByName(fe_CoreTasks_C),
...
Using the object register
in the plugin components
The mechanism for
registering objects can be easily built using any approach to
organizing data storage, and not just using the pzl.pack package .
Using the pzl.pack package is remarkable in that the
plugin components also use the pzl.pack package to work with registered
objects. But the most important
thing is that plug-in components, being DLLs in their essence, have
access to the repository of objects of the main application.
This means that plug-in
components can access each other’s objects and the main application’s
objects using a single database of registered objects.
Using fe_Connector and
be_Connector object modules
The main modules of the
kernel access each other using the described mechanism for registering
objects.
To reduce the size of the
code, operations to obtain objects are placed
- in the FrontEnd part - to
the fe_Connector module
- in the BackEnd part - to
the be_Connector module
Registration of kernel
objects is performed at application startup in the classes Common\AppFrontEnd\frontEnd.pro and Common\AppBackEnd\backEnd.pro,
respectively.
The following trick is used
(using the fe_CoreTasks module object as an example ).
pzl :: register ( string :: concat ( toString ( This ), fe_CoreTasks_C ), Tasks )
That
is, the name of the object during registration consists of the string
name of the class in the form of the constant fe_CoreTasks_C
to which the string
representation of the object is assigned to the left (frontEnd or
backEnd).
Within the
AppFrame, this is not a significant trick. However, the name means
that any of the ApplFrame parts can itself be a plug-in component
in some application (including those built on the basis of
AppFrame), adding such a prefix makes the name of each object
unique within one application.
Finally, in the
xe_Connector class, which is the parent class of application kernel modules,
accessing any application kernel object is made simple by using predicates
for FrontEnd
predicates
fe_AppWindow : () -> fe_MainWindow .
fe_CoreTasks : () -> fe_CoreTasks .
fe_Tasks : () -> fe_Tasks .
fe_Tests : () -> fe_Tests .
be_Responses : () -> be_Responses .
fe_Dictionary : () -> fe_Dictionary .
for BackEnd
predicates
be_CoreTasks : () -> be_CoreTasks .
be_Tasks : () -> be_Tasks .
be_Tests : () -> be_Tests .
fe_Requests : () -> fe_Requests .
be_Options : () -> be_Options .
be_Dictionary : () -> be_Dictionary .
At the same time, obtaining
and converting the object to fe_Connector and be_Connector are done as
described above, as shown below for the object of class fe_CoreTasks
clauses
fe_CoreTasks () = convert ( fe_CoreTasks , GuiTasks ): -
GuiTasks = pzl :: getObjectByName_nd ( string :: concat ( toString ( frontEnd_P ), fe_CoreTasks_C )),!.
fe_CoreTasks () = _ : -
exception :: raise_User ( string :: format( "Component% not Registered!" , Fe_CoreTasks_C )).
Hence it can be understood
by recording the next track code
setRibbonScriptFilesAndNameSpace ( Dialog ): -
Future = be_Responses () : createResponseReciever_async ( be_TakeRibbonScriptFiles_C ),
fe_CoreTasks () : getRibbonScriptFiles (),
...
Where be_Responses () and fe_CoreTasks () prepared
in the manner described objects.