1 // File: TObj_Model.cxx
2 // Created: Tue Nov 23 09:38:21 2004
3 // Author: Pavel TELKOV
4 // Copyright: Open CASCADE 2007
5 // The original implementation Copyright: (C) RINA S.p.A
7 #include <TObj_Model.hxx>
9 #include <OSD_File.hxx>
10 #include <Precision.hxx>
11 #include <Standard_ErrorHandler.hxx>
12 #include <TCollection_ExtendedString.hxx>
13 #include <TCollection_HAsciiString.hxx>
14 #include <TDataStd_Integer.hxx>
15 #include <TDataStd_Real.hxx>
16 #include <TDF_Tool.hxx>
17 #include <TDF_ChildIterator.hxx>
18 #include <TDocStd_Document.hxx>
19 #include <TDocStd_Owner.hxx>
21 #include <TObj_Assistant.hxx>
22 #include <TObj_Application.hxx>
23 #include <TObj_CheckModel.hxx>
24 #include <TObj_HiddenPartition.hxx>
25 #include <TObj_LabelIterator.hxx>
26 #include <TObj_ModelIterator.hxx>
27 #include <TObj_Object.hxx>
28 #include <TObj_Partition.hxx>
29 #include <TObj_TObject.hxx>
30 #include <TObj_TModel.hxx>
31 #include <TObj_TNameContainer.hxx>
32 #include <Message_Msg.hxx>
40 IMPLEMENT_STANDARD_HANDLE(TObj_Model,MMgt_TShared)
41 IMPLEMENT_STANDARD_RTTIEXT(TObj_Model,MMgt_TShared)
43 //=======================================================================
44 //function : TObj_Model
46 //=======================================================================
48 TObj_Model::TObj_Model ()
50 myMessenger = GetApplication()->Messenger();
53 //=======================================================================
54 //function : GetApplication
56 //=======================================================================
58 const Handle(TObj_Application) TObj_Model::GetApplication()
60 return TObj_Application::GetInstance();
63 //=======================================================================
64 //function : Destructor
66 //=======================================================================
68 TObj_Model::~TObj_Model ()
73 //=======================================================================
74 //function : CloseDocument
75 //purpose : free OCAF document
76 //=======================================================================
78 void TObj_Model::CloseDocument (const Handle(TDocStd_Document)& theDoc)
80 // prevent Abort of the following modifs at document destruction if
81 // a transaction is open: see theDoc->myUndoTransaction.~()
82 if ( theDoc->HasOpenCommand() )
83 theDoc->AbortCommand();
86 const Handle(TObj_Application) anApplication = GetApplication();
88 // just all other attributes
89 theDoc->Main().Root().ForgetAllAttributes(Standard_True);
90 anApplication->Close( theDoc );
93 //=======================================================================
95 //purpose : Loads the model from the file
96 //=======================================================================
98 Standard_Boolean TObj_Model::Load (const char* theFile)
101 Standard_Boolean aStatus = Standard_True;
104 Handle(TDocStd_Document) aDoc;
107 const Handle(TObj_Application) anApplication = GetApplication();
110 const Handle(TObj_Model) me = this;
111 TObj_Assistant::SetCurrentModel( me );
112 TObj_Assistant::ClearTypeMap();
114 Standard_Boolean isFileEmpty = checkDocumentEmpty( theFile );
117 // theFile is empty, create new TDocStd_Document for this model
118 aStatus = anApplication->CreateNewDocument(aDoc, GetFormat());
120 if ( aStatus == Standard_True )
122 // Put model in a new attribute on root label
123 TDF_Label aLabel = aDoc->Main();
124 Handle(TObj_TModel) anAtr = new TObj_TModel;
125 aLabel.AddAttribute(anAtr);
127 // Record that label in the model object, and initialise the new model
133 // retrieve TDocStd_Document from <theFile>
134 Messenger()->Send(Message_Msg("TObj_M_LoadDocument") << (Standard_CString)theFile,
136 aStatus = anApplication->LoadDocument(theFile,aDoc);
138 if ( aStatus == Standard_True )
140 // Check for validity of the model read:
141 // if it had wrong type, it has not been not properly restored
142 TDF_Label aLabel = GetLabel();
143 Standard_Boolean isValid = !aLabel.IsNull() && !aDoc.IsNull();
147 isValid = isValid && aLabel.Data() == aDoc->GetData();
149 catch (Standard_Failure)
151 isValid = Standard_False;
156 if (!aDoc.IsNull()) CloseDocument (aDoc);
158 Messenger()->Send(Message_Msg("TObj_M_WrongFile") << (Standard_CString)theFile,
160 aStatus = Standard_False;
165 // release document from session
166 // no message is needed as it has been put in anApplication->LoadDocument()
167 if (!aDoc.IsNull()) CloseDocument (aDoc);
171 // initialise the new model
172 if ( aStatus == Standard_True )
174 Standard_Boolean isInitOk = Standard_False;
178 isInitOk = initNewModel(isFileEmpty);
180 catch (Standard_Failure)
182 #if defined(_DEBUG) || defined(DEB)
183 Handle(Standard_Failure) anExc = Standard_Failure::Caught();
184 TCollection_ExtendedString aString(anExc->DynamicType()->Name());
185 aString = aString + ": " + anExc->GetMessageString();
186 Messenger()->Send(Message_Msg("TObj_Appl_Exception") << aString);
188 Messenger()->Send(Message_Msg("TObj_M_WrongFile") << (Standard_CString)theFile,
194 if (!aDoc.IsNull()) CloseDocument (aDoc);
196 aStatus = Standard_False;
199 TObj_Assistant::UnSetCurrentModel();
200 TObj_Assistant::ClearTypeMap();
204 //=======================================================================
206 //purpose : Returns the full file name this model is to be saved to,
207 // or null if the model was not saved yet
208 //=======================================================================
210 Handle(TCollection_HAsciiString) TObj_Model::GetFile() const
212 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
213 if ( !aDoc.IsNull() ) {
214 TCollection_AsciiString anOldPath( aDoc->GetPath() );
215 if ( !anOldPath.IsEmpty() )
216 return new TCollection_HAsciiString( anOldPath );
221 //=======================================================================
223 //purpose : Save the model to the same file
224 //=======================================================================
226 Standard_Boolean TObj_Model::Save ()
228 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
230 return Standard_False;
232 TCollection_AsciiString anOldPath( aDoc->GetPath() );
233 if ( !anOldPath.IsEmpty() )
234 return SaveAs( anOldPath.ToCString() );
235 return Standard_True;
238 //=======================================================================
240 //purpose : Save the model to a file
241 //=======================================================================
243 Standard_Boolean TObj_Model::SaveAs (const char* theFile)
245 TObj_Assistant::ClearTypeMap();
247 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
249 return Standard_False;
251 // checking that file is present on disk
252 /* do not check, because could try to save as new document to existent file
253 if(!access(theFile, 0))
255 // checking that document has not been changed from last save
256 if(!aDoc->IsChanged())
257 return Standard_True;
260 // checking write access permission
261 FILE *aF = fopen (theFile, "w");
263 Messenger()->Send (Message_Msg("TObj_M_NoWriteAccess") << (Standard_CString)theFile,
265 return Standard_False;
270 // store transaction mode
271 Standard_Boolean aTrMode = aDoc->ModificationMode();
272 aDoc->SetModificationMode( Standard_False );
273 // store all trancienmt fields of object in OCAF document if any
274 Handle(TObj_ObjectIterator) anIterator;
275 for(anIterator = GetObjects(); anIterator->More(); anIterator->Next())
277 Handle(TObj_Object) anOCAFObj = anIterator->Value();
278 if (anOCAFObj.IsNull())
280 anOCAFObj->BeforeStoring();
281 } // end of for(anIterator = ...)
282 // set transaction mode back
283 aDoc->SetModificationMode( aTrMode );
286 const Handle(TObj_Application) anApplication = GetApplication();
288 // call Application->SaveAs()
289 Standard_Boolean aStatus = anApplication->SaveDocument (aDoc, theFile);
291 TObj_Assistant::ClearTypeMap();
295 //=======================================================================
297 //purpose : Close the model and free related OCAF document
298 //=======================================================================
300 Standard_Boolean TObj_Model::Close()
303 TDF_Label aLabel = GetLabel();
304 if ( aLabel.IsNull() )
305 return Standard_False;
306 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(aLabel);
308 return Standard_False;
310 CloseDocument (aDoc);
313 return Standard_True;
316 //=======================================================================
317 //function : GetDocumentModel
318 //purpose : returns model which contains a document with the label
319 // returns NULL handle if label is NULL
320 //=======================================================================
322 Handle(TObj_Model) TObj_Model::GetDocumentModel
323 (const TDF_Label& theLabel)
325 Handle(TObj_Model) aModel;
326 if(theLabel.IsNull())
329 Handle(TDocStd_Document) aDoc;
330 Handle(TDF_Data) aData = theLabel.Data();
331 TDF_Label aRootL = aData->Root();
332 if ( aRootL.IsNull())
334 Handle(TDocStd_Owner) aDocOwnerAtt;
335 if (aRootL.FindAttribute (TDocStd_Owner::GetID(), aDocOwnerAtt))
336 aDoc = aDocOwnerAtt->GetDocument();
341 TDF_Label aLabel = aDoc->Main();
342 Handle(TObj_TModel) anAttr;
343 if(aLabel.FindAttribute(TObj_TModel::GetID(), anAttr))
344 aModel = anAttr->Model();
349 //=======================================================================
350 //function : GetObjects
352 //=======================================================================
354 Handle(TObj_ObjectIterator) TObj_Model::GetObjects() const
356 Handle(TObj_Model) me = this;
357 return new TObj_ModelIterator(me);
360 //=======================================================================
361 //function : GetChildren
363 //=======================================================================
365 Handle(TObj_ObjectIterator) TObj_Model::GetChildren() const
367 Handle(TObj_Partition) aMainPartition = GetMainPartition();
368 if(aMainPartition.IsNull())
370 return aMainPartition->GetChildren();
373 //=======================================================================
374 //function : FindObject
376 //=======================================================================
378 Handle(TObj_Object) TObj_Model::FindObject
379 (const Handle(TCollection_HExtendedString)& theName,
380 const Handle(TObj_TNameContainer)& theDictionary ) const
382 Handle(TObj_TNameContainer) aDictionary = theDictionary;
383 if ( aDictionary.IsNull() )
384 aDictionary = GetDictionary();
385 Handle(TObj_Object) aResult;
386 //Check is object with given name is present in model
387 if( IsRegisteredName( theName, aDictionary ) )
389 TDF_Label aLabel = aDictionary->Get().Find( theName );
390 TObj_Object::GetObj( aLabel, aResult );
396 //=======================================================================
399 //=======================================================================
401 Handle(TObj_Object) TObj_Model::GetRoot() const
403 return getPartition(GetLabel());
406 //=======================================================================
407 //function : GetMainPartition
409 //=======================================================================
411 Handle(TObj_Partition) TObj_Model::GetMainPartition() const
413 return getPartition( GetLabel() );
416 //=======================================================================
417 //function : SetNewName
419 //=======================================================================
421 void TObj_Model::SetNewName(const Handle(TObj_Object)& theObject)
423 Handle(TObj_Partition) aPartition = TObj_Partition::GetPartition(theObject);
425 //sets name if partition is found
426 if(aPartition.IsNull()) return;
428 Handle(TCollection_HExtendedString) name = aPartition->GetNewName();
429 if ( ! name.IsNull() ) theObject->SetName(name);
432 //=======================================================================
433 //function : IsRegisteredName
435 //=======================================================================
437 Standard_Boolean TObj_Model::IsRegisteredName(const Handle(TCollection_HExtendedString)& theName,
438 const Handle(TObj_TNameContainer)& theDictionary ) const
440 Handle(TObj_TNameContainer) aDictionary = theDictionary;
441 if ( aDictionary.IsNull() )
442 aDictionary = GetDictionary();
444 if ( aDictionary.IsNull() )
445 return Standard_False;
446 return aDictionary->IsRegistered( theName );
449 //=======================================================================
450 //function : RegisterName
452 //=======================================================================
454 void TObj_Model::RegisterName(const Handle(TCollection_HExtendedString)& theName,
455 const TDF_Label& theLabel,
456 const Handle(TObj_TNameContainer)& theDictionary ) const
458 Handle(TObj_TNameContainer) aDictionary = theDictionary;
459 if ( aDictionary.IsNull() )
460 aDictionary = GetDictionary();
462 if ( !aDictionary.IsNull() )
463 aDictionary->RecordName( theName, theLabel );
466 //=======================================================================
467 //function : UnRegisterName
469 //=======================================================================
471 void TObj_Model::UnRegisterName(const Handle(TCollection_HExtendedString)& theName,
472 const Handle(TObj_TNameContainer)& theDictionary ) const
474 Handle(TObj_TNameContainer) aDictionary = theDictionary;
475 if ( aDictionary.IsNull() )
476 aDictionary = GetDictionary();
478 if ( !aDictionary.IsNull() )
479 aDictionary->RemoveName( theName );
482 //=======================================================================
483 //function : GetDictionary
485 //=======================================================================
487 Handle(TObj_TNameContainer) TObj_Model::GetDictionary() const
489 Handle(TObj_TNameContainer) A;
490 TDF_Label aLabel = GetLabel();
491 if (!aLabel.IsNull())
492 aLabel.FindAttribute(TObj_TNameContainer::GetID(),A);
496 //=======================================================================
497 //function : getPartition
499 //=======================================================================
501 Handle(TObj_Partition) TObj_Model::getPartition
502 (const TDF_Label& theLabel,
503 const Standard_Boolean theHidden) const
505 Handle(TObj_Partition) aPartition;
506 if(theLabel.IsNull()) return aPartition;
507 Handle(TObj_TObject) A;
509 if (!theLabel.FindAttribute (TObj_TObject::GetID(), A))
512 aPartition = new TObj_HiddenPartition(theLabel);
514 aPartition = TObj_Partition::Create(theLabel);
517 aPartition = Handle(TObj_Partition)::DownCast(A->Get());
522 //=======================================================================
523 //function : getPartition
525 //=======================================================================
527 Handle(TObj_Partition) TObj_Model::getPartition
528 (const TDF_Label& theLabel,
529 const Standard_Integer theIndex,
530 const TCollection_ExtendedString& theName,
531 const Standard_Boolean theHidden) const
533 Handle(TObj_Partition) aPartition;
534 if(theLabel.IsNull()) return aPartition;
536 TDF_Label aLabel = theLabel.FindChild(theIndex,Standard_False);
537 Standard_Boolean isNew = Standard_False;
538 // defining is partition new
539 if ( aLabel.IsNull() )
541 aLabel = theLabel.FindChild(theIndex,Standard_True);
542 isNew = Standard_True;
544 // obtaining the partition
545 aPartition = getPartition( aLabel, theHidden );
547 //setting name to new partition
549 aPartition->SetName(new TCollection_HExtendedString(theName));
554 //=======================================================================
555 //function : getPartition
557 //=======================================================================
559 Handle(TObj_Partition) TObj_Model::getPartition
560 (const Standard_Integer theIndex,
561 const TCollection_ExtendedString& theName,
562 const Standard_Boolean theHidden) const
564 return getPartition (GetMainPartition()->GetChildLabel(),
565 theIndex, theName, theHidden);
568 //=======================================================================
569 //function : initNewModel
571 //=======================================================================
573 Standard_Boolean TObj_Model::initNewModel (const Standard_Boolean IsNew)
576 TObj_TNameContainer::Set(GetLabel());
578 // do something for loaded model.
581 // Register names of model in names map.
582 Handle(TObj_ObjectIterator) anIterator;
583 for(anIterator = GetObjects(); anIterator->More(); anIterator->Next())
585 Handle(TObj_Object) anOCAFObj = anIterator->Value();
586 if (anOCAFObj.IsNull())
588 anOCAFObj->AfterRetrieval();
589 } // end of for(anIterator = ...)
590 // update back references for loaded model by references
591 updateBackReferences( GetMainPartition() );
595 // check model consistency
596 Handle(TObj_CheckModel) aCheck = GetChecker();
598 aCheck->SendMessages();
599 // tell that the model has been modified
600 SetModified(Standard_True);
603 return Standard_True;
606 //=======================================================================
607 //function : updateBackReferences
609 //=======================================================================
611 void TObj_Model::updateBackReferences (const Handle(TObj_Object)& theObject)
613 // recursive update back references
614 if ( theObject.IsNull() )
616 Handle(TObj_ObjectIterator) aChildren = theObject->GetChildren();
617 for(;aChildren->More() && aChildren->More(); aChildren->Next())
619 Handle(TObj_Object) aChild = aChildren->Value();
620 updateBackReferences( aChild );
622 // update back references of reference objects
623 Handle(TObj_LabelIterator) anIter =
624 Handle(TObj_LabelIterator)::DownCast(theObject->GetReferences());
626 if(anIter.IsNull()) // to avoid exception
629 // LH3D15722. Remove all back references to make sure there will be no unnecessary
630 // duplicates, since some back references may already exist after model upgrading.
631 // (do not take care that object can be from other document, because
632 // we do not modify document, all modifications are made in transient fields)
633 for( ; anIter->More() ; anIter->Next())
635 Handle(TObj_Object) anObject = anIter->Value();
636 if ( !anObject.IsNull() )
637 anObject->RemoveBackReference( theObject, Standard_False );
639 // and at last create back references
640 anIter = Handle(TObj_LabelIterator)::DownCast(theObject->GetReferences());
642 for( ; anIter->More() ; anIter->Next())
644 Handle(TObj_Object) anObject = anIter->Value();
645 if ( !anObject.IsNull() )
646 anObject->AddBackReference( theObject );
650 //=======================================================================
651 //function : GetDocument
653 //=======================================================================
655 Handle(TDocStd_Document) TObj_Model::GetDocument() const
657 Handle(TDocStd_Document) D;
658 TDF_Label aLabel = GetLabel();
659 if (!aLabel.IsNull())
660 D = TDocStd_Document::Get(aLabel);
664 //=======================================================================
665 //function : HasOpenCommand
667 //=======================================================================
669 Standard_Boolean TObj_Model::HasOpenCommand() const
671 return GetDocument()->HasOpenCommand();
674 //=======================================================================
675 //function : OpenCommand
677 //=======================================================================
679 void TObj_Model::OpenCommand() const
681 GetDocument()->OpenCommand();
684 //=======================================================================
685 //function : CommitCommand
687 //=======================================================================
689 void TObj_Model::CommitCommand() const
691 GetDocument()->CommitCommand();
694 //=======================================================================
695 //function : AbortCommand
697 //=======================================================================
699 void TObj_Model::AbortCommand() const
701 GetDocument()->AbortCommand();
704 //=======================================================================
705 //function : IsModified
706 //purpose : Status of modification
707 //=======================================================================
709 Standard_Boolean TObj_Model::IsModified () const
711 Handle(TDocStd_Document) aDoc = GetDocument();
712 return aDoc.IsNull() ? Standard_False : aDoc->IsChanged();
715 //=======================================================================
716 //function : SetModified
717 //purpose : Status of modification
718 //=======================================================================
720 void TObj_Model::SetModified (const Standard_Boolean theModified)
722 Handle(TDocStd_Document) aDoc = GetDocument();
725 Standard_Integer aSavedTime = aDoc->GetData()->Time();
728 aDoc->SetSavedTime (aSavedTime);
732 //=======================================================================
733 //function : checkDocumentEmpty
734 //purpose : Check whether the document contains the Ocaf data
735 //=======================================================================
737 Standard_Boolean TObj_Model::checkDocumentEmpty (const char* theFile)
740 return Standard_True;
742 TCollection_AsciiString aFile ((Standard_CString) theFile);
744 return Standard_True;
746 OSD_Path aPath (aFile);
747 OSD_File osdfile (aPath);
748 if ( !osdfile.Exists() )
749 return Standard_True;
751 FILE* f = fopen( theFile, "r" );
754 Standard_Boolean isZeroLengh = Standard_False;
755 fseek( f, 0, SEEK_END );
756 if ( ftell( f ) == 0 )
757 isZeroLengh = Standard_True;
762 return Standard_False;
765 //=======================================================================
768 //=======================================================================
770 Standard_GUID TObj_Model::GetGUID() const
772 Standard_GUID aGUID("3bbefb49-e618-11d4-ba38-0060b0ee18ea");
776 //=======================================================================
777 //function : GetFormat
779 //=======================================================================
781 TCollection_ExtendedString TObj_Model::GetFormat() const
783 return TCollection_ExtendedString ("TObjBin");
786 //=======================================================================
787 //function : GetFormatVersion
789 //=======================================================================
791 Standard_Integer TObj_Model::GetFormatVersion() const
793 TDF_Label aLabel = GetDataLabel().FindChild(DataTag_FormatVersion,Standard_False);
797 Handle(TDataStd_Integer) aNum;
798 if(!aLabel.FindAttribute ( TDataStd_Integer::GetID(), aNum ))
804 //=======================================================================
805 //function : SetFormatVersion
807 //=======================================================================
809 void TObj_Model::SetFormatVersion(const Standard_Integer theVersion)
811 TDF_Label aLabel = GetDataLabel().FindChild(DataTag_FormatVersion,Standard_True);
812 TDataStd_Integer::Set(aLabel,theVersion);
816 //=======================================================================
817 //function : GetDataLabel
819 //=======================================================================
821 TDF_Label TObj_Model::GetDataLabel() const
823 return GetMainPartition()->GetDataLabel();
826 //=======================================================================
829 //=======================================================================
831 Standard_Boolean TObj_Model::Paste (Handle(TObj_Model) theModel,
832 Handle(TDF_RelocationTable) theRelocTable)
834 if(theModel.IsNull()) return Standard_False;
835 // clearing dictionary of objects names
836 // theModel->GetDictionary()->NewEmpty()->Paste(theModel->GetDictionary(),
837 // new TDF_RelocationTable);
838 // theModel->GetLabel().ForgetAllAttributes(Standard_True);
839 TObj_TNameContainer::Set(theModel->GetLabel());
840 GetMainPartition()->Clone(theModel->GetLabel(), theRelocTable);
841 return Standard_True;
844 //=======================================================================
845 //function : CopyReferences
847 //=======================================================================
849 void TObj_Model::CopyReferences(const Handle(TObj_Model)& theTarget,
850 const Handle(TDF_RelocationTable)& theRelocTable)
852 Handle(TObj_Object) aMyRoot = GetMainPartition();
853 Handle(TObj_Object) aTargetRoot = theTarget->GetMainPartition();
854 aMyRoot->CopyReferences(aTargetRoot, theRelocTable);
857 //=======================================================================
858 //function : GetModelName
859 //purpose : Returns the name of the model
860 // by default returns TObj
861 //=======================================================================
863 Handle(TCollection_HExtendedString) TObj_Model::GetModelName() const
865 Handle(TCollection_HExtendedString) aName =
866 new TCollection_HExtendedString("TObj");
870 //=======================================================================
872 //purpose : default implementation is empty
873 //=======================================================================
875 Standard_Boolean TObj_Model::Update ()
877 return Standard_True;
880 //=======================================================================
881 //function : GetChecker
883 //=======================================================================
885 Handle(TObj_CheckModel) TObj_Model::GetChecker() const
887 return new TObj_CheckModel (this);