Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/kernel.git] / src / DSC / DSC_User / Datastream / Calcium / CalciumCxxInterface.hxx
1 //  Copyright (C) 2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //
21 //
22 //  File   : CalciumCxxInterface.hxx
23 //  Author : Eric Fayolle (EDF)
24 //  Module : KERNEL
25 // Modified by : $LastChangedBy$
26 // Date        : $LastChangedDate: 2007-03-01 13:27:58 +0100 (jeu, 01 mar 2007) $
27 // Id          : $Id$
28
29 #ifndef _CALCIUM_CXXINTERFACE_HXX_
30 #define _CALCIUM_CXXINTERFACE_HXX_
31
32 #include <string>
33 #include <vector>
34 #include <iostream>
35 #include "Superv_Component_i.hxx"
36 #include "CalciumException.hxx"
37 #include "CalciumTypes.hxx"
38 #include "CalciumGenericUsesPort.hxx"
39 #include "Copy2UserSpace.hxx"
40 #include "Copy2CorbaSpace.hxx"
41 #include "CalciumPortTraits.hxx"
42
43 #include <stdio.h>
44
45 //#define _DEBUG_
46
47 template <typename T1, typename T2>
48 struct IsSameType {
49   static const bool value = false;
50 };
51 template <typename T1>
52 struct IsSameType<T1,T1> {
53   static const bool value = true;
54 };
55
56
57
58 namespace CalciumInterface {
59   
60   /********************* INTERFACE DE DECONNEXION *****************/
61
62   static void
63   ecp_fin (Superv_Component_i & component, bool provideLastGivenValue)
64   { 
65     std::vector<std::string> usesPortNames;
66     std::vector<std::string>::const_iterator it;
67     component.get_uses_port_names(usesPortNames);    
68     
69     //récupérer le type de réel du port est un peu difficile
70     //car l'interface nous donne aucune indication
71
72     //     uses_port *myUsesPort;
73     calcium_uses_port* myCalciumUsesPort;
74       
75     for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) {
76       try {
77
78         myCalciumUsesPort= 
79           component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str());
80
81 //      component.Superv_Component_i::get_port(myUsesPort,(*it).c_str());
82 //      calcium_uses_port* myCalciumUsesPort=
83 //        dynamic_cast<calcium_uses_port*>(myUsesPort);
84
85 #ifdef _DEBUG_
86         std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<< 
87           //      typeid(myUsesPort).name() <<"-------------" <<
88           typeid(myCalciumUsesPort).name() <<"-------------" << std::endl;
89 #endif
90         
91 //      if ( !myCalciumUsesPort )
92 //        throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port "
93 //                                              << *it << " en port de type calcium_uses_port." ));
94
95         myCalciumUsesPort->disconnect(provideLastGivenValue);
96
97       } catch ( const Superv_Component_i::BadCast & ex) {
98 #ifdef _DEBUG_
99         std::cerr << ex.what() << std::endl;
100 #endif
101         throw (CalciumException(CalciumTypes::CPTPVR,ex));
102       } catch ( const DSC_Exception & ex) {
103 #ifdef _DEBUG_
104         std::cerr << ex.what() << std::endl;
105 #endif
106         // Exception venant de SupervComponent :
107         //   PortNotDefined(CPNMVR), PortNotConnected(CPLIEN)  
108         // ou du port uses : Dsc_Exception
109         // On continue à traiter la deconnexion des autres ports uses
110       } catch (...) {
111         throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue"));
112         // En fonction du mode de gestion des erreurs throw;
113       }
114     }
115   }
116
117
118   /********************* INTERFACES DE DESALLOCATION  *****************/
119
120   // Uniquement appelé par l'utilisateur s'il utilise la 0 copie
121   //   ( pointeur de données data==NULL à l'appel de ecp_lecture )
122   // Une désallocation aura lieu uniquement si un buffer intermédiaire
123   // était necessaire (type utilisateur et corba diffférent)
124   // La propriété du buffer est rendue à CORBA sinon  
125   template <typename T1, typename T2> static void
126   ecp_free ( T1 * dataPtr )
127   {
128     typedef typename ProvidesPortTraits<T2>::PortType     PortType;
129     typedef typename PortType::DataManipulator            DataManipulator;
130     typedef typename DataManipulator::Type                DataType; // Attention != T
131     typedef typename DataManipulator::InnerType           InnerType;
132
133     DeleteTraits<IsSameType<T1,InnerType>::value >::apply(dataPtr);
134   }
135
136   template <typename T1> static void
137   ecp_free ( T1 * dataPtr )
138   {
139     ecp_free<T1,T1> ( dataPtr );
140   }
141
142
143   /********************* INTERFACES DE LECTURE *****************/
144
145   // T1 est le type de données
146   template <typename T1 > static void
147   ecp_lecture ( Superv_Component_i & component,
148                CalciumTypes::DependencyType dependencyType,
149                double        & ti,
150                double const  & tf,
151                long          & i,
152                const string  & nomVar, 
153                size_t          bufferLength,
154                size_t        & nRead, 
155                T1            * &data )
156   {
157     ecp_lecture<T1,T1> (component,dependencyType,ti,tf,
158                         i,nomVar,bufferLength,nRead,data);
159   
160   }
161
162   // T1 est le type de données
163   // T2 est un <nom> de type Calcium permettant de sélectionner le port correspondant 
164   // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes
165   //  -> Les données des nombres complexes sont de type float mais
166   //     le port à utiliser est le port cplx
167   template <typename T1, typename T2 > static void
168   ecp_lecture ( Superv_Component_i & component,
169                CalciumTypes::DependencyType dependencyType,
170                double        & ti,
171                double const  & tf,
172                long          & i,
173                const string  & nomVar, 
174                size_t          bufferLength,
175                size_t        & nRead, 
176                T1            * &data )
177   {
178
179     assert(&component);
180
181     typedef typename ProvidesPortTraits<T2>::PortType     PortType;
182     typedef typename PortType::DataManipulator            DataManipulator;
183     typedef typename DataManipulator::Type                CorbaDataType; // Attention != T1
184     typedef typename DataManipulator::InnerType           InnerType;
185
186     CorbaDataType     corbaData;
187
188 #ifdef _DEBUG_
189     std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl;
190 #endif
191
192     if (nomVar.empty())
193       throw CalciumException(CalciumTypes::CPNMVR,
194                                 LOC("Le nom de la variable est <nul>"));
195     PortType * port;
196 #ifdef _DEBUG_
197     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl;
198 #endif
199
200     try {
201       port  = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
202 #ifdef _DEBUG_
203       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl;
204 #endif
205     } catch ( const Superv_Component_i::PortNotDefined & ex) {
206 #ifdef _DEBUG_
207       std::cerr << ex.what() << std::endl;
208 #endif
209       throw (CalciumException(CalciumTypes::CPNMVR,ex));
210     } catch ( const Superv_Component_i::PortNotConnected & ex) {
211 #ifdef _DEBUG_
212       std::cerr << ex.what() << std::endl;;
213 #endif
214       throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
215       // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
216     } catch ( const Superv_Component_i::BadCast & ex) {
217 #ifdef _DEBUG_
218       std::cerr << ex.what() << std::endl;
219 #endif
220       throw (CalciumException(CalciumTypes::CPTPVR,ex));
221     }
222   
223     // mode == mode du port 
224     CalciumTypes::DependencyType portDependencyType = port->getDependencyType();
225
226     if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
227       throw CalciumException(CalciumTypes::CPIT,
228                              LOC(OSS()<<"Le mode de dépendance de la variable " 
229                                  << nomVar << " est indéfini."));
230
231     if ( ( portDependencyType != dependencyType ) && 
232          ( dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) ) 
233       throw CalciumException(CalciumTypes::CPITVR,
234                              LOC(OSS()<<"Le mode de dépendance de la variable " 
235                                  << nomVar << ": " << portDependencyType 
236                                  << " ne correspond pas au mode demandé."));
237
238   
239     if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
240       corbaData = port->get(ti,tf, 0);
241 #ifdef _DEBUG_
242       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl;
243 #endif
244     } 
245     else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
246       corbaData = port->get(0, i);
247 #ifdef _DEBUG_
248       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl;
249 #endif
250     } else {
251       // Lecture en séquence
252 #ifdef _DEBUG_
253       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl;
254 #endif
255       corbaData = port->next(ti,i);
256     }
257  
258 #ifdef _DEBUG_
259     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl;
260 #endif
261     size_t corbaDataSize = DataManipulator::size(corbaData);
262 #ifdef _DEBUG_
263     std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl;
264 #endif
265    
266     // Vérifie si l'utilisateur demande du 0 copie
267     if ( data == NULL ) {
268       if ( bufferLength != 0 ) {
269         MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)");
270       }
271       nRead = corbaDataSize;
272       // Si les types T et InnerType sont différents, il faudra effectuer tout de même une recopie
273       if (!IsSameType<T1,InnerType>::value) data = new T1[nRead];
274 #ifdef _DEBUG_
275       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl;
276 #endif
277       // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes
278       Copy2UserSpace< IsSameType<T1,InnerType>::value >::apply(data,corbaData,nRead);
279 #ifdef _DEBUG_
280       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl;
281 #endif
282       // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
283       // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
284       // DataManipulator::delete_data(corbaData);
285       //  old : Dans les deux cas la structure CORBA n'est plus utile 
286       //  old : Si !IsSameType<T1,InnerType>::value l'objet CORBA est détruit avec son contenu
287       //  old : Dans l'autre cas seul la coquille CORBA est détruite 
288       //  L'utilisateur devra appeler ecp_free (version modifiée) qui déterminera s'il est necessaire
289       //   de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété
290    } else {
291       nRead = std::min < size_t > (corbaDataSize,bufferLength);
292 #ifdef _DEBUG_
293       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl;
294 #endif
295       Copy2UserSpace<false>::apply(data,corbaData,nRead);
296 #ifdef _DEBUG_
297       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl;
298 #endif
299       // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
300       // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
301       // DataManipulator::delete_data(corbaData);
302    }
303 #ifdef _DEBUG_
304     std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl;
305     std::copy(data,data+nRead,std::ostream_iterator<T1>(std::cout," "));
306     std::cout << "Ptr :" << data << std::endl;
307
308     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl;
309 #endif
310  
311   
312     return;
313   }
314
315
316   /********************* INTERFACES D'ECRITURE *****************/
317
318   template <typename T1> static void
319   ecp_ecriture ( Superv_Component_i & component,
320                  CalciumTypes::DependencyType dependencyType,
321                  double const  & t,
322                  long   const  & i,
323                  const string  & nomVar, 
324                  size_t bufferLength,
325                  T1  & data ) {
326     ecp_ecriture<T1,T1> (component,dependencyType,t,i,nomVar,bufferLength,data); 
327   }
328
329   template <typename T1, typename T2> static void
330   ecp_ecriture ( Superv_Component_i & component,
331                  CalciumTypes::DependencyType dependencyType,
332                  double const  & t,
333                  long   const  & i,
334                  const string  & nomVar, 
335                  size_t bufferLength,
336                  T1  & data ) 
337   {
338     
339     assert(&component);
340
341     //typedef typename StarTrait<TT>::NonStarType           T;
342     typedef typename UsesPortTraits<T2>::PortType          PortType;
343     typedef typename ProvidesPortTraits<T2>::PortType      ProvidesPortType;
344     typedef typename ProvidesPortType::DataManipulator     DataManipulator;
345     // Verifier que l'on peut définir UsesPortType::DataManipulator
346     //    typedef typename PortType::DataManipulator            DataManipulator;
347     typedef typename DataManipulator::Type                CorbaDataType; // Attention != T1
348     typedef typename DataManipulator::InnerType           InnerType;
349
350 #ifdef _DEBUG_
351     std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl;
352 #endif
353     if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR,
354                                                     LOC("Le nom de la variable est <nul>"));
355     PortType * port;
356 #ifdef _DEBUG_
357     std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl;
358 #endif
359
360     try {
361       port  = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
362 #ifdef _DEBUG_
363       std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl;
364 #endif
365     } catch ( const Superv_Component_i::PortNotDefined & ex) {
366 #ifdef _DEBUG_
367       std::cerr << ex.what() << std::endl;
368 #endif
369       throw (CalciumException(CalciumTypes::CPNMVR,ex));
370     } catch ( const Superv_Component_i::PortNotConnected & ex) {
371 #ifdef _DEBUG_
372       std::cerr << ex.what() << std::endl;;
373 #endif
374       throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
375       // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
376     } catch ( const Superv_Component_i::BadCast & ex) {
377 #ifdef _DEBUG_
378       std::cerr << ex.what() << std::endl;
379 #endif
380       throw (CalciumException(CalciumTypes::CPTPVR,ex));
381     }
382  
383     // mode == mode du port 
384     // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM.
385     // et donc ajouter cette cette méthode uniquement dans l'IDL calcium !
386
387 //     CalciumTypes::DependencyType portDependencyType;
388 //     try {
389 //       portDependencyType = port->getDependencyType();
390 //       std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
391 //     } catch ( const DSC_Exception & ex ) {
392 //       std::cerr << ex.what() << std::endl;;
393 //       throw (CalciumException(CalciumTypes::CPIT,ex));
394 //     }
395
396     if ( dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
397       throw CalciumException(CalciumTypes::CPIT,
398                                 LOC(OSS()<<"Le mode de dépendance demandé pour la variable " 
399                                     << nomVar << " est indéfini."));
400
401     if ( dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY )
402       throw CalciumException(CalciumTypes::CPIT,
403                                 LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable " 
404                                     << nomVar << " est impossible en écriture."));
405
406     // Il faudrait que le port provides génère une exception si le mode donnée n'est pas
407     // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération
408     // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut
409     // modifier l'interface IDL pour y ajouter un mode de dépendance !
410     // ---->
411 //     if ( portDependencyType != dependencyType ) 
412 //       throw CalciumException(CalciumTypes::CPITVR,
413 //                              LOC(OSS()<<"Le mode de dépendance de la variable " 
414 //                                  << nomVar << " ne correspond pas au mode demandé."));
415
416   
417     if ( bufferLength < 1 )
418       throw CalciumException(CalciumTypes::CPNTNULL,
419                                 LOC(OSS()<<"Le buffer a envoyer est de taille nulle "));
420
421
422 #ifdef _DEBUG_
423     std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
424 #endif
425     CorbaDataType corbaData;
426
427     
428     // Si les types Utilisateurs et CORBA sont différents
429     // il faut effectuer une recopie sinon on utilise directement le
430     // buffer data pour constituer la séquence
431     // TODO : 
432     // - Attention en mode asynchrone il faudra eventuellement
433     //   faire une copie des données même si elles sont de même type.
434     // - OLD : En cas de collocalisation (du port provide et du port uses)
435     //   OLD : il est necessaire d'effectuer une recopie du buffer car la
436     //   OLD : séquence est envoyée au port provide par une référence sur 
437     //   OLD : la séquence locale. Or la méthode put récupère le buffer directement
438     //   OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que :
439     //   OLD :   * Le recepteur efface le buffer emetteur
440     //   OLD :   * Le port lui-même efface le buffer de l'ulisateur !
441     //   OLD : Cette copie est effectuée dans GenericPortUses::put 
442     //   OLD : en fonction de la collocalisation ou non.
443     // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides
444     //   OLD : collocalisés les ports provides partagent la même copie de la donnée ! 
445     //   OLD : Il faut effectuer une copie dans le port provides.
446     //   OLD : Cette copie est effectuée dans GenericPortUses::put 
447     //   OLD : en fonction de la collocalisation ou non.
448     Copy2CorbaSpace<IsSameType<T1,InnerType>::value >::apply(corbaData,data,bufferLength);
449  
450     //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté
451     if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
452       try
453       {
454         port->put(*corbaData,t, -1); 
455       }
456       catch ( const DSC_Exception & ex) 
457       {
458         throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
459       }
460       //Le -1 peut être traité par le cst DataIdContainer et transformé en 0 
461       //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq
462 #ifdef _DEBUG_
463       std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl;
464 #endif
465     } 
466     else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
467       try
468       {
469         port->put(*corbaData,-1, i);
470       }
471       catch ( const DSC_Exception & ex) 
472       {
473         throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
474       }
475 #ifdef _DEBUG_
476       std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl;
477 #endif
478     } 
479
480     
481 #ifdef _DEBUG_
482     std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl;
483     for (int i = 0; i < corbaData->length(); ++i)
484       cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << endl;
485 #endif
486     
487     //    if ( !IsSameType<T1,InnerType>::value ) delete corbaData;
488     // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie)
489     delete corbaData;
490
491 #ifdef _DEBUG_
492     std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl;
493 #endif
494    
495     return;
496   }
497
498 };
499
500 #endif