1 // Created on: 2004-11-23
2 // Created by: Pavel TELKOV
3 // Copyright (c) 2004-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
20 // The original implementation Copyright: (C) RINA S.p.A
22 #include <TObj_Model.hxx>
24 #include <OSD_File.hxx>
25 #include <Precision.hxx>
26 #include <Standard_ErrorHandler.hxx>
27 #include <TCollection_ExtendedString.hxx>
28 #include <TCollection_HAsciiString.hxx>
29 #include <TDataStd_Integer.hxx>
30 #include <TDataStd_Real.hxx>
31 #include <TDF_Tool.hxx>
32 #include <TDF_ChildIterator.hxx>
33 #include <TDocStd_Document.hxx>
34 #include <TDocStd_Owner.hxx>
36 #include <TObj_Assistant.hxx>
37 #include <TObj_Application.hxx>
38 #include <TObj_CheckModel.hxx>
39 #include <TObj_HiddenPartition.hxx>
40 #include <TObj_LabelIterator.hxx>
41 #include <TObj_ModelIterator.hxx>
42 #include <TObj_Object.hxx>
43 #include <TObj_Partition.hxx>
44 #include <TObj_TObject.hxx>
45 #include <TObj_TModel.hxx>
46 #include <TObj_TNameContainer.hxx>
47 #include <Message_Msg.hxx>
55 IMPLEMENT_STANDARD_HANDLE(TObj_Model,MMgt_TShared)
56 IMPLEMENT_STANDARD_RTTIEXT(TObj_Model,MMgt_TShared)
58 //=======================================================================
59 //function : TObj_Model
61 //=======================================================================
63 TObj_Model::TObj_Model ()
65 myMessenger = GetApplication()->Messenger();
68 //=======================================================================
69 //function : GetApplication
71 //=======================================================================
73 const Handle(TObj_Application) TObj_Model::GetApplication()
75 return TObj_Application::GetInstance();
78 //=======================================================================
79 //function : Destructor
81 //=======================================================================
83 TObj_Model::~TObj_Model ()
88 //=======================================================================
89 //function : CloseDocument
90 //purpose : free OCAF document
91 //=======================================================================
93 void TObj_Model::CloseDocument (const Handle(TDocStd_Document)& theDoc)
95 // prevent Abort of the following modifs at document destruction if
96 // a transaction is open: see theDoc->myUndoTransaction.~()
97 if ( theDoc->HasOpenCommand() )
98 theDoc->AbortCommand();
101 const Handle(TObj_Application) anApplication = GetApplication();
103 // just all other attributes
104 theDoc->Main().Root().ForgetAllAttributes(Standard_True);
105 anApplication->Close( theDoc );
108 //=======================================================================
110 //purpose : Loads the model from the file
111 //=======================================================================
113 Standard_Boolean TObj_Model::Load (const char* theFile)
116 Standard_Boolean aStatus = Standard_True;
119 Handle(TDocStd_Document) aDoc;
122 const Handle(TObj_Application) anApplication = GetApplication();
125 const Handle(TObj_Model) me = this;
126 TObj_Assistant::SetCurrentModel( me );
127 TObj_Assistant::ClearTypeMap();
129 Standard_Boolean isFileEmpty = checkDocumentEmpty( theFile );
132 // theFile is empty, create new TDocStd_Document for this model
133 aStatus = anApplication->CreateNewDocument(aDoc, GetFormat());
135 if ( aStatus == Standard_True )
137 // Put model in a new attribute on root label
138 TDF_Label aLabel = aDoc->Main();
139 Handle(TObj_TModel) anAtr = new TObj_TModel;
140 aLabel.AddAttribute(anAtr);
142 // Record that label in the model object, and initialise the new model
148 // retrieve TDocStd_Document from <theFile>
149 Messenger()->Send(Message_Msg("TObj_M_LoadDocument") << (Standard_CString)theFile,
151 aStatus = anApplication->LoadDocument(theFile,aDoc);
153 if ( aStatus == Standard_True )
155 // Check for validity of the model read:
156 // if it had wrong type, it has not been not properly restored
157 TDF_Label aLabel = GetLabel();
158 Standard_Boolean isValid = !aLabel.IsNull() && !aDoc.IsNull();
162 isValid = isValid && aLabel.Data() == aDoc->GetData();
164 catch (Standard_Failure)
166 isValid = Standard_False;
171 if (!aDoc.IsNull()) CloseDocument (aDoc);
173 Messenger()->Send(Message_Msg("TObj_M_WrongFile") << (Standard_CString)theFile,
175 aStatus = Standard_False;
180 // release document from session
181 // no message is needed as it has been put in anApplication->LoadDocument()
182 if (!aDoc.IsNull()) CloseDocument (aDoc);
186 // initialise the new model
187 if ( aStatus == Standard_True )
189 Standard_Boolean isInitOk = Standard_False;
193 isInitOk = initNewModel(isFileEmpty);
195 catch (Standard_Failure)
197 #if defined(_DEBUG) || defined(DEB)
198 Handle(Standard_Failure) anExc = Standard_Failure::Caught();
199 TCollection_ExtendedString aString(anExc->DynamicType()->Name());
200 aString = aString + ": " + anExc->GetMessageString();
201 Messenger()->Send(Message_Msg("TObj_Appl_Exception") << aString);
203 Messenger()->Send(Message_Msg("TObj_M_WrongFile") << (Standard_CString)theFile,
209 if (!aDoc.IsNull()) CloseDocument (aDoc);
211 aStatus = Standard_False;
214 TObj_Assistant::UnSetCurrentModel();
215 TObj_Assistant::ClearTypeMap();
219 //=======================================================================
221 //purpose : Returns the full file name this model is to be saved to,
222 // or null if the model was not saved yet
223 //=======================================================================
225 Handle(TCollection_HAsciiString) TObj_Model::GetFile() const
227 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
228 if ( !aDoc.IsNull() ) {
229 TCollection_AsciiString anOldPath( aDoc->GetPath() );
230 if ( !anOldPath.IsEmpty() )
231 return new TCollection_HAsciiString( anOldPath );
236 //=======================================================================
238 //purpose : Save the model to the same file
239 //=======================================================================
241 Standard_Boolean TObj_Model::Save ()
243 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
245 return Standard_False;
247 TCollection_AsciiString anOldPath( aDoc->GetPath() );
248 if ( !anOldPath.IsEmpty() )
249 return SaveAs( anOldPath.ToCString() );
250 return Standard_True;
253 //=======================================================================
255 //purpose : Save the model to a file
256 //=======================================================================
258 Standard_Boolean TObj_Model::SaveAs (const char* theFile)
260 TObj_Assistant::ClearTypeMap();
262 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
264 return Standard_False;
266 // checking that file is present on disk
267 /* do not check, because could try to save as new document to existent file
268 if(!access(theFile, 0))
270 // checking that document has not been changed from last save
271 if(!aDoc->IsChanged())
272 return Standard_True;
275 // checking write access permission
276 FILE *aF = fopen (theFile, "w");
278 Messenger()->Send (Message_Msg("TObj_M_NoWriteAccess") << (Standard_CString)theFile,
280 return Standard_False;
285 // store transaction mode
286 Standard_Boolean aTrMode = aDoc->ModificationMode();
287 aDoc->SetModificationMode( Standard_False );
288 // store all trancienmt fields of object in OCAF document if any
289 Handle(TObj_ObjectIterator) anIterator;
290 for(anIterator = GetObjects(); anIterator->More(); anIterator->Next())
292 Handle(TObj_Object) anOCAFObj = anIterator->Value();
293 if (anOCAFObj.IsNull())
295 anOCAFObj->BeforeStoring();
296 } // end of for(anIterator = ...)
297 // set transaction mode back
298 aDoc->SetModificationMode( aTrMode );
301 const Handle(TObj_Application) anApplication = GetApplication();
303 // call Application->SaveAs()
304 Standard_Boolean aStatus = anApplication->SaveDocument (aDoc, theFile);
306 TObj_Assistant::ClearTypeMap();
310 //=======================================================================
312 //purpose : Close the model and free related OCAF document
313 //=======================================================================
315 Standard_Boolean TObj_Model::Close()
318 TDF_Label aLabel = GetLabel();
319 if ( aLabel.IsNull() )
320 return Standard_False;
321 Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(aLabel);
323 return Standard_False;
325 CloseDocument (aDoc);
328 return Standard_True;
331 //=======================================================================
332 //function : GetDocumentModel
333 //purpose : returns model which contains a document with the label
334 // returns NULL handle if label is NULL
335 //=======================================================================
337 Handle(TObj_Model) TObj_Model::GetDocumentModel
338 (const TDF_Label& theLabel)
340 Handle(TObj_Model) aModel;
341 if(theLabel.IsNull())
344 Handle(TDocStd_Document) aDoc;
345 Handle(TDF_Data) aData = theLabel.Data();
346 TDF_Label aRootL = aData->Root();
347 if ( aRootL.IsNull())
349 Handle(TDocStd_Owner) aDocOwnerAtt;
350 if (aRootL.FindAttribute (TDocStd_Owner::GetID(), aDocOwnerAtt))
351 aDoc = aDocOwnerAtt->GetDocument();
356 TDF_Label aLabel = aDoc->Main();
357 Handle(TObj_TModel) anAttr;
358 if(aLabel.FindAttribute(TObj_TModel::GetID(), anAttr))
359 aModel = anAttr->Model();
364 //=======================================================================
365 //function : GetObjects
367 //=======================================================================
369 Handle(TObj_ObjectIterator) TObj_Model::GetObjects() const
371 Handle(TObj_Model) me = this;
372 return new TObj_ModelIterator(me);
375 //=======================================================================
376 //function : GetChildren
378 //=======================================================================
380 Handle(TObj_ObjectIterator) TObj_Model::GetChildren() const
382 Handle(TObj_Partition) aMainPartition = GetMainPartition();
383 if(aMainPartition.IsNull())
385 return aMainPartition->GetChildren();
388 //=======================================================================
389 //function : FindObject
391 //=======================================================================
393 Handle(TObj_Object) TObj_Model::FindObject
394 (const Handle(TCollection_HExtendedString)& theName,
395 const Handle(TObj_TNameContainer)& theDictionary ) const
397 Handle(TObj_TNameContainer) aDictionary = theDictionary;
398 if ( aDictionary.IsNull() )
399 aDictionary = GetDictionary();
400 Handle(TObj_Object) aResult;
401 //Check is object with given name is present in model
402 if( IsRegisteredName( theName, aDictionary ) )
404 TDF_Label aLabel = aDictionary->Get().Find( theName );
405 TObj_Object::GetObj( aLabel, aResult );
411 //=======================================================================
414 //=======================================================================
416 Handle(TObj_Object) TObj_Model::GetRoot() const
418 return getPartition(GetLabel());
421 //=======================================================================
422 //function : GetMainPartition
424 //=======================================================================
426 Handle(TObj_Partition) TObj_Model::GetMainPartition() const
428 return getPartition( GetLabel() );
431 //=======================================================================
432 //function : SetNewName
434 //=======================================================================
436 void TObj_Model::SetNewName(const Handle(TObj_Object)& theObject)
438 Handle(TObj_Partition) aPartition = TObj_Partition::GetPartition(theObject);
440 //sets name if partition is found
441 if(aPartition.IsNull()) return;
443 Handle(TCollection_HExtendedString) name = aPartition->GetNewName();
444 if ( ! name.IsNull() ) theObject->SetName(name);
447 //=======================================================================
448 //function : IsRegisteredName
450 //=======================================================================
452 Standard_Boolean TObj_Model::IsRegisteredName(const Handle(TCollection_HExtendedString)& theName,
453 const Handle(TObj_TNameContainer)& theDictionary ) const
455 Handle(TObj_TNameContainer) aDictionary = theDictionary;
456 if ( aDictionary.IsNull() )
457 aDictionary = GetDictionary();
459 if ( aDictionary.IsNull() )
460 return Standard_False;
461 return aDictionary->IsRegistered( theName );
464 //=======================================================================
465 //function : RegisterName
467 //=======================================================================
469 void TObj_Model::RegisterName(const Handle(TCollection_HExtendedString)& theName,
470 const TDF_Label& theLabel,
471 const Handle(TObj_TNameContainer)& theDictionary ) const
473 Handle(TObj_TNameContainer) aDictionary = theDictionary;
474 if ( aDictionary.IsNull() )
475 aDictionary = GetDictionary();
477 if ( !aDictionary.IsNull() )
478 aDictionary->RecordName( theName, theLabel );
481 //=======================================================================
482 //function : UnRegisterName
484 //=======================================================================
486 void TObj_Model::UnRegisterName(const Handle(TCollection_HExtendedString)& theName,
487 const Handle(TObj_TNameContainer)& theDictionary ) const
489 Handle(TObj_TNameContainer) aDictionary = theDictionary;
490 if ( aDictionary.IsNull() )
491 aDictionary = GetDictionary();
493 if ( !aDictionary.IsNull() )
494 aDictionary->RemoveName( theName );
497 //=======================================================================
498 //function : GetDictionary
500 //=======================================================================
502 Handle(TObj_TNameContainer) TObj_Model::GetDictionary() const
504 Handle(TObj_TNameContainer) A;
505 TDF_Label aLabel = GetLabel();
506 if (!aLabel.IsNull())
507 aLabel.FindAttribute(TObj_TNameContainer::GetID(),A);
511 //=======================================================================
512 //function : getPartition
514 //=======================================================================
516 Handle(TObj_Partition) TObj_Model::getPartition
517 (const TDF_Label& theLabel,
518 const Standard_Boolean theHidden) const
520 Handle(TObj_Partition) aPartition;
521 if(theLabel.IsNull()) return aPartition;
522 Handle(TObj_TObject) A;
524 if (!theLabel.FindAttribute (TObj_TObject::GetID(), A))
527 aPartition = new TObj_HiddenPartition(theLabel);
529 aPartition = TObj_Partition::Create(theLabel);
532 aPartition = Handle(TObj_Partition)::DownCast(A->Get());
537 //=======================================================================
538 //function : getPartition
540 //=======================================================================
542 Handle(TObj_Partition) TObj_Model::getPartition
543 (const TDF_Label& theLabel,
544 const Standard_Integer theIndex,
545 const TCollection_ExtendedString& theName,
546 const Standard_Boolean theHidden) const
548 Handle(TObj_Partition) aPartition;
549 if(theLabel.IsNull()) return aPartition;
551 TDF_Label aLabel = theLabel.FindChild(theIndex,Standard_False);
552 Standard_Boolean isNew = Standard_False;
553 // defining is partition new
554 if ( aLabel.IsNull() )
556 aLabel = theLabel.FindChild(theIndex,Standard_True);
557 isNew = Standard_True;
559 // obtaining the partition
560 aPartition = getPartition( aLabel, theHidden );
562 //setting name to new partition
564 aPartition->SetName(new TCollection_HExtendedString(theName));
569 //=======================================================================
570 //function : getPartition
572 //=======================================================================
574 Handle(TObj_Partition) TObj_Model::getPartition
575 (const Standard_Integer theIndex,
576 const TCollection_ExtendedString& theName,
577 const Standard_Boolean theHidden) const
579 return getPartition (GetMainPartition()->GetChildLabel(),
580 theIndex, theName, theHidden);
583 //=======================================================================
584 //function : initNewModel
586 //=======================================================================
588 Standard_Boolean TObj_Model::initNewModel (const Standard_Boolean IsNew)
591 TObj_TNameContainer::Set(GetLabel());
593 // do something for loaded model.
596 // Register names of model in names map.
597 Handle(TObj_ObjectIterator) anIterator;
598 for(anIterator = GetObjects(); anIterator->More(); anIterator->Next())
600 Handle(TObj_Object) anOCAFObj = anIterator->Value();
601 if (anOCAFObj.IsNull())
603 anOCAFObj->AfterRetrieval();
604 } // end of for(anIterator = ...)
605 // update back references for loaded model by references
606 updateBackReferences( GetMainPartition() );
610 // check model consistency
611 Handle(TObj_CheckModel) aCheck = GetChecker();
613 aCheck->SendMessages();
614 // tell that the model has been modified
615 SetModified(Standard_True);
618 return Standard_True;
621 //=======================================================================
622 //function : updateBackReferences
624 //=======================================================================
626 void TObj_Model::updateBackReferences (const Handle(TObj_Object)& theObject)
628 // recursive update back references
629 if ( theObject.IsNull() )
631 Handle(TObj_ObjectIterator) aChildren = theObject->GetChildren();
632 for(;aChildren->More() && aChildren->More(); aChildren->Next())
634 Handle(TObj_Object) aChild = aChildren->Value();
635 updateBackReferences( aChild );
637 // update back references of reference objects
638 Handle(TObj_LabelIterator) anIter =
639 Handle(TObj_LabelIterator)::DownCast(theObject->GetReferences());
641 if(anIter.IsNull()) // to avoid exception
644 // LH3D15722. Remove all back references to make sure there will be no unnecessary
645 // duplicates, since some back references may already exist after model upgrading.
646 // (do not take care that object can be from other document, because
647 // we do not modify document, all modifications are made in transient fields)
648 for( ; anIter->More() ; anIter->Next())
650 Handle(TObj_Object) anObject = anIter->Value();
651 if ( !anObject.IsNull() )
652 anObject->RemoveBackReference( theObject, Standard_False );
654 // and at last create back references
655 anIter = Handle(TObj_LabelIterator)::DownCast(theObject->GetReferences());
657 for( ; anIter->More() ; anIter->Next())
659 Handle(TObj_Object) anObject = anIter->Value();
660 if ( !anObject.IsNull() )
661 anObject->AddBackReference( theObject );
665 //=======================================================================
666 //function : GetDocument
668 //=======================================================================
670 Handle(TDocStd_Document) TObj_Model::GetDocument() const
672 Handle(TDocStd_Document) D;
673 TDF_Label aLabel = GetLabel();
674 if (!aLabel.IsNull())
675 D = TDocStd_Document::Get(aLabel);
679 //=======================================================================
680 //function : HasOpenCommand
682 //=======================================================================
684 Standard_Boolean TObj_Model::HasOpenCommand() const
686 return GetDocument()->HasOpenCommand();
689 //=======================================================================
690 //function : OpenCommand
692 //=======================================================================
694 void TObj_Model::OpenCommand() const
696 GetDocument()->OpenCommand();
699 //=======================================================================
700 //function : CommitCommand
702 //=======================================================================
704 void TObj_Model::CommitCommand() const
706 GetDocument()->CommitCommand();
709 //=======================================================================
710 //function : AbortCommand
712 //=======================================================================
714 void TObj_Model::AbortCommand() const
716 GetDocument()->AbortCommand();
719 //=======================================================================
720 //function : IsModified
721 //purpose : Status of modification
722 //=======================================================================
724 Standard_Boolean TObj_Model::IsModified () const
726 Handle(TDocStd_Document) aDoc = GetDocument();
727 return aDoc.IsNull() ? Standard_False : aDoc->IsChanged();
730 //=======================================================================
731 //function : SetModified
732 //purpose : Status of modification
733 //=======================================================================
735 void TObj_Model::SetModified (const Standard_Boolean theModified)
737 Handle(TDocStd_Document) aDoc = GetDocument();
740 Standard_Integer aSavedTime = aDoc->GetData()->Time();
743 aDoc->SetSavedTime (aSavedTime);
747 //=======================================================================
748 //function : checkDocumentEmpty
749 //purpose : Check whether the document contains the Ocaf data
750 //=======================================================================
752 Standard_Boolean TObj_Model::checkDocumentEmpty (const char* theFile)
755 return Standard_True;
757 TCollection_AsciiString aFile ((Standard_CString) theFile);
759 return Standard_True;
761 OSD_Path aPath (aFile);
762 OSD_File osdfile (aPath);
763 if ( !osdfile.Exists() )
764 return Standard_True;
766 FILE* f = fopen( theFile, "r" );
769 Standard_Boolean isZeroLengh = Standard_False;
770 fseek( f, 0, SEEK_END );
771 if ( ftell( f ) == 0 )
772 isZeroLengh = Standard_True;
777 return Standard_False;
780 //=======================================================================
783 //=======================================================================
785 Standard_GUID TObj_Model::GetGUID() const
787 Standard_GUID aGUID("3bbefb49-e618-11d4-ba38-0060b0ee18ea");
791 //=======================================================================
792 //function : GetFormat
794 //=======================================================================
796 TCollection_ExtendedString TObj_Model::GetFormat() const
798 return TCollection_ExtendedString ("TObjBin");
801 //=======================================================================
802 //function : GetFormatVersion
804 //=======================================================================
806 Standard_Integer TObj_Model::GetFormatVersion() const
808 TDF_Label aLabel = GetDataLabel().FindChild(DataTag_FormatVersion,Standard_False);
812 Handle(TDataStd_Integer) aNum;
813 if(!aLabel.FindAttribute ( TDataStd_Integer::GetID(), aNum ))
819 //=======================================================================
820 //function : SetFormatVersion
822 //=======================================================================
824 void TObj_Model::SetFormatVersion(const Standard_Integer theVersion)
826 TDF_Label aLabel = GetDataLabel().FindChild(DataTag_FormatVersion,Standard_True);
827 TDataStd_Integer::Set(aLabel,theVersion);
831 //=======================================================================
832 //function : GetDataLabel
834 //=======================================================================
836 TDF_Label TObj_Model::GetDataLabel() const
838 return GetMainPartition()->GetDataLabel();
841 //=======================================================================
844 //=======================================================================
846 Standard_Boolean TObj_Model::Paste (Handle(TObj_Model) theModel,
847 Handle(TDF_RelocationTable) theRelocTable)
849 if(theModel.IsNull()) return Standard_False;
850 // clearing dictionary of objects names
851 // theModel->GetDictionary()->NewEmpty()->Paste(theModel->GetDictionary(),
852 // new TDF_RelocationTable);
853 // theModel->GetLabel().ForgetAllAttributes(Standard_True);
854 TObj_TNameContainer::Set(theModel->GetLabel());
855 GetMainPartition()->Clone(theModel->GetLabel(), theRelocTable);
856 return Standard_True;
859 //=======================================================================
860 //function : CopyReferences
862 //=======================================================================
864 void TObj_Model::CopyReferences(const Handle(TObj_Model)& theTarget,
865 const Handle(TDF_RelocationTable)& theRelocTable)
867 Handle(TObj_Object) aMyRoot = GetMainPartition();
868 Handle(TObj_Object) aTargetRoot = theTarget->GetMainPartition();
869 aMyRoot->CopyReferences(aTargetRoot, theRelocTable);
872 //=======================================================================
873 //function : GetModelName
874 //purpose : Returns the name of the model
875 // by default returns TObj
876 //=======================================================================
878 Handle(TCollection_HExtendedString) TObj_Model::GetModelName() const
880 Handle(TCollection_HExtendedString) aName =
881 new TCollection_HExtendedString("TObj");
885 //=======================================================================
887 //purpose : default implementation is empty
888 //=======================================================================
890 Standard_Boolean TObj_Model::Update ()
892 return Standard_True;
895 //=======================================================================
896 //function : GetChecker
898 //=======================================================================
900 Handle(TObj_CheckModel) TObj_Model::GetChecker() const
902 return new TObj_CheckModel (this);