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