1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13 
14 
15 #include <Interface_CopyControl.hxx>
16 #include <Interface_CopyMap.hxx>
17 #include <Interface_CopyTool.hxx>
18 #include <Interface_EntityIterator.hxx>
19 #include <Interface_GeneralLib.hxx>
20 #include <Interface_GeneralModule.hxx>
21 #include <Interface_InterfaceError.hxx>
22 #include <Interface_InterfaceModel.hxx>
23 #include <Interface_Protocol.hxx>
24 #include <Interface_ReportEntity.hxx>
25 #include <Standard_Transient.hxx>
26 #include <TCollection_HAsciiString.hxx>
27 
28 // Se souvenir qu une version plus riche de CopyTool existe : c est
29 // TransferDispatch (package Transfer). Cette classe offre beaucoup plus de
30 // possibilite (parametrage des actions, gestion du Mapping ...)
31 // Mais le principe (transfert en 2 passes) reste le meme, a savoir :
32 // Passe 1 normale : les entites a transferer sont designees, elles entrainent
33 // leurs sous-references vraies
34 // Passe 2 : une fois tous les transferts faits, les relations "Imply" sont
35 // mises, pour les entites designees ET QUI ONT ETE AUSSI TRANSFEREES, la
36 // relation est reconduite (pas de nouveau Share)
37 //  #####################################################################
38 //  ....                        CONSTRUCTEURS                        ....
Interface_CopyTool(const Handle (Interface_InterfaceModel)& amodel,const Interface_GeneralLib & lib)39 Interface_CopyTool::Interface_CopyTool
40   (const Handle(Interface_InterfaceModel)& amodel,
41    const Interface_GeneralLib& lib)
42     : thelib (lib) , thelst (amodel->NbEntities())
43 {
44   thelst.Init(Standard_False);
45   themod = amodel;
46   themap = new Interface_CopyMap (amodel);
47   therep = new Interface_CopyMap (amodel);
48   thelev = 0;  theimp = Standard_False;
49 }
50 
Interface_CopyTool(const Handle (Interface_InterfaceModel)& amodel,const Handle (Interface_Protocol)& protocol)51     Interface_CopyTool::Interface_CopyTool
52   (const Handle(Interface_InterfaceModel)& amodel,
53    const Handle(Interface_Protocol)& protocol)
54     : thelib (protocol) , thelst (amodel->NbEntities())
55 {
56   thelst.Init(Standard_False);
57   themod = amodel;
58   themap = new Interface_CopyMap (amodel);
59   therep = new Interface_CopyMap (amodel);
60   thelev = 0;  theimp = Standard_False;
61 }
62 
63 
Interface_CopyTool(const Handle (Interface_InterfaceModel)& amodel)64     Interface_CopyTool::Interface_CopyTool
65   (const Handle(Interface_InterfaceModel)& amodel)
66     : thelib (Interface_Protocol::Active()) , thelst (amodel->NbEntities())
67 {
68   if (Interface_Protocol::Active().IsNull()) throw Interface_InterfaceError("Interface CopyTool : Create with Active Protocol undefined");
69 
70   thelst.Init(Standard_False);
71   themod = amodel;
72   themap = new Interface_CopyMap (amodel);
73   therep = new Interface_CopyMap (amodel);
74   thelev = 0;  theimp = Standard_False;
75 }
76 
Handle(Interface_InterfaceModel)77     Handle(Interface_InterfaceModel)  Interface_CopyTool::Model () const
78       {  return themod;  }
79 
SetControl(const Handle (Interface_CopyControl)& othermap)80     void Interface_CopyTool::SetControl
81   (const Handle(Interface_CopyControl)& othermap)
82       {  themap = othermap;  }
83 
Handle(Interface_CopyControl)84     Handle(Interface_CopyControl)  Interface_CopyTool::Control () const
85       {  return themap;  }
86 
87 
88 //  #####################################################################
89 //  ....                    Actions Individuelles                    ....
90 
Clear()91     void Interface_CopyTool::Clear ()
92 {
93   themap->Clear();
94   therep->Clear();
95   thelev = 0;  theimp = Standard_False;
96   therts.Clear();
97   ClearLastFlags();
98 }
99 
NewVoid(const Handle (Standard_Transient)& entfrom,Handle (Standard_Transient)& entto)100     Standard_Boolean Interface_CopyTool::NewVoid
101   (const Handle(Standard_Transient)& entfrom,
102    Handle(Standard_Transient)& entto)
103 {
104   if (entfrom == theent) {
105     if (themdu.IsNull()) return Standard_False;
106     return themdu->NewVoid(theCN,entto);
107   }
108   theent = entfrom;
109   Standard_Boolean res = thelib.Select (entfrom,themdu,theCN);
110   if (res)   res   = themdu->NewVoid (theCN,entto);
111   if (!res)  res   = themdu->NewCopiedCase (theCN,entfrom,entto,*this);
112 //  if (!res) entto = entfrom->ShallowCopy();   sorry, nothing more possible
113   return res;
114 }
115 
116 
Copy(const Handle (Standard_Transient)& entfrom,Handle (Standard_Transient)& entto,const Standard_Boolean mapped,const Standard_Boolean errstat)117     Standard_Boolean Interface_CopyTool::Copy
118   (const Handle(Standard_Transient)& entfrom,
119    Handle(Standard_Transient)& entto,
120    const Standard_Boolean mapped, const Standard_Boolean errstat)
121 {
122   Standard_Boolean res = Standard_True;
123   if (entfrom == theent) {
124     if (themdu.IsNull()) res = Standard_False;
125   } else {
126     theent = entfrom;
127     res = thelib.Select(entfrom,themdu,theCN);
128   }
129   if (!res) {
130 //  Built-in :
131     if (entfrom.IsNull()) return res;
132     if (entfrom->DynamicType() == STANDARD_TYPE(TCollection_HAsciiString)) {
133       entto = new TCollection_HAsciiString
134 	( Handle(TCollection_HAsciiString)::DownCast(entfrom)->ToCString() );
135       res = Standard_True;
136     }
137     return res;
138   }
139 //  On cree l Entite vide (NewVoid), la Copie reste a faire
140   res = NewVoid(entfrom,entto);
141   if (mapped) themap->Bind (entfrom,entto);    // Mapper avant de continuer ...
142 
143 //  A present, on effectue la Copie (selon cas; si ShallowCopy ne suffit pas :
144 //  c est <themdu> qui decide)
145 
146 //    Une Entite en Erreur n est pas copiee (pas de sens et c est risque ...)
147 //    Cependant, elle est "Copiee a Vide (NewVoid)" donc referencable
148   if (!errstat)    themdu->CopyCase(theCN,entfrom,entto,*this);
149   return res;
150 }
151 
Implied(const Handle (Standard_Transient)& entfrom,const Handle (Standard_Transient)& entto)152     void  Interface_CopyTool::Implied
153   (const Handle(Standard_Transient)& entfrom,
154    const Handle(Standard_Transient)& entto)
155 {
156   Handle(Interface_GeneralModule) module;
157   Standard_Integer CN;
158   if (thelib.Select(entfrom,module,CN))
159     module->RenewImpliedCase(CN,entfrom,entto,*this);
160 }
161 
162 
163 //  ....                Alimentation de la Map                ....
164 
Handle(Standard_Transient)165     Handle(Standard_Transient) Interface_CopyTool::Transferred
166   (const Handle(Standard_Transient)& ent)
167 {
168   Handle(Standard_Transient) res;
169   if (ent.IsNull()) return res;    // Copie d un Null : tres simple ...
170   Standard_Integer nument = themod->Number(ent);
171 
172 //  <nument> == 0 -> Peut etre une sous-partie non partagee ...
173 //  On accepte mais on se protege contre un bouclage
174   if (nument == 0 && thelev > 100) throw Interface_InterfaceError("CopyTool : Transferred, Entity is not contained in Starting Model");
175   if (!themap->Search(ent,res)) {       // deja transfere ? sinon, le faire
176 
177 //  On opere la Copie (enfin, on tente)
178 //  En cas d echec, rien n est enregistre
179     if (!Copy(ent,res, (nument != 0), themod->IsRedefinedContent(nument) ))
180       return res;
181 
182     thelev ++;
183     if (nument != 0) thelst.SetTrue (nument);
184     Handle(Interface_ReportEntity) rep;
185     if (nument != 0) rep = themod->ReportEntity (nument);
186     if (!rep.IsNull()) {
187 //  ATTENTION ATTENTION, si ReportEntity : Copier aussi Content et refaire une
188 //  ReportEntity avec les termes initiaux
189       if (rep->IsUnknown()) therep->Bind
190 	(ent, new Interface_ReportEntity(res));
191       else {
192 	Handle(Standard_Transient) contfrom, contto;
193 	contfrom = rep->Content();
194 	Handle(Interface_ReportEntity) repto =
195 	  new Interface_ReportEntity (rep->Check(),res);
196 	if (!contfrom.IsNull()) {
197 	  if (contfrom == ent) contto = res;
198 	  else  Copy (contfrom,contto, themod->Contains(contfrom), Standard_False);
199 	  repto->SetContent (contto);
200 	}
201 	therep->Bind (ent,repto);
202       }
203     }
204 //    Gerer le niveau d imbrication (0 = racine du transfert)
205     thelev --;
206   }
207   if (thelev == 0 && nument > 0) therts.Append(nument);
208   return res;
209 }
210 
Bind(const Handle (Standard_Transient)& ent,const Handle (Standard_Transient)& res)211     void Interface_CopyTool::Bind
212   (const Handle(Standard_Transient)& ent,
213    const Handle(Standard_Transient)& res)
214 {
215   Standard_Integer num = themod->Number(ent);
216   themap->Bind (ent,res);
217   thelst.SetTrue (num);
218 }
219 
Search(const Handle (Standard_Transient)& ent,Handle (Standard_Transient)& res) const220     Standard_Boolean Interface_CopyTool::Search
221   (const Handle(Standard_Transient)& ent,
222    Handle(Standard_Transient)& res) const
223       {  return themap->Search (ent,res);  }
224 
225 //  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
226 //                              LastFlag
227 
ClearLastFlags()228     void Interface_CopyTool::ClearLastFlags ()
229       {  thelst.Init(Standard_False);  }
230 
LastCopiedAfter(const Standard_Integer numfrom,Handle (Standard_Transient)& ent,Handle (Standard_Transient)& res) const231     Standard_Integer  Interface_CopyTool::LastCopiedAfter
232   (const Standard_Integer numfrom,
233    Handle(Standard_Transient)& ent, Handle(Standard_Transient)& res) const
234 {
235   Standard_Integer nb = thelst.Length();
236   for (Standard_Integer num = numfrom + 1; num <= nb; num ++) {
237     if (thelst.Value(num)) {
238       ent = themod->Value(num);
239       if (themap->Search(ent,res)) return num;
240     }
241   }
242   return 0;
243 }
244 
245 
246 //  #########################################################################
247 //  ....                        Actions Generales                        ....
248 
TransferEntity(const Handle (Standard_Transient)& ent)249     void Interface_CopyTool::TransferEntity
250   (const Handle(Standard_Transient)& ent)
251       {  Handle(Standard_Transient) res = Transferred(ent);  }
252 
RenewImpliedRefs()253     void Interface_CopyTool::RenewImpliedRefs ()
254 {
255   if (theimp) return;    // deja fait
256   theimp = Standard_True;
257 
258 //  Transfert Passe 2 : recuperation des relations non "Share" (mais "Imply")
259 //  c-a-d portant sur des entites qui ont pu ou non etre transferees
260 //  (Et que la 1re passe n a pas copie mais laisse en Null)
261 //  N.B. : on devrait interdire de commander des nouveaux transferts ...
262 
263   Standard_Integer nb = themod->NbEntities();
264   for (Standard_Integer i = 1; i <= nb; i ++) {
265     Handle(Standard_Transient) ent = themod->Value(i);
266     Handle(Standard_Transient) res;
267     if (!themap->Search(ent,res)) continue;        // entite pas transferee
268 //    Reconduction des references "Imply".  Attention, ne pas copier si non chargee
269     Handle(Standard_Transient) aRep;
270     if (!therep->Search(ent,aRep))
271     {
272       Implied (ent,res);
273     }
274     else
275     {
276       Handle(Interface_ReportEntity) rep = Handle(Interface_ReportEntity)::DownCast (aRep);
277       if (! rep.IsNull() && ! rep->HasNewContent())
278         Implied (ent,res);
279     }
280   }
281 }
282 
283 
FillModel(const Handle (Interface_InterfaceModel)& bmodel)284     void Interface_CopyTool::FillModel
285   (const Handle(Interface_InterfaceModel)& bmodel)
286 {
287 //  Travaux preparatoires concernant les modeles
288 //  On commence : cela implique le Header
289   bmodel->Clear();
290   bmodel->GetFromAnother(themod);
291 
292 //  Transfert Passe 1 : On prend les Entites prealablement copiees
293   Interface_EntityIterator list = CompleteResult(Standard_True);
294   bmodel->GetFromTransfer(list);
295 
296 //  Transfert Passe 2 : recuperation des relations non "Share" (mais "Imply")
297   RenewImpliedRefs();
298 }
299 
300 
CompleteResult(const Standard_Boolean withreports) const301     Interface_EntityIterator Interface_CopyTool::CompleteResult
302   (const Standard_Boolean withreports) const
303 {
304   Interface_EntityIterator iter;
305   Standard_Integer nb = themod->NbEntities();
306   for (Standard_Integer i = 1; i <= nb; i ++) {
307     Handle(Standard_Transient) ent = themod->Value(i);
308     Handle(Standard_Transient) res;
309     if (!themap->Search(ent,res)) continue;
310     if (withreports) {
311       Handle(Standard_Transient) rep;
312       if (therep->Search(ent,rep)) res = rep;
313     }
314     iter.GetOneItem(res);
315   }
316   return iter;
317 }
318 
RootResult(const Standard_Boolean withreports) const319     Interface_EntityIterator Interface_CopyTool::RootResult
320   (const Standard_Boolean withreports) const
321 {
322   Interface_EntityIterator iter;
323   Standard_Integer nb = therts.Length();
324   for (Standard_Integer i = 1; i <= nb; i ++) {
325     Standard_Integer j = therts.Value(i);
326     Handle(Standard_Transient) ent = themod->Value(j);
327     Handle(Standard_Transient) res;
328     if (!themap->Search(ent,res)) continue;
329     if (withreports) {
330       Handle(Standard_Transient) rep;
331       if (therep->Search(ent,rep)) res = rep;
332     }
333     iter.GetOneItem(res);
334   }
335   return iter;
336 }
337 
338 //=======================================================================
339 //function : ~Interface_CopyTool
340 //purpose  : Destructor
341 //=======================================================================
342 
~Interface_CopyTool()343 Interface_CopyTool::~Interface_CopyTool()
344 {
345 }
346