Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2001-07-09 |
2 | // Created by: Julia DOROVSKIKH | |
973c2be1 | 3 | // Copyright (c) 2001-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
7fd59977 | 16 | |
42cf5bc1 | 17 | #include <CDM_Application.hxx> |
18 | #include <CDM_Document.hxx> | |
19 | #include <CDM_MessageDriver.hxx> | |
20 | #include <CDM_NullMessageDriver.hxx> | |
21 | #include <LDOM_DocumentType.hxx> | |
22 | #include <LDOM_LDOMImplementation.hxx> | |
23 | #include <LDOM_XmlWriter.hxx> | |
24 | #include <OSD_Environment.hxx> | |
25 | #include <OSD_File.hxx> | |
26 | #include <OSD_OpenFile.hxx> | |
27 | #include <PCDM.hxx> | |
28 | #include <PCDM_ReadWriter.hxx> | |
29 | #include <Standard_ErrorHandler.hxx> | |
30 | #include <Standard_Failure.hxx> | |
31 | #include <Standard_Type.hxx> | |
32 | #include <Storage_Data.hxx> | |
33 | #include <TCollection_AsciiString.hxx> | |
34 | #include <TCollection_ExtendedString.hxx> | |
35 | #include <TColStd_SequenceOfAsciiString.hxx> | |
36 | #include <TDocStd_Document.hxx> | |
7fd59977 | 37 | #include <XmlLDrivers.hxx> |
42cf5bc1 | 38 | #include <XmlLDrivers_DocumentStorageDriver.hxx> |
7fd59977 | 39 | #include <XmlLDrivers_NamespaceDef.hxx> |
40 | #include <XmlMDF.hxx> | |
41 | #include <XmlMDF_ADriverTable.hxx> | |
7fd59977 | 42 | #include <XmlObjMgt.hxx> |
7fd59977 | 43 | #include <XmlObjMgt_Document.hxx> |
42cf5bc1 | 44 | #include <XmlObjMgt_SRelocationTable.hxx> |
7fd59977 | 45 | |
46 | #include <locale.h> | |
92efcf78 | 47 | IMPLEMENT_STANDARD_RTTIEXT(XmlLDrivers_DocumentStorageDriver,PCDM_StorageDriver) |
48 | ||
7fd59977 | 49 | #define STORAGE_VERSION "STORAGE_VERSION: " |
50 | #define REFERENCE_COUNTER "REFERENCE_COUNTER: " | |
51 | #define MODIFICATION_COUNTER "MODIFICATION_COUNTER: " | |
52 | #define START_REF "START_REF" | |
53 | #define END_REF "END_REF" | |
54 | ||
55 | #define FAILSTR "Failed to write xsi:schemaLocation : " | |
56 | ||
57 | //#define TAKE_TIMES | |
58 | static void take_time (const Standard_Integer, const char *, | |
59 | const Handle(CDM_MessageDriver)&) | |
60 | #ifdef TAKE_TIMES | |
61 | ; | |
62 | #else | |
63 | {} | |
64 | #endif | |
65 | ||
66 | //======================================================================= | |
67 | //function : XmlLDrivers_DocumentStorageDriver | |
68 | //purpose : Constructor | |
69 | //======================================================================= | |
70 | XmlLDrivers_DocumentStorageDriver::XmlLDrivers_DocumentStorageDriver | |
71 | (const TCollection_ExtendedString& theCopyright) | |
72 | : myCopyright (theCopyright) | |
73 | { | |
74 | } | |
75 | ||
7fd59977 | 76 | //======================================================================= |
77 | //function : AddNamespace | |
78 | //purpose : | |
79 | //======================================================================= | |
80 | ||
81 | void XmlLDrivers_DocumentStorageDriver::AddNamespace | |
82 | (const TCollection_AsciiString& thePrefix, | |
83 | const TCollection_AsciiString& theURI) | |
84 | { | |
85 | for (Standard_Integer i = 1; i <= mySeqOfNS.Length(); i++) | |
86 | if (thePrefix == mySeqOfNS(i).Prefix()) return; | |
87 | mySeqOfNS.Append (XmlLDrivers_NamespaceDef(thePrefix, theURI)); | |
88 | } | |
89 | ||
90 | //======================================================================= | |
91 | //function : Write | |
92 | //purpose : | |
93 | //======================================================================= | |
4ff92abe | 94 | void XmlLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theDocument, |
95 | const TCollection_ExtendedString& theFileName) | |
7fd59977 | 96 | { |
4ff92abe | 97 | myFileName = theFileName; |
98 | ||
99 | std::ofstream aFileStream; | |
100 | OSD_OpenStream (aFileStream, theFileName, std::ios::out); | |
101 | ||
102 | if (aFileStream.is_open() && aFileStream.good()) | |
103 | { | |
104 | Write (theDocument, aFileStream); | |
105 | } | |
106 | else | |
107 | { | |
108 | SetIsError (Standard_True); | |
109 | SetStoreStatus(PCDM_SS_WriteFailure); | |
110 | ||
111 | TCollection_ExtendedString aMsg = TCollection_ExtendedString("Error: the file ") + | |
112 | theFileName + " cannot be opened for writing"; | |
113 | ||
114 | theDocument->Application()->MessageDriver()->Write (aMsg.ToExtString()); | |
115 | Standard_Failure::Raise("File cannot be opened for writing"); | |
116 | } | |
117 | } | |
118 | ||
119 | //======================================================================= | |
120 | //function : Write | |
121 | //purpose : | |
122 | //======================================================================= | |
123 | Standard_EXPORT void XmlLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theDocument, | |
124 | Standard_OStream& theOStream) | |
125 | { | |
126 | Handle(CDM_MessageDriver) aMessageDriver = theDocument->Application()->MessageDriver(); | |
7fd59977 | 127 | ::take_time (~0, " +++++ Start STORAGE procedures ++++++", aMessageDriver); |
128 | ||
129 | // Create new DOM_Document | |
130 | XmlObjMgt_Document aDOMDoc = XmlObjMgt_Document::createDocument ("document"); | |
131 | ||
132 | // Fill the document with data | |
133 | XmlObjMgt_Element anElement = aDOMDoc.getDocumentElement(); | |
134 | ||
4ff92abe | 135 | if (WriteToDomDocument (theDocument, anElement) == Standard_False) { |
7fd59977 | 136 | |
4ff92abe | 137 | LDOM_XmlWriter aWriter; |
138 | aWriter.SetIndentation(1); | |
139 | ||
140 | if (theOStream.good()) | |
141 | { | |
142 | aWriter.Write (theOStream, aDOMDoc); | |
143 | } | |
144 | else | |
145 | { | |
15e8b082 | 146 | SetIsError (Standard_True); |
8e1e79f0 | 147 | SetStoreStatus(PCDM_SS_WriteFailure); |
4ff92abe | 148 | |
149 | TCollection_ExtendedString aMsg = TCollection_ExtendedString("Error: the stream is bad and") + | |
150 | " cannot be used for writing"; | |
151 | theDocument->Application()->MessageDriver()->Write (aMsg.ToExtString()); | |
152 | ||
153 | Standard_Failure::Raise("File cannot be opened for writing"); | |
7fd59977 | 154 | } |
4ff92abe | 155 | |
156 | ::take_time (0, " +++++ Fin formatting to XML : ", aMessageDriver); | |
7fd59977 | 157 | } |
7fd59977 | 158 | } |
159 | ||
160 | //======================================================================= | |
161 | //function : WriteToDomDocument | |
162 | //purpose : management of the macro-structure of XML document data | |
163 | //remark : If the application needs to use myRelocTable to store additional | |
164 | // data to XML, this method should be reimplemented avoiding step 3 | |
165 | //======================================================================= | |
166 | ||
4ff92abe | 167 | Standard_Boolean XmlLDrivers_DocumentStorageDriver::WriteToDomDocument (const Handle(CDM_Document)& theDocument, |
168 | XmlObjMgt_Element& theElement) | |
7fd59977 | 169 | { |
15e8b082 | 170 | SetIsError(Standard_False); |
7fd59977 | 171 | Handle(CDM_MessageDriver) aMessageDriver = |
172 | theDocument -> Application() -> MessageDriver(); | |
173 | // 1. Write header information | |
174 | Standard_Integer i; | |
175 | XmlObjMgt_Document aDOMDoc = theElement.getOwnerDocument(); | |
176 | ||
177 | // 1.a File Format | |
178 | TCollection_AsciiString aStorageFormat (theDocument->StorageFormat(), '?'); | |
179 | theElement.setAttribute ("format", aStorageFormat.ToCString()); | |
180 | // theElement.setAttribute ("schema", "XSD"); | |
181 | ||
182 | theElement.setAttribute ("xmlns" , "http://www.opencascade.org/OCAF/XML"); | |
183 | for (i = 1; i <= mySeqOfNS.Length(); i++) { | |
184 | TCollection_AsciiString aPrefix = | |
185 | TCollection_AsciiString("xmlns:") + mySeqOfNS(i).Prefix().ToCString(); | |
186 | theElement.setAttribute (aPrefix.ToCString(), | |
187 | mySeqOfNS(i).URI().ToCString()); | |
188 | } | |
189 | theElement.setAttribute ("xmlns:xsi", | |
190 | "http://www.w3.org/2001/XMLSchema-instance"); | |
191 | //mkv 15.09.05 OCC10001 | |
192 | //theElement.setAttribute ("xsi:schemaLocation", | |
193 | // "http://www.opencascade.org/OCAF/XML" | |
194 | // " http://www.nnov.matra-dtv.fr/~agv/XmlOcaf.xsd"); | |
195 | // | |
196 | // the order of search : by CSF_XmlOcafResource and then by CASROOT | |
197 | TCollection_AsciiString anHTTP = "http://www.opencascade.org/OCAF/XML"; | |
198 | Standard_Boolean aToSetCSFVariable = Standard_False; | |
199 | const char * aCSFVariable [2] = { | |
200 | "CSF_XmlOcafResource", | |
201 | "CASROOT" | |
202 | }; | |
742cc8b0 | 203 | OSD_Environment anEnv (aCSFVariable[0]); |
204 | TCollection_AsciiString aResourceDir = anEnv.Value(); | |
7fd59977 | 205 | if (aResourceDir.IsEmpty()) { |
206 | // now try by CASROOT | |
742cc8b0 | 207 | OSD_Environment anEnv2(aCSFVariable[1]); |
208 | aResourceDir = anEnv2.Value(); | |
7fd59977 | 209 | if ( !aResourceDir.IsEmpty() ) { |
210 | aResourceDir += "/src/XmlOcafResource" ; | |
211 | aToSetCSFVariable = Standard_True; //CSF variable to be set later | |
212 | } | |
0797d9d3 | 213 | #ifdef OCCT_DEBUG |
7fd59977 | 214 | else { |
215 | TCollection_ExtendedString aWarn = FAILSTR "Neither "; | |
216 | aWarn = (aWarn + aCSFVariable[0] + ", nor " + aCSFVariable[1] | |
217 | + " variables have been set"); | |
218 | aMessageDriver->Write (aWarn.ToExtString()); | |
219 | } | |
220 | #endif | |
221 | } | |
222 | if (!aResourceDir.IsEmpty()) { | |
223 | TCollection_AsciiString aResourceFileName = aResourceDir + "/XmlOcaf.xsd"; | |
224 | // search directory name that has been constructed, now check whether | |
225 | // it and the file exist | |
226 | OSD_File aResourceFile ( aResourceFileName ); | |
227 | if ( aResourceFile.Exists() ) { | |
228 | if (aToSetCSFVariable) { | |
229 | OSD_Environment aCSFVarEnv ( aCSFVariable[0], aResourceDir ); | |
230 | aCSFVarEnv.Build(); | |
0797d9d3 | 231 | #ifdef OCCT_DEBUG |
7fd59977 | 232 | TCollection_ExtendedString aWarn1 = "Variable "; |
233 | aWarn1 = (aWarn1 + aCSFVariable[0] | |
234 | + " has not been explicitly defined. Set to " + aResourceDir); | |
235 | aMessageDriver->Write (aWarn1.ToExtString()); | |
236 | #endif | |
237 | if ( aCSFVarEnv.Failed() ) { | |
238 | TCollection_ExtendedString aWarn = FAILSTR "Failed to initialize "; | |
239 | aWarn = aWarn + aCSFVariable[0] + " with " + aResourceDir; | |
240 | aMessageDriver->Write (aWarn.ToExtString()); | |
241 | } | |
242 | } | |
243 | } | |
0797d9d3 | 244 | #ifdef OCCT_DEBUG |
7fd59977 | 245 | else { |
246 | TCollection_ExtendedString aWarn = FAILSTR "Schema definition file "; | |
247 | aWarn += (aResourceFileName + " was not found"); | |
248 | aMessageDriver->Write (aWarn.ToExtString()); | |
249 | } | |
250 | #endif | |
251 | anHTTP = anHTTP + ' ' + aResourceFileName; | |
252 | } | |
253 | theElement.setAttribute ("xsi:schemaLocation", anHTTP.ToCString() ); | |
254 | ||
255 | // 1.b Info section | |
256 | XmlObjMgt_Element anInfoElem = aDOMDoc.createElement("info"); | |
257 | theElement.appendChild(anInfoElem); | |
258 | ||
259 | TCollection_AsciiString aCreationDate = XmlLDrivers::CreationDate(); | |
260 | ||
261 | // anInfoElem.setAttribute("dbv", 0); | |
262 | anInfoElem.setAttribute("date", aCreationDate.ToCString()); | |
263 | anInfoElem.setAttribute("schemav", 0); | |
264 | // anInfoElem.setAttribute("appv", anAppVersion.ToCString()); | |
265 | ||
266 | // Document version | |
267 | anInfoElem.setAttribute("DocVersion", XmlLDrivers::StorageVersion().ToCString()); | |
268 | ||
269 | // User info with Copyright | |
270 | TColStd_SequenceOfAsciiString aUserInfo; | |
271 | if (myCopyright.Length() > 0) | |
272 | aUserInfo.Append (TCollection_AsciiString(myCopyright,'?')); | |
273 | ||
274 | Handle(Storage_Data) theData = new Storage_Data; | |
275 | //PCDM_ReadWriter::WriteFileFormat( theData, theDocument ); | |
276 | PCDM_ReadWriter::Writer()->WriteReferenceCounter(theData,theDocument); | |
4ff92abe | 277 | PCDM_ReadWriter::Writer()->WriteReferences(theData,theDocument, myFileName); |
7fd59977 | 278 | PCDM_ReadWriter::Writer()->WriteExtensions(theData,theDocument); |
279 | PCDM_ReadWriter::Writer()->WriteVersion(theData,theDocument); | |
280 | ||
281 | const TColStd_SequenceOfAsciiString& aRefs = theData->UserInfo(); | |
282 | for(i = 1; i <= aRefs.Length(); i++) | |
283 | aUserInfo.Append(aRefs.Value(i)); | |
284 | ||
285 | for (i = 1; i <= aUserInfo.Length(); i++) | |
286 | { | |
287 | XmlObjMgt_Element aUIItem = aDOMDoc.createElement ("iitem"); | |
288 | anInfoElem.appendChild (aUIItem); | |
289 | LDOM_Text aUIText = aDOMDoc.createTextNode (aUserInfo(i).ToCString()); | |
290 | aUIItem.appendChild (aUIText); | |
291 | } | |
292 | ||
293 | // 1.c Comments section | |
294 | TColStd_SequenceOfExtendedString aComments; | |
295 | theDocument->Comments(aComments); | |
296 | ||
297 | XmlObjMgt_Element aCommentsElem = aDOMDoc.createElement ("comments"); | |
298 | theElement.appendChild (aCommentsElem); | |
299 | ||
300 | for (i = 1; i <= aComments.Length(); i++) | |
301 | { | |
302 | XmlObjMgt_Element aCItem = aDOMDoc.createElement ("citem"); | |
303 | aCommentsElem.appendChild (aCItem); | |
304 | XmlObjMgt::SetExtendedString (aCItem, aComments(i)); | |
305 | } | |
306 | ||
307 | // 2a. Write document contents | |
308 | Standard_Integer anObjNb = 0; | |
309 | { | |
310 | try | |
311 | { | |
312 | OCC_CATCH_SIGNALS | |
313 | anObjNb = MakeDocument(theDocument, theElement); | |
314 | } | |
315 | catch (Standard_Failure) | |
316 | { | |
15e8b082 | 317 | SetIsError (Standard_True); |
8e1e79f0 | 318 | SetStoreStatus(PCDM_SS_Failure); |
7fd59977 | 319 | TCollection_ExtendedString anErrorString (Standard_Failure::Caught()->GetMessageString()); |
320 | aMessageDriver -> Write (anErrorString.ToExtString()); | |
321 | } | |
322 | } | |
15e8b082 M |
323 | if (anObjNb <= 0 && IsError() == Standard_False) { |
324 | SetIsError (Standard_True); | |
8e1e79f0 | 325 | SetStoreStatus(PCDM_SS_No_Obj); |
7fd59977 | 326 | TCollection_ExtendedString anErrorString ("error occurred"); |
327 | aMessageDriver -> Write (anErrorString.ToExtString()); | |
328 | } | |
329 | // 2b. Write number of objects into the info section | |
330 | anInfoElem.setAttribute("objnb", anObjNb); | |
331 | ::take_time (0, " +++++ Fin DOM data for OCAF : ", aMessageDriver); | |
332 | ||
333 | // 3. Clear relocation table | |
334 | // If the application needs to use myRelocTable to store additional | |
335 | // data to XML, this method should be reimplemented avoiding this step | |
336 | myRelocTable.Clear(); | |
337 | ||
338 | // 4. Write Shapes section | |
339 | if(WriteShapeSection(theElement)) | |
340 | ::take_time (0, " +++ Fin DOM data for Shapes : ", aMessageDriver); | |
15e8b082 | 341 | return IsError(); |
7fd59977 | 342 | } |
343 | ||
344 | //======================================================================= | |
345 | //function : MakeDocument | |
346 | //purpose : | |
347 | //======================================================================= | |
348 | Standard_Integer XmlLDrivers_DocumentStorageDriver::MakeDocument | |
349 | (const Handle(CDM_Document)& theTDoc, | |
350 | XmlObjMgt_Element& theElement) | |
351 | { | |
352 | TCollection_ExtendedString aMessage; | |
353 | Handle(TDocStd_Document) TDOC = Handle(TDocStd_Document)::DownCast(theTDoc); | |
354 | myRelocTable.Clear(); | |
355 | if (!TDOC.IsNull()) | |
356 | { | |
357 | // myRelocTable.SetDocument (theElement.getOwnerDocument()); | |
358 | Handle(TDF_Data) aTDF = TDOC->GetData(); | |
359 | ||
360 | // Find MessageDriver and pass it to AttributeDrivers() | |
361 | Handle(CDM_Application) anApplication= theTDoc -> Application(); | |
362 | Handle(CDM_MessageDriver) aMessageDriver; | |
363 | if (anApplication.IsNull()) | |
364 | aMessageDriver = new CDM_NullMessageDriver; | |
365 | else | |
366 | aMessageDriver = anApplication -> MessageDriver(); | |
367 | if (myDrivers.IsNull()) myDrivers = AttributeDrivers (aMessageDriver); | |
368 | ||
369 | // Retrieve from DOM_Document | |
370 | XmlMDF::FromTo (aTDF, theElement, myRelocTable, myDrivers); | |
0797d9d3 | 371 | #ifdef OCCT_DEBUG |
7fd59977 | 372 | aMessage = "First step successfull"; |
373 | aMessageDriver -> Write (aMessage.ToExtString()); | |
374 | #endif | |
375 | return myRelocTable.Extent(); | |
376 | } | |
0797d9d3 | 377 | #ifdef OCCT_DEBUG |
7fd59977 | 378 | cout << "First step failed" << endl; // No MessageDriver available |
379 | #endif | |
380 | return -1; // error | |
381 | } | |
382 | ||
7fd59977 | 383 | //======================================================================= |
384 | //function : AttributeDrivers | |
385 | //purpose : | |
386 | //======================================================================= | |
387 | Handle(XmlMDF_ADriverTable) XmlLDrivers_DocumentStorageDriver::AttributeDrivers | |
388 | (const Handle(CDM_MessageDriver)& theMessageDriver) | |
389 | { | |
390 | return XmlLDrivers::AttributeDrivers (theMessageDriver); | |
391 | } | |
392 | ||
393 | //======================================================================= | |
394 | //function : take_time | |
395 | //class : static | |
396 | //purpose : output astronomical time elapsed | |
397 | //======================================================================= | |
398 | #ifdef TAKE_TIMES | |
399 | #include <time.h> | |
400 | #include <sys/timeb.h> | |
401 | #include <sys/types.h> | |
402 | #include <stdio.h> | |
57c28b61 | 403 | #ifndef _WIN32 |
7fd59977 | 404 | extern "C" int ftime (struct timeb *tp); |
405 | #endif | |
406 | struct timeb tmbuf0; | |
407 | ||
408 | static void take_time (const Standard_Integer isReset, const char * aHeader, | |
409 | const Handle(CDM_MessageDriver)& aMessageDriver) | |
410 | { | |
411 | struct timeb tmbuf; | |
412 | ftime (&tmbuf); | |
413 | TCollection_ExtendedString aMessage ((Standard_CString)aHeader); | |
414 | if (isReset) tmbuf0 = tmbuf; | |
415 | else { | |
416 | char take_tm_buf [64]; | |
91322f44 | 417 | Sprintf (take_tm_buf, "%9.2f s ++++", |
7fd59977 | 418 | double(tmbuf.time - tmbuf0.time) + |
419 | double(tmbuf.millitm - tmbuf0.millitm)/1000.); | |
420 | aMessage += take_tm_buf; | |
421 | } | |
422 | aMessageDriver -> Write (aMessage.ToExtString()); | |
423 | } | |
424 | #endif | |
425 | ||
426 | //======================================================================= | |
427 | //function : WriteShapeSection | |
428 | //purpose : defines WriteShapeSection | |
429 | //======================================================================= | |
430 | Standard_Boolean XmlLDrivers_DocumentStorageDriver::WriteShapeSection | |
431 | (XmlObjMgt_Element& /*theElement*/) | |
432 | { | |
433 | // empty; should be redefined in subclasses | |
434 | return Standard_False; | |
435 | } | |
436 |