Salome HOME
Copyright update 2022
[modules/kernel.git] / src / ModuleCatalog / SALOME_ModuleCatalog_impl.cxx
1 // Copyright (C) 2007-2022  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 //  SALOME ModuleCatalog : implementation of ModuleCatalog server which parsers xml description of modules
24 //  File   : SALOME_ModuleCatalog_impl.cxx
25 //  Author : Estelle Deville
26 //  Module : SALOME
27 //  $Header$
28 //
29 #include "SALOME_ModuleCatalog_impl.hxx"
30 #include "SALOME_ModuleCatalog_Acomponent_impl.hxx"
31 #include "SALOME_ModuleCatalog_Handler.hxx"
32 #include "SALOME_Fake_NamingService.hxx"
33
34 #include <libxml/parser.h>
35 #include <fstream>
36 #include <map>
37 #include "utilities.h"
38
39 #include <Basics_Utils.hxx>
40
41 #ifdef WIN32
42 # include <process.h>
43 # include <windows.h>
44 #include <fcntl.h>  
45 #include <sys/types.h>  
46 #include <sys/stat.h> 
47 #include <io.h>
48 #include <stdio.h>
49 #include <stddef.h>
50 #include <stdlib.h>
51 #include <wchar.h>
52 #else
53 # include <unistd.h>
54 #endif
55
56 #ifdef _DEBUG_
57 static int MYDEBUG = 0;
58 #else
59 static int MYDEBUG = 0;
60 #endif
61
62 static const char* SEPARATOR     = "::";
63 static const char* OLD_SEPARATOR = ":";
64
65 const char SALOME_ModuleCatalogImpl::ENTRY_IN_NS[] = "/Kernel/ModulCatalog";
66
67 SALOME_ModuleCatalog::ModuleCatalog_ptr KERNEL::getModuleComponentServantSA(const char *listOfCatalogs)
68 {
69   static SALOME_ModuleCatalog::ModuleCatalog_var moduleCata;
70   if(CORBA::is_nil(moduleCata))
71   {
72     CORBA::ORB_ptr orb = KERNEL::getORB();
73     constexpr int NB_OF_ELT_IN_CMD = 3;
74     char *argv[NB_OF_ELT_IN_CMD] = {"SALOME_ModuleCatalog_Server","-common",nullptr};
75     if(listOfCatalogs)
76       argv[2] = const_cast<char*>(listOfCatalogs);
77     SALOME_ModuleCatalogImpl *servant = new SALOME_ModuleCatalogImpl(NB_OF_ELT_IN_CMD,argv,orb);
78     moduleCata = servant->_this();
79     SALOME_Fake_NamingService NS;
80     NS.Register(moduleCata,SALOME_ModuleCatalogImpl::ENTRY_IN_NS);
81   }
82   return SALOME_ModuleCatalog::ModuleCatalog::_duplicate(moduleCata);
83 }
84
85 std::list<std::string> splitStringToList(const std::string& theString, const std::string& theSeparator)
86 {
87   std::list<std::string> aList;
88
89   size_t sepLen = theSeparator.length();
90   size_t startPos = 0, sepPos = theString.find(theSeparator, startPos);
91
92   while (1)
93     {
94       std::string anItem ;
95       if(sepPos != std::string::npos)
96         anItem = theString.substr(startPos, sepPos - startPos);
97       else
98         anItem = theString.substr(startPos);
99       if (anItem.length() > 0)
100         aList.push_back(anItem);
101       if(sepPos == std::string::npos)
102         break;
103       startPos = sepPos + sepLen;
104       sepPos = theString.find(theSeparator, startPos);
105     }
106
107   return aList;
108 }
109
110 class SALOME_ModuleCatalogImpl::Private
111 {
112   friend class SALOME_ModuleCatalogImpl;
113 public:
114   //! method to parse one module catalog
115   /*! 
116     \param file const char* arguments
117     \param modulelist ParserComponents arguments
118     \param pathlist ParserPathPrefixes arguments
119     \param typeMap ParserTypes arguments
120   */
121   void _parse_xml_file(const char* file, 
122                        ParserComponents & modulelist, 
123                        ParserPathPrefixes & pathlist,
124                        ParserTypes& typeMap,
125                        TypeList& typeList);
126
127   //! method to find component in the parser list
128   /*!
129     \param name  string argument
130     \return pointer on a component, NULL if not found
131   */
132   ParserComponent *findComponent(const std::string & name);
133
134   //! method to create a CORBA component description from parser
135   /*!
136     \param C_corba  Component argument
137     \param C_parser const ParserComponent argument
138   */
139   void duplicate(SALOME_ModuleCatalog::ComponentDef & C_corba,
140                  const ParserComponent & C_parser);
141     
142   //! method to create a CORBA interface description from parser
143   /*!
144     \param I_corba  DefinitionInterface argument
145     \param I_parser const ParserInterface argument
146   */
147   void duplicate(SALOME_ModuleCatalog::DefinitionInterface & I_corba,
148                  const ParserInterface & I_parser);
149   
150   //! method to create a CORBA service description from parser
151   /*!
152     \param S_corba  Service argument
153     \param S_parser const ParserService argument
154   */
155   void duplicate(SALOME_ModuleCatalog::Service & S_corba,
156                  const ParserService & service);
157   
158   //! method to create a CORBA parameter description from parser
159   /*!
160     \param P_corba  ServicesParameter argument
161     \param P_parser const ParserParameter argument
162   */
163   void duplicate(SALOME_ModuleCatalog::ServicesParameter & P_corba,
164                  const ParserParameter & P_parser);
165   
166   //! method to create a CORBA datastream parameter description from parser
167   /*!
168     \param P_corba  ServicesDataStreamParameter argument
169     \param P_parser const ParserDataStreamParameter argument
170   */
171   void duplicate(SALOME_ModuleCatalog::ServicesDataStreamParameter & P_corba,
172                  const ParserDataStreamParameter & P_parser);
173   
174   //! method to create the path prefix structures from the catalog parsing
175   /*!
176     \param paths ParserPathPrefixes arguments
177     \return the paths
178   */
179   void duplicate(ParserPathPrefixes & p_out, const ParserPathPrefixes & P_in);
180
181  //! method to verify path prefix content
182   /*!
183     \param pathlist ListOfParserPathPrefix arguments
184     \return true if verification is OK
185   */
186   bool _verify_path_prefix(ParserPathPrefixes & pathlist);
187
188   // Theses variables will contain the path to the general and personal catalogs
189   char* _general_path;
190   char* _personal_path;
191
192   // These variables will contain the information on the general common catalog
193   ParserComponents    _general_module_list ;
194   ParserPathPrefixes  _general_path_list ;
195   ParserTypes _typeMap;
196   TypeList _typeList;
197
198   // These variables will contain the information on the personal catalog
199   ParserComponents    _personal_module_list ;
200   ParserPathPrefixes  _personal_path_list ; 
201
202   std::map <std::string, SALOME_ModuleCatalog::DataStreamDependency> 
203   DataStreamDepConvert;
204
205   std::map <ParserComponentType, SALOME_ModuleCatalog::ComponentType> 
206   ComponentTypeConvert;
207 };
208
209 //----------------------------------------------------------------------
210 // Function : SALOME_ModuleCatalogImpl
211 // Purpose  : Constructor 
212 //----------------------------------------------------------------------
213 SALOME_ModuleCatalogImpl::SALOME_ModuleCatalogImpl(int argc, char** argv, CORBA::ORB_ptr orb) : _orb(orb)
214 {
215   myPrivate = new Private;
216   if(MYDEBUG) MESSAGE("Catalog creation");
217   /* Init libxml */
218   xmlInitParser();
219
220   // Conversion rules for component types
221   myPrivate->ComponentTypeConvert[GEOM]
222     = SALOME_ModuleCatalog::GEOM;
223   myPrivate->ComponentTypeConvert[MESH]
224     = SALOME_ModuleCatalog::MESH;
225   myPrivate->ComponentTypeConvert[Med]
226     = SALOME_ModuleCatalog::Med;
227   myPrivate->ComponentTypeConvert[SOLVER]
228     = SALOME_ModuleCatalog::SOLVER;
229   myPrivate->ComponentTypeConvert[DATA]
230     = SALOME_ModuleCatalog::DATA;
231   myPrivate->ComponentTypeConvert[VISU]
232     = SALOME_ModuleCatalog::VISU;
233   myPrivate->ComponentTypeConvert[SUPERV]
234     = SALOME_ModuleCatalog::SUPERV;
235   myPrivate->ComponentTypeConvert[OTHER]
236     = SALOME_ModuleCatalog::OTHER;
237
238   // Conversion rules for datastream parameters dependency
239   myPrivate->DataStreamDepConvert["UNDEFINED"] 
240     = SALOME_ModuleCatalog::DATASTREAM_UNDEFINED;
241   myPrivate->DataStreamDepConvert["T"]
242     = SALOME_ModuleCatalog::DATASTREAM_TEMPORAL;
243   myPrivate->DataStreamDepConvert["I"] 
244     = SALOME_ModuleCatalog::DATASTREAM_ITERATIVE;
245
246   // Empty used variables
247   myPrivate->_general_module_list.resize(0);
248   myPrivate->_general_path_list.resize(0);
249
250   myPrivate->_personal_module_list.resize(0);
251   myPrivate->_personal_path_list.resize(0);
252   
253   // Parse the arguments given at server run
254   if (!_parseArguments(argc, argv,&myPrivate->_general_path,&myPrivate->_personal_path))
255     if(MYDEBUG) MESSAGE( "Error while argument parsing" );
256
257   // Test existency of files
258   if (myPrivate->_general_path == NULL)
259   {
260     if(MYDEBUG) MESSAGE( "Error the general catalog should be indicated" );
261   }
262   else
263   {
264     // Affect the _general_module_list and _general_path_list members
265     // with the common catalog
266
267     std::list<std::string> dirList;
268
269 #ifdef WIN32
270     dirList = splitStringToList(myPrivate->_general_path, SEPARATOR);
271 #else
272     //check for new format
273     bool isNew = (std::string( myPrivate->_general_path ).find(SEPARATOR) != std::string::npos);
274     if ( isNew ) {
275       //using new format
276       dirList = splitStringToList(myPrivate->_general_path, SEPARATOR);
277     } else {
278       //support old format
279       dirList = splitStringToList(myPrivate->_general_path, OLD_SEPARATOR);
280     }
281 #endif
282
283     for (std::list<std::string>::iterator iter = dirList.begin(); iter != dirList.end(); iter++)
284     {
285       std::string aPath = (*iter);
286       //remove inverted commas from filename
287       while (aPath.find('\"') != std::string::npos)
288         aPath.erase(aPath.find('\"'), 1);
289
290       myPrivate->_parse_xml_file(aPath.c_str(), 
291                                  myPrivate->_general_module_list, 
292                                  myPrivate->_general_path_list,
293                                  myPrivate->_typeMap,
294                                  myPrivate->_typeList);
295     }
296
297     // Verification of _general_path_list content
298     if (!myPrivate->_verify_path_prefix(myPrivate->_general_path_list)) {
299       if(MYDEBUG) MESSAGE( "Error while parsing the general path list, "
300                            "different paths are associated to the same computer," 
301                            "the first one will be chosen");
302     } else {
303       if(MYDEBUG) MESSAGE("General path list OK");
304     }
305
306     if (myPrivate->_personal_path != NULL) {
307       // Initialize the _personal_module_list and 
308       // _personal_path_list members with the personal catalog files
309       myPrivate->_parse_xml_file(myPrivate->_personal_path,
310                                  myPrivate->_personal_module_list, 
311                                  myPrivate->_personal_path_list,
312                                  myPrivate->_typeMap,
313                                  myPrivate->_typeList);
314       
315       // Verification of _general_path_list content
316       if(!myPrivate->_verify_path_prefix(myPrivate->_personal_path_list)){
317         if(MYDEBUG) MESSAGE("Error while parsing the personal path list, "
318                             "different paths are associated to the same computer, "
319                             "the first one will be chosen" );
320       }else {
321         if(MYDEBUG) MESSAGE("Personal path list OK");
322       }
323     }else 
324       if(MYDEBUG) MESSAGE("No personal catalog indicated or error while "
325                           "opening the personal catalog");
326   }
327 }
328
329 //----------------------------------------------------------------------
330 // Function : ~SALOME_ModuleCatalogImpl
331 // Purpose  : Destructor 
332 //----------------------------------------------------------------------
333 SALOME_ModuleCatalogImpl::~SALOME_ModuleCatalogImpl()
334 {
335   if(MYDEBUG) MESSAGE("Catalog Destruction");
336   delete myPrivate;
337 }
338
339
340 //! Get the list of all types of the catalog
341 /*!
342  *   \return  the list of types
343  */
344 SALOME_ModuleCatalog::ListOfTypeDefinition* SALOME_ModuleCatalogImpl::GetTypes()
345 {
346   SALOME_ModuleCatalog::ListOfTypeDefinition_var type_list = new SALOME_ModuleCatalog::ListOfTypeDefinition();
347   type_list->length((CORBA::ULong)myPrivate->_typeList.size());
348
349   for (unsigned int ind = 0 ; ind < myPrivate->_typeList.size() ; ind++)
350     {
351       //no real need to call string_dup, omniorb calls it on operator= (const char *) but it is safer
352       type_list[ind].name=CORBA::string_dup(myPrivate->_typeList[ind].name.c_str());
353       type_list[ind].kind=SALOME_ModuleCatalog::NONE;
354       if(myPrivate->_typeList[ind].kind=="double")
355         type_list[ind].kind=SALOME_ModuleCatalog::Dble;
356       else if(myPrivate->_typeList[ind].kind=="int")
357         type_list[ind].kind=SALOME_ModuleCatalog::Int;
358       else if(myPrivate->_typeList[ind].kind=="bool")
359         type_list[ind].kind=SALOME_ModuleCatalog::Bool;
360       else if(myPrivate->_typeList[ind].kind=="string")
361         type_list[ind].kind=SALOME_ModuleCatalog::Str;
362       else if(myPrivate->_typeList[ind].kind=="objref")
363         {
364           type_list[ind].kind=SALOME_ModuleCatalog::Objref;
365           type_list[ind].id=CORBA::string_dup(myPrivate->_typeList[ind].id.c_str());
366           //bases
367           type_list[ind].bases.length((CORBA::ULong)myPrivate->_typeList[ind].bases.size());
368           std::vector<std::string>::const_iterator miter;
369           miter=myPrivate->_typeList[ind].bases.begin();
370           int n_memb=0;
371           while(miter != myPrivate->_typeList[ind].bases.end())
372             {
373               type_list[ind].bases[n_memb]=CORBA::string_dup(miter->c_str());
374               miter++;
375               n_memb++;
376             }
377         }
378       else if(myPrivate->_typeList[ind].kind=="sequence")
379         {
380           type_list[ind].kind=SALOME_ModuleCatalog::Seq;
381           type_list[ind].content=CORBA::string_dup(myPrivate->_typeList[ind].content.c_str());
382         }
383       else if(myPrivate->_typeList[ind].kind=="array")
384         {
385           type_list[ind].kind=SALOME_ModuleCatalog::Array;
386           type_list[ind].content=CORBA::string_dup(myPrivate->_typeList[ind].content.c_str());
387         }
388       else if(myPrivate->_typeList[ind].kind=="struct")
389         {
390           type_list[ind].kind=SALOME_ModuleCatalog::Struc;
391           //members
392           type_list[ind].members.length((CORBA::ULong)myPrivate->_typeList[ind].members.size());
393
394           std::vector< std::pair<std::string,std::string> >::const_iterator miter;
395           miter=myPrivate->_typeList[ind].members.begin();
396           int n_memb=0;
397           while(miter != myPrivate->_typeList[ind].members.end())
398             {
399               type_list[ind].members[n_memb].name=CORBA::string_dup(miter->first.c_str());
400               type_list[ind].members[n_memb].type=CORBA::string_dup(miter->second.c_str());
401               n_memb++;
402               miter++;
403             }
404         }
405     }
406   return type_list._retn();
407 }
408
409 //----------------------------------------------------------------------
410 // Function : GetComputerList
411 // Purpose  : get a computer list
412 //----------------------------------------------------------------------
413 SALOME_ModuleCatalog::ListOfComputers* 
414 SALOME_ModuleCatalogImpl::GetComputerList()
415 {
416   SALOME_ModuleCatalog::ListOfComputers_var _list_computers = 
417     new SALOME_ModuleCatalog::ListOfComputers;
418   return _list_computers._retn();
419 }
420
421 //----------------------------------------------------------------------
422 // Function : GetPathPrefix
423 // Purpose  : get the PathPrefix of a computer
424 //----------------------------------------------------------------------
425 char* 
426 SALOME_ModuleCatalogImpl::GetPathPrefix(const char* machinename) {
427   if(MYDEBUG) MESSAGE("Begin of GetPathPrefix");
428   // Variables initialisation
429   std::string _path;
430   bool _find = false;
431
432   // Parse all the path prefixes
433   // looking for the wanted computer
434   for (unsigned int ind = 0; ind < myPrivate->_personal_path_list.size() && !_find; ind++)
435   {
436     for (unsigned int ind1 = 0; ind1 < myPrivate->_personal_path_list[ind].listOfComputer.size() && !_find; ind1++)
437     {
438       if ( myPrivate->_personal_path_list[ind].listOfComputer[ind1] == machinename )
439       {
440         _find = true;
441         // Wanted computer
442         // affect the path to be returned
443         _path = myPrivate->_personal_path_list[ind].path;
444       }
445     }
446   }
447
448   for (unsigned int ind = 0; ind < myPrivate->_general_path_list.size() && !_find; ind++)
449   {
450     for (unsigned int ind1 = 0; ind1 < myPrivate->_general_path_list[ind].listOfComputer.size() && !_find; ind1++)
451     {
452       if (myPrivate->_general_path_list[ind].listOfComputer[ind1] == machinename)
453       {
454         _find = true;
455         // Wanted computer
456         // affect the path to be returned
457         _path = myPrivate->_general_path_list[ind].path;
458       }
459     }
460   }
461   return CORBA::string_dup(_path.c_str()) ;
462 }
463
464 //----------------------------------------------------------------------
465 // Function : GetComponentList
466 // Purpose  : get a component list
467 //            If a component is defined in the personal catalog and 
468 //            in the general catalog (same name), the component defined
469 //            in the personal catalog is used
470 //----------------------------------------------------------------------
471 SALOME_ModuleCatalog::ListOfComponents* 
472 SALOME_ModuleCatalogImpl::GetComponentList()
473 {
474   if(MYDEBUG) MESSAGE("Begin of GetComponentList");
475   SALOME_ModuleCatalog::ListOfComponents_var _list_components = 
476     new SALOME_ModuleCatalog::ListOfComponents;
477
478   _list_components->length((CORBA::ULong)myPrivate->_personal_module_list.size());
479
480   // All the components defined in the personal catalog are taken
481   for(unsigned int ind=0; ind < myPrivate->_personal_module_list.size();ind++){
482     _list_components[ind]=(myPrivate->_personal_module_list[ind].name).c_str();
483     if(MYDEBUG) SCRUTE(_list_components[ind]) ;
484   }
485
486   size_t indice = myPrivate->_personal_module_list.size();
487   bool _find = false;
488   
489   // The components in the general catalog are taken only if they're
490   // not defined in the personal catalog
491   for(unsigned int ind=0; ind < myPrivate->_general_module_list.size();ind++){
492     _find = false;
493     for(unsigned int ind1=0; ind1 < myPrivate->_personal_module_list.size();ind1++){
494       // searching if the component is already defined in 
495       // the personal catalog
496       if ((myPrivate->_general_module_list[ind].name.compare(myPrivate->_personal_module_list[ind1].name)) == 0)
497         _find = true;
498     }
499     if(!_find){
500       if(MYDEBUG) MESSAGE("A new component " << myPrivate->_general_module_list[ind].name 
501                           << " has to be to added in the list");
502       _list_components->length((CORBA::ULong)indice+1);
503       // The component is not already defined => has to be taken
504       _list_components[(CORBA::ULong)indice]=(myPrivate->_general_module_list[ind].name).c_str();
505       if(MYDEBUG) SCRUTE(_list_components[(CORBA::ULong)indice]) ;
506       
507       indice++;
508     }else{
509       if(MYDEBUG) MESSAGE("The component " <<myPrivate->_general_module_list[ind].name 
510                           << " was already defined in the personal catalog") ;
511     }
512   }
513   
514   if(MYDEBUG) MESSAGE ( "End of GetComponentList" );
515   return _list_components._retn();
516 }
517
518
519 //----------------------------------------------------------------------
520 // Function : GetComponentIconeList
521 // Purpose  : get a component list of component name and component icone
522 //            If a component is defined in the personal catalog and 
523 //            in the general catalog (same name), the component defined
524 //            in the personal catalog is used
525 //----------------------------------------------------------------------
526 SALOME_ModuleCatalog::ListOfIAPP_Affich* 
527 SALOME_ModuleCatalogImpl::GetComponentIconeList()
528 {
529   if(MYDEBUG) MESSAGE("Begin of GetComponentIconeList");
530
531   SALOME_ModuleCatalog::ListOfIAPP_Affich_var _list_components_icone = 
532     new SALOME_ModuleCatalog::ListOfIAPP_Affich;
533
534   _list_components_icone->length((CORBA::ULong)myPrivate->_personal_module_list.size());
535
536   // All the components defined in the personal catalog are taken
537   for(unsigned int ind=0; ind < myPrivate->_personal_module_list.size();ind++){
538     _list_components_icone[ind].modulename=(myPrivate->_personal_module_list[ind].name).c_str();
539     _list_components_icone[ind].moduleusername=(myPrivate->_personal_module_list[ind].username).c_str();
540     _list_components_icone[ind].moduleicone=(myPrivate->_personal_module_list[ind].icon).c_str();
541     _list_components_icone[ind].moduleversion=(myPrivate->_personal_module_list[ind].version).c_str();
542     _list_components_icone[ind].modulecomment=(myPrivate->_personal_module_list[ind].comment).c_str();
543     //if(MYDEBUG) SCRUTE(_list_components_icone[ind].modulename); 
544     //if(MYDEBUG) SCRUTE(_list_components_icone[ind].moduleicone);
545   }
546   
547   size_t indice = myPrivate->_personal_module_list.size();
548   bool _find = false;
549   
550   // The components in the general catalog are taken only if they're
551   // not defined in the personal catalog
552   for(unsigned int ind=0; ind < myPrivate->_general_module_list.size();ind++){
553     _find = false;
554     for(unsigned int ind1=0; ind1 < myPrivate->_personal_module_list.size();ind1++){
555       // searching if the component is aleready defined in 
556       // the personal catalog
557       if((myPrivate->_general_module_list[ind].name.compare(myPrivate->_personal_module_list[ind1].name)) == 0)
558         _find = true;
559     }
560     if(!_find){
561       //          if(MYDEBUG) MESSAGE("A new component " << _general_module_list[ind].name << " has to be to added in the list");
562       _list_components_icone->length((CORBA::ULong)indice+1);
563       // The component is not already defined => has to be taken
564       _list_components_icone[(CORBA::ULong)indice].modulename=myPrivate->_general_module_list[ind].name.c_str();  
565       _list_components_icone[(CORBA::ULong)indice].moduleusername=myPrivate->_general_module_list[ind].username.c_str();  
566       _list_components_icone[(CORBA::ULong)indice].moduleicone=myPrivate->_general_module_list[ind].icon.c_str(); 
567       _list_components_icone[(CORBA::ULong)indice].moduleversion=myPrivate->_general_module_list[ind].version.c_str();
568       _list_components_icone[(CORBA::ULong)indice].modulecomment=myPrivate->_general_module_list[ind].comment.c_str();
569       //if(MYDEBUG) SCRUTE(_list_components_icone[(CORBA::ULong)indice].modulename) ;
570       //if(MYDEBUG) SCRUTE(_list_components_icone[(CORBA::ULong)indice].moduleicone);
571       
572       indice++;
573     }
574     // else 
575     //if(MYDEBUG) MESSAGE("The component " <<_general_module_list[ind].name << " was already defined in the personal catalog"); 
576   }
577   
578   return _list_components_icone._retn() ;
579 }
580
581 //----------------------------------------------------------------------
582 // Function : GetTypedComponentList
583 // Purpose  : get a component list of a wanted type
584 //            If a component is defined in the personal catalog and 
585 //            in the general catalog (same name), the component defined
586 //            in the personal catalog is used
587 //----------------------------------------------------------------------
588 SALOME_ModuleCatalog::ListOfComponents* 
589 SALOME_ModuleCatalogImpl::GetTypedComponentList(SALOME_ModuleCatalog::ComponentType component_type)
590 {
591   if(MYDEBUG) MESSAGE("Begin of GetTypedComponentList");
592   SALOME_ModuleCatalog::ListOfComponents_var _list_typed_component = 
593     new SALOME_ModuleCatalog::ListOfComponents;
594   int _j = 0;
595
596   _list_typed_component->length(0);
597   // Transform SALOME_ModuleCatalog::ComponentType in ParserComponentType
598   ParserComponentType _temp_component_type = OTHER;
599   switch(component_type){
600   case SALOME_ModuleCatalog::GEOM:
601     _temp_component_type = GEOM ;
602     break;
603   case SALOME_ModuleCatalog::MESH:
604     _temp_component_type = MESH;
605     break;   
606   case SALOME_ModuleCatalog::Med:
607     _temp_component_type = Med;
608     break;    
609   case SALOME_ModuleCatalog::SOLVER:   
610     _temp_component_type = SOLVER;
611     break;
612   case SALOME_ModuleCatalog::DATA:
613     _temp_component_type = DATA;
614     break;
615   case SALOME_ModuleCatalog::VISU:
616     _temp_component_type = VISU;
617     break;  
618   case SALOME_ModuleCatalog::SUPERV:
619     _temp_component_type = SUPERV;
620     break;
621   case SALOME_ModuleCatalog::OTHER:
622     _temp_component_type = OTHER;
623     break;
624   }
625
626   // All the components in the personal catalog are taken
627   for (unsigned int ind=0; ind < myPrivate->_personal_module_list.size();ind++)
628     {
629       if  (myPrivate->_personal_module_list[ind].type == _temp_component_type)
630         {
631           _list_typed_component->length(_j + 1); 
632            _list_typed_component[_j] = myPrivate->_personal_module_list[ind].name.c_str();
633           //if(MYDEBUG) SCRUTE(_list_typed_component[_j]);
634           _j++;
635         }
636     }
637
638   int indice = _list_typed_component->length() ;
639   bool _find = false;
640   
641   // The components in the general catalog are taken only if they're
642   // not defined in the personal catalog
643   for (unsigned int ind=0; ind < myPrivate->_general_module_list.size();ind++)
644     {
645       _find = false;
646
647       if(myPrivate->_general_module_list[ind].type == _temp_component_type)
648         {
649           for (unsigned int ind1=0; ind1 < myPrivate->_personal_module_list.size();ind1++)
650             {
651               // searching if the component is aleready defined in 
652               // the personal catalog
653               if ((myPrivate->_general_module_list[ind].name.compare(myPrivate->_personal_module_list[ind1].name)) == 0)
654                 _find = true;
655             }
656           if (!_find)
657             {
658               //if(MYDEBUG) MESSAGE("A new component " << _general_module_list[ind].name << " has to be to added in the list");
659               _list_typed_component->length(indice+1);
660               // The component is not already defined => has to be taken
661               _list_typed_component[indice]=(myPrivate->_general_module_list[ind].name).c_str();   
662               //if(MYDEBUG) SCRUTE(_list_typed_component[indice]) ;
663
664               indice++;
665             }
666           //else 
667             //if(MYDEBUG) MESSAGE("The component " <<_general_module_list[ind].name << " was already defined in the personal catalog") ;
668         }
669     }
670
671
672   return _list_typed_component._retn();
673 }
674
675 //----------------------------------------------------------------------
676 // Function : GetComponent
677 // Purpose  : get a component 
678 //            If a component is defined in the personal catalog and 
679 //            in the general catalog (same name), the component defined
680 //            in the personal catalog is used
681 //----------------------------------------------------------------------
682 SALOME_ModuleCatalog::Acomponent_ptr 
683 SALOME_ModuleCatalogImpl::GetComponent(const char* name)
684 {
685   // Looking for component named "componentname" in the personal catalog
686   // If found, get name, interfaces and constraint
687   // If not found, looking for component named "componentname" in
688   // the general catalog
689   // If found, get name, interfaces and constraint
690   // If not found, NULL pointer is returned
691
692   std::string s(name);
693   ParserComponent *C_parser = NULL;
694   //ParserPathPrefixes *pp = NULL;
695
696   SALOME_ModuleCatalog::Acomponent_ptr compo
697     = SALOME_ModuleCatalog::Acomponent::_nil();
698   C_parser = myPrivate->findComponent(s);
699   if (C_parser) {
700     
701     //    DebugParserComponent(*C_parser);
702
703     SALOME_ModuleCatalog::ComponentDef C_corba;
704     myPrivate->duplicate(C_corba, *C_parser);
705
706     
707     SALOME_ModuleCatalog_AcomponentImpl * aComponentImpl = 
708       new SALOME_ModuleCatalog_AcomponentImpl(C_corba);
709     
710     compo = aComponentImpl->_this();
711   }
712   else {
713     // Not found in the personal catalog and in the general catalog
714     // return NULL object
715     if(MYDEBUG) MESSAGE("Component with name  " << name 
716                         << " not found in catalog");
717   }
718   
719   return compo;
720 }
721
722 SALOME_ModuleCatalog::ComponentDef *
723 SALOME_ModuleCatalogImpl::GetComponentInfo(const char *name)
724 {
725   std::string s(name);
726
727   ParserComponent * C_parser = myPrivate->findComponent(s);
728   
729   if (C_parser) {
730     
731     SALOME_ModuleCatalog::ComponentDef * C_corba 
732       = new SALOME_ModuleCatalog::ComponentDef; 
733     myPrivate->duplicate(*C_corba, *C_parser);
734     return C_corba;
735   }
736
737   return NULL;
738 }
739
740 void SALOME_ModuleCatalogImpl::ping()
741 {
742 }
743
744 CORBA::Long SALOME_ModuleCatalogImpl::getPID()
745
746   return 
747 #ifndef WIN32
748     (CORBA::Long)getpid();
749 #else
750     (CORBA::Long)_getpid();
751 #endif
752 }
753
754 void SALOME_ModuleCatalogImpl::ShutdownWithExit()
755 {
756   exit( EXIT_SUCCESS );
757 }
758
759 void SALOME_ModuleCatalogImpl::shutdown()
760 {
761   if (!CORBA::is_nil(_orb)) _orb->shutdown(0);
762 }
763
764
765
766 //----------------------------------------------------------------------
767 // Function : _parseArguments
768 // Purpose  : parse arguments to get general and personal catalog files
769 //----------------------------------------------------------------------
770 bool
771 SALOME_ModuleCatalogImpl::_parseArguments(int argc, char **argv, 
772                                           char **_general, 
773                                           char** _personal)
774 {
775   bool _return_value = true;
776   *_general = NULL;
777   *_personal = NULL ;
778   for (int ind = 0; ind < argc ; ind++)
779     {
780
781       if (strcmp(argv[ind],"-help") == 0)
782         {
783           INFOS( "Usage: " << argv[0] 
784                  << " -common 'path to general catalog' "
785                  " -personal 'path to personal catalog' "
786                  " -ORBInitRef NameService=corbaname::localhost");
787             _return_value = false ;
788         }
789
790       if (strcmp(argv[ind],"-common") == 0)
791         {
792           if (ind + 1 < argc)
793             {
794               // General catalog file
795               *_general = argv[ind + 1] ;
796             }
797         }
798       else if (strcmp(argv[ind],"-personal") == 0)
799         {
800           if (ind + 1 < argc)
801             {
802               // Personal catalog file
803               *_personal = argv[ind + 1] ;
804             }
805         }
806     }
807   return _return_value;
808 }
809
810 ParserComponent *
811 SALOME_ModuleCatalogImpl::Private::findComponent(const std::string & name)
812 {
813   ParserComponent * C_parser = NULL;
814
815   if (!C_parser)
816     for (unsigned int ind=0; ind < _personal_module_list.size();ind++)
817       {
818         if (name.compare(_personal_module_list[ind].name) == 0)
819           {
820             if(MYDEBUG) MESSAGE("Component named " << name 
821                                 << " found in the personal catalog");
822             C_parser = &(_personal_module_list[ind]);
823             break;
824           }
825       }
826
827   if (!C_parser)
828     for (unsigned int ind=0; ind < _general_module_list.size();ind++)
829       {
830         if (name.compare(_general_module_list[ind].name) == 0)
831           {
832             //      if(MYDEBUG) MESSAGE("Component named " << name 
833             //                  << " found in the general catalog");
834             C_parser = &(_general_module_list[ind]);
835             break;
836           }
837       }
838
839   return C_parser;
840 }
841
842 //----------------------------------------------------------------------
843 // Function : _parse_xml_file
844 // Purpose  : parse one module catalog 
845 //----------------------------------------------------------------------
846 void 
847 SALOME_ModuleCatalogImpl::Private::_parse_xml_file(const char* file, 
848                                                    ParserComponents& modulelist, 
849                                                    ParserPathPrefixes& pathList,
850                                                    ParserTypes& typeMap,
851                                                    TypeList& typeList)
852 {
853   if(MYDEBUG) BEGIN_OF("_parse_xml_file");
854   if(MYDEBUG) SCRUTE(file);
855
856   //Local path and module list for the file to parse
857   ParserPathPrefixes  _pathList;
858   ParserComponents    _moduleList;
859  
860   SALOME_ModuleCatalog_Handler* handler = new SALOME_ModuleCatalog_Handler(_pathList,_moduleList,typeMap,typeList);
861 #if defined(WIN32)
862   const wchar_t* w_file = Kernel_Utils::utf8_decode(file);
863   FILE* aFile  = _wfopen(w_file, L"r");
864 #else
865   FILE* aFile = fopen(file, "r");
866 #endif
867   
868   if (aFile != NULL)
869     {
870       xmlDocPtr aDoc = xmlReadFile(file, NULL, 0);
871       
872       if (aDoc != NULL) 
873         handler->ProcessXmlDocument(aDoc);
874       else
875         MESSAGE("ModuleCatalog: could not parse file "<<file);
876
877       xmlFreeDoc(aDoc);
878       fclose(aFile);
879     }
880   else
881     MESSAGE("ModuleCatalog: file "<<file<<" is not readable.");
882   
883   delete handler;
884   
885   unsigned int i, j;
886
887   for ( i = 0; i < _moduleList.size(); i++) {
888     for (j=0; j<modulelist.size(); j++) {
889       if (modulelist[j].name == _moduleList[i].name)
890         break;
891     }
892     if (j < modulelist.size())
893       modulelist[j] = _moduleList[i];
894     else
895       modulelist.push_back(_moduleList[i]);
896   }
897
898   for ( i=0; i < _pathList.size(); i++)
899     pathList.push_back(_pathList[i]) ;
900
901   for (j=0; j<modulelist.size(); j++)
902     modulelist[j].prefixes = pathList;
903 }
904
905 void 
906 SALOME_ModuleCatalogImpl::ImportXmlCatalogFile(const char* file)
907 {
908   myPrivate->_parse_xml_file(file, myPrivate->_personal_module_list, myPrivate->_personal_path_list,myPrivate->_typeMap,myPrivate->_typeList);
909 }
910
911
912 //
913 //  Duplicate functions create a Corba structure (component,
914 //  interface, service, parameter) from the corresponding C++ 
915 //  parser structure
916 //
917
918 //----------------------------------------------------------------------
919 // Function : duplicate
920 // Purpose  : create a component from the catalog parsing
921 //----------------------------------------------------------------------
922 void SALOME_ModuleCatalogImpl::Private::duplicate
923 (SALOME_ModuleCatalog::ComponentDef & C_corba, 
924  const ParserComponent & C_parser)
925 {
926   C_corba.name = CORBA::string_dup(C_parser.name.c_str());
927   C_corba.username = CORBA::string_dup(C_parser.username.c_str());
928   C_corba.icon = CORBA::string_dup(C_parser.icon.c_str());
929   C_corba.type = ComponentTypeConvert[C_parser.type];
930   if(C_parser.implementationType == "EXE")
931     C_corba.implementationType=SALOME_ModuleCatalog::EXE;
932   else if(C_parser.implementationType == "CEXE")
933     C_corba.implementationType=SALOME_ModuleCatalog::CEXE;
934   else if(C_parser.implementationType == "PY")
935     C_corba.implementationType=SALOME_ModuleCatalog::PY;
936   else
937     C_corba.implementationType=SALOME_ModuleCatalog::SO;
938   C_corba.implname = CORBA::string_dup(C_parser.implementationName.c_str());
939
940   size_t _length = C_parser.interfaces.size();
941   C_corba.interfaces.length((CORBA::ULong)_length);
942   
943   for (unsigned int ind = 0; ind < _length; ind++)
944     duplicate(C_corba.interfaces[ind], C_parser.interfaces[ind]);
945 }
946
947
948 //----------------------------------------------------------------------
949 // Function : duplicate
950 // Purpose  : create an interface from the catalog parsing
951 //----------------------------------------------------------------------
952 void SALOME_ModuleCatalogImpl::Private::duplicate
953 (SALOME_ModuleCatalog::DefinitionInterface & I_corba,
954  const ParserInterface & I_parser)
955 {
956   //duplicate interface name
957   I_corba.interfacename = CORBA::string_dup(I_parser.name.c_str());
958   
959   // duplicate service list
960   size_t _length = I_parser.services.size();
961   //  if(MYDEBUG) SCRUTE(_length);
962   //  I_corba.interfaceservicelist 
963   //  = new SALOME_ModuleCatalog::ListOfInterfaceService;
964   I_corba.interfaceservicelist.length((CORBA::ULong)_length);
965   
966   for (unsigned int ind1 = 0; ind1 < _length ; ind1 ++)
967     duplicate(I_corba.interfaceservicelist[ind1],
968               I_parser.services[ind1]);
969 }
970
971 //----------------------------------------------------------------------
972 // Function : duplicate
973 // Purpose  : create a service from the catalog parsing
974 //----------------------------------------------------------------------
975 void SALOME_ModuleCatalogImpl::Private::duplicate
976 (SALOME_ModuleCatalog::Service & S_corba,
977  const ParserService & S_parser)
978 {
979   // duplicate service name
980   S_corba.ServiceName = CORBA::string_dup(S_parser.name.c_str());
981   
982   // duplicate service by default
983   S_corba.Servicebydefault = S_parser.byDefault;
984
985   S_corba.TypeOfNode = S_parser.typeOfNode;
986
987   size_t _length;
988
989   // duplicate in Parameters
990   _length = S_parser.inParameters.size();
991   S_corba.ServiceinParameter.length((CORBA::ULong)_length);
992
993   for (unsigned int ind2 = 0; ind2 < _length ; ind2 ++)
994     duplicate(S_corba.ServiceinParameter[ind2],
995               S_parser.inParameters[ind2]);
996   
997   // duplicate out Parameters
998   _length = S_parser.outParameters.size();
999   S_corba.ServiceoutParameter.length((CORBA::ULong)_length);
1000
1001   for (unsigned int ind2 = 0; ind2 < _length ; ind2 ++)
1002     duplicate(S_corba.ServiceoutParameter[ind2],
1003               S_parser.outParameters[ind2]);
1004   
1005   // duplicate in DataStreamParameters
1006   _length = S_parser.inDataStreamParameters.size();
1007   S_corba.ServiceinDataStreamParameter.length((CORBA::ULong)_length);
1008
1009   for (unsigned int ind2 = 0; ind2 < _length ; ind2 ++)
1010     duplicate(S_corba.ServiceinDataStreamParameter[ind2],
1011               S_parser.inDataStreamParameters[ind2]);
1012   
1013   // duplicate out DataStreamParameters
1014   _length = S_parser.outDataStreamParameters.size();
1015   //  if(MYDEBUG) SCRUTE(_length);
1016   S_corba.ServiceoutDataStreamParameter.length((CORBA::ULong)_length);
1017
1018   for (unsigned int ind2 = 0; ind2 < _length ; ind2 ++)
1019     duplicate(S_corba.ServiceoutDataStreamParameter[ind2],
1020               S_parser.outDataStreamParameters[ind2]);
1021 }
1022
1023 //----------------------------------------------------------------------
1024 // Function : duplicate
1025 // Purpose  : create a service parameter from the catalog parsing
1026 //----------------------------------------------------------------------
1027 void SALOME_ModuleCatalogImpl::Private::duplicate
1028 (SALOME_ModuleCatalog::ServicesParameter & P_corba,
1029  const ParserParameter & P_parser)
1030 {
1031   // duplicate parameter name
1032   P_corba.Parametername = CORBA::string_dup(P_parser.name.c_str());
1033   
1034   // duplicate parameter type
1035   P_corba.Parametertype = CORBA::string_dup(P_parser.type.c_str());
1036 }
1037
1038
1039 //----------------------------------------------------------------------
1040 // Function : duplicate
1041 // Purpose  : create a service datastream parameter from the catalog parsing
1042 //----------------------------------------------------------------------
1043 void SALOME_ModuleCatalogImpl::Private::duplicate
1044 (SALOME_ModuleCatalog::ServicesDataStreamParameter & P_corba,
1045  const ParserDataStreamParameter & P_parser)
1046 {
1047   std::map < std::string, 
1048     SALOME_ModuleCatalog::DataStreamDependency >::const_iterator it_dep;
1049
1050   // duplicate parameter name
1051   P_corba.Parametername = CORBA::string_dup(P_parser.name.c_str());
1052   
1053   // duplicate parameter type
1054
1055   // doesn't work ??? 
1056   //   it_type = DataStreamTypeConvert.find(P_parser.type);
1057   //   P_corba.Parametertype
1058   //     = (it_type == DataStreamTypeConvert.end()) 
1059   //     ? it_type->second : SALOME_ModuleCatalog::DATASTREAM_UNKNOWN;
1060
1061   P_corba.Parametertype = CORBA::string_dup(P_parser.type.c_str());
1062
1063   // duplicate parameter dependency
1064   
1065   if(MYDEBUG) SCRUTE(P_parser.dependency);
1066   P_corba.Parameterdependency = SALOME_ModuleCatalog::DATASTREAM_UNDEFINED;
1067   for (it_dep = DataStreamDepConvert.begin(); 
1068        it_dep != DataStreamDepConvert.end(); 
1069        it_dep++)
1070     if (P_parser.dependency.compare(it_dep->first) == 0) {
1071       P_corba.Parameterdependency = it_dep->second;
1072       break;
1073     }
1074
1075   if(MYDEBUG) SCRUTE(P_corba.Parameterdependency);
1076 }
1077
1078 //----------------------------------------------------------------------
1079 // Function : duplicate
1080 // Purpose  : create the path prefix structures from the catalog parsing
1081 //----------------------------------------------------------------------
1082 void
1083 SALOME_ModuleCatalogImpl::Private::duplicate(ParserPathPrefixes &L_out, 
1084                                              const ParserPathPrefixes &L_in)
1085 {
1086   L_out = L_in;
1087 }
1088
1089
1090 //----------------------------------------------------------------------
1091 // Function : _verify_path_prefix
1092 // Purpose  : verify the path prefix structures from the catalog parsing
1093 //            Verify that there only one path prefix associated to a 
1094 //            particular computer
1095 //----------------------------------------------------------------------
1096 bool
1097 SALOME_ModuleCatalogImpl::Private::_verify_path_prefix(ParserPathPrefixes & pathList)
1098 {
1099   bool _return_value = true;
1100   std::vector<std::string> _machine_list;
1101
1102   // Fill a list of all computers indicated in the path list
1103   for (unsigned int ind = 0; ind < pathList.size(); ind++)
1104     { 
1105       for (unsigned int ind1 = 0 ; ind1 < pathList[ind].listOfComputer.size(); ind1++)
1106         {
1107           _machine_list.push_back(pathList[ind].listOfComputer[ind1]);
1108         }
1109     }
1110
1111   // Parse if a computer name is twice in the list of computers
1112   for (unsigned int ind = 0; ind < _machine_list.size(); ind++)
1113     {
1114      for (unsigned int ind1 = ind+1 ; ind1 < _machine_list.size(); ind1++)
1115        {
1116          if(_machine_list[ind].compare(_machine_list[ind1]) == 0)
1117            {
1118              if(MYDEBUG) MESSAGE( "The computer " << _machine_list[ind] << " is indicated more than once in the path list");
1119              _return_value = false; 
1120            }
1121        }
1122     }
1123   return _return_value;
1124 }