0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / StdLDrivers / StdLDrivers_DocumentRetrievalDriver.cxx
1 // Copyright (c) 2015 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <StdLDrivers_DocumentRetrievalDriver.hxx>
15 #include <StdLDrivers.hxx>
16
17 #include <StdObjMgt_Persistent.hxx>
18 #include <StdObjMgt_MapOfInstantiators.hxx>
19 #include <StdObjMgt_ReadData.hxx>
20
21 #include <Storage_HeaderData.hxx>
22 #include <Storage_TypeData.hxx>
23 #include <Storage_RootData.hxx>
24 #include <Storage_BaseDriver.hxx>
25 #include <Storage_StreamTypeMismatchError.hxx>
26 #include <Storage_StreamFormatError.hxx>
27 #include <Storage_StreamReadError.hxx>
28
29 #include <PCDM.hxx>
30 #include <PCDM_ReadWriter.hxx>
31
32 #include <Standard_ErrorHandler.hxx>
33 #include <Standard_NotImplemented.hxx>
34 #include <NCollection_Array1.hxx>
35 #include <NCollection_Handle.hxx>
36 #include <TDocStd_Document.hxx>
37
38 IMPLEMENT_STANDARD_RTTIEXT (StdLDrivers_DocumentRetrievalDriver, PCDM_RetrievalDriver)
39
40 //=======================================================================
41 //function : CreateDocument
42 //purpose  : Create an empty TDocStd_Document
43 //=======================================================================
44 Handle(CDM_Document) StdLDrivers_DocumentRetrievalDriver::CreateDocument()
45 {
46   return new TDocStd_Document (PCDM_RetrievalDriver::GetFormat());
47 }
48
49 //=======================================================================
50 //function : Read
51 //purpose  : Retrieve the content of a file into a new document
52 //=======================================================================
53 void StdLDrivers_DocumentRetrievalDriver::Read (const TCollection_ExtendedString& theFileName,
54                                                 const Handle(CDM_Document)&       theNewDocument,
55                                                 const Handle(CDM_Application)&)
56 {
57   // Read header data and persistent document
58   Storage_HeaderData aHeaderData;
59   Handle(StdObjMgt_Persistent) aPDocument = read (theFileName, aHeaderData);
60   if (aPDocument.IsNull())
61     return;
62
63   // Import transient document from the persistent one
64   aPDocument->ImportDocument (
65     Handle(TDocStd_Document)::DownCast (theNewDocument));
66
67   // Copy comments from the header data
68   theNewDocument->SetComments (aHeaderData.Comments());
69 }
70
71 //=======================================================================
72 //function : read
73 //purpose  : Read persistent document from a file
74 //=======================================================================
75 Handle(StdObjMgt_Persistent) StdLDrivers_DocumentRetrievalDriver::read (
76   const TCollection_ExtendedString& theFileName,
77   Storage_HeaderData&               theHeaderData)
78 {
79   Standard_Integer i;
80
81   // Create a driver appropriate for the given file
82   PCDM_BaseDriverPointer aFileDriverPtr;
83   if (PCDM::FileDriverType (TCollection_AsciiString (theFileName), aFileDriverPtr) == PCDM_TOFD_Unknown)
84   {
85     myReaderStatus = PCDM_RS_UnknownFileDriver;
86     return NULL;
87   }
88
89   NCollection_Handle<Storage_BaseDriver> aFileDriver (aFileDriverPtr);
90
91   // Try to open the file
92   try
93   {
94     OCC_CATCH_SIGNALS
95     PCDM_ReadWriter::Open (*aFileDriver, theFileName, Storage_VSRead);
96     myReaderStatus = PCDM_RS_OK;
97   } 
98   catch (Standard_Failure const& anException)
99   {
100     myReaderStatus = PCDM_RS_OpenError;
101
102     Standard_SStream aMsg;
103     aMsg << anException << endl;
104     throw Standard_Failure(aMsg.str().c_str());
105   }
106   
107   // Read header section
108   if (!theHeaderData.Read (*aFileDriver))
109     raiseOnStorageError (theHeaderData.ErrorStatus());
110
111   // Read type section
112   Storage_TypeData aTypeData;
113   if (!aTypeData.Read (*aFileDriver))
114     raiseOnStorageError (aTypeData.ErrorStatus());
115
116   // Read root section
117   Storage_RootData aRootData;
118   if (!aRootData.Read (*aFileDriver))
119     raiseOnStorageError (aRootData.ErrorStatus());
120
121   if (aRootData.NumberOfRoots() < 1)
122   {
123     myReaderStatus = PCDM_RS_NoDocument;
124
125     Standard_SStream aMsg;
126     aMsg << "could not find any document in this file" << endl;
127     throw Standard_Failure(aMsg.str().c_str());
128   }
129
130   // Select instantiators for the used types
131   NCollection_Array1<StdObjMgt_Persistent::Instantiator>
132     anInstantiators (1, aTypeData.NumberOfTypes());
133   {
134     StdObjMgt_MapOfInstantiators aMapOfInst;
135     bindTypes (aMapOfInst);
136
137     TColStd_SequenceOfAsciiString anUnknownTypes;
138     Standard_Integer        aCurTypeNum;
139     TCollection_AsciiString aCurTypeName;
140
141     for (i = 1; i <= aTypeData.NumberOfTypes(); i++)
142     {
143       aCurTypeName = aTypeData.Type (i);
144       aCurTypeNum  = aTypeData.Type (aCurTypeName);
145
146       StdObjMgt_Persistent::Instantiator anInstantiator;
147       if (aMapOfInst.Find(aCurTypeName, anInstantiator))
148         anInstantiators (aCurTypeNum) = anInstantiator;
149       else
150         anUnknownTypes.Append (aCurTypeName);
151     }
152
153     if (!anUnknownTypes.IsEmpty())
154     {
155       myReaderStatus = PCDM_RS_TypeNotFoundInSchema;
156
157       Standard_SStream aMsg;
158       aMsg << "cannot read: `" << theFileName
159             << "' because it contains the following unknown types: ";
160       for (i = 1; i <= anUnknownTypes.Length(); i++)
161       {
162         aMsg << anUnknownTypes(i);
163         if (i < anUnknownTypes.Length()) aMsg << ",";
164         else                             aMsg << endl;
165       }
166
167       throw Standard_Failure(aMsg.str().c_str());
168     }
169   }
170
171   // Read and parse reference section
172   StdObjMgt_ReadData aReadData (*aFileDriver, theHeaderData.NumberOfObjects());
173
174   raiseOnStorageError (aFileDriver->BeginReadRefSection());
175
176   Standard_Integer len = aFileDriver->RefSectionSize();
177   for (i = 1; i <= len; i++)
178   {
179     Standard_Integer aRef = 0, aType = 0;
180     Storage_Error anError;
181     try
182     {
183       OCC_CATCH_SIGNALS
184       aFileDriver->ReadReferenceType (aRef, aType);
185       anError = Storage_VSOk;
186     }
187     catch (Storage_StreamTypeMismatchError)
188     {
189       anError = Storage_VSTypeMismatch;
190     }
191
192     raiseOnStorageError (anError);
193
194     aReadData.CreatePersistentObject (aRef, anInstantiators (aType));
195   }
196
197   raiseOnStorageError (aFileDriver->EndReadRefSection());
198
199   // Read and parse data section
200   raiseOnStorageError (aFileDriver->BeginReadDataSection());
201
202   for (i = 1; i <= theHeaderData.NumberOfObjects(); i++)
203   {
204     Storage_Error anError;
205     try
206     {
207       OCC_CATCH_SIGNALS
208       aReadData.ReadPersistentObject (i);
209       anError = Storage_VSOk;
210     }
211     catch (Storage_StreamTypeMismatchError) { anError = Storage_VSTypeMismatch; }
212     catch (Storage_StreamFormatError      ) { anError = Storage_VSFormatError;  }
213     catch (Storage_StreamReadError        ) { anError = Storage_VSFormatError;  }
214
215     raiseOnStorageError (anError);
216   }
217
218   raiseOnStorageError (aFileDriver->EndReadDataSection());
219
220   // Get persistent document from the root object
221   return aReadData.PersistentObject (aRootData.Roots()->First()->Reference());
222 }
223
224 //=======================================================================
225 //function : Read
226 //purpose  : not implemented
227 //=======================================================================
228
229 void StdLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&               /*theIStream*/,
230                                                 const Handle(Storage_Data)&     /*theStorageData*/,
231                                                 const Handle(CDM_Document)&     /*theDoc*/,
232                                                 const Handle(CDM_Application)&  /*theApplication*/)
233 {
234   throw Standard_NotImplemented("Reading from stream is not supported by StdLDrivers_DocumentRetrievalDriver");
235 }
236
237 //=======================================================================
238 //function : raiseOnStorageError
239 //purpose  : Update the reader status and raise an exception
240 //           appropriate for the given storage error
241 //=======================================================================
242 void StdLDrivers_DocumentRetrievalDriver::raiseOnStorageError (Storage_Error theError)
243 {
244   Standard_SStream aMsg;
245
246   switch (theError)
247   {
248   case Storage_VSOk:
249     break;
250
251   case Storage_VSOpenError:
252   case Storage_VSNotOpen:
253   case Storage_VSAlreadyOpen:
254     myReaderStatus = PCDM_RS_OpenError;
255     aMsg << "Stream Open Error" << endl;
256     throw Standard_Failure(aMsg.str().c_str());
257
258   case Storage_VSModeError:
259     myReaderStatus = PCDM_RS_WrongStreamMode;
260     aMsg << "Stream is opened with a wrong mode for operation" << endl;
261     throw Standard_Failure(aMsg.str().c_str());
262
263   case Storage_VSSectionNotFound:
264     myReaderStatus = PCDM_RS_FormatFailure;
265     aMsg << "Section is not found" << endl;
266     throw Standard_Failure(aMsg.str().c_str());
267
268   case Storage_VSFormatError:
269     myReaderStatus = PCDM_RS_FormatFailure;
270     aMsg << "Wrong format error" << endl;
271     throw Standard_Failure(aMsg.str().c_str());
272
273   case Storage_VSUnknownType:
274     myReaderStatus = PCDM_RS_TypeFailure;
275     aMsg << "Try to read an unknown type" << endl;
276     throw Standard_Failure(aMsg.str().c_str());
277
278   case Storage_VSTypeMismatch:
279     myReaderStatus = PCDM_RS_TypeFailure;
280     aMsg << "Try to read a wrong primitive type" << endl;
281     throw Standard_Failure(aMsg.str().c_str());
282
283   default:
284     myReaderStatus = PCDM_RS_DriverFailure;
285     aMsg << "Retrieval Driver Failure" << endl;
286     throw Standard_Failure(aMsg.str().c_str());
287   }
288 }
289
290 //=======================================================================
291 //function : bindTypes
292 //purpose  : Register types
293 //=======================================================================
294 void StdLDrivers_DocumentRetrievalDriver::bindTypes (StdObjMgt_MapOfInstantiators& theMap)
295 {
296   StdLDrivers::BindTypes (theMap);
297 }