0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / XmlMDF / XmlMDF.cxx
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
20
21 #include <XmlMDF.ixx>
22 #include <XmlMDF_ADriver.hxx>
23 #include <XmlMDF_TagSourceDriver.hxx>
24 #include <XmlMDF_ReferenceDriver.hxx>
25 #include <XmlMDF_DataMapIteratorOfTypeADriverMap.hxx>
26
27 #include <XmlObjMgt_Persistent.hxx>
28 #include <XmlObjMgt_DOMString.hxx>
29 #include <XmlObjMgt_Document.hxx>
30
31 #include <TDF_TagSource.hxx>
32 #include <TDF_Label.hxx>
33 #include <TDF_Tool.hxx>
34 #include <TDF_AttributeIterator.hxx>
35 #include <TDF_ChildIterator.hxx>
36 #include <TColStd_MapOfTransient.hxx>
37 #include <Storage_Schema.hxx>
38
39 IMPLEMENT_DOMSTRING (TagString,         "tag")
40 IMPLEMENT_DOMSTRING (LabelString,       "label")
41 #define DATATYPE_MIGRATION
42 //#define DATATYPE_MIGRATION_DEB
43 //=======================================================================
44 //function : UnsuppTypesMap
45 //purpose  : 
46 //=======================================================================
47
48 static TColStd_MapOfTransient& UnsuppTypesMap ()
49 {
50   static TColStd_MapOfTransient anUnsuppTypes;
51   return anUnsuppTypes;
52 }
53
54 //=======================================================================
55 //function : FromTo
56 //purpose  : Paste transient data into DOM_Element
57 //=======================================================================
58 void XmlMDF::FromTo (const Handle(TDF_Data)&             theData,
59                      XmlObjMgt_Element&                  theElement,
60                      XmlObjMgt_SRelocationTable&         theRelocTable,
61                      const Handle(XmlMDF_ADriverTable)&  theDrivers)
62 {
63   UnsuppTypesMap().Clear();
64 //  Standard_Integer count =
65   WriteSubTree(theData->Root(), theElement, theRelocTable, theDrivers);
66   UnsuppTypesMap().Clear();
67 }
68
69 //=======================================================================
70 //function : WriteSubTree
71 //purpose  : 
72 //=======================================================================
73 Standard_Integer XmlMDF::WriteSubTree
74                       (const TDF_Label&                    theLabel,
75                        XmlObjMgt_Element&                  theElement,
76                        XmlObjMgt_SRelocationTable&         theRelocTable,
77                        const Handle(XmlMDF_ADriverTable)&  theDrivers)
78 {
79   XmlObjMgt_Document aDoc = theElement.getOwnerDocument();
80
81   // create element "label"
82   XmlObjMgt_Element aLabElem = aDoc.createElement (::LabelString());
83
84   // Extraction of the driver subset.
85   const XmlMDF_TypeADriverMap& aDriverMap = theDrivers->GetDrivers();
86
87   // write attributes
88   Standard_Integer count = 0;
89   TDF_AttributeIterator itr1 (theLabel);
90   for ( ; itr1.More(); itr1.Next())
91   {
92     const Handle(TDF_Attribute)& tAtt = itr1.Value();
93     const Handle(Standard_Type)& aType = tAtt->DynamicType();
94     if (aDriverMap.IsBound (aType))
95     {
96       const Handle(XmlMDF_ADriver)& aDriver = aDriverMap.Find (aType);
97       count++;
98
99       //    Add source to relocation table
100       Standard_Integer anId      = theRelocTable.Add (tAtt);
101
102       //    Create DOM data item
103       XmlObjMgt_Persistent pAtt;
104       pAtt.CreateElement (aLabElem, aDriver->TypeName().ToCString(), anId);
105
106       //    Paste
107       aDriver -> Paste (tAtt, pAtt, theRelocTable);
108     }
109 #ifdef DEB
110     else if (!UnsuppTypesMap().Contains (aType))
111     {
112       cout << "attribute driver for type "<< aType -> Name()<< " not found"<< endl;
113       UnsuppTypesMap().Add (aType);
114     }
115 #endif
116   }
117
118   // write sub-labels
119   TDF_ChildIterator itr2 (theLabel);
120   for ( ; itr2.More(); itr2.Next())
121   {
122     const TDF_Label& aChildLab = itr2.Value();
123     count += WriteSubTree(aChildLab, aLabElem, theRelocTable, theDrivers);
124   }
125
126   if (count > 0)
127   {
128     theElement.appendChild(aLabElem);
129
130     // set attribute "tag"
131     aLabElem.setAttribute (::TagString(), theLabel.Tag());
132   }
133
134   return count;
135 }
136
137 //=======================================================================
138 //function : FromTo
139 //purpose  : Paste data from DOM_Element into transient document
140 //=======================================================================
141 Standard_Boolean XmlMDF::FromTo (const XmlObjMgt_Element&         theElement,
142                                  Handle(TDF_Data)&                theData,
143                                  XmlObjMgt_RRelocationTable&      theRelocTable,
144                                  const Handle(XmlMDF_ADriverTable)& theDrivers)
145 {
146   TDF_Label aRootLab = theData->Root();
147   XmlMDF_MapOfDriver aDriverMap;
148   CreateDrvMap (theDrivers, aDriverMap);
149
150   Standard_Integer count = 0;
151
152   LDOM_Node theNode = theElement.getFirstChild();
153   XmlObjMgt_Element anElem = (const XmlObjMgt_Element&)theNode;
154   while ( !anElem.isNull() )
155   {
156     if ( anElem.getNodeName().equals (::LabelString()) )
157     {
158       Standard_Integer subcount =
159         ReadSubTree(anElem, aRootLab, theRelocTable, aDriverMap);
160       // check for error
161       if (subcount < 0)
162         return Standard_False;
163       count += subcount;
164     }
165     //anElem = (const XmlObjMgt_Element &) anElem.getNextSibling();
166     LDOM_Node theNode1 = anElem.getNextSibling();
167     anElem = (const XmlObjMgt_Element &) theNode1;
168   }
169
170   return Standard_True;
171 }
172
173 //=======================================================================
174 //function : ReadSubTree
175 //purpose  : 
176 //=======================================================================
177 Standard_Integer XmlMDF::ReadSubTree (const XmlObjMgt_Element&    theElement,
178                                       const TDF_Label&            theLabel,
179                                       XmlObjMgt_RRelocationTable& theRelocTable,
180                                       const XmlMDF_MapOfDriver&   theDriverMap)
181 {
182   // Extraction of the driver subset.
183   Standard_Integer count = 0;
184
185   //XmlObjMgt_Element anElem = (const XmlObjMgt_Element &) theElement.getFirstChild();
186   LDOM_Node theNode = theElement.getFirstChild();
187   XmlObjMgt_Element anElem = (const XmlObjMgt_Element &) theNode;
188   while ( !anElem.isNull() )
189   {
190     if ( anElem.getNodeType() == LDOM_Node::ELEMENT_NODE )
191     {
192       if ( anElem.getNodeName().equals (::LabelString()) )
193       {
194         // read tag
195         Standard_Integer tag;
196         XmlObjMgt_DOMString aTag (anElem.getAttribute(::TagString()));
197         if ( !aTag.GetInteger (tag) ) {
198           TCollection_ExtendedString anErrorMessage =
199             TCollection_ExtendedString ("Wrong Tag value for OCAF Label: ")
200               + aTag;
201           theDriverMap.Find("TDF_TagSource") -> WriteMessage (anErrorMessage);
202           return -1;
203         }
204         // create label
205         TDF_Label aLab = theLabel.FindChild(tag, Standard_True);
206
207         // read sub-tree
208         Standard_Integer subcount =
209           ReadSubTree(anElem, aLab, theRelocTable, theDriverMap);
210         // check for error
211         if (subcount == -1)
212           return -1;
213         count += subcount;
214       }
215       else
216       {
217         // read attribute
218         XmlObjMgt_DOMString aName = anElem.getNodeName();
219
220 #ifdef DATATYPE_MIGRATION
221         TCollection_AsciiString  newName;       
222         if(Storage_Schema::CheckTypeMigration(aName, newName)) {
223 #ifdef DATATYPE_MIGRATION_DEB
224           cout << "CheckTypeMigration:OldType = " <<aName.GetString() << " Len = "<<strlen(aName.GetString())<<endl;
225           cout << "CheckTypeMigration:NewType = " <<newName  << " Len = "<< newName.Length()<<endl;
226 #endif
227           aName = newName.ToCString();
228         }
229 #endif  
230        
231         if (theDriverMap.IsBound (aName))
232         {
233           count++;
234           const Handle(XmlMDF_ADriver)& driver = theDriverMap.Find(aName);
235           XmlObjMgt_Persistent pAtt (anElem);
236           Standard_Integer anID = pAtt.Id ();
237           if (anID <= 0) {      // check for ID validity
238             TCollection_ExtendedString anErrorMessage =
239              TCollection_ExtendedString("Wrong ID of OCAF attribute with type ")
240                + aName;
241             driver -> WriteMessage (anErrorMessage);
242             return -1;
243           }
244           Handle(TDF_Attribute) tAtt;
245           Standard_Boolean isBound = theRelocTable.IsBound(anID);
246           if (isBound)
247             tAtt = Handle(TDF_Attribute)::DownCast(theRelocTable.Find(anID));
248           else
249             tAtt = driver -> NewEmpty();
250           if (tAtt->Label().IsNull())
251             theLabel.AddAttribute (tAtt);
252           else
253             driver->WriteMessage
254               (TCollection_ExtendedString("XmlDriver warning: ") +
255                "attempt to attach attribute " +
256                aName + " to a second label");
257
258           if (! driver -> Paste (pAtt, tAtt, theRelocTable))
259           {
260             // error converting persistent to transient
261             driver->WriteMessage
262               (TCollection_ExtendedString("XmlDriver warning: ") +
263                "failure reading attribute " + aName);
264           }
265           else if (isBound == Standard_False)
266             theRelocTable.Bind (anID, tAtt);
267         }
268 #ifdef DEB
269         else
270         {
271           const TCollection_AsciiString anAsciiName = aName;
272           cerr << "XmlDriver warning: "
273                << "label contains object of unknown type "<< anAsciiName<< endl;
274         }
275 #endif
276       }
277     }
278     //anElem = (const XmlObjMgt_Element &) anElem.getNextSibling();
279     LDOM_Node theNode1 = anElem.getNextSibling();
280     anElem = (const XmlObjMgt_Element &) theNode1;
281   }
282
283   // AfterRetrieval
284   if (count > 0)
285   {
286   }
287
288   return count;
289 }
290
291 //=======================================================================
292 //function : AddDrivers
293 //purpose  : 
294 //=======================================================================
295 void XmlMDF::AddDrivers (const Handle(XmlMDF_ADriverTable)& aDriverTable,
296                          const Handle(CDM_MessageDriver)&   aMessageDriver)
297 {
298   aDriverTable->AddDriver (new XmlMDF_TagSourceDriver(aMessageDriver)); 
299   aDriverTable->AddDriver (new XmlMDF_ReferenceDriver(aMessageDriver));
300 }
301
302 //=======================================================================
303 //function : CreateDrvMap
304 //purpose  : 
305 //=======================================================================
306
307 void XmlMDF::CreateDrvMap (const Handle(XmlMDF_ADriverTable)& theDrivers,
308                            XmlMDF_MapOfDriver&                theAsciiDriverMap)
309 {
310   const XmlMDF_TypeADriverMap& aDriverMap = theDrivers->GetDrivers();
311   XmlMDF_DataMapIteratorOfTypeADriverMap anIter (aDriverMap);
312   while (anIter.More()) {
313     const Handle(XmlMDF_ADriver)& aDriver = anIter.Value();
314     const TCollection_AsciiString aTypeName = aDriver -> TypeName();
315     if (theAsciiDriverMap.IsBound (aTypeName) == Standard_False)
316       theAsciiDriverMap.Bind (aTypeName, aDriver);
317     else
318       aDriver -> WriteMessage
319         (TCollection_ExtendedString ("Warning: skipped driver name: \"")
320          + aTypeName + '\"');
321     anIter.Next();
322   }
323 }