Salome HOME
be15994347673fc38892da5a5296114cb5d3b016
[modules/kernel.git] / src / SALOMEDS / SALOMEDS_Study_i.cxx
1 //  SALOME SALOMEDS : data structure of SALOME and sources of Salome data server 
2 //
3 //  Copyright (C) 2003  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. 
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOMEDS_Study_i.cxx
25 //  Author : Yves FRICAUD
26 //  Module : SALOME
27 //  $Header$
28
29 using namespace std;
30 #include "utilities.h"
31 #include "SALOMEDS_Study_i.hxx"
32
33 #include "SALOMEDS_DataMapIteratorOfDataMapStringLabel.hxx"
34 #include <TColStd_SequenceOfExtendedString.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <TCollection_ExtendedString.hxx>
37 #include <TDataStd_ChildNodeIterator.hxx>
38 #include <TDocStd_Application.hxx>
39 #include <TDocStd_Owner.hxx>
40 #include <CDM_Document.hxx>
41 #include <CDM_Application.hxx>
42 #include <TDF_ChildIDIterator.hxx>
43 #include <SALOME_GenericObj_i.hh>
44 #include "SALOMEDS_LocalIDAttribute.hxx"
45 #include "SALOMEDS_PersRefAttribute.hxx"
46 #include "SALOMEDS_UseCaseIterator_i.hxx"
47
48
49 #define DIRECTORYID 16661
50 #define FILEID "FILE: "
51 #define FILELOCALID 26662 
52
53 //============================================================================
54 /*! Function : SALOMEDS_Study_i
55  *  Purpose  : SALOMEDS_Study_i constructor
56  */
57 //============================================================================
58 SALOMEDS_Study_i::SALOMEDS_Study_i(const Handle(TDocStd_Document) doc,
59                                    CORBA::ORB_ptr                 orb,
60                                    const char* study_name)
61 {
62   _orb = CORBA::ORB::_duplicate(orb);
63   _doc = doc;
64   _name = new char[strlen(study_name) +1];
65   strcpy(_name,study_name);
66   _isSaved = false ;
67   _URL = NULL;
68   _StudyId = -1;
69   _autoFill = true;
70   myNbPostponed.Append(0);
71   myNbUndos = 0;
72 }
73   
74 //============================================================================
75 /*! Function : ~SALOMEDS_Study_i
76  *  Purpose  : SALOMEDS_Study_i destructor
77  */
78 //============================================================================
79 SALOMEDS_Study_i::~SALOMEDS_Study_i()
80 {
81   delete [] _name ;
82   delete [] _URL ;
83 }  
84
85 //============================================================================
86 /*! Function : GetPersistentReference
87  *  Purpose  : Get persistent reference of study (idem URL())
88  */
89 //============================================================================
90 char* SALOMEDS_Study_i::GetPersistentReference()
91 {
92   return URL();
93 }
94 //============================================================================
95 /*! Function : GetTransientReference
96  *  Purpose  : Get IOR of the Study (registred in OCAF document in doc->Root)
97  */
98 //============================================================================
99 char* SALOMEDS_Study_i::GetTransientReference()
100 {
101   CORBA::String_var IOR;
102
103   Handle(SALOMEDS_IORAttribute) Att;
104   TDF_Label _lab = _doc->GetData()->Root();
105   if (!_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(),Att)){
106
107     TCollection_AsciiString ch(Att->Get());
108     IOR = CORBA::string_dup(ch.ToCString());
109   }
110   else IOR = CORBA::string_dup(""); // NULL ?
111
112   return CORBA::string_dup(IOR); 
113 }
114
115 //============================================================================
116 /*! Function : IsEmpty
117  *  Purpose  : Detect if study is empty
118  */
119 //============================================================================
120 CORBA::Boolean SALOMEDS_Study_i::IsEmpty()
121 {
122   if (_doc.IsNull()) return true;
123   return _doc->IsEmpty();
124 }
125
126 //============================================================================
127 /*! Function : FindComponent
128  *  Purpose  : Find a Component with ComponentDataType = aComponentName
129  */
130 //============================================================================
131 SALOMEDS::SComponent_ptr SALOMEDS_Study_i::FindComponent (const char* aComponentName)
132 {
133   bool _find = false;
134   Standard_CString name;
135   SALOMEDS::SComponentIterator_var itcomp = NewComponentIterator();
136   SALOMEDS::SComponent_var compo;
137
138   for (; itcomp->More(); itcomp->Next()) {
139     SALOMEDS::SComponent_var SC = itcomp->Value();
140     name = SC->ComponentDataType();
141     //ED if ( TCollection_AsciiString(name).IsEqual(TCollection_AsciiString(strdup(aComponentName))) ) {
142     if(strcmp(aComponentName,name) == 0){
143       _find = true;
144       return SALOMEDS::SComponent::_narrow(SC); 
145     }
146   }
147   if(!_find)
148     {
149       return SALOMEDS::SComponent::_nil();
150     }
151   return compo;
152 }
153
154 //============================================================================
155 /*! Function : FindComponentID
156  *  Purpose  : Find a Component from it's ID
157  */
158 //============================================================================
159 SALOMEDS::SComponent_ptr SALOMEDS_Study_i::FindComponentID(const char* aComponentID)
160 {
161   // Iterate on each components defined in the study
162   // Get the component ID and compare with aComponentID 
163   bool _find = false;
164   char *ID;
165   SALOMEDS::SComponent_ptr compo;
166
167   SALOMEDS::SComponentIterator_var itcomp = NewComponentIterator();
168   for (; itcomp->More(); itcomp->Next()) {
169     SALOMEDS::SComponent_var SC = itcomp->Value();
170     ID = SC->GetID();
171     if(strcmp(aComponentID,ID)==0)
172       {
173         // ComponentID found
174         _find = true;
175         compo = SALOMEDS::SComponent::_narrow(SC);
176       }
177   }
178   if(!_find)
179     {
180       compo = SALOMEDS::SComponent::_nil();
181     }
182   return compo;
183 }
184
185 //============================================================================
186 /*! Function : FindObject
187  *  Purpose  : Find an Object with SALOMEDS::Name = anObjectName
188  */
189 //============================================================================
190 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObject(const char* anObjectName)
191 {
192   // Iterate to all components defined in the study
193   // After testing the component name, iterate in all objects defined under
194   // components (function _FindObject)
195   bool _find = false;
196   SALOMEDS::SObject_ptr RefSO = SALOMEDS::SObject::_nil();
197
198   SALOMEDS::SComponentIterator_var it = NewComponentIterator();
199   for (; it->More();it->Next()){
200     if(!_find)
201       {
202         SALOMEDS::SComponent_var SC = it->Value();
203         SALOMEDS::GenericAttribute_var anAttr;
204         if (SC->FindAttribute(anAttr,"AttributeName")) 
205         {
206           SALOMEDS::AttributeName_var Name = SALOMEDS::AttributeName::_narrow(anAttr);
207           CORBA::String_var Val = Name->Value();
208           if (strcmp(Val, anObjectName) == 0)
209             {
210               _find = true;
211               RefSO = SALOMEDS::SObject::_narrow(SC);
212             }
213         }
214         if (!_find) RefSO =  _FindObject(SC,anObjectName, _find);
215       }
216   }
217   return RefSO;
218 }
219
220 //============================================================================
221 /*! Function : FindObjectID
222  *  Purpose  : Find an Object with ID = anObjectID
223  */
224 //============================================================================
225 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectID(const char* anObjectID)
226 {
227   // Convert aSO->GetID in TDF_Label.
228   TDF_Label Lab;
229   TDF_Tool::Label(_doc->GetData(), (char*)anObjectID, Lab);
230   
231   if (Lab.IsNull()) return SALOMEDS::SObject::_nil();
232   SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (Lab,_orb);
233   SALOMEDS::SObject_var so = SALOMEDS::SObject::_narrow(so_servant->_this()); 
234   return so;
235
236 }
237
238 //============================================================================
239 /*! Function : CreateObjectID
240  *  Purpose  : Creates an Object with ID = anObjectID
241  */
242 //============================================================================
243 SALOMEDS::SObject_ptr SALOMEDS_Study_i::CreateObjectID(const char* anObjectID)
244 {
245   // Convert aSO->GetID in TDF_Label.
246   TDF_Label Lab;
247   TDF_Tool::Label(_doc->GetData(), (char*)anObjectID, Lab, Standard_True);
248   
249   if (Lab.IsNull()) return SALOMEDS::SObject::_nil();
250   SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (Lab,_orb);
251   SALOMEDS::SObject_var so = SALOMEDS::SObject::_narrow(so_servant->_this()); 
252   return so;
253
254 }
255
256 //============================================================================
257 /*! Function : FindObjectByName
258  *  Purpose  : Find Objects with SALOMEDS::Name = anObjectName in a Component
259  *           : with ComponentDataType = aComponentName
260  */
261 //============================================================================
262 SALOMEDS::Study::ListOfSObject* SALOMEDS_Study_i::FindObjectByName( const char* anObjectName,
263                                                                     const char* aComponentName )
264 {
265   SALOMEDS::Study::ListOfSObject_var listSO = new SALOMEDS::Study::ListOfSObject ;
266   listSO->length(0);
267   
268   SALOMEDS::SComponent_ptr compo = FindComponent(aComponentName) ;
269   if ( compo->_is_nil() ) {
270     MESSAGE ("In FindObjectByName() :  Component named " << aComponentName << " not found ");
271     return listSO._retn();
272   }
273
274   // Iterate on each object and subobject of the component
275   // If objectName is found add it to the list of SObjects 
276   char *name;
277   char *childName ;
278   SALOMEDS::SObject_ptr addSO = SALOMEDS::SObject::_nil();
279
280   CORBA::String_var compoId = compo->GetID();
281   SALOMEDS::ChildIterator_var it = NewChildIterator(compo);
282   int length = 0 ;
283   for ( ; it->More();it->Next() ) {
284     
285     SALOMEDS::SObject_var CSO = it->Value();
286     SALOMEDS::GenericAttribute_var anAttr;
287     SALOMEDS::AttributeName_var    aName;
288     if ( CSO->FindAttribute(anAttr, "AttributeName") ) {
289       aName = SALOMEDS::AttributeName::_narrow(anAttr);
290       name = aName->Value();
291       if ( strcmp( name, anObjectName ) == 0) {
292         addSO = SALOMEDS::SObject::_narrow(CSO);
293         /* add to list */
294         length++ ;
295         listSO->length(length);
296         listSO[length-1] = addSO ;
297       }
298       
299       /* looks also for eventual children */
300       bool found = false ;
301       addSO = _FindObject( CSO, anObjectName, found ) ;
302       if( found) {
303         length++ ;
304         listSO->length(length);
305         listSO[length-1] = addSO ;
306       }
307     }
308   }
309   return listSO._retn() ;
310 }
311
312
313
314 //============================================================================
315 /*! Function : FindObjectIOR
316  *  Purpose  : Find an Object with IOR = anObjectIOR
317  */
318 //============================================================================
319 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectIOR(const char* anObjectIOR)
320 {
321   // firstly searching in the datamap for optimization
322   CORBA::String_var anIOR = CORBA::string_dup(anObjectIOR);
323   if (myIORLabels.IsBound(TCollection_ExtendedString(anIOR))) {
324     SALOMEDS_SObject_i* aResult = new SALOMEDS_SObject_i(myIORLabels.Find(TCollection_ExtendedString(anIOR)),_orb);
325     // 11 oct 2002: forbidden attributes must be checked here
326     SALOMEDS::GenericAttribute_var anAttr;
327     if (!aResult->FindAttribute(anAttr,"AttributeIOR")) {
328       myIORLabels.UnBind(TCollection_ExtendedString(anIOR));
329     } else return aResult->_this();
330   }
331   // Iterate to all components defined in the study
332   // After testing the component name, iterate in all objects defined under
333   // components (function _FindObject)
334   bool _find = false;
335   SALOMEDS::SObject_ptr RefSO = SALOMEDS::SObject::_nil();
336
337   SALOMEDS::SComponentIterator_var it = NewComponentIterator();
338   for (; it->More();it->Next()){
339     if(!_find)
340       {
341         SALOMEDS::SComponent_var SC = it->Value();
342         SALOMEDS::GenericAttribute_var anAttr;
343         if (SC->FindAttribute(anAttr,"AttributeIOR")) 
344         {
345           SALOMEDS::AttributeIOR_var IOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
346           CORBA::String_var Val = IOR->Value();
347           if (strcmp(Val, anObjectIOR) == 0)
348             {
349               _find = true;
350               RefSO = SALOMEDS::SObject::_narrow(SC);
351             }
352         }
353         if (!_find) 
354           RefSO =  _FindObjectIOR(SC,anObjectIOR, _find);
355       }
356   }
357   if (!RefSO->_is_nil()) MESSAGE("SALOMEDS_Study_i::FindObjectIOR: found label with old methods");
358
359   return RefSO;
360 }
361
362 //============================================================================
363 /*! Function : FindObjectByPath
364  *  Purpose  : Find an Object by its path = thePath
365  */
366 //============================================================================
367 SALOMEDS::SObject_ptr SALOMEDS_Study_i::FindObjectByPath(const char* thePath)
368 {
369   TCollection_AsciiString aPath(CORBA::string_dup(thePath)), aToken;
370   SALOMEDS::SObject_var aSO = SALOMEDS::SObject::_nil();
371   int i = 1, aLength = aPath.Length();
372   bool isRelative = false;
373
374   if(aLength == 0) {  //Empty path - return the current context
375     SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (_current, _orb);
376     aSO = SALOMEDS::SObject::_narrow(so_servant->_this()); 
377     return aSO._retn();
378   }
379
380   if(aPath.Value(1) != '/')  //Relative path 
381     isRelative = true;
382
383   TDF_ChildIterator anIterator;
384   TDF_Label aLabel;
385   Handle(TDataStd_Name) anAttr;
386
387   if(isRelative) {
388     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext(); 
389     anIterator.Initialize(_current, Standard_False);
390   }
391   else {
392     if(aPath.Length() == 1 && aPath.Value(1) == '/') {    //Root
393       SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (_doc->Main(), _orb);
394       aSO = SALOMEDS::SObject::_narrow(so_servant->_this());
395       return aSO._retn();
396     }
397     anIterator.Initialize(_doc->Main(), Standard_False);
398   }
399
400   while(i <= aLength) {
401
402     aToken = aPath.Token("/", i);
403     if(aToken.Length() == 0) break;
404
405     for ( ; anIterator.More(); anIterator.Next() ) {
406       aLabel = anIterator.Value();
407       if(aLabel.FindAttribute(TDataStd_Name::GetID(), anAttr)) {
408         if(anAttr->Get() == aToken) {
409           aToken = aPath.Token("/", i+1); //Check if it was the last part of the path
410           if(aToken.Length() == 0) {  //The searched label is found (no part of the path is left)
411               SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (aLabel, _orb);
412               aSO = SALOMEDS::SObject::_narrow(so_servant->_this()); 
413               return aSO._retn();
414           }
415
416           anIterator.Initialize(aLabel, Standard_False);
417           break;
418         }
419       }
420     }
421
422     i++;
423   }
424
425   return aSO._retn();
426 }
427
428 //============================================================================
429 /*! Function : GetObjectPath
430  *  Purpose  : 
431  */
432 //============================================================================
433 char* SALOMEDS_Study_i::GetObjectPath(CORBA::Object_ptr theObject)
434 {
435   TCollection_AsciiString aPath("");
436   if(CORBA::is_nil(theObject)) return CORBA::string_dup(aPath.ToCString());
437
438   SALOMEDS::SObject_var anObject = SALOMEDS::SObject::_narrow(theObject);
439   if(anObject->_is_nil()) {
440     anObject = FindObjectIOR(_orb->object_to_string(theObject));
441     if(anObject->_is_nil()) return CORBA::string_dup(aPath.ToCString());
442   }
443
444   SALOMEDS::GenericAttribute_var anAttr;
445   if(anObject->FindAttribute(anAttr, "AttributeName")) {
446     SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
447     if(anAttr->_is_nil()) return CORBA::string_dup(aPath.ToCString());
448     TCollection_AsciiString aValue(aName->Value());
449     aValue.Prepend("/");
450     aValue += aPath;
451     aPath = aValue;
452     SALOMEDS::SObject_ptr aFather = anObject->GetFather();
453     if(!aFather->_is_nil()) {
454       TDF_Label aLabel;
455       Handle(TDataStd_Name) aNameAttrib;
456       TDF_Tool::Label(_doc->GetData(), aFather->GetID(), aLabel);
457       if(aLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttrib)) {
458           aValue = GetObjectPath(aFather);
459           aPath = aValue + aPath;
460       }
461     }
462   }
463
464   return  CORBA::string_dup(aPath.ToCString());
465 }
466
467
468 //============================================================================
469 /*! Function : SetContext
470  *  Purpose  : Sets the current context
471  */
472 //============================================================================
473 void SALOMEDS_Study_i::SetContext(const char* thePath) 
474 {
475   if(thePath == NULL || strlen(thePath) == 0) throw SALOMEDS::Study::StudyInvalidDirectory();
476   TCollection_AsciiString aPath(CORBA::string_dup(thePath)), aContext("");
477   bool isInvalid = false, isFound = false;
478   SALOMEDS::SObject_var aSO;
479   
480   if(aPath.Value(1) != '/') { //Relative path 
481     aContext = TCollection_AsciiString(GetContext());
482     aContext += '/';
483     aContext += aPath;
484   }
485   else
486     aContext = aPath;
487   
488   try {
489     aSO = FindObjectByPath(aContext.ToCString());
490   }
491   catch( ... ) {
492     isInvalid = true;
493   }
494
495   if(isInvalid || aSO->_is_nil()) throw SALOMEDS::Study::StudyInvalidContext();
496
497   TDF_Label aLabel;
498   TDF_Tool::Label(_doc->GetData(), aSO->GetID(), aLabel);
499   if(aLabel.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();
500   else
501     _current = aLabel;  //Set the current context
502   
503 }
504
505 //============================================================================
506 /*! Function : GetContext
507  *  Purpose  : Gets the current context
508  */
509 //============================================================================
510 char* SALOMEDS_Study_i::GetContext() 
511 {
512   if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
513   SALOMEDS_SObject_i *  so_servant = new SALOMEDS_SObject_i (_current, _orb);
514   SALOMEDS::SObject_var aSO = SALOMEDS::SObject::_narrow(so_servant->_this()); 
515   return GetObjectPath(aSO._retn());
516 }
517
518 //============================================================================
519 /*! Function : GetObjectNames
520  *  Purpose  : method to get all object names in the given context (or in the current context, if 'theContext' is empty)
521  */
522 //============================================================================
523 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetObjectNames(const char* theContext) {
524   TColStd_SequenceOfExtendedString aResultSeq;
525   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
526   TDF_Label aLabel;
527   if (strlen(theContext) == 0) {
528     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
529     aLabel = _current;
530   } else {
531     TDF_Label aTmp = _current;
532     SetContext(theContext);
533     aLabel = _current;
534     _current = aTmp;
535   }
536   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate all subchildren at all sublevels
537   for(; anIter.More(); anIter.Next()) {
538     TDF_Label aLabel = anIter.Value();
539 //      Handle(TDF_Attribute) anAttribute;
540 //      if (aLabel.FindAttribute(SALOMEDS_IORAttribute::GetID(), anAttribute) ||
541 //      aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anAttribute)) {
542     Handle(TDataStd_Name) aName;
543     if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) aResultSeq.Append(aName->Get());
544 //    }
545   }
546   // fill the result table
547   int anIndex, aLength = aResultSeq.Length();
548   aResult->length(aLength);
549   for(anIndex = 0; anIndex < aLength; anIndex++) {
550     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
551   }
552   return aResult._retn();
553 }
554
555 //============================================================================
556 /*! Function : GetDirectoryNames
557  *  Purpose  : method to get all directory names in the given context (or in the current context, if 'theContext' is empty)
558  */
559 //============================================================================
560 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetDirectoryNames(const char* theContext) {
561   TColStd_SequenceOfExtendedString aResultSeq;
562   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
563   TDF_Label aLabel;
564   if (strlen(theContext) == 0) {
565     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
566     aLabel = _current;
567   } else {
568     TDF_Label aTmp = _current;
569     SetContext(theContext);
570     aLabel = _current;
571     _current = aTmp;
572   }
573   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate first-level children at all sublevels
574   for(; anIter.More(); anIter.Next()) {
575     TDF_Label aLabel = anIter.Value();
576     Handle(SALOMEDS_LocalIDAttribute) anID;
577     if (aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anID)) {
578       if (anID->Get() == DIRECTORYID) {
579         Handle(TDataStd_Name) aName;
580         if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) {
581           aResultSeq.Append(aName->Get());
582         }
583       }
584     }
585   }
586   // fill the result table
587   int anIndex, aLength = aResultSeq.Length();
588   aResult->length(aLength);
589   for(anIndex = 0; anIndex < aLength; anIndex++) {
590     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
591   }
592   return aResult._retn();
593 }
594
595 //============================================================================
596 /*! Function : GetFileNames
597  *  Purpose  : method to get all file names in the given context (or in the current context, if 'theContext' is empty)
598  */
599 //============================================================================
600 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetFileNames(const char* theContext) {
601   TColStd_SequenceOfExtendedString aResultSeq;
602   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
603   TDF_Label aLabel;
604   if (strlen(theContext) == 0) {
605     if(_current.IsNull()) throw SALOMEDS::Study::StudyInvalidContext();   
606     aLabel = _current;
607   } else {
608     TDF_Label aTmp = _current;
609     SetContext(theContext);
610     aLabel = _current;
611     _current = aTmp;
612   }
613   TDF_ChildIterator anIter(aLabel, Standard_False); // iterate all subchildren at all sublevels
614   for(; anIter.More(); anIter.Next()) {
615     TDF_Label aLabel = anIter.Value();
616     Handle(SALOMEDS_LocalIDAttribute) anID;
617     if (aLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(), anID)) {
618       if (anID->Get() == FILELOCALID) {
619         Handle(SALOMEDS_PersRefAttribute) aName;
620         if(aLabel.FindAttribute(SALOMEDS_PersRefAttribute::GetID(), aName)) {
621           TCollection_ExtendedString aFileName = aName->Get();
622           if(aFileName.Length() > 0)
623             aResultSeq.Append(aFileName.Split(strlen(FILEID)));
624         }
625       }
626     }
627 //      }
628   }
629   // fill the result table
630   int anIndex, aLength = aResultSeq.Length();
631   aResult->length(aLength);
632   for(anIndex = 0; anIndex < aLength; anIndex++) {
633     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
634   }
635   return aResult._retn();
636 }
637
638 //============================================================================
639 /*! Function : GetComponentNames
640  *  Purpose  : method to get all components names
641  */
642 //============================================================================
643 SALOMEDS::ListOfStrings* SALOMEDS_Study_i::GetComponentNames(const char* theContext) {
644   TColStd_SequenceOfExtendedString aResultSeq;
645   SALOMEDS::ListOfStrings_var aResult = new SALOMEDS::ListOfStrings;
646   TDF_ChildIterator anIter(_doc->Main(), Standard_False); // iterate all subchildren at first level
647   for(; anIter.More(); anIter.Next()) {
648     TDF_Label aLabel = anIter.Value();
649     Handle(TDataStd_Name) aName;
650     if (aLabel.FindAttribute(TDataStd_Name::GetID(), aName)) aResultSeq.Append(aName->Get());
651   }
652   // fill the result table
653   int anIndex, aLength = aResultSeq.Length();
654   aResult->length(aLength);
655   for(anIndex = 0; anIndex < aLength; anIndex++) {
656     aResult[anIndex] = CORBA::string_dup(TCollection_AsciiString(aResultSeq.Value(anIndex + 1)).ToCString());
657   }
658   return aResult._retn();
659 }
660
661 //============================================================================
662 /*! Function : NewChildIterator
663  *  Purpose  : Create a ChildIterator from an SObject
664  */
665 //============================================================================
666 SALOMEDS::ChildIterator_ptr SALOMEDS_Study_i::NewChildIterator(SALOMEDS::SObject_ptr aSO)
667 {
668   //Convert aSO->GetID in TDF_Label.
669   TDF_Label Lab;
670   TDF_Tool::Label(_doc->GetData(), aSO->GetID(), Lab);
671
672   //Create iterator
673   SALOMEDS_ChildIterator_i* it_servant = new SALOMEDS_ChildIterator_i(Lab,_orb);
674   SALOMEDS::ChildIterator_var it = SALOMEDS::ChildIterator::_narrow(it_servant->_this()); 
675
676   return it;
677 }
678
679
680 //============================================================================
681 /*! Function : NewComponentIterator
682  *  Purpose  : Create a SComponentIterator
683  */
684 //============================================================================
685 SALOMEDS::SComponentIterator_ptr SALOMEDS_Study_i::NewComponentIterator()
686 {
687   SALOMEDS_SComponentIterator_i* it_servant = new SALOMEDS_SComponentIterator_i(_doc,_orb);
688   SALOMEDS::SComponentIterator_var it = SALOMEDS::SComponentIterator::_narrow(it_servant->_this()); 
689   return it;
690 }
691
692
693 //============================================================================
694 /*! Function : NewBuilder
695  *  Purpose  : Create a StudyBuilder
696  */
697 //============================================================================
698 SALOMEDS::StudyBuilder_ptr SALOMEDS_Study_i::NewBuilder()
699 {
700   SALOMEDS_StudyBuilder_i* it_servant = new SALOMEDS_StudyBuilder_i(_doc,_orb);
701   SALOMEDS::StudyBuilder_var it = SALOMEDS::StudyBuilder::_narrow(it_servant->_this()); 
702
703   if(_autoFill) {
704     SALOMEDS_Callback_i* callback = new SALOMEDS_Callback_i(GetUseCaseBuilder(), _orb);
705     SALOMEDS::Callback_var cb = SALOMEDS::Callback::_narrow(callback->_this()); 
706
707     it->SetOnAddSObject(cb);
708     it->SetOnRemoveSObject(cb);
709   }
710
711   return it;
712
713 }
714  
715 //============================================================================
716 /*! Function : Name
717  *  Purpose  : get study name
718  */
719 //============================================================================
720 char* SALOMEDS_Study_i::Name()
721 {
722   return CORBA::string_dup(_name);
723 }
724
725 //============================================================================
726 /*! Function : Name
727  *  Purpose  : set study name
728  */
729 //============================================================================
730 void SALOMEDS_Study_i::Name(const char* name)
731 {
732   _name = new char[strlen(name) +1];
733   strcpy(_name,name);
734 }
735
736 //============================================================================
737 /*! Function : IsSaved
738  *  Purpose  : get if study has been saved
739  */
740 //============================================================================
741 CORBA::Boolean  SALOMEDS_Study_i::IsSaved()
742 {
743   return _isSaved;
744 }
745
746 //============================================================================
747 /*! Function : IsSaved
748  *  Purpose  : set if study has been saved
749  */
750 //============================================================================
751 void SALOMEDS_Study_i::IsSaved(CORBA::Boolean save)
752 {
753   _isSaved = save;
754 }
755
756 //============================================================================
757 /*! Function : IsModified
758  *  Purpose  : Detect if a Study has been modified since it has been saved
759  */
760 //============================================================================
761 CORBA::Boolean  SALOMEDS_Study_i::IsModified()
762 {
763   // True if is modified and not saved
764   if (_doc->IsModified())
765     if (!_isSaved) return true;
766     else return false;
767   else return false;
768 }
769
770 //============================================================================
771 /*! Function : URL
772  *  Purpose  : get URL of the study (persistent reference of the study)
773  */
774 //============================================================================
775 char* SALOMEDS_Study_i::URL()
776 {
777   if(!_URL) {
778     _URL = new char[1];
779     _URL[0] = (char)0;
780   }
781   return CORBA::string_dup(_URL);
782 }
783
784 //============================================================================
785 /*! Function : URL
786  *  Purpose  : set URL of the study (persistent reference of the study)
787  */
788 //============================================================================
789 void SALOMEDS_Study_i::URL(const char* url)
790 {
791   if (_URL) delete [] _URL;
792   _URL = new char[strlen(url) +1];
793   strcpy(_URL,url);
794   SCRUTE(_URL);
795
796   char *aName = _URL;
797   char *adr = strtok(aName, "/");
798   while (adr)
799     {
800       aName = adr;
801       adr = strtok(NULL, "/");
802     }
803   strcpy(_URL,url);
804   Name(aName);
805 }
806
807
808 //============================================================================
809 /*! Function : _FindObject
810  *  Purpose  : Find an Object with SALOMEDS::Name = anObjectName
811  */
812 //============================================================================
813 SALOMEDS::SObject_ptr SALOMEDS_Study_i::_FindObject(SALOMEDS::SObject_ptr SO,
814                                                     const char* anObjectName, 
815                                                     bool& _find)
816 {
817   // Iterate on each objects and subobjects of the component
818   // If objectName find, stop the loop and get the object reference
819   SALOMEDS::SObject_ptr RefSO = SALOMEDS::SObject::_nil();
820
821   CORBA::String_var soid = SO->GetID();
822   SALOMEDS::ChildIterator_var it = NewChildIterator(SO);
823   for (; it->More();it->Next()){
824     if(!_find)
825       {
826         SALOMEDS::SObject_var CSO = it->Value();
827         SALOMEDS::GenericAttribute_var anAttr;
828         if (CSO->FindAttribute(anAttr,"AttributeName")) 
829         {
830           SALOMEDS::AttributeName_var Name = SALOMEDS::AttributeName::_narrow(anAttr);
831           CORBA::String_var Val = Name->Value();
832           if (strcmp(Val, anObjectName) == 0)
833             {
834               RefSO = SALOMEDS::SObject::_narrow(CSO);
835               _find = true;
836             }
837         }
838         if (!_find) RefSO =  _FindObject(CSO, anObjectName, _find);
839       }
840   }
841   return RefSO;
842 }
843
844 //============================================================================
845 /*! Function : _FindObject
846  *  Purpose  : Find an Object with SALOMEDS::IOR = anObjectIOR
847  */
848 //============================================================================
849 SALOMEDS::SObject_ptr 
850 SALOMEDS_Study_i::_FindObjectIOR(SALOMEDS::SObject_ptr SO,
851                               const char* anObjectIOR, 
852                               bool& _find)
853 {
854   // Iterate on each objects and subobjects of the component
855   // If objectName find, stop the loop and get the object reference
856   SALOMEDS::SObject_ptr RefSO = SALOMEDS::SObject::_nil();
857
858   SALOMEDS::ChildIterator_var it = NewChildIterator(SO);
859   for (; it->More();it->Next()){
860     if(!_find)
861       {
862         SALOMEDS::SObject_var CSO = it->Value();
863         SALOMEDS::GenericAttribute_var anAttr;
864         if (CSO->FindAttribute(anAttr,"AttributeIOR")) 
865         {
866           SALOMEDS::AttributeIOR_var IOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
867           CORBA::String_var Val = IOR->Value();
868           if (strcmp(Val, anObjectIOR) == 0)
869             {
870               RefSO = SALOMEDS::SObject::_narrow(CSO);
871               _find = true;
872             }
873         }
874         if (!_find) RefSO =  _FindObjectIOR(CSO, anObjectIOR, _find);
875       }
876   }
877   return RefSO;
878 }
879
880 CORBA::Short SALOMEDS_Study_i::StudyId()
881 {
882   return _StudyId;
883 }
884
885 void SALOMEDS_Study_i::StudyId(CORBA::Short id)
886 {
887   _StudyId = id;
888 }
889
890 void SALOMEDS_Study_i::UpdateIORLabelMap(const char* anIOR,const char* anEntry) {
891   TDF_Label aLabel;
892   CORBA::String_var anEn = CORBA::string_dup(anEntry);
893   CORBA::String_var IOR = CORBA::string_dup(anIOR);
894   TDF_Tool::Label(_doc->GetData(),anEn,aLabel, Standard_True);
895   if (myIORLabels.IsBound(TCollection_ExtendedString(IOR))) myIORLabels.UnBind(TCollection_ExtendedString(IOR));
896   myIORLabels.Bind(TCollection_ExtendedString(IOR), aLabel);
897 }
898
899 SALOMEDS::Study_ptr SALOMEDS_Study_i::GetStudy(const TDF_Label theLabel, CORBA::ORB_ptr orb) {
900   Handle(SALOMEDS_IORAttribute) Att;
901   if (theLabel.Root().FindAttribute(SALOMEDS_IORAttribute::GetID(),Att)){
902     char* IOR = CORBA::string_dup(TCollection_AsciiString(Att->Get()).ToCString());
903     CORBA::Object_var obj = orb->string_to_object(IOR);
904     SALOMEDS::Study_ptr aStudy = SALOMEDS::Study::_narrow(obj) ;
905     ASSERT(!CORBA::is_nil(aStudy));
906     return SALOMEDS::Study::_duplicate(aStudy);
907   } else {
908     MESSAGE("GetStudy: Problem to get study");
909   }
910   return SALOMEDS::Study::_nil();
911 }
912
913 void SALOMEDS_Study_i::IORUpdated(const Handle(SALOMEDS_IORAttribute) theAttribute, CORBA::ORB_ptr orb) {
914   TCollection_AsciiString aString;
915   TDF_Tool::Entry(theAttribute->Label(), aString);
916   GetStudy(theAttribute->Label(), orb)->UpdateIORLabelMap(TCollection_AsciiString(theAttribute->Get()).ToCString(),
917                                                           aString.ToCString());
918 }
919
920 SALOMEDS::Study::ListOfSObject* SALOMEDS_Study_i::FindDependances(SALOMEDS::SObject_ptr anObject) {
921   SALOMEDS::GenericAttribute_ptr aTarget;
922   if (anObject->FindAttribute(aTarget,"AttributeTarget")) {
923     return SALOMEDS::AttributeTarget::_narrow(aTarget)->Get();
924   }
925   SALOMEDS::Study::ListOfSObject* aList = new SALOMEDS::Study::ListOfSObject;
926   aList->length(0);
927   return aList;
928 }
929
930
931 SALOMEDS::AttributeStudyProperties_ptr SALOMEDS_Study_i::GetProperties() {
932   SALOMEDS::GenericAttribute_ptr anAttr =  NewBuilder()->FindOrCreateAttribute(FindObjectID("0:1"),
933                                                                                "AttributeStudyProperties");
934   return SALOMEDS::AttributeStudyProperties::_narrow(anAttr);
935 }
936
937 char* SALOMEDS_Study_i::GetLastModificationDate() {
938   SALOMEDS::AttributeStudyProperties_var aProp = GetProperties();
939   SALOMEDS::StringSeq_var aNames;
940   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
941   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, true);
942   int aLastIndex = aNames->length() - 1;
943   char aResult[20];
944   sprintf(aResult, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d", (int)(aDays[aLastIndex]),(int)(aMonths[aLastIndex]),
945           (int)(aYears[aLastIndex]), (int)(aHours[aLastIndex]), (int)(aMinutes[aLastIndex]));
946   CORBA::String_var aResStr = CORBA::string_dup(aResult);
947   return aResStr._retn();
948 }
949
950 SALOMEDS::ListOfDates* SALOMEDS_Study_i::GetModificationsDate() {
951   SALOMEDS::AttributeStudyProperties_var aProp = GetProperties();
952   SALOMEDS::StringSeq_var aNames;
953   SALOMEDS::LongSeq_var aMinutes, aHours, aDays, aMonths, aYears;
954   aProp->GetModificationsList(aNames , aMinutes ,aHours, aDays, aMonths, aYears, false);
955
956   int anIndex, aLength = aNames->length();
957   SALOMEDS::ListOfDates_var aDates = new SALOMEDS::ListOfDates;
958   aDates->length(aLength);
959
960   for(anIndex = 0; anIndex < aLength; anIndex++) {
961     char aDate[20];
962     sprintf(aDate, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d", (int)(aDays[anIndex]), (int)(aMonths[anIndex]),
963             (int)(aYears[anIndex]), (int)(aHours[anIndex]), (int)(aMinutes[anIndex]));
964     aDates[anIndex] = CORBA::string_dup(aDate);
965   }
966   return aDates._retn();
967 }
968
969
970
971 //============================================================================
972 /*! Function : GetUseCaseBuilder
973  *  Purpose  : Returns a UseCase builder
974  */
975 //============================================================================
976 SALOMEDS::UseCaseBuilder_ptr SALOMEDS_Study_i::GetUseCaseBuilder() 
977 {
978   SALOMEDS_UseCaseBuilder_i* _caseBuilder = new SALOMEDS_UseCaseBuilder_i(_doc, _orb);
979   SALOMEDS::UseCaseBuilder_var aBuilder = SALOMEDS::UseCaseBuilder::_narrow(_caseBuilder->_this());
980   return aBuilder._retn();
981 }
982
983
984 //============================================================================
985 /*! Function : Close
986  *  Purpose  : 
987  */
988 //============================================================================
989 void SALOMEDS_Study_i::Close()
990 {
991   SALOMEDS::SComponentIterator_var itcomponent = NewComponentIterator();
992
993   for (; itcomponent->More(); itcomponent->Next()) {
994     SALOMEDS::SComponent_var sco = itcomponent->Value();
995           
996     MESSAGE ( "Look for an engine for data type :"<< sco->ComponentDataType());
997     // if there is an associated Engine call its method for closing
998     CORBA::String_var IOREngine;
999     if (sco->ComponentIOR(IOREngine)) {
1000       // we have found the associated engine to write the data 
1001       MESSAGE ( "We have found an engine for data type :"<< sco->ComponentDataType());
1002       CORBA::Object_var obj = _orb->string_to_object(IOREngine);
1003       if (!CORBA::is_nil(obj)) {
1004         SALOMEDS::Driver_var anEngine = SALOMEDS::Driver::_narrow(obj) ;
1005         
1006         if (!anEngine->_is_nil())  
1007           anEngine->Close(sco);
1008       }
1009     }
1010   }
1011
1012   Handle(TDocStd_Application) anApp = Handle(TDocStd_Application)::DownCast(_doc->Application());
1013 //    Handle(TDocStd_Owner) anOwner;
1014 //    if (_doc->Main().Root().FindAttribute(TDocStd_Owner::GetID(), anOwner)) {
1015 //      Handle(TDocStd_Document) anEmptyDoc;
1016 //      anOwner->SetDocument(anEmptyDoc);
1017 //    }
1018   if(!anApp.IsNull()) anApp->Close(_doc);
1019   _doc.Nullify();
1020 }
1021
1022 //============================================================================
1023 /*! Function : AddPostponed
1024  *  Purpose  : 
1025  */
1026  //============================================================================
1027 void SALOMEDS_Study_i::AddPostponed(const char* theIOR) {
1028   if (!NewBuilder()->HasOpenCommand()) return;
1029   try {
1030     CORBA::Object_var obj = _orb->string_to_object(theIOR);
1031     if (!CORBA::is_nil(obj)) {
1032       SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj) ;
1033       if (!CORBA::is_nil(aGeneric)) {
1034         TCollection_AsciiString anIOR((char*)theIOR);
1035         anIOR.Prepend("d");
1036         myPostponedIORs.Append(anIOR); // add prefix: deleted
1037         myNbPostponed.SetValue(myNbPostponed.Length(), myNbPostponed.Last() + 1);
1038       }
1039     }
1040   } catch(...) {}
1041 }
1042
1043 void SALOMEDS_Study_i::AddCreatedPostponed(const char* theIOR) {
1044   if (!NewBuilder()->HasOpenCommand()) return;
1045   try {
1046     CORBA::Object_var obj = _orb->string_to_object(theIOR);
1047     if (!CORBA::is_nil(obj)) {
1048       SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj) ;
1049       if (!CORBA::is_nil(aGeneric)) {
1050         TCollection_AsciiString anIOR((char*)theIOR);
1051         anIOR.Prepend("c");
1052         myPostponedIORs.Append(anIOR); // add prefix: created
1053         myNbPostponed.SetValue(myNbPostponed.Length(), myNbPostponed.Last() + 1);
1054       }
1055     }
1056   } catch(...) {}
1057 }
1058
1059 //============================================================================
1060 /*! Function : RemovePostponed
1061  *  Purpose  : 
1062  */
1063 //============================================================================
1064 void SALOMEDS_Study_i::RemovePostponed(const CORBA::Long theUndoLimit) {
1065   int anIndex;
1066   int anOld;
1067
1068   int aUndoLimit = theUndoLimit;
1069   if (theUndoLimit < 0) aUndoLimit = 0;
1070
1071   if (myNbUndos > 0) { // remove undone
1072     anOld = 0;
1073     for(anIndex = 1; anIndex < myNbPostponed.Length() - myNbUndos; anIndex++)
1074       anOld += myNbPostponed(anIndex);
1075     int aNew = myPostponedIORs.Length() - myNbPostponed.Last();
1076
1077     for(anIndex = anOld + 1; anIndex <= aNew; anIndex++) {
1078       TCollection_AsciiString anIOR = myPostponedIORs(anIndex);
1079       if (anIOR.Value(1) == 'c') {
1080         CORBA::Object_var obj = _orb->string_to_object(anIOR.Split(1).ToCString());
1081         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1082         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1083       }
1084     }
1085     if (anOld < aNew) myPostponedIORs.Remove(anOld + 1, aNew);
1086     if (myNbPostponed.Length() > 0) myNbPostponed.Remove(myNbPostponed.Length() - myNbUndos, myNbPostponed.Length() - 1);
1087
1088     myNbUndos = 0;
1089   }
1090
1091   if (myNbPostponed.Length() > aUndoLimit) { // remove objects, that can not be undone
1092     anOld = 0;
1093     for(anIndex = myNbPostponed.Length() - aUndoLimit; anIndex >= 1; anIndex--)
1094       anOld += myNbPostponed(anIndex);
1095     for(anIndex = 1; anIndex <= anOld; anIndex++) {
1096       TCollection_AsciiString anIOR = myPostponedIORs(anIndex);
1097       if (anIOR.Value(1) == 'd') {
1098         CORBA::Object_var obj = _orb->string_to_object(anIOR.Split(1).ToCString());
1099         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1100         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1101       }
1102     }
1103     if (anOld > 0) myPostponedIORs.Remove(1, anOld);
1104     myNbPostponed.Remove(1, myNbPostponed.Length() - aUndoLimit);
1105   }
1106
1107   if (theUndoLimit == -1) { // remove all IORs from the study on the study close
1108     TDF_ChildIDIterator anIter(_doc->GetData()->Root(), SALOMEDS_IORAttribute::GetID(), Standard_True);
1109     for(; anIter.More(); anIter.Next()) {
1110       Handle(SALOMEDS_IORAttribute) anAttr = Handle(SALOMEDS_IORAttribute)::DownCast(anIter.Value());
1111       CORBA::String_var anIOR = CORBA::string_dup(TCollection_AsciiString(anAttr->Get()).ToCString());
1112       try {
1113         CORBA::Object_var obj = _orb->string_to_object(anIOR);
1114         SALOME::GenericObj_var aGeneric = SALOME::GenericObj::_narrow(obj);
1115         if (!CORBA::is_nil(aGeneric)) aGeneric->Destroy();
1116       } catch (...) {}
1117     }
1118   } else myNbPostponed.Append(0);
1119 }
1120
1121 //============================================================================
1122 /*! Function : UndoPostponed
1123  *  Purpose  : 
1124  */
1125 //============================================================================
1126 void SALOMEDS_Study_i::UndoPostponed(const CORBA::Long theWay) {
1127   myNbUndos += theWay;
1128   // remove current postponed
1129   if (myNbPostponed.Last() > 0)
1130     myPostponedIORs.Remove(myPostponedIORs.Length() - myNbPostponed.Last() + 1, myPostponedIORs.Length());
1131   myNbPostponed(myNbPostponed.Length()) = 0;
1132 }