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