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 <Message_Messenger.hxx>
18 #include <Message_ProgressScope.hxx>
19 #include <Storage_Schema.hxx>
20 #include <TColStd_MapOfTransient.hxx>
21 #include <TDF_AttributeIterator.hxx>
22 #include <TDF_ChildIterator.hxx>
23 #include <TDF_Data.hxx>
24 #include <TDF_Label.hxx>
25 #include <TDF_Tool.hxx>
27 #include <XmlMDF_ADriver.hxx>
28 #include <XmlMDF_ADriverTable.hxx>
29 #include <XmlMDF_ReferenceDriver.hxx>
30 #include <XmlMDF_TagSourceDriver.hxx>
31 #include <XmlObjMgt_Document.hxx>
32 #include <XmlObjMgt_Persistent.hxx>
33 #include <TDocStd_Owner.hxx>
34 #include <TDocStd_Document.hxx>
35 #include <Standard_GUID.hxx>
37 IMPLEMENT_DOMSTRING (TagString, "tag")
38 IMPLEMENT_DOMSTRING (LabelString, "label")
39 #define DATATYPE_MIGRATION
40 //#define DATATYPE_MIGRATION_DEB
41 //=======================================================================
42 //function : UnsuppTypesMap
44 //=======================================================================
46 static TColStd_MapOfTransient& UnsuppTypesMap ()
48 static TColStd_MapOfTransient anUnsuppTypes;
52 //=======================================================================
54 //purpose : Paste transient data into DOM_Element
55 //=======================================================================
56 void XmlMDF::FromTo (const Handle(TDF_Data)& theData,
57 XmlObjMgt_Element& theElement,
58 XmlObjMgt_SRelocationTable& theRelocTable,
59 const Handle(XmlMDF_ADriverTable)& theDrivers,
60 const Message_ProgressRange& theRange)
62 UnsuppTypesMap().Clear();
63 // Standard_Integer count =
64 WriteSubTree(theData->Root(), theElement, theRelocTable, theDrivers, theRange);
65 UnsuppTypesMap().Clear();
68 //=======================================================================
69 //function : WriteSubTree
71 //=======================================================================
72 Standard_Integer XmlMDF::WriteSubTree
73 (const TDF_Label& theLabel,
74 XmlObjMgt_Element& theElement,
75 XmlObjMgt_SRelocationTable& theRelocTable,
76 const Handle(XmlMDF_ADriverTable)& theDrivers,
77 const Message_ProgressRange& theRange)
79 XmlObjMgt_Document aDoc = theElement.getOwnerDocument();
81 // create element "label"
82 XmlObjMgt_Element aLabElem = aDoc.createElement (::LabelString());
85 Standard_Integer count = 0;
86 TDF_AttributeIterator itr1 (theLabel);
87 for ( ; itr1.More(); itr1.Next())
89 const Handle(TDF_Attribute)& tAtt = itr1.Value();
90 const Handle(Standard_Type)& aType = tAtt->DynamicType();
91 Handle(XmlMDF_ADriver) aDriver;
92 if (theDrivers->GetDriver(aType, aDriver))
96 // Add source to relocation table
97 Standard_Integer anId = theRelocTable.Add (tAtt);
99 // Create DOM data item
100 XmlObjMgt_Persistent pAtt;
101 // In the document version 8 the attribute TPrsStd_AISPresentation
102 // was replaced by TDataXtd_Presentation. Therefore, for old versions
103 // we write old name of the attribute (TPrsStd_AISPresentation).
104 Standard_CString typeName = aDriver->TypeName().ToCString();
105 if (theRelocTable.GetHeaderData()->StorageVersion().IntegerValue() < TDocStd_FormatVersion_VERSION_8 &&
106 strcmp(typeName, "TDataXtd_Presentation") == 0)
108 typeName = "TPrsStd_AISPresentation";
110 pAtt.CreateElement (aLabElem, typeName, anId);
113 aDriver -> Paste (tAtt, pAtt, theRelocTable);
116 else if (!UnsuppTypesMap().Contains (aType))
118 std::cout << "attribute driver for type "<< aType -> Name()<< " not found"<< std::endl;
119 UnsuppTypesMap().Add (aType);
125 TDF_ChildIterator itr2 (theLabel);
126 Standard_Real child_count = 0;
127 for (; itr2.More(); ++child_count, itr2.Next())
130 itr2.Initialize(theLabel);
131 Message_ProgressScope aPS(theRange, "Writing sub-tree", child_count, true);
132 for ( ; itr2.More() && aPS.More(); itr2.Next())
134 const TDF_Label& aChildLab = itr2.Value();
135 count += WriteSubTree(aChildLab, aLabElem, theRelocTable, theDrivers, aPS.Next());
138 if (count > 0 || TDocStd_Owner::GetDocument(theLabel.Data())->EmptyLabelsSavingMode())
140 theElement.appendChild(aLabElem);
142 // set attribute "tag"
143 aLabElem.setAttribute (::TagString(), theLabel.Tag());
148 //=======================================================================
150 //purpose : Paste data from DOM_Element into transient document
151 //=======================================================================
152 Standard_Boolean XmlMDF::FromTo (const XmlObjMgt_Element& theElement,
153 Handle(TDF_Data)& theData,
154 XmlObjMgt_RRelocationTable& theRelocTable,
155 const Handle(XmlMDF_ADriverTable)& theDrivers,
156 const Message_ProgressRange& theRange)
158 TDF_Label aRootLab = theData->Root();
159 XmlMDF_MapOfDriver aDriverMap;
160 theDrivers->CreateDrvMap (aDriverMap);
162 Standard_Integer count = 0;
164 LDOM_Node theNode = theElement.getFirstChild();
165 XmlObjMgt_Element anElem = (const XmlObjMgt_Element&)theNode;
166 while ( !anElem.isNull() )
168 if ( anElem.getNodeName().equals (::LabelString()) )
170 Standard_Integer subcount =
171 ReadSubTree(anElem, aRootLab, theRelocTable, aDriverMap, theRange);
174 return Standard_False;
176 (void )count; // unused but set for debug
179 //anElem = (const XmlObjMgt_Element &) anElem.getNextSibling();
180 LDOM_Node theNode1 = anElem.getNextSibling();
181 anElem = (const XmlObjMgt_Element &) theNode1;
184 return Standard_True;
187 //=======================================================================
188 //function : ReadSubTree
190 //=======================================================================
191 Standard_Integer XmlMDF::ReadSubTree (const XmlObjMgt_Element& theElement,
192 const TDF_Label& theLabel,
193 XmlObjMgt_RRelocationTable& theRelocTable,
194 const XmlMDF_MapOfDriver& theDriverMap,
195 const Message_ProgressRange& theRange)
197 // Extraction of the driver subset.
198 Standard_Integer count = 0;
200 //XmlObjMgt_Element anElem = (const XmlObjMgt_Element &) theElement.getFirstChild();
201 LDOM_Node theNode = theElement.getFirstChild();
202 XmlObjMgt_Element anElem = (const XmlObjMgt_Element &) theNode;
203 Message_ProgressScope aPS(theRange, "Reading sub-tree", 2, true);
204 while ( !anElem.isNull() )
206 if ( anElem.getNodeType() == LDOM_Node::ELEMENT_NODE )
208 if ( anElem.getNodeName().equals (::LabelString()) )
211 Standard_Integer tag;
212 XmlObjMgt_DOMString aTag (anElem.getAttribute(::TagString()));
213 if ( !aTag.GetInteger (tag) ) {
214 TCollection_ExtendedString anErrorMessage =
215 TCollection_ExtendedString ("Wrong Tag value for OCAF Label: ")
217 theDriverMap.Find("TDF_TagSource") -> myMessageDriver->Send (anErrorMessage, Message_Fail);
221 TDF_Label aLab = theLabel.FindChild(tag, Standard_True);
224 Standard_Integer subcount =
225 ReadSubTree(anElem, aLab, theRelocTable, theDriverMap, aPS.Next());
234 XmlObjMgt_DOMString aName = anElem.getNodeName();
236 #ifdef DATATYPE_MIGRATION
237 TCollection_AsciiString newName;
238 if(Storage_Schema::CheckTypeMigration(aName, newName)) {
240 std::cout << "CheckTypeMigration:OldType = " <<aName.GetString() << " Len = "<<strlen(aName.GetString())<<std::endl;
241 std::cout << "CheckTypeMigration:NewType = " <<newName << " Len = "<< newName.Length()<<std::endl;
243 aName = newName.ToCString();
247 if (theDriverMap.IsBound (aName))
250 const Handle(XmlMDF_ADriver)& driver = theDriverMap.Find(aName);
251 XmlObjMgt_Persistent pAtt (anElem);
252 Standard_Integer anID = pAtt.Id ();
253 if (anID <= 0) { // check for ID validity
254 TCollection_ExtendedString anErrorMessage =
255 TCollection_ExtendedString("Wrong ID of OCAF attribute with type ")
257 driver -> myMessageDriver->Send (anErrorMessage, Message_Fail);
260 Handle(TDF_Attribute) tAtt;
261 Standard_Boolean isBound = theRelocTable.IsBound(anID);
263 tAtt = Handle(TDF_Attribute)::DownCast(theRelocTable.Find(anID));
265 tAtt = driver -> NewEmpty();
267 if (tAtt->Label().IsNull())
271 theLabel.AddAttribute (tAtt);
273 catch (const Standard_DomainError&)
275 // For attributes that can have arbitrary GUID (e.g. TDataStd_Integer), exception
276 // will be raised in valid case if attribute of that type with default GUID is already
277 // present on the same label; the reason is that actual GUID will be read later.
278 // To avoid this, set invalid (null) GUID to the newly added attribute (see #29669)
279 static const Standard_GUID fbidGuid;
280 tAtt->SetID (fbidGuid);
281 theLabel.AddAttribute (tAtt);
285 driver->myMessageDriver->Send
286 (TCollection_ExtendedString("XmlDriver warning: ") +
287 "attempt to attach attribute " +
288 aName + " to a second label", Message_Warning);
290 if (! driver -> Paste (pAtt, tAtt, theRelocTable))
292 // error converting persistent to transient
293 driver->myMessageDriver->Send
294 (TCollection_ExtendedString("XmlDriver warning: ") +
295 "failure reading attribute " + aName, Message_Warning);
297 else if (isBound == Standard_False)
298 theRelocTable.Bind (anID, tAtt);
303 const TCollection_AsciiString anAsciiName = aName;
304 std::cerr << "XmlDriver warning: "
305 << "label contains object of unknown type "<< anAsciiName<< std::endl;
310 //anElem = (const XmlObjMgt_Element &) anElem.getNextSibling();
311 LDOM_Node theNode1 = anElem.getNextSibling();
312 anElem = (const XmlObjMgt_Element &) theNode1;
326 //=======================================================================
327 //function : AddDrivers
329 //=======================================================================
330 void XmlMDF::AddDrivers (const Handle(XmlMDF_ADriverTable)& aDriverTable,
331 const Handle(Message_Messenger)& aMessageDriver)
333 aDriverTable->AddDriver (new XmlMDF_TagSourceDriver(aMessageDriver));
334 aDriverTable->AddDriver (new XmlMDF_ReferenceDriver(aMessageDriver));