Salome HOME
debug#2 (setID(); GetID())
[modules/hydro.git] / src / HYDROData / HYDROData_PriorityQueue.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include <HYDROData_PriorityQueue.h>
20 #include <HYDROData_CalculationCase.h>
21 #include <HYDROData_Iterator.h>
22 #include <TDataStd_ReferenceList.hxx>
23 #include <TDataStd_Integer.hxx>
24 #include <TDF_ChildIterator.hxx>
25
26 HYDROData_PriorityQueue::HYDROData_PriorityQueue( HYDROData_CalculationCase* theCalcCase,
27                                                   Standard_Integer aTag )
28 {
29   myObjects = theCalcCase->GetGeometryObjects();
30   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
31   {
32     Handle(HYDROData_Entity) anObj = myObjects.Value( i );
33     if( !anObj.IsNull() )
34     {
35       QString anObjName = anObj->GetName();
36       myNames[anObjName] = anObj;
37     }
38   }
39
40   myRules = GetRules( theCalcCase->Label().FindChild( aTag ) );
41 }
42
43 HYDROData_PriorityQueue::~HYDROData_PriorityQueue()
44 {
45 }
46
47 Handle(HYDROData_Entity) HYDROData_PriorityQueue::GetMostPriorityObject( const QStringList& theZoneObjects,
48                                                                          HYDROData_Zone::MergeType& theMergeType ) const
49 {
50   QStringList aSortedZoneObjects;
51   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
52   {
53     QString aName = myObjects.Value( i )->GetName();
54     if( theZoneObjects.contains( aName ) )
55       aSortedZoneObjects.append( aName );
56   }
57
58   Handle(HYDROData_Entity) aMostPriorityObj;
59   theMergeType = HYDROData_Zone::Merge_UNKNOWN;
60   QStringList::const_iterator anIt = aSortedZoneObjects.begin(), aLast = aSortedZoneObjects.end();
61   for( ; anIt!=aLast; anIt++ )
62   {
63     HYDROData_Zone::MergeType aLocalMerge = HYDROData_Zone::Merge_UNKNOWN;
64     Handle(HYDROData_Entity) anObj = myNames[*anIt];
65     if( !anObj.IsNull() )
66     {
67       if( aMostPriorityObj.IsNull() )
68       {
69         aMostPriorityObj = anObj;
70         continue;
71       }
72
73       bool isMorePriority = IsMorePriority( anObj, aMostPriorityObj, aLocalMerge );
74
75       if( isMorePriority )
76         aMostPriorityObj = anObj;
77
78       if( aLocalMerge != HYDROData_Zone::Merge_UNKNOWN && 
79           ( theMergeType==HYDROData_Zone::Merge_UNKNOWN || isMorePriority ) )
80         theMergeType = aLocalMerge;
81     }
82   }
83   return aMostPriorityObj;
84 }
85
86 bool HYDROData_PriorityQueue::IsMorePriority( const Handle(HYDROData_Entity)& theObj1,
87                                               const Handle(HYDROData_Entity)& theObj2,
88                                               HYDROData_Zone::MergeType& theMergeType ) const
89 {
90   // 1. First we check custom rules
91   HYDROData_ListOfRules::const_iterator anIt = myRules.begin(), aLast = myRules.end();
92   for( ; anIt!=aLast; anIt++ )
93   {
94     if( anIt->Object1->Label()==theObj1->Label() && anIt->Object2->Label()==theObj2->Label() )
95     {
96       theMergeType = anIt->MergeType;
97       return anIt->Priority==GREATER;
98     }
99     if( anIt->Object1->Label()==theObj2->Label() && anIt->Object2->Label()==theObj1->Label() )
100     {
101       theMergeType = anIt->MergeType;
102       return anIt->Priority==LESS;
103     }
104   }
105
106   // 2. If no custom rule found, the standard ordering list is applied
107   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
108   {
109     if( myObjects.Value( i )->Label() == theObj1->Label() )
110     {
111       theMergeType = HYDROData_Zone::Merge_Object;
112       return true;
113     }
114     if( myObjects.Value( i )->Label() == theObj2->Label() )
115     {
116       theMergeType = HYDROData_Zone::Merge_Object;
117       return false;
118     }
119   }
120   return false;
121 }
122
123 void HYDROData_PriorityQueue::ClearRules( TDF_Label& theRulesLabel )
124 {
125   theRulesLabel.ForgetAllAttributes( true );
126 }
127
128 enum HYDROData_PriorityQueueTag
129 {
130   Object1_Tag,
131   Priority_Tag,
132   Object2_Tag,
133   Merge_Tag,
134 };
135
136 void HYDROData_PriorityQueue::AddRule( TDF_Label&                      theRulesLabel,
137                                        const Handle(HYDROData_Entity)& theObject1,
138                                        HYDROData_PriorityType          thePriority,
139                                        const Handle(HYDROData_Entity)& theObject2,
140                                        HYDROData_Zone::MergeType       theMergeType )
141 {
142   // Get the last rule index
143   Standard_Integer aRuleIndex = 0;
144   Handle(TDataStd_Integer) anIntVal;
145   if ( theRulesLabel.FindAttribute( TDataStd_Integer::GetID(), anIntVal ) ) {
146     aRuleIndex = anIntVal->Get();
147   }
148
149   TDF_Label aNewRuleLab = theRulesLabel.FindChild( aRuleIndex );
150
151   TDF_Label anObj1Lab = aNewRuleLab.FindChild( Object1_Tag );
152   Handle(TDataStd_ReferenceList) aRefs = TDataStd_ReferenceList::Set( anObj1Lab );
153   aRefs->SetID(TDataStd_ReferenceList::GetID());
154   aRefs->Append( theObject1->Label() );
155   
156   TDF_Label aPriorityLab = aNewRuleLab.FindChild( Priority_Tag );
157   Handle(TDataStd_Integer) anPLAttr = TDataStd_Integer::Set( aPriorityLab, thePriority );
158   anPLAttr->SetID(TDataStd_Integer::GetID());
159
160   TDF_Label anObj2Lab = aNewRuleLab.FindChild( Object2_Tag );
161   aRefs = TDataStd_ReferenceList::Set( anObj2Lab );
162   aRefs->SetID(TDataStd_ReferenceList::GetID());
163   aRefs->Append( theObject2->Label() );
164
165   TDF_Label aMergeLab = aNewRuleLab.FindChild( Merge_Tag );
166   Handle(TDataStd_Integer) anMLAttr = TDataStd_Integer::Set( aMergeLab, theMergeType );
167   anMLAttr->SetID(TDataStd_Integer::GetID());
168
169   // Increment the last rule index
170   Handle(TDataStd_Integer) anRLAttr = TDataStd_Integer::Set( theRulesLabel, aRuleIndex + 1 );
171   anRLAttr->SetID(TDataStd_Integer::GetID());
172 }
173
174 HYDROData_ListOfRules HYDROData_PriorityQueue::GetRules( const TDF_Label& theRulesLabel )
175 {
176   HYDROData_ListOfRules aRules;
177
178   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
179   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
180
181   TDF_ChildIterator anIt( theRulesLabel );
182   for( ; anIt.More(); anIt.Next() )
183   {
184     TDF_Label aRuleLabel = anIt.Value();
185
186     bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
187     bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
188     bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
189     bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
190
191     if( isObj1OK && isPriorityOK && isObj2OK && isMergeOK )
192     {
193       HYDROData_CustomRule aRule;
194       aRule.Object1 = HYDROData_Iterator::Object( aRefs1->First() );
195       aRule.Priority = ( HYDROData_PriorityType ) aPriorityAttr->Get();
196       aRule.Object2 = HYDROData_Iterator::Object( aRefs2->First() );
197       aRule.MergeType = ( HYDROData_Zone::MergeType ) aMergeAttr->Get();
198       aRules.append( aRule );
199     }
200   }
201
202   return aRules;
203 }
204
205 QString HYDROData_PriorityQueue::DumpRules( const TDF_Label& theRulesLab )
206 {
207   QString aDump = "Rules:\n";
208
209   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
210   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
211   for( ; anIt!=aLast; anIt++ )
212   {
213     QString aRule = anIt->Object1->GetName() + " ";
214     aRule += ( anIt->Priority == LESS ? "<" : ">" ) + QString( " " );
215     aRule += anIt->Object2->GetName() + " ";
216
217     switch( anIt->MergeType )
218     {
219     case HYDROData_Zone::Merge_UNKNOWN:
220       aRule += "unknown";
221       break;
222     case HYDROData_Zone::Merge_ZMIN:
223       aRule += "zmin";
224       break;
225     case HYDROData_Zone::Merge_ZMAX:
226       aRule += "zmax";
227       break;
228     case HYDROData_Zone::Merge_Object:
229       aRule += "object";
230       break;
231     }
232     aDump += aRule + "\n";
233   }
234   return aDump;
235 }
236
237 void HYDROData_PriorityQueue::DumpRulesToPython( const TDF_Label& theRulesLab,
238                                                  const QString& theCalcCaseName,
239                                                  QStringList& theScript )
240 {
241   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
242   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
243   for( ; anIt!=aLast; anIt++ )
244   {
245     QString anObj1 = anIt->Object1->GetObjPyName();
246     QString anObj2 = anIt->Object2->GetObjPyName();
247     QString aPriority = anIt->Priority == LESS ? "LESS" : "GREATER";
248     QString aMergeType;
249
250     HYDROData_CalculationCase::DataTag aDataTag = HYDROData_CalculationCase::DataTag_CustomRules;
251
252     switch( anIt->MergeType )
253     {
254     case HYDROData_Zone::Merge_UNKNOWN:
255       aMergeType = "HYDROData_Zone.Merge_UNKNOWN";
256       break;
257     case HYDROData_Zone::Merge_ZMIN:
258       aMergeType = "HYDROData_Zone.Merge_ZMIN";
259       break;
260     case HYDROData_Zone::Merge_ZMAX:
261       aMergeType = "HYDROData_Zone.Merge_ZMAX";
262       break;
263     case HYDROData_Zone::Merge_Object:
264       aMergeType = "HYDROData_Zone.Merge_Object";
265       break;
266     }
267
268     QString aRule = QString( "%0.AddRule( %1, %2, %3, %4, %5 )" ).
269       arg( theCalcCaseName ).arg( anObj1 ).arg( aPriority ).arg( anObj2 ).arg( aMergeType ).arg( aDataTag );
270
271     theScript << aRule;
272   }
273 }
274
275 bool HYDROData_PriorityQueue::GetRule( const TDF_Label& theRulesLab,
276                                        int theIndex, 
277                                        Handle(HYDROData_Entity)&  theObject1,
278                                        HYDROData_PriorityType&    thePriority,
279                                        Handle(HYDROData_Entity)&  theObject2,
280                                        HYDROData_Zone::MergeType& theMergeType )
281 {
282   TDF_Label aRuleLabel = theRulesLab.FindChild( theIndex );
283
284   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
285   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
286
287   bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
288   bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
289   bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
290   bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
291
292   bool isOK = isObj1OK && isPriorityOK && isObj2OK && isMergeOK;
293   if( isOK )
294   {
295     theObject1   = HYDROData_Iterator::Object( aRefs1->First() );
296     thePriority  = ( HYDROData_PriorityType ) aPriorityAttr->Get();
297     theObject2   = HYDROData_Iterator::Object( aRefs2->First() );
298     theMergeType = ( HYDROData_Zone::MergeType ) aMergeAttr->Get();
299   }
300   return isOK;
301 }