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