Salome HOME
Copyright update 2021
[modules/kernel.git] / src / DSC / DSC_User / Superv_Component_i.hxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : Superv_Component_i.hxx
24 //  Author : André RIBES (EDF), Eric Fayolle (EDF)
25 //  Module : KERNEL
26 //
27 #ifndef _SUPERV_COMPONENT_I_HXX_
28 #define _SUPERV_COMPONENT_I_HXX_
29
30 #include "DSC_i.hxx"
31 #include "base_port.hxx"
32 #include "uses_port.hxx"
33 #include "provides_port.hxx"
34 #include "port_factory.hxx"
35
36 #include "DSC_Exception.hxx"
37 #include <vector>
38
39 //#define MYDEBUG
40
41 /*! \class Superv_Component_i
42  *  \brief This class implements DSC_User component.
43  *
44  *  This class allows a higher programming level than DSC_Basic. It enables
45  *  a programming level for service's developers who want to use DSC ports.
46  *
47  *  This class has two level for using and declare ports. The higher level proposes
48  *  operations to add ports that are provided by default by SALOME like Calcium ports.
49  *  It provides too some methods to add their own DSC_User ports.
50  *
51  *  \note This class doesn't implement the init_service CORBA operation.
52  */
53 class Superv_Component_i :
54   public Engines_DSC_i,
55   virtual public POA_Engines::Superv_Component
56 {
57 public:
58   Superv_Component_i(CORBA::ORB_ptr orb,
59                      PortableServer::POA_ptr poa,
60                      PortableServer::ObjectId * contId,
61                      const char *instanceName,
62                      const char *interfaceName,
63                      bool notif = false);
64   Superv_Component_i(CORBA::ORB_ptr orb,
65                      PortableServer::POA_ptr poa,
66                      Engines::Container_ptr container, 
67                      const char *instanceName,
68                      const char *interfaceName,
69                      bool notif = false,
70          bool regist = true );
71   virtual ~Superv_Component_i();
72
73   // Exceptions declarations.
74   // There are defined on the Superv_Component_i.cxx to avoid problems
75   // from dlopen.
76   DSC_EXCEPTION(BadFabType)
77   DSC_EXCEPTION(BadType)
78   DSC_EXCEPTION(BadCast)
79   DSC_EXCEPTION(UnexpectedState)
80   DSC_EXCEPTION(PortAlreadyDefined)
81   DSC_EXCEPTION(PortNotDefined)
82   DSC_EXCEPTION(PortNotConnected)
83   DSC_EXCEPTION(NilPort)
84   DSC_EXCEPTION(BadProperty)
85   
86   /*!
87    * \warning currently disabled.
88    */
89   virtual provides_port * create_provides_control_port() 
90   {return NULL;}
91
92   /*!
93    * \warning currently disabled.
94    */
95   virtual provides_port * create_provides_data_and_control_port(const char* /*port_type*/) 
96   {return NULL;}
97
98   /*!
99    * \warning currently disabled.
100    */
101   virtual uses_port * create_uses_control_port()
102   {return NULL;}
103
104   /*!
105    * \warning currently disabled.
106    */
107   virtual uses_port * create_uses_data_and_control_port(const char* /*port_type*/)
108   {return NULL;}
109
110   /*!
111    * This method permits to create a provides port provided by the platform.
112    * (See documentation of DSC for knoing these ports).
113    *   
114    *
115    * \param port_fab_type type provides port.
116    * \return the provides port.
117    *
118    * \note It's user repsonsability to destroy the provides port.
119    */
120   virtual provides_port * create_provides_data_port(const std::string& port_fab_type);
121
122
123   /*!
124    * This method permits to create a uses port provided by the platform.
125    * (See documentation of DSC for knoing these ports).
126    *   
127    *
128    * \param port_fab_type type uses port.
129    * \return the uses port.
130    *
131    * \note It's user repsonsability to destroy the uses port.
132    */
133   virtual uses_port * create_uses_data_port(const std::string& port_fab_type);
134
135   /*!
136    * Adds a port to the component. With this method only Salomé's provided DSC ports
137    * can be added.
138    *
139    * \param port_fab_type type of the port.
140    * \param port_type uses or provides.
141    * \param port_name the name of the port in the component.
142    */
143   virtual void add_port(const char * port_fab_type,
144                         const char * port_type,
145                         const char * port_name);
146
147   /*!
148    * Adds a port to the component. With this method only Salomé's provided DSC ports
149    * can be added.
150    *
151    * \param port_fab_type type of the port.
152    * \param port_type uses or provides.
153    * \param port_name the name of the port in the component.
154    * \return the created port.   
155    */
156   template < typename SpecificPortType >  
157   SpecificPortType * add_port(const char * port_fab_type,
158                               const char * port_type,
159                               const char * port_name);
160
161   /*!
162    * Adds a created provides port to the component.
163    *
164    * \param port the provides port.
165    * \param provides_port_name the name of the port in the component.
166    */
167   virtual void add_port(provides_port * port, 
168                         const char* provides_port_name);
169
170   /*!
171    * Adds a created uses port to the component.
172    *
173    * \param port the uses port.
174    * \param uses_port_name the name of the port in the component.
175    */
176   virtual void add_port(uses_port * port, 
177                         const char* uses_port_name);
178
179   /*!
180    * Gets the provides port already added in the component.
181    *
182    * \param port the provides port pointer.
183    * \param provides_port_name the name of the port.
184    */
185   virtual void get_port(provides_port *& port, 
186                         const char* provides_port_name);
187   
188   /*!
189    * Gets the uses port already added in the component.
190    *
191    * \param port the uses port pointer.
192    * \param uses_port_name the name of the port.
193    */
194   virtual void get_port(uses_port *& port, 
195                         const char* uses_port_name);
196
197   /*!
198    * Gets the list of the ports of a service.
199    * If servicename is not set, all the ports of the component are 
200    * returned.
201    *
202    * \param port_names the ports's list.
203    * \param servicename service's name.
204    */
205   virtual void get_uses_port_names(std::vector<std::string> & port_names,
206                                    const std::string servicename="") const;
207
208   /*!
209    * Gets a port already added in the component.
210    *
211    * \param port_name the name of the port.
212    * \return a port's pointer.
213    */
214   template <typename SpecificPortType > 
215   SpecificPortType * get_port( const char * port_name);
216  
217   /*!
218    * \see DSC_Callbacks::provides_port_changed
219    */
220   virtual void provides_port_changed(const char* provides_port_name,
221                                      int connection_nbr,
222                                      const Engines::DSC::Message message);
223
224   /*!
225    * \see DSC_Callbacks::uses_port_changed
226    */
227   virtual void uses_port_changed(const char* uses_port_name,
228                                  Engines::DSC::uses_port * new_uses_port,
229                                  const Engines::DSC::Message message);
230
231
232   /*!
233    * Add a factory the component. If the factory_name is already
234    * used, the new library is not added.
235    *
236    * \param factory_name name of the factory (used by Superv_Component_i::create_provides_data_port
237    * and Superv_Component_i::create_uses_data_port)
238    * \param factory_ptr factory pointer (destroyed by the component)
239    */
240   static void register_factory(const std::string & factory_name,
241                                 port_factory * factory_ptr);
242
243   /*!
244    * Get a factory from the component. 
245    *
246    * \param factory_name name of the factory.
247    * \return factory pointer, NULL if the factory doesn't exist.
248    */
249   virtual port_factory * get_factory(const std::string & factory_name);
250
251   /*!
252    */
253   static long dscTimeOut;
254   static void setTimeOut();
255   void beginService(const char *serviceName);
256
257
258   // This method is implemented by default since it is a very specific usage.
259   // It also permits to not break compatibility with older components.
260   virtual CORBA::Boolean init_service_with_multiple(const char* /*service_name*/,
261                                                     const Engines::Superv_Component::seq_multiple_param & /*params*/)
262   {
263     return true;
264   }
265
266 private:
267   // Factory map
268   typedef std::map<std::string, port_factory*> factory_map_t;
269   static factory_map_t _factory_map;
270
271   /*-------------------------------------------------*/
272   // A Superv_Component port.
273   struct superv_port_t {
274     superv_port_t():u_ref(NULL),p_ref(NULL){};
275     ~superv_port_t()
276     {
277       if(u_ref)delete u_ref;
278       if(p_ref)
279         {
280           // do not delete CORBA servant : deactivate it and then call _remove_ref or delete
281           PortableServer::ServantBase* servant=dynamic_cast<PortableServer::ServantBase*>(p_ref);
282           if(servant)
283             {
284               PortableServer::POA_var poa =servant->_default_POA();
285               PortableServer::ObjectId_var oid = poa->servant_to_id(servant);
286               poa->deactivate_object(oid);
287               servant->_remove_ref();
288             }
289         }
290     };
291     // For uses ports.
292     uses_port * u_ref;
293     // For provides ports.
294     provides_port * p_ref;
295   };
296
297   typedef std::map<std::string, superv_port_t *> superv_ports;
298
299   /*-------------------------------------------------*/
300   /*-------------------------------------------------*/
301
302   superv_ports my_superv_ports;
303   superv_ports::iterator my_superv_ports_it;
304 };
305
306
307
308 template < typename SpecificPortType >  SpecificPortType * 
309 Superv_Component_i::add_port(const char * port_fab_type,
310                              const char * port_type,
311                              const char * port_name)
312   
313 {
314   assert(port_fab_type);
315   assert(port_type);
316   assert(port_name);
317   SpecificPortType * retPort; 
318
319 #ifdef MYDEBUG
320   std::cout << "---- Superv_Component_i::add_port :  Mark 0 ----  " << port_name << "----" << std::endl;
321 #endif
322     
323   std::string s_port_type(port_type);
324   if (s_port_type == "provides") {
325     provides_port * port = create_provides_data_port(port_fab_type);
326     add_port(port, port_name);
327     retPort = dynamic_cast<SpecificPortType *>(port);
328     if ( retPort == NULL ) { delete port;  
329       throw BadCast( LOC("Can't cast to asked port type " ));
330     }
331   }
332   else if (s_port_type == "uses") {
333     uses_port * port = create_uses_data_port(port_fab_type);
334     add_port(port, port_name);
335 #ifdef MYDEBUG
336     std::cout << "---- Superv_Component_i::add_port :  Mark 1 ----  " << port << "----" << std::endl;
337     std::cout << "---- Superv_Component_i::add_port :  Mark 1 ----   get_repository_id()" << port->get_repository_id() << std::endl;
338 #endif
339     retPort = dynamic_cast<SpecificPortType *>(port);
340 #ifdef MYDEBUG
341     std::cout << "---- Superv_Component_i::add_port :  Mark 2 ----  " << retPort << "----" << std::endl;
342 #endif
343     if ( retPort == NULL ) { delete port;  
344       throw BadCast( LOC("Can't cast to asked port type " ));
345     }
346   }
347   else
348     throw BadType(LOC(OSS()<< "port_type must be either 'provides' either 'uses' not "
349                       << port_type));
350   
351   return retPort;
352 }
353
354
355 template <typename SpecificPortType > SpecificPortType * 
356 Superv_Component_i::get_port( const char * port_name)
357   
358 {
359   assert(port_name);
360     
361   SpecificPortType * retPort;
362   base_port        * port;
363
364   my_superv_ports_it = my_superv_ports.find(port_name);
365   if (my_superv_ports_it == my_superv_ports.end())
366   {
367     throw PortNotDefined( LOC(OSS()<< "Port " << port_name <<" does not exist"));
368   }
369
370   superv_port_t * superv_port =  my_superv_ports[port_name];
371   try {
372     if ( superv_port->p_ref != NULL ) {
373       port = superv_port->p_ref;
374       Ports::Port_var portref=Engines_DSC_interface::get_provides_port(port_name, false); 
375     } 
376     else if ( superv_port->u_ref != NULL ) {
377       port = superv_port->u_ref;
378       Engines::DSC::uses_port * portseq=Engines_DSC_i::get_uses_port(port_name);
379       delete portseq;
380     } else {
381       throw UnexpectedState( LOC(OSS()<< "Internal Error superv_port struct is inconsistent "));
382     
383     }
384   } catch (const Engines::DSC::PortNotDefined&) {
385     throw PortNotDefined( LOC(OSS()<< "port "
386                               << port_name <<" does not exist."));
387   } catch (const Engines::DSC::PortNotConnected&) {
388     throw PortNotConnected( LOC(OSS()<< "port " << port_name 
389                                 << " is not connected."));
390   }
391   
392   retPort = dynamic_cast<SpecificPortType *>(port);
393   if ( retPort == NULL ) {
394     throw BadCast( LOC("Can't cast to required port type " ));
395   }
396
397   return retPort;
398 }
399
400
401 #endif