0025748: Parallel version of progress indicator
[occt.git] / src / XmlMNaming / XmlMNaming_NamedShapeDriver.cxx
1 // Created on: 2001-07-11
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 //AGV 150202: Changed prototype LDOM_Node::getOwnerDocument()
17
18 #include <BRepTools.hxx>
19 #include <Message_Messenger.hxx>
20 #include <Message_ProgressScope.hxx>
21 #include <LDOM_OSStream.hxx>
22 #include <LDOM_Text.hxx>
23 #include <Standard_SStream.hxx>
24 #include <Standard_Type.hxx>
25 #include <TDF_Attribute.hxx>
26 #include <TDF_Label.hxx>
27 #include <TNaming_Builder.hxx>
28 #include <TNaming_Iterator.hxx>
29 #include <TNaming_NamedShape.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopTools_LocationSet.hxx>
32 #include <XmlMNaming_NamedShapeDriver.hxx>
33 #include <XmlMNaming_Shape1.hxx>
34 #include <XmlObjMgt.hxx>
35 #include <XmlObjMgt_Array1.hxx>
36 #include <XmlObjMgt_Persistent.hxx>
37
38 IMPLEMENT_STANDARD_RTTIEXT(XmlMNaming_NamedShapeDriver,XmlMDF_ADriver)
39
40 static TNaming_Evolution          EvolutionEnum   (const XmlObjMgt_DOMString&);
41 static const XmlObjMgt_DOMString& EvolutionString (const TNaming_Evolution);
42 static void                       doTranslate     (const TopoDS_Shape&,
43                                                    XmlMNaming_Shape1&,
44                                                    BRepTools_ShapeSet&);
45 static int                        doTranslate     (const XmlMNaming_Shape1&,
46                                                    TopoDS_Shape&,
47                                                    BRepTools_ShapeSet&);
48
49 IMPLEMENT_DOMSTRING (OldsString,    "olds")
50 IMPLEMENT_DOMSTRING (NewsString,    "news")
51 IMPLEMENT_DOMSTRING (StatusString,  "evolution")
52 IMPLEMENT_DOMSTRING (VersionString, "version")
53 IMPLEMENT_DOMSTRING (ShapesString,  "shapes")
54
55 IMPLEMENT_DOMSTRING (EvolPrimitiveString, "primitive")
56 IMPLEMENT_DOMSTRING (EvolGeneratedString, "generated")
57 IMPLEMENT_DOMSTRING (EvolModifyString,    "modify")
58 IMPLEMENT_DOMSTRING (EvolDeleteString,    "delete")
59 IMPLEMENT_DOMSTRING (EvolSelectedString,  "selected")
60 IMPLEMENT_DOMSTRING (EvolReplaceString,   "replace")
61
62 //=======================================================================
63 //function : XmlMNaming_NamedShapeDriver
64 //purpose  : Constructor
65 //=======================================================================
66
67 XmlMNaming_NamedShapeDriver::XmlMNaming_NamedShapeDriver
68                         (const Handle(Message_Messenger)& theMessageDriver)
69      : XmlMDF_ADriver (theMessageDriver, NULL),
70   myShapeSet (Standard_False) // triangles mode
71 {}
72
73 //=======================================================================
74 //function : NewEmpty()
75 //purpose  : 
76 //=======================================================================
77 Handle(TDF_Attribute) XmlMNaming_NamedShapeDriver::NewEmpty () const
78 {
79   return (new TNaming_NamedShape());
80 }
81
82 //=======================================================================
83 //function : Paste()
84 //purpose  : retrieval of TNaming_NamedShape
85 //=======================================================================
86
87 Standard_Boolean XmlMNaming_NamedShapeDriver::Paste
88                                        (const XmlObjMgt_Persistent&  theSource,
89                                         const Handle(TDF_Attribute)& theTarget,
90                                         XmlObjMgt_RRelocationTable&) const
91 {
92   Handle(TNaming_NamedShape) aTarget =
93     Handle(TNaming_NamedShape)::DownCast(theTarget);
94   TDF_Label Label = aTarget -> Label();
95   TNaming_Builder aBld (Label);
96
97   //    Get Version
98   Standard_Integer    aVersion = 0;
99   const XmlObjMgt_Element& anElement = theSource;
100   XmlObjMgt_DOMString aVerString = anElement.getAttribute (::VersionString());
101   if (aVerString != NULL)
102     aVerString.GetInteger (aVersion);
103
104   //    Get Evolution status
105   XmlObjMgt_DOMString aStatus = anElement.getAttribute (::StatusString());
106   TNaming_Evolution evol = EvolutionEnum (aStatus);
107   // apres creation Builder qui a mis la version a 1 :
108   aTarget -> SetVersion (aVersion);
109
110   const XmlObjMgt_Array1 OldPShapes (anElement, ::OldsString());
111   const XmlObjMgt_Array1 NewPShapes (anElement, ::NewsString());
112   if (NewPShapes.Length() == 0 && OldPShapes.Length() == 0)
113     return Standard_True;
114
115   TopoDS_Shape anOldShape;
116   TopoDS_Shape aNewShape;
117   BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
118
119   Standard_Integer lower = NewPShapes.Lower();
120   if (OldPShapes.Lower() < lower) lower = OldPShapes.Lower();
121
122   Standard_Integer upper = NewPShapes.Upper();
123   if (OldPShapes.Upper() > upper) upper = OldPShapes.Upper();
124
125   for (Standard_Integer i = upper; i >= lower; --i)
126   {
127     const XmlMNaming_Shape1 aNewPShape  = NewPShapes.Value(i);
128     const XmlMNaming_Shape1 anOldPShape = OldPShapes.Value(i);
129
130     if ( evol != TNaming_PRIMITIVE && anOldPShape.Element() != NULL )
131     {
132       if (::doTranslate (anOldPShape, anOldShape, aShapeSet)) {
133         myMessageDriver->Send ("NamedShapeDriver: Error reading a shape from array", Message_Fail);
134         return Standard_False;
135       }
136     }
137
138     if (evol != TNaming_DELETE && aNewPShape.Element() != NULL )
139     {
140       if (::doTranslate (aNewPShape, aNewShape, aShapeSet)) {
141         myMessageDriver->Send ("NamedShapeDriver: Error reading a shape from array", Message_Fail);
142         return Standard_False;
143       }
144     }
145
146     switch (evol)
147     {
148     case TNaming_PRIMITIVE:
149       aBld.Generated(aNewShape);
150       break;
151     case TNaming_GENERATED:
152       aBld.Generated(anOldShape,aNewShape);
153       break;
154     case TNaming_MODIFY:
155       aBld.Modify(anOldShape,aNewShape);
156       break;
157     case TNaming_DELETE:
158       aBld.Delete(anOldShape);
159       break;
160     case TNaming_SELECTED:
161       aBld.Select(aNewShape, anOldShape);
162       break;
163     case TNaming_REPLACE:
164       aBld.Modify(anOldShape,aNewShape);
165       break; // for compatibility
166       //    case TNaming_REPLACE:
167       //      aBld.Replace(anOldShape,aNewShape);
168       //      break;
169     default:
170       throw Standard_DomainError("TNaming_Evolution; enum term unknown");
171     }
172     anOldShape.Nullify();
173     aNewShape.Nullify();
174   }
175   return Standard_True;
176 }
177
178 //=======================================================================
179 //function : Paste()
180 //purpose  : storage of TNaming_NamedShape
181 //=======================================================================
182
183 void XmlMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
184                                          XmlObjMgt_Persistent&        theTarget,
185                                          XmlObjMgt_SRelocationTable&) const
186 {
187 //AGV  XmlObjMgt_Document& aDoc =
188 //AGV    (XmlObjMgt_Document&) theTarget.Element().getOwnerDocument();
189   XmlObjMgt_Document aDoc =
190     XmlObjMgt_Document (theTarget.Element().getOwnerDocument());
191
192   Handle(TNaming_NamedShape) aNamedShape =
193     Handle(TNaming_NamedShape)::DownCast(theSource);
194   TNaming_Evolution evol = aNamedShape->Evolution();
195
196   //    Create arrays
197   Standard_Integer NbShapes = 0;
198   TNaming_Iterator SItr (aNamedShape);
199   while (SItr.More()) {
200     NbShapes++;
201     SItr.Next ();
202   }
203
204   BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
205   XmlObjMgt_Array1 OldPShapes (1,NbShapes), NewPShapes (1,NbShapes);
206
207   OldPShapes.CreateArrayElement (theTarget, ::OldsString());
208   NewPShapes.CreateArrayElement (theTarget, ::NewsString());
209
210   //    Fill arrays
211   Standard_Integer i = 1;
212   TNaming_Iterator SIterator(aNamedShape);
213   while (SIterator.More())
214   {
215     const TopoDS_Shape& OldShape = SIterator.OldShape();
216     const TopoDS_Shape& NewShape = SIterator.NewShape();
217
218     if ( evol != TNaming_PRIMITIVE )
219     {
220       XmlMNaming_Shape1 anOldPShape (aDoc);
221       ::doTranslate (OldShape, anOldPShape, aShapeSet);
222       OldPShapes.SetValue (i, anOldPShape.Element());
223     }
224
225     if (evol != TNaming_DELETE)
226     {
227       XmlMNaming_Shape1 aNewPShape (aDoc);
228       ::doTranslate (NewShape, aNewPShape, aShapeSet);
229       NewPShapes.SetValue (i, aNewPShape.Element());
230     }
231     i++;
232     SIterator.Next();
233   }
234
235   theTarget.Element().setAttribute (::StatusString(), EvolutionString(evol));
236   Standard_Integer aVersion = aNamedShape -> Version();
237   if (aVersion != 0)
238     theTarget.Element().setAttribute (::VersionString(), aVersion);
239 }
240
241 //=======================================================================
242 //function : EvolutionEnum
243 //purpose  : static
244 //=======================================================================
245
246 static const XmlObjMgt_DOMString& EvolutionString(const TNaming_Evolution i)
247 {
248   switch(i) {
249     case TNaming_PRIMITIVE    : return ::EvolPrimitiveString();
250     case TNaming_GENERATED    : return ::EvolGeneratedString();
251     case TNaming_MODIFY       : return ::EvolModifyString();
252     case TNaming_DELETE       : return ::EvolDeleteString();
253     case TNaming_SELECTED     : return ::EvolSelectedString();
254     case TNaming_REPLACE      : return ::EvolModifyString();  //    case TNaming_REPLACE      : return ::EvolReplaceString(); for compatibility
255   default:
256     throw Standard_DomainError("TNaming_Evolution; enum term unknown");
257   }
258 }
259
260 //=======================================================================
261 //function : EvolutionEnum
262 //purpose  : static
263 //=======================================================================
264
265 static TNaming_Evolution EvolutionEnum (const XmlObjMgt_DOMString& theString)
266 {
267   TNaming_Evolution aResult = TNaming_PRIMITIVE;
268   if (theString.equals (::EvolPrimitiveString()) == Standard_False) {
269     if (theString.equals (::EvolGeneratedString()))
270       aResult = TNaming_GENERATED;
271     else if (theString.equals (::EvolModifyString()))
272       aResult = TNaming_MODIFY;
273     else if (theString.equals (::EvolDeleteString()))
274       aResult = TNaming_DELETE;
275     else if (theString.equals (::EvolSelectedString()))
276       aResult = TNaming_SELECTED;
277     else if (theString.equals (::EvolReplaceString()))
278       aResult = TNaming_MODIFY; // for compatibility //TNaming_REPLACE;
279     else
280       throw Standard_DomainError("TNaming_Evolution; string value without enum term equivalence");
281   }
282   return aResult;
283 }
284
285 //=======================================================================
286 //function : doTranslate
287 //purpose  : shape storage to XML
288 //=======================================================================
289
290 static void doTranslate (const TopoDS_Shape&            theShape,
291                          XmlMNaming_Shape1&             theResult,
292                          BRepTools_ShapeSet&            theShapeSet)
293 {
294   // Check for empty shape
295   if (theShape.IsNull()) return;
296
297   // Add to shape set both TShape and Location contained in theShape
298   const Standard_Integer aTShapeId = theShapeSet.Add (theShape);
299   const Standard_Integer aLocId =
300     theShapeSet.Locations().Index (theShape.Location());
301
302   // Fill theResult with shape parameters: TShape ID, Location, Orientation
303   theResult.SetShape (aTShapeId, aLocId, theShape.Orientation());
304
305   if (theShape.ShapeType() == TopAbs_VERTEX)
306   {
307     theResult.SetVertex(theShape);
308   }
309 }
310
311 //=======================================================================
312 //function : doTranslate
313 //purpose  : shape retrieval from XML
314 //=======================================================================
315
316 static int doTranslate  (const XmlMNaming_Shape1&       thePShape,
317                          TopoDS_Shape&                  theResult,
318                          BRepTools_ShapeSet&            theShapeSet)
319 {
320   const Standard_Integer aShapeId = thePShape.TShapeId();
321
322   // Read TShape and Orientation
323   if (aShapeId <= 0 || aShapeId > theShapeSet.NbShapes())
324     return 1;
325   theResult.TShape      (theShapeSet.Shape(aShapeId).TShape());
326   theResult.Orientation (thePShape.Orientation());
327   theResult.Location    (theShapeSet.Locations().Location (thePShape.LocId()));
328
329   return 0;
330 }
331
332 //=======================================================================
333 //function : ReadShapeSection
334 //purpose  : 
335 //=======================================================================
336
337 void XmlMNaming_NamedShapeDriver::ReadShapeSection (const XmlObjMgt_Element& theElement, 
338                                                     const Message_ProgressRange& theRange)
339 {
340   XmlObjMgt_Element anElement =
341     XmlObjMgt::FindChildByName (theElement, ::ShapesString());
342   if (anElement != NULL) {
343     for (LDOM_Node aNode = anElement.getFirstChild();
344          aNode != NULL;
345          aNode = anElement.getNextSibling())
346     {
347       if (aNode.getNodeType() == LDOM_Node::TEXT_NODE) {
348         LDOMString aData = aNode.getNodeValue();
349         std::stringstream aStream (std::string(aData.GetString()));
350         myShapeSet.Clear();
351         myShapeSet.Read (aStream, theRange);
352         break;
353       }
354     }
355   }
356 }
357
358 //=======================================================================
359 //function : WriteShapeSection
360 //purpose  : 
361 //=======================================================================
362
363 void XmlMNaming_NamedShapeDriver::WriteShapeSection (XmlObjMgt_Element& theElement,
364                                                      const Message_ProgressRange& theRange)
365 {
366   //  Create "shapes" element and append it as child
367   XmlObjMgt_Document aDoc     = theElement.getOwnerDocument();
368   XmlObjMgt_Element anElement = aDoc.createElement (::ShapesString());
369   theElement.appendChild (anElement);
370
371   //  Add text to the "shapes" element
372   if (myShapeSet.NbShapes() > 0) {
373     myShapeSet.SetFormatNb(2);
374     LDOM_OSStream aStream (16 * 1024);
375 //    ostrstream aStream;
376 //    aStream.rdbuf() -> setbuf (0, 16380);
377     Message_ProgressScope aPS(theRange, "Writing shape section", 2);
378     myShapeSet.Write (aStream, aPS.Next());
379     if (!aPS.More())
380       return;
381
382     aStream << std::ends;
383     char * aStr = (char *)aStream.str();
384     LDOM_Text aText = aDoc.createTextNode (aStr);
385     delete [] aStr;
386     aText.SetValueClear();      // There are no characters '<' and '&' and like
387 //    aStream.rdbuf() -> freeze(0);                     // release the buffer
388     anElement.appendChild (aText);
389   // Clear the shape set to avoid appending to it on the next write
390     BRepTools_ShapeSet& aShapeSet = (BRepTools_ShapeSet&) myShapeSet;
391     aShapeSet.Clear();
392     if (!aPS.More())
393       return;
394     aPS.Next();
395   }
396 }
397
398 //=======================================================================
399 //function : Clear
400 //purpose  : 
401 //=======================================================================
402
403 void XmlMNaming_NamedShapeDriver::Clear()
404 {
405   myShapeSet.Clear();
406 }