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