Salome HOME
[EDF27816] : Fix bug presence of proxy into a list
[modules/yacs.git] / doc / salome.rst
1
2 SALOME component
3 ================
4 Principle
5 -----------
6 A SALOME component is a CORBA component as described in the previous chapter, using services of the SALOME kernel.  
7 This component also has to be “declared” to SALOME (i.e. SALOME resource files need to be supplied or completed with 
8 information about this component).  The following operations need to be carried out:
9
10 1. adapt the IDL file
11 2. declare the component to the SALOME modules catalog
12 3. modify the implementation class (C++ or python) to
13
14    - monitor adaptation of the IDL file (point 1)
15    - enable supervision of the component by SALOME, in the different component services 
16    - prepare use of the notification service (send messages to monitor execution of calculations in the component) – optional (but useful)
17 4. Declare any graphic resources
18
19
20 IDL file
21 -----------
22 Principle
23 ^^^^^^^^^^^^
24 The IDL description is similar to the description of a standard CORBA component with the following special features:
25
26 - the component must form part of the basic ``Engines`` module (CORBA)
27 - the component must inherit from the SALOME basic component:  ``Engines::EngineComponent`` (defined in the IDL ``“SALOME_Component.idl”`` file)
28 - the services of the component may have ``in``, ``out`` parameters and /or a return value, but no ``inout`` parameters.
29
30 **Notes**
31
32 #.  The ``Engines`` module includes all SALOME components other than the SALOME central components
33 #.  The ``Engines::EngineComponent`` basic component avoids the need to redefine common services (stop, restart, etc.) for each 
34     component added to the system
35 #.  This is not a limitation, an ``inout`` parameter can be decoupled into an ``in`` parameter and an ``out`` 
36     parameter (in any case, this is the form in which python clients will see it).
37
38 Example 9 (start)
39 ^^^^^^^^^^^^^^^^^
40 We will reuse the ``alglin.idl`` file and adapt it:
41
42 ``alglin.idl``
43
44 .. include:: ./exemples/exemple9/alglin.idl
45    :literal:
46
47 **Note**  
48   It is important to take care when structures are defined in the IDL (like the ``vecteur`` structure in ``algin.idl``). 
49   The chosen name ``vecteur`` might be “reserved” by another SALOME component.
50  
51 Example 10 (start)
52 ^^^^^^^^^^^^^^^^^^
53 Similar modifications are made on the IDL ``FreeFem.idl`` file:
54
55 ``FreeFem.idl``
56
57 .. include:: ./exemples/exemple10/FreeFemComponent.idl
58    :literal:
59
60
61 Registration into the modules catalog
62 --------------------------------------------
63 Before they can be used in SALOME, components must be registered in one of the SALOME modules catalogs.  This catalog is 
64 distributed in several files (general catalog, user catalog).  It will be assumed that the component will be declared in 
65 a user's personal catalog.  The component catalog file is an XML file that contains:
66
67 #. the list of services of the component and their parameters
68 #. the name of the file containing the icon of the component, version information, comments, default service, etc. (this information is optional).
69
70 This catalog can be completed by hand or a utility supplied by SALOME can be used that generates information in 
71 point 1 above (nevertheless, this file must be edited to enter information in point 2).  This tool is available in 
72 the SALOME graphic interface (``Tools->Catalog Generator`` menu) indicating the name of the catalog (XML file) and 
73 the name of the IDL file of the component.
74
75 C++ implementation class
76 ---------------------------
77 **In this section, it will be assumed that the IDL file defines a CORBA class: A and that the C++ implementation class A_impl will be used.**
78
79 Making conforming with the component IDL
80 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81 Proceed as follows to adapt the standard CORBA / C++ implementation classes (as seen in the previous chapter):
82
83 #. Insert the ``SALOMEconfig.h`` file that contains a number of useful definitions to make the code of the implementation
84    class independent from the CORBA version used::
85
86             #include <SALOMEconfig.h>
87
88 #. then insert the ``SALOME_Component_i.hxx`` file that contains the interface of the C++ implementation class of the SALOME basic component::
89
90             #include "SALOME_Component_i.hxx"
91
92 #. for the CORBA class that is implemented, add the following line::
93
94             #include CORBA_SERVER_HEADER(A)
95
96    ``CORBA_SERVER_HEADER`` is a macro defined in ``SALOMEconfig.h`` that makes CORBA inclusion file names independent 
97    from the CORBA implementation used.
98
99 #. for each CORBA class used in the implementation class, add the following line::
100
101             #include CORBA_CLIENT_HEADER(<CORBA class name>)
102
103    ``CORBA_CLIENT_HEADER`` is a macro defined in ``SALOMEconfig.h`` that makes CORBA inclusion file names independent 
104    from the CORBA implementation used.
105
106 #. derive the implementation class from the class of the basic SALOME component::
107
108       class A_impl :
109            public POA_Engines::A,
110            public Engines_Component_i {
111
112 #. define the (sole) constructor as follows in the C++ header file (.hxx)::
113
114            A_impl(CORBA::ORB_ptr orb,
115                   PortableServer::POA_ptr poa,
116                   PortableServer::ObjectId * contId, 
117                   const char *instanceName,
118                   const char *interfaceName);
119
120    and in the C++ implementation file (.cxx)::
121
122            A_impl:: A_impl
123                      (CORBA::ORB_ptr orb,
124                       PortableServer::POA_ptr poa,
125                       PortableServer::ObjectId * contId, 
126                       const char *instanceName, 
127                       const char *interfaceName) :
128                 Engines_Component_i(orb, poa, contId, 
129                                     instanceName, interfaceName)
130            {
131              _thisObj = this ;
132              _id = _poa->activate_object(_thisObj);
133            }
134
135    This constructor may possibly be responsible for creation and initialisation of the internal object associated with the CORBA component.
136
137 #. If structures are defined by the IDL file in the Engines module, adapt declarations of the implementation class methods.
138
139 The above example illustrates the modifications made on example 6.
140  
141 .. _remsuper:
142
143 Enable component supervision
144 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
145 The following needs to be inserted in each service of the component (i.e. in each method of the implementation class 
146 called during a CORBA request), before the component can be controlled from supervision.
147
148 - at the beginning, the instruction::
149
150      beginService(<nom du service>);
151
152 - at the end, the instruction::
153
154      endService(<nom du service>);
155
156 These two instructions notify the SALOME supervision that the component service has actually received the CORBA request (beginService) 
157 and that execution of the service has actually terminated (endService).
158
159 **Note**  
160   Put beginService and endService in the methods of the implementation class of a component declares to SALOME that the component 
161   is "supervisable”.  This is not an assurance that this component can be used without precautions in the case in which the 
162   component has an internal state modified by one or more services.
163
164   **Example**:  
165     Consider a component with an internal variable ``Quantity`` and two services:
166
167     * ``S1(x):  Quantity = Quantity + x;``   returns ``Quantity`` and
168     * ``S2(x) :  Quantity = Quantity * x ;``  returns ``Quantity``.
169
170     *A priori*, it is impossible to know the value of ``Quantity`` after the calculation graph on the following figure has been executed.
171
172 .. _figpara:
173
174
175 .. image:: images/parallele.png
176      :align: center
177
178 .. centered::
179      Calculation graph containing parallel branches
180
181 Using the notification
182 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
183 The constructor of the implementation class must be modified as follows, so as to signal use of the notification (that will 
184 cause opening of a connection to an events channel)::
185
186         A_impl:: A_impl
187                   (CORBA::ORB_ptr orb,
188                    PortableServer::POA_ptr poa,
189                    PortableServer::ObjectId * contId, 
190                    const char *instanceName, 
191                    const char *interfaceName) :
192              Engines_Component_i(orb, poa, contId, 
193                                  instanceName, interfaceName, 1)
194         {
195           _thisObj = this ;
196           _id = _poa->activate_object(_thisObj);
197         }
198
199 in which the parameter “1” has been added to the end of the call to the ``Engines_Component_i`` of the constructor.  
200 The component can then use the instruction::
201
202    void sendMessage(const char *event_type, const char *message);
203
204 to send messages indicating progress with the calculation or an abnormal situation, etc.  These messages will be visible to the 
205 SALOME user.  The first parameter indicates the message type (“warning”, “step”, “trace”, “verbose”), and the second parameter 
206 indicates the message contents (character string).
207
208 Connection to the “factory” object of a container
209 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
210 A “C” function has to be provided with an imposed name and code, for a component to be loaded and initialised by a container::
211
212    extern "C"
213    {
214      PortableServer::ObjectId * <nom du composant>Engine_factory(
215                                   CORBA::ORB_ptr orb,
216                                   PortableServer::POA_ptr poa,
217                                   PortableServer::ObjectId * contId,
218                                   const char *instanceName,
219                                   const char *interfaceName)
220      {
221        <classe d'implementation> * O
222          = new <classe d'implementation>(orb, poa, contId, 
223                                          instanceName, interfaceName);
224        return O->getId() ;
225      }
226    }
227
228 ``<component name>`` (or CORBA class name, ``A`` in this case) and ``<implementation class>`` (``A_impl`` here) are specific 
229 to each component.  This function is called by the container when a component is loaded.  It creates a CORBA object that 
230 will receive requests to the component and will forward them to the different services of the component.
231
232 Example 9 (continued)
233 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
234 We will use the implementation files ``algin_i.hxx`` and ``algin_i.cxx`` again and adapt them:
235
236 ``alglin_i.hxx``
237
238 .. include:: ./exemples/exemple9/alglin_i.hxx
239    :literal:
240
241
242 ``alglin_i.cxx``
243
244 .. include:: ./exemples/exemple9/alglin_i.cxx
245    :literal:
246
247 Python implementation class
248 ------------------------------
249 **In this section, it is assumed that the IDL file defines a CORBA class: B and that we will use the python implementation class: B.**  
250
251 The procedure is similar to the case of the C++ server interface:
252
253 Making conforming with the component IDL
254 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
255
256 #. import the class of the basic component::
257
258       from SALOME_ComponentPy import *
259
260 #. derive the implementation class from the class of the basic SALOME component::
261
262       class B(Engines__POA.B,
263               SALOME_ComponentPy_i):
264
265 #. The constructor of the implementation class must begin by::
266
267           def __init__(self, orb, poa, this, containerName,
268                        instanceName, interfaceName):
269               SALOME_ComponentPy_i.__init__(self, orb, poa, this, 
270                                             containerName, instanceName, 
271                                             interfaceName, False)
272
273 Enable supervision of the component
274 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
275 Before the component can be controlled from supervision, the following have to be inserted in each service of the 
276 component (i.e. in each method of the implementation class called during a CORBA request).
277
278 * at the beginning, the instruction::
279
280      beginService(<service name>);
281
282 * at the end, the instruction::
283
284      endService(<service name>);
285
286 These two instructions notify the SALOME supervision that the component service has actually received the CORBA 
287 request (beginService) and that execution of the service has actually terminated (endService). 
288 Same comment as in the C++ case (:ref:`remsuper`).
289
290 Using the notification
291 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
292 The implementation class constructor should be modified as follows to signal use of the notification::
293
294        def __init__(self, orb, poa, this, containerName,
295                     instanceName, interfaceName):
296            SALOME_ComponentPy_i.__init__(self, orb, poa, this, 
297                                          containerName, instanceName, 
298                                          interfaceName, True)
299
300 in which the parameter “1” is added to the end of the call to the ``SALOME_ComponentPy_i`` of the constructor.  
301 The component can then use the following instruction::
302
303    sendMessage(event_type, message);
304
305 to send messages providing information about progress with the calculation or an abnormal situation, etc.  
306 These messages will be visible to the SALOME user.  The first parameter indicates the message 
307 type (“warning”, “step”, “trace”, “verbose”), and the second parameter indicates the message contents (character string).
308
309
310 Example 10 (continued)
311 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
312 Consider the ``FreeFem.py`` implementation file and adapt it:
313
314 ``FreeFemComponent.py``
315
316 .. include:: ./exemples/exemple10/FreeFemComponent.py
317    :literal:
318
319
320 Using the SALOME compilation and execution environment
321 -----------------------------------------------------------------------
322 Autotools like SALOME will be used.
323
324 Using data structures provided by SALOME or returned by the component
325 ---------------------------------------------------------------------------------------
326 This part will be done with reference to CORBA [CORBA]_ specifications, and particularly IDL specifications – languages [LANG]_ 
327 or the different CORBA manuals, for example [HENVIN]_ (C++) and [PyCorba]_ (python).
328
329 Meshes and MED fields
330 ^^^^^^^^^^^^^^^^^^^^^^^
331 This part will be done with reference to MED and MEDMemory documentation [MEDDoc]_ and [MEDMemory]_.
332