1 // Created on: 2001-07-09
2 // Created by: Julia DOROVSKIKH
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <CDM_Application.hxx>
18 #include <CDM_Document.hxx>
19 #include <CDM_MessageDriver.hxx>
20 #include <CDM_MetaData.hxx>
21 #include <LDOM_DocumentType.hxx>
22 #include <LDOM_LDOMImplementation.hxx>
23 #include <LDOMParser.hxx>
24 #include <OSD_Path.hxx>
25 #include <PCDM_Document.hxx>
26 #include <Standard_Type.hxx>
27 #include <TCollection_AsciiString.hxx>
28 #include <TCollection_ExtendedString.hxx>
29 #include <TDF_Data.hxx>
30 #include <TDocStd_Document.hxx>
31 #include <TDocStd_Owner.hxx>
33 #include <XmlLDrivers.hxx>
34 #include <XmlLDrivers_DocumentRetrievalDriver.hxx>
35 #include <XmlMDataStd.hxx>
37 #include <XmlMDF_ADriver.hxx>
38 #include <XmlMDF_ADriverTable.hxx>
39 #include <XmlObjMgt.hxx>
40 #include <XmlObjMgt_Document.hxx>
41 #include <XmlObjMgt_RRelocationTable.hxx>
48 #include <Standard_Failure.hxx>
49 #include <Standard_ErrorHandler.hxx>
51 #define START_REF "START_REF"
52 #define END_REF "END_REF"
53 #define REFERENCE_COUNTER "REFERENCE_COUNTER"
56 static void take_time (const Standard_Integer, const char *,
57 const Handle(CDM_MessageDriver)&)
64 static Standard_Integer RemoveExtraSeparator(TCollection_AsciiString& aString) {
66 Standard_Integer i, j, len ;
68 len = aString.Length() ;
70 // Case of network path, such as \\MACHINE\dir
71 for (i = j = 2 ; j <= len ; i++,j++) {
73 for (i = j = 1 ; j <= len ; i++,j++) {
75 Standard_Character c = aString.Value(j) ;
76 aString.SetValue(i,c) ;
78 while(j < len && aString.Value(j+1) == '/') j++ ;
81 if (aString.Value(len) == '/') len-- ;
85 static TCollection_AsciiString GetDirFromFile(const TCollection_ExtendedString& aFileName) {
86 TCollection_AsciiString theCFile=UTL::CString(aFileName);
87 TCollection_AsciiString theDirectory;
88 Standard_Integer i=theCFile.SearchFromEnd("/");
90 // if(i==-1) i=theCFile.SearchFromEnd("\\");
91 if(theCFile.SearchFromEnd("\\") > i)
92 i=theCFile.SearchFromEnd("\\");
94 if(i!=-1) theDirectory=theCFile.SubString(1,i);
98 static TCollection_AsciiString AbsolutePath(
99 const TCollection_AsciiString& aDirPath,
100 const TCollection_AsciiString& aRelFilePath)
102 TCollection_AsciiString EmptyString = "" ;
104 if (aRelFilePath.Search(":") == 2 ||
105 (aRelFilePath.Search("\\") == 1 && aRelFilePath.Value(2) == '\\'))
107 if(aRelFilePath.Search("/") == 1)
109 return aRelFilePath ;
111 TCollection_AsciiString DirPath = aDirPath, RelFilePath = aRelFilePath ;
112 Standard_Integer i,len ;
115 if(DirPath.Search(":") != 2 &&
116 (DirPath.Search("\\") != 1 || DirPath.Value(2) != '\\'))
118 if (DirPath.Search("/") != 1 )
123 DirPath.ChangeAll('\\','/') ;
124 RelFilePath.ChangeAll('\\','/') ;
127 RemoveExtraSeparator(DirPath) ;
128 len = RemoveExtraSeparator(RelFilePath) ;
130 while (RelFilePath.Search("../") == 1) {
133 RelFilePath = RelFilePath.SubString(4,len) ;
135 if (DirPath.IsEmpty())
137 i = DirPath.SearchFromEnd("/") ;
142 TCollection_AsciiString retx;
149 //=======================================================================
150 //function : XmlLDrivers_DocumentRetrievalDriver
151 //purpose : Constructor
152 //=======================================================================
153 XmlLDrivers_DocumentRetrievalDriver::XmlLDrivers_DocumentRetrievalDriver()
155 myReaderStatus = PCDM_RS_OK;
158 //=======================================================================
159 //function : CreateDocument
160 //purpose : pure virtual method definition
161 //=======================================================================
162 Handle(CDM_Document) XmlLDrivers_DocumentRetrievalDriver::CreateDocument()
164 return new TDocStd_Document(PCDM_RetrievalDriver::GetFormat());
167 //=======================================================================
168 //function : SchemaName
169 //purpose : pure virtual method definition
170 //=======================================================================
171 TCollection_ExtendedString XmlLDrivers_DocumentRetrievalDriver::SchemaName() const
173 TCollection_ExtendedString schemaname;
177 //=======================================================================
179 //purpose : pure virtual method definition
180 //=======================================================================
181 void XmlLDrivers_DocumentRetrievalDriver::Make (const Handle(PCDM_Document)&,
182 const Handle(CDM_Document)&)
186 //=======================================================================
189 //=======================================================================
190 void XmlLDrivers_DocumentRetrievalDriver::Read
191 (const TCollection_ExtendedString& theFileName,
192 const Handle(CDM_Document)& theNewDocument,
193 const Handle(CDM_Application)& theApplication)
195 myReaderStatus = PCDM_RS_DriverFailure;
196 myFileName = theFileName;
197 Handle(CDM_MessageDriver) aMessageDriver = theApplication -> MessageDriver();
198 ::take_time (~0, " +++++ Start RETRIEVE procedures ++++++", aMessageDriver);
200 // 1. Read DOM_Document from file
202 TCollection_AsciiString aName (theFileName,'?');
203 if (aParser.parse(aName.ToCString()))
205 TCollection_AsciiString aData;
206 cout << aParser.GetError(aData) << ": " << aData << endl;
207 myReaderStatus = PCDM_RS_FormatFailure;
210 const XmlObjMgt_Element anElement= aParser.getDocument().getDocumentElement();
211 ::take_time (0, " +++++ Fin parsing XML : ", aMessageDriver);
213 ReadFromDomDocument (anElement, theNewDocument, theApplication);
216 //=======================================================================
217 //function : ReadFromDomDocument
218 //purpose : management of the macro-structure of XML document data
219 //remark : If the application needs to use myRelocTable to retrieve additional
220 // data from LDOM, this method should be reimplemented
221 //=======================================================================
223 void XmlLDrivers_DocumentRetrievalDriver::ReadFromDomDocument
224 (const XmlObjMgt_Element& theElement,
225 const Handle(CDM_Document)& theNewDocument,
226 const Handle(CDM_Application)& theApplication)
228 const Handle(CDM_MessageDriver) aMsgDriver =
229 theApplication -> MessageDriver();
230 // 1. Read info // to be done
231 TCollection_AsciiString anAbsoluteDirectory = GetDirFromFile(myFileName);
232 Standard_Integer aCurDocVersion = 0;
233 TCollection_ExtendedString anInfo;
234 const XmlObjMgt_Element anInfoElem =
235 theElement.GetChildByTagName ("info");
236 if (anInfoElem != NULL) {
237 XmlObjMgt_DOMString aDocVerStr = anInfoElem.getAttribute("DocVersion");
238 if(aDocVerStr == NULL)
240 else if (!aDocVerStr.GetInteger(aCurDocVersion)) {
241 TCollection_ExtendedString aMsg =
242 TCollection_ExtendedString ("Cannot retrieve the current Document version"
243 " attribute as \"") + aDocVerStr + "\"";
244 if(!aMsgDriver.IsNull())
245 aMsgDriver->Write(aMsg.ToExtString());
248 // oan: OCC22305 - check a document verison and if it's greater than
249 // current version of storage driver set an error status and return
250 if( aCurDocVersion > XmlLDrivers::StorageVersion().IntegerValue() )
252 TCollection_ExtendedString aMsg =
253 TCollection_ExtendedString ("error: wrong file version: ") +
254 aDocVerStr + " while current is " +
255 XmlLDrivers::StorageVersion();
256 myReaderStatus = PCDM_RS_NoVersion;
257 if(!aMsgDriver.IsNull())
258 aMsgDriver->Write(aMsg.ToExtString());
262 if( aCurDocVersion < 2) aCurDocVersion = 2;
264 PropagateDocumentVersion(aCurDocVersion);
266 Standard_Boolean isRef = Standard_False;
267 for (LDOM_Node aNode = anInfoElem.getFirstChild();
268 aNode != NULL; aNode = aNode.getNextSibling()) {
269 if (aNode.getNodeType() == LDOM_Node::ELEMENT_NODE) {
270 if (XmlObjMgt::GetExtendedString ((LDOM_Element&)aNode, anInfo)) {
273 if(anInfo.Search(REFERENCE_COUNTER) != -1) {
276 TCollection_AsciiString anInf(anInfo,'?');
277 //Standard_Integer aRefCounter = anInf.Token(" ",2).IntegerValue();
278 //theNewDocument->SetReferenceCounter(aRefCounter);
280 catch (Standard_Failure) {
281 // cout << "warning: could not read the reference counter in " << aFileName << endl;
282 TCollection_ExtendedString aMsg("Warning: ");
283 aMsg = aMsg.Cat("could not read the reference counter").Cat("\0");
284 if(!aMsgDriver.IsNull())
285 aMsgDriver->Write(aMsg.ToExtString());
289 if(anInfo == END_REF)
290 isRef = Standard_False;
291 if(isRef) { // Process References
293 Standard_Integer pos=anInfo.Search(" ");
295 // Parce RefId, DocumentVersion and FileName
296 Standard_Integer aRefId;
297 TCollection_ExtendedString aFileName;
298 Standard_Integer aDocumentVersion;
301 TCollection_ExtendedString aRest=anInfo.Split(pos);
302 aRefId = UTL::IntegerValue(anInfo);
304 Standard_Integer pos2 = aRest.Search(" ");
306 aFileName = aRest.Split(pos2);
307 aDocumentVersion = UTL::IntegerValue(aRest);
309 TCollection_AsciiString aPath = UTL::CString(aFileName);
310 TCollection_AsciiString anAbsolutePath;
311 if(!anAbsoluteDirectory.IsEmpty()) {
312 anAbsolutePath = AbsolutePath(anAbsoluteDirectory,aPath);
313 if(!anAbsolutePath.IsEmpty()) aPath=anAbsolutePath;
315 if(!aMsgDriver.IsNull()) {
316 // cout << "reference found; ReferenceIdentifier: " << theReferenceIdentifier << "; File:" << thePath << ", version:" << theDocumentVersion;
317 TCollection_ExtendedString aMsg("Warning: ");
318 aMsg = aMsg.Cat("reference found; ReferenceIdentifier: ").Cat(aRefId).Cat("; File:").Cat(aPath).Cat(", version:").Cat(aDocumentVersion).Cat("\0");
319 aMsgDriver->Write(aMsg.ToExtString());
323 TCollection_ExtendedString theFolder,theName;
324 //TCollection_ExtendedString theFile=myReferences(myIterator).FileName();
325 TCollection_ExtendedString f(aPath);
328 Standard_Integer i= f.SearchFromEnd("/");
329 TCollection_ExtendedString n = f.Split(i);
330 f.Trunc(f.Length()-1);
334 OSD_Path p = UTL::Path(f);
335 Standard_ExtCharacter chr;
336 TCollection_ExtendedString dir, dirRet, name;
341 for ( int i = 1; i <= dir.Length (); ++i ) {
343 chr = dir.Value ( i );
348 dirRet += _TEXT( "/" );
353 dirRet += _TEXT( ".." );
362 theName = UTL::Name(p); theName+= UTL::Extension(p);
365 Handle(CDM_MetaData) aMetaData = CDM_MetaData::LookUp(theFolder,theName,aPath,aPath,UTL::IsReadOnly(aFileName));
367 theNewDocument->CreateReference(aMetaData,aRefId,
368 theApplication,aDocumentVersion,Standard_False);
375 if(anInfo == START_REF)
376 isRef = Standard_True;
383 TCollection_ExtendedString aComment;
384 const XmlObjMgt_Element aCommentsElem =
385 theElement.GetChildByTagName ("comments");
386 if (aCommentsElem != NULL)
388 for (LDOM_Node aNode = aCommentsElem.getFirstChild();
389 aNode != NULL; aNode = aNode.getNextSibling())
391 if (aNode.getNodeType() == LDOM_Node::ELEMENT_NODE)
393 if (XmlObjMgt::GetExtendedString ((LDOM_Element&)aNode, aComment))
395 theNewDocument->AddComment(aComment);
401 // 2. Read Shapes section
402 if (myDrivers.IsNull()) myDrivers = AttributeDrivers (aMsgDriver);
403 const Handle(XmlMDF_ADriver) aNSDriver = ReadShapeSection(theElement, aMsgDriver);
404 if(!aNSDriver.IsNull())
405 ::take_time (0, " +++++ Fin reading Shapes : ", aMsgDriver);
407 // 5. Read document contents
412 TCollection_ExtendedString aMessage ("PasteDocument");
413 aMsgDriver -> Write (aMessage.ToExtString());
415 if (!MakeDocument(theElement, theNewDocument))
416 myReaderStatus = PCDM_RS_MakeFailure;
418 myReaderStatus = PCDM_RS_OK;
420 catch (Standard_Failure)
422 TCollection_ExtendedString anErrorString (Standard_Failure::Caught()->GetMessageString());
423 aMsgDriver -> Write (anErrorString.ToExtString());
426 // Wipe off the shapes written to the <shapes> section
427 ShapeSetCleaning(aNSDriver);
429 // Clean the relocation table.
430 // If the application needs to use myRelocTable to retrieve additional
431 // data from LDOM, this method should be reimplemented avoiding this step
432 myRelocTable.Clear();
433 ::take_time (0, " +++++ Fin reading data OCAF : ", aMsgDriver);
436 //=======================================================================
437 //function : MakeDocument
439 //=======================================================================
440 Standard_Boolean XmlLDrivers_DocumentRetrievalDriver::MakeDocument
441 (const XmlObjMgt_Element& theElement,
442 const Handle(CDM_Document)& theTDoc)
444 Standard_Boolean aResult = Standard_False;
445 Handle(TDocStd_Document) TDOC = Handle(TDocStd_Document)::DownCast(theTDoc);
446 myRelocTable.Clear();
449 Handle(TDF_Data) aTDF = new TDF_Data();
450 aResult = XmlMDF::FromTo (theElement, aTDF, myRelocTable, myDrivers);
452 TDOC->SetData (aTDF);
453 TDocStd_Owner::SetDocument (aTDF, TDOC);
459 //=======================================================================
460 //function : AttributeDrivers
462 //=======================================================================
463 Handle(XmlMDF_ADriverTable) XmlLDrivers_DocumentRetrievalDriver::AttributeDrivers
464 (const Handle(CDM_MessageDriver)& theMessageDriver)
466 return XmlLDrivers::AttributeDrivers (theMessageDriver);
469 //=======================================================================
470 //function : take_time
472 //purpose : output astronomical time elapsed
473 //=======================================================================
476 #include <sys/timeb.h>
477 #include <sys/types.h>
480 extern "C" int ftime (struct timeb *tp);
482 extern struct timeb tmbuf0;
484 static void take_time (const Standard_Integer isReset, const char * aHeader,
485 const Handle(CDM_MessageDriver)& aMessageDriver)
489 TCollection_ExtendedString aMessage ((Standard_CString)aHeader);
490 if (isReset) tmbuf0 = tmbuf;
492 char take_tm_buf [64];
493 Sprintf (take_tm_buf, "%9.2f s ++++",
494 double(tmbuf.time - tmbuf0.time) +
495 double(tmbuf.millitm - tmbuf0.millitm)/1000.);
496 aMessage += take_tm_buf;
498 aMessageDriver -> Write (aMessage.ToExtString());
502 //=======================================================================
503 //function : PropagateDocumentVersion
505 //=======================================================================
506 void XmlLDrivers_DocumentRetrievalDriver::PropagateDocumentVersion(
507 const Standard_Integer theDocVersion )
509 XmlMDataStd::SetDocumentVersion(theDocVersion);
512 //=======================================================================
513 //function : ReadShapeSection
514 //purpose : definition of ReadShapeSection
515 //=======================================================================
516 Handle(XmlMDF_ADriver) XmlLDrivers_DocumentRetrievalDriver::ReadShapeSection(
517 const XmlObjMgt_Element& /*theElement*/,
518 const Handle(CDM_MessageDriver)& /*aMsgDriver*/)
520 Handle(XmlMDF_ADriver) aDriver;
521 //empty; to be redefined
525 //=======================================================================
526 //function : ShapeSetCleaning
527 //purpose : definition of ShapeSetCleaning
528 //=======================================================================
529 void XmlLDrivers_DocumentRetrievalDriver::ShapeSetCleaning(
530 const Handle(XmlMDF_ADriver)& /*theDriver*/)