Salome HOME
35067de1e99f8f04ac6ee2db46dbd13311f0f079
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeTableOfInteger.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : SALOMEDSImpl_AttributeTableOfInteger.cxx
24 //  Author : Michael Ponikarov
25 //  Module : SALOME
26 //
27 #include "SALOMEDSImpl_AttributeTableOfInteger.hxx"
28
29 #include <sstream>
30 #include <algorithm>
31
32 #define SEPARATOR '\1'
33 typedef std::map<int, int>::const_iterator MI;
34
35 static std::string getUnit(std::string theString)
36 {
37   std::string aString(theString);
38   int aPos = aString.find(SEPARATOR);
39   if(aPos <= 0 || aPos == aString.size() ) return std::string();
40   return aString.substr(aPos+1, aString.size());
41 }
42
43 static std::string getTitle(std::string theString)
44 {
45   std::string aString(theString);
46   int aPos = aString.find(SEPARATOR);
47   if(aPos < 1) return aString;
48   if(aPos == 0) return std::string();
49   return aString.substr(0, aPos);
50 }
51
52 const std::string& SALOMEDSImpl_AttributeTableOfInteger::GetID() 
53 {
54   static std::string SALOMEDSImpl_AttributeTableOfIntegerID ("128371A0-8F52-11d6-A8A3-0001021E8C7F");
55   return SALOMEDSImpl_AttributeTableOfIntegerID;
56 }
57
58 SALOMEDSImpl_AttributeTableOfInteger* SALOMEDSImpl_AttributeTableOfInteger::Set(const DF_Label& label) 
59 {
60   SALOMEDSImpl_AttributeTableOfInteger* A = NULL;
61   if (!(A=(SALOMEDSImpl_AttributeTableOfInteger*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfInteger::GetID()))) {
62     A = new SALOMEDSImpl_AttributeTableOfInteger();
63     label.AddAttribute(A);
64   }
65   return A;
66 }
67
68 SALOMEDSImpl_AttributeTableOfInteger::SALOMEDSImpl_AttributeTableOfInteger() 
69 :SALOMEDSImpl_GenericAttribute("AttributeTableOfInteger")
70 {
71   myNbRows = 0;
72   myNbColumns = 0;
73 }
74
75 void SALOMEDSImpl_AttributeTableOfInteger::SetNbColumns(const int theNbColumns)
76 {
77   CheckLocked();  
78   Backup();
79   
80   std::map<int, int> aMap;
81   aMap = myTable;
82   myTable.clear();
83
84   for(MI p = aMap.begin(); p != aMap.end(); p++) {
85     int aRow = (int)(p->first/myNbColumns) + 1;
86     int aCol = (int)(p->first - myNbColumns*(aRow-1));
87     if(aCol == 0) { aCol = myNbColumns; aRow--; }
88     if(aCol > theNbColumns) continue;
89     int aKey = (aRow-1)*theNbColumns+aCol;
90     myTable[aKey] = p->second;
91   }
92
93   myNbColumns = theNbColumns;
94
95   while (myCols.size() < myNbColumns) { // append empty columns titles
96     myCols.push_back(std::string(""));
97   }
98
99   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
100 }
101
102 void SALOMEDSImpl_AttributeTableOfInteger::SetTitle(const std::string& theTitle) 
103 {
104   CheckLocked();  
105   Backup();
106   myTitle = theTitle;
107
108   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
109 }
110
111 std::string SALOMEDSImpl_AttributeTableOfInteger::GetTitle() const 
112 {
113   return myTitle;
114 }
115
116 void SALOMEDSImpl_AttributeTableOfInteger::SetRowData(const int theRow,
117                                                       const std::vector<int>& theData) 
118 {
119   CheckLocked();  
120   if(theData.size() > myNbColumns) SetNbColumns(theData.size());
121
122   Backup();
123
124   while (myRows.size() < theRow) { // append new row titles
125     myRows.push_back(std::string(""));
126   }
127
128   int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
129   for(i = 1; i <= aLength; i++) {
130     myTable[aShift + i] = theData[i-1];
131   }
132
133   if(theRow > myNbRows) myNbRows = theRow;
134   
135   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
136 }
137
138 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetRowData(const int theRow)
139 {
140   std::vector<int> aSeq;
141   int i, aShift = (theRow-1)*myNbColumns;
142   for(i = 1; i <= myNbColumns; i++) {
143      if(myTable.find(aShift+i) != myTable.end()) 
144        aSeq.push_back(myTable[aShift+i]);
145      else
146        aSeq.push_back(0);
147   }
148   
149   return aSeq;
150 }
151
152 void SALOMEDSImpl_AttributeTableOfInteger::SetRowTitle(const int theRow,
153                                                        const std::string& theTitle) 
154 {
155   CheckLocked();  
156   Backup();
157   std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
158   if(aUnit.size()>0) {
159     aTitle += SEPARATOR;
160     aTitle += aUnit;
161   }
162   myRows[theRow-1] =  aTitle;
163   
164   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
165 }
166
167 void SALOMEDSImpl_AttributeTableOfInteger::SetRowUnit(const int theRow,
168                                                       const std::string& theUnit) 
169 {
170   CheckLocked();  
171   Backup();
172   std::string aTitle = GetRowTitle(theRow);
173   aTitle += SEPARATOR;
174   aTitle += theUnit;
175
176   myRows[theRow-1] = aTitle;
177   
178   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
179 }
180
181 void SALOMEDSImpl_AttributeTableOfInteger::SetRowUnits(const std::vector<std::string>& theUnits)
182 {
183   if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
184   int aLength = theUnits.size(), i;
185   for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
186   
187   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
188 }
189
190 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetRowUnits()
191 {
192   std::vector<std::string> aSeq;
193   int aLength = myRows.size(), i;
194   for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
195   return aSeq;
196 }
197
198 void SALOMEDSImpl_AttributeTableOfInteger::SetRowTitles(const std::vector<std::string>& theTitles)
199 {
200   if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
201   int aLength = theTitles.size(), i;
202   for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
203   
204   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
205 }
206
207 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetRowTitles()
208 {
209   std::vector<std::string> aSeq;
210   int aLength = myRows.size(), i;
211   for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
212   return aSeq;
213 }
214
215 std::string SALOMEDSImpl_AttributeTableOfInteger::GetRowTitle(const int theRow) const 
216 {
217   return getTitle(myRows[theRow-1]);
218 }
219
220 std::string SALOMEDSImpl_AttributeTableOfInteger::GetRowUnit(const int theRow) const 
221 {
222   return getUnit(myRows[theRow-1]);
223 }
224
225 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnData(const int theColumn,
226                                                          const std::vector<int>& theData) 
227 {
228   CheckLocked();  
229   if(theColumn > myNbColumns) SetNbColumns(theColumn);
230
231   Backup();
232
233   int i, aLength = theData.size();
234   for(i = 1; i <= aLength; i++) {
235     myTable[myNbColumns*(i-1)+theColumn] = theData[i-1];
236   }
237
238   if(aLength > myNbRows) {
239     myNbRows = aLength;
240     while (myRows.size() < myNbRows) { // append empty row titles
241       myRows.push_back(std::string(""));
242     }
243   }
244   
245   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
246 }
247
248
249 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetColumnData(const int theColumn)
250 {
251   std::vector<int> aSeq;
252   int i, anIndex;
253   for(i = 1; i <= myNbRows; i++) {
254     anIndex = myNbColumns*(i-1) + theColumn;
255     if(myTable.find(anIndex) != myTable.end()) 
256       aSeq.push_back(myTable[anIndex]);
257     else
258       aSeq.push_back(0);
259   }
260   
261   return aSeq;
262 }
263
264 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnTitle(const int theColumn,
265                                                           const std::string& theTitle) 
266 {
267   CheckLocked();                                                      
268   Backup();
269   while(myCols.size() < theColumn) myCols.push_back(std::string(""));
270   myCols[theColumn-1] = theTitle;
271   
272   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
273 }
274
275 std::string SALOMEDSImpl_AttributeTableOfInteger::GetColumnTitle(const int theColumn) const 
276 {
277   if(myCols.empty()) return "";
278   if(myCols.size() < theColumn) return "";
279   return myCols[theColumn-1];
280 }
281
282 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnTitles(const std::vector<std::string>& theTitles)
283 {
284   if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
285   int aLength = theTitles.size(), i;
286   for(i = 0; i < aLength; i++)  myCols[i] = theTitles[i];
287   
288   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
289 }
290
291 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetColumnTitles()
292 {
293   std::vector<std::string> aSeq;
294   int aLength = myCols.size(), i;
295   for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
296   return aSeq;
297 }
298
299 int SALOMEDSImpl_AttributeTableOfInteger::GetNbRows() const
300 {
301   return myNbRows;
302 }
303
304 int SALOMEDSImpl_AttributeTableOfInteger::GetNbColumns() const
305 {
306   return myNbColumns;
307 }
308
309 void SALOMEDSImpl_AttributeTableOfInteger::PutValue(const int theValue,
310                                                     const int theRow,
311                                                     const int theColumn) 
312 {
313   CheckLocked();  
314   //Backup();
315   if(theColumn > myNbColumns) SetNbColumns(theColumn);
316
317   int anIndex = (theRow-1)*myNbColumns + theColumn;
318   myTable[anIndex] = theValue;
319
320   if(theRow > myNbRows) {
321     while (myRows.size() < theRow) { // append empty row titles
322       myRows.push_back(std::string(""));
323     }
324     myNbRows = theRow;
325   }
326   
327   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
328 }
329
330 bool SALOMEDSImpl_AttributeTableOfInteger::HasValue(const int theRow,
331                                                     const int theColumn) 
332 {
333   if(theRow > myNbRows || theRow < 1) return false;
334   if(theColumn > myNbColumns || theColumn < 1) return false;
335   int anIndex = (theRow-1)*myNbColumns + theColumn;
336   return (myTable.find(anIndex) != myTable.end()); 
337 }
338
339 int SALOMEDSImpl_AttributeTableOfInteger::GetValue(const int theRow,
340                                                    const int theColumn) 
341 {
342   if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
343   if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
344
345   int anIndex = (theRow-1)*myNbColumns + theColumn;
346   if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
347   
348   throw DFexception("Invalid cell index");
349   return 0;
350 }
351
352 void SALOMEDSImpl_AttributeTableOfInteger::RemoveValue(const int theRow, const int theColumn)
353 {
354   CheckLocked();  
355   if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
356   if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
357
358   int anIndex = (theRow-1)*myNbColumns + theColumn;
359   if (myTable.find(anIndex) != myTable.end()) {
360     //Backup();
361     myTable.erase(anIndex);
362     SetModifyFlag(); // table is modified
363   }
364 }
365
366 const std::string& SALOMEDSImpl_AttributeTableOfInteger::ID() const
367 {
368   return GetID();
369 }
370
371 void SALOMEDSImpl_AttributeTableOfInteger::Restore(DF_Attribute* with) 
372 {
373   int anIndex;
374   SALOMEDSImpl_AttributeTableOfInteger* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfInteger*>(with);
375   if(!aTable) throw DFexception("Can't Restore from a null attribute");    
376
377   myTable.clear();
378   myCols.clear();
379   myRows.clear();
380
381   myTable = aTable->myTable;
382   myNbRows = aTable->myNbRows;
383   myNbColumns = aTable->myNbColumns;
384   myTitle = aTable->myTitle;
385   
386   for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
387     myRows.push_back(aTable->GetRowTitle(anIndex));
388
389   for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++) 
390     myCols.push_back(aTable->GetColumnTitle(anIndex));
391 }
392
393 DF_Attribute* SALOMEDSImpl_AttributeTableOfInteger::NewEmpty() const
394 {
395   return new SALOMEDSImpl_AttributeTableOfInteger();
396 }
397
398 void SALOMEDSImpl_AttributeTableOfInteger::Paste(DF_Attribute* into)
399 {
400   int anIndex;
401   SALOMEDSImpl_AttributeTableOfInteger* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfInteger*>(into);
402   if(!aTable) throw DFexception("Can't Paste into a null attribute");    
403
404   aTable->myTable.clear();
405   aTable->myCols.clear();
406   aTable->myRows.clear();
407
408   aTable->myTable = myTable;
409   aTable->myTitle = myTitle;
410   aTable->myNbRows = myNbRows;
411   aTable->myNbColumns = myNbColumns;
412
413   for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
414     aTable->myRows.push_back(GetRowTitle(anIndex));
415   for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++) 
416     aTable->myCols.push_back(GetColumnTitle(anIndex));
417 }
418
419 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetSetRowIndices(const int theRow)
420 {
421   std::vector<int> aSeq;
422
423   int i, aShift = myNbColumns*(theRow-1);
424   for(i = 1; i <= myNbColumns; i++) {
425     if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
426   }
427   
428   return aSeq;
429 }
430
431 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetSetColumnIndices(const int theColumn)
432 {
433   std::vector<int> aSeq;
434
435   int i, anIndex;
436   for(i = 1; i <= myNbRows; i++) {
437     anIndex = myNbColumns*(i-1)+theColumn;
438     if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
439   }
440   
441   return aSeq;
442 }
443
444 std::string SALOMEDSImpl_AttributeTableOfInteger::Save() 
445 {
446   std::string aString;
447   char* buffer = new char[1024];
448   int i, j, l;
449
450   //Title
451   l = myTitle.size();
452   sprintf(buffer, "%d\n", l);
453   aString+=buffer;
454   for(i=0; i<l; i++) {
455     aString += myTitle[i];
456     aString +='\n';
457   }
458   
459   //Nb rows
460   sprintf(buffer, "%d\n", myNbRows);
461   aString+=buffer;
462
463   //Row titles
464   for(i=0; i<myNbRows; i++) {
465     l = myRows[i].size();
466     sprintf(buffer, "%d\n", l);
467     aString+=buffer;
468     for(j=0; j<l; j++) {
469       aString += myRows[i][j];
470       aString += '\n';
471     }
472   }  
473
474   //Nb columns
475   sprintf(buffer, "%d\n", myNbColumns);
476   aString+=buffer;
477
478   //Columns titles
479   for(i=0; i<myNbColumns; i++) {
480     l = myCols[i].size();
481     sprintf(buffer, "%d\n", l);
482     aString+=buffer;
483     for(j=0; j<l; j++) {
484       aString += myCols[i][j];
485       aString += '\n';
486     }
487   }
488
489   //Store the table values
490   l = myTable.size();
491   sprintf(buffer, "%d\n", l);
492   aString+=buffer;
493   for(MI p = myTable.begin(); p != myTable.end(); p++) {
494     sprintf(buffer, "%d\n%d\n", p->first, p->second);
495     aString += buffer;
496   }
497
498   delete []buffer;
499   return aString;
500 }
501
502 void SALOMEDSImpl_AttributeTableOfInteger::Load(const std::string& value) 
503 {
504   std::vector<std::string> v;
505   int i,  j, l, pos, aSize = (int)value.size(); 
506   for(i = 0, pos = 0; i<aSize; i++) {
507     if(value[i] == '\n') {
508        v.push_back(value.substr(pos, i-pos));
509        pos = i+1;
510     }
511   }
512
513   Backup();
514
515   pos = 0;
516   std::string aStr;
517
518   //Title
519   l = strtol(v[pos++].c_str(), NULL, 10);
520
521   myTitle = std::string(l, 0);
522   for(i=0; i<l; i++) {
523     myTitle[i] = v[pos++][0];
524   }
525
526   //Nb rows
527   myNbRows = strtol(v[pos++].c_str(), NULL, 10);
528
529   //Rows titles
530   myRows.clear();  
531   for(i=1; i<=myNbRows; i++) { 
532     l = strtol(v[pos++].c_str(), NULL, 10);
533     aStr = std::string(l,0);
534     for(j=0; j<l; j++) {
535       aStr[j] = v[pos++][0];
536     }
537     myRows.push_back(aStr);
538   }
539
540   //Nb columns
541   myNbColumns = strtol(v[pos++].c_str(), NULL, 10);
542
543   //Columns titles
544   myCols.clear();
545   for(i=1; i<=myNbColumns; i++) {
546     l = strtol(v[pos++].c_str(), NULL, 10);
547     aStr = std::string(l,0);
548     for(j=0; j<l; j++) {
549       aStr[j] = v[pos++][0];
550     }
551     myCols.push_back(aStr);
552   }
553
554   //Restore the table values
555   l = strtol(v[pos++].c_str(), NULL, 10);
556   myTable.clear();
557   for(i=1; i<=l; i++) {
558     int aKey = strtol(v[pos++].c_str(), NULL, 10);
559     int aValue = strtol(v[pos++].c_str(), NULL, 10);
560     myTable[aKey] = aValue;
561   }
562 }
563
564 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
565 {
566   CheckLocked();
567   std::vector<int> result;
568   if ( theRow > 0 && theRow <= myNbRows ) {
569     std::vector<int> indices( myNbColumns );
570     int cnt = 0;
571     for ( int i = 0; i < myNbColumns; i++ ) {
572       if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
573         indices[cnt++] = i+1;
574       }
575     }
576     indices.resize(cnt);
577     
578     TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theRow, true );
579     std::stable_sort( indices.begin(), indices.end(), sorter );
580     
581     if ( sortPolicy == EmptyIgnore ) {
582       std::vector<int> other( myNbColumns );
583       cnt = 0;
584       for( int i = 0; i < myNbColumns; i++ )
585         other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
586       indices = other;
587     }
588     result = indices;
589
590     for ( int col = 0; col < indices.size(); col++ ) {
591       int idx = indices[col];
592       if ( col+1 == idx ) continue;
593       SwapCells(theRow, col+1, theRow, idx);
594       int idx1 = 0;
595       for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
596         if ( indices[i] == col+1 ) idx1 = i;
597       indices[idx1] = idx;
598     }
599     // no need for SetModifyFlag(), since it is done by SwapCells()
600   }
601   return result;
602 }
603
604 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
605 {
606   CheckLocked();  
607   std::vector<int> result;
608   if ( theColumn > 0 && theColumn <= myNbColumns ) {
609     std::vector<int> indices( myNbRows );
610     int cnt = 0;
611     for ( int i = 0; i < myNbRows; i++ ) {
612       if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
613         indices[cnt++] = i+1;
614       }
615     }
616     indices.resize(cnt);
617     
618     TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theColumn, false );
619     std::stable_sort( indices.begin(), indices.end(), sorter );
620     
621     if ( sortPolicy == EmptyIgnore ) {
622       std::vector<int> other( myNbRows );
623       cnt = 0;
624       for( int i = 0; i < myNbRows; i++ )
625         other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
626       indices = other;
627     }
628     result = indices;
629
630     for ( int row = 0; row < indices.size(); row++ ) {
631       int idx = indices[row];
632       if ( row+1 == idx ) continue;
633       SwapCells(row+1, theColumn, idx, theColumn);
634       int idx1 = 0;
635       for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
636         if ( indices[i] == row+1 ) idx1 = i;
637       indices[idx1] = idx;
638     }
639     // no need for SetModifyFlag(), since it is done by SwapCells()
640   }
641   return result;
642 }
643
644 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortByRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
645 {
646   CheckLocked();  
647   std::vector<int> result;
648   if ( theRow > 0 && theRow <= myNbRows ) {
649     std::vector<int> indices( myNbColumns );
650     int cnt = 0;
651     for ( int i = 0; i < myNbColumns; i++ ) {
652       if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
653         indices[cnt++] = i+1;
654       }
655     }
656     indices.resize(cnt);
657     
658     TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theRow, true );
659     std::stable_sort( indices.begin(), indices.end(), sorter );
660
661     if ( sortPolicy == EmptyIgnore ) {
662       std::vector<int> other( myNbColumns );
663       cnt = 0;
664       for( int i = 0; i < myNbColumns; i++ )
665         other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
666       indices = other;
667     }
668     result = indices;
669
670     for ( int col = 0; col < indices.size(); col++ ) {
671       int idx = indices[col];
672       if ( col+1 == idx ) continue;
673       SwapColumns(col+1, idx);
674       int idx1 = 0;
675       for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
676         if ( indices[i] == col+1 ) idx1 = i;
677       indices[idx1] = idx;
678     }
679     // no need for SetModifyFlag(), since it is done by SwapColumns()
680   }
681   return result;
682 }
683
684 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortByColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
685 {
686   CheckLocked();  
687   std::vector<int> result;
688   if ( theColumn > 0 && theColumn <= myNbColumns ) {
689     std::vector<int> indices( myNbRows );
690     int cnt = 0;
691     for ( int i = 0; i < myNbRows; i++ ) {
692       if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
693         indices[cnt++] = i+1;
694       }
695     }
696     indices.resize(cnt);
697     
698     TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theColumn, false );
699     std::stable_sort( indices.begin(), indices.end(), sorter );
700
701     if ( sortPolicy == EmptyIgnore ) {
702       std::vector<int> other( myNbRows );
703       cnt = 0;
704       for( int i = 0; i < myNbRows; i++ )
705         other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
706       indices = other;
707     }
708     result = indices;
709
710     for ( int row = 0; row < indices.size(); row++ ) {
711       int idx = indices[row];
712       if ( row+1 == idx ) continue;
713       SwapRows(row+1, idx);
714       int idx1 = 0;
715       for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
716         if ( indices[i] == row+1 ) idx1 = i;
717       indices[idx1] = idx;
718     }
719     // no need for SetModifyFlag(), since it is done by SwapRows()
720   }
721   return result;
722 }
723
724 void SALOMEDSImpl_AttributeTableOfInteger::SwapCells(const int theRow1, const int theColumn1, 
725                                                      const int theRow2, const int theColumn2)
726 {
727   CheckLocked();  
728   if (theRow1    > myNbRows    || theRow1 < 1)    throw DFexception("Invalid cell index");
729   if (theRow2    > myNbRows    || theRow2 < 1)    throw DFexception("Invalid cell index");
730   if (theColumn1 > myNbColumns || theColumn1 < 1) throw DFexception("Invalid cell index");
731   if (theColumn2 > myNbColumns || theColumn2 < 1) throw DFexception("Invalid cell index");
732
733   int anIndex1 = (theRow1-1)*myNbColumns + theColumn1;
734   int anIndex2 = (theRow2-1)*myNbColumns + theColumn2;
735
736   bool hasValue1 = myTable.find(anIndex1) != myTable.end();
737   bool hasValue2 = myTable.find(anIndex2) != myTable.end();
738
739   if (!hasValue1 && !hasValue2) return;                   // nothing changed
740
741   int  value1    = hasValue1 ? myTable[anIndex1] : 0;
742   int  value2    = hasValue2 ? myTable[anIndex2] : 0;
743
744   if (hasValue1 && hasValue2 && value1 == value2) return; // nothing changed
745
746   if (hasValue1) myTable[anIndex2] = value1;
747   else           myTable.erase(anIndex2);
748   if (hasValue2) myTable[anIndex1] = value2;
749   else           myTable.erase(anIndex1);
750
751   SetModifyFlag(); // table is modified
752 }
753
754 void SALOMEDSImpl_AttributeTableOfInteger::SwapRows(const int theRow1, const int theRow2)
755 {
756   CheckLocked();  
757   for (int i = 1; i <= myNbColumns; i++)
758     SwapCells(theRow1, i, theRow2, i);
759   // swap row titles
760   std::string tmp = myRows[theRow1-1];
761   myRows[theRow1-1] = myRows[theRow2-1];
762   myRows[theRow2-1] = tmp;
763   // no need for SetModifyFlag(), since it is done by SwapCells()
764 }
765
766 void SALOMEDSImpl_AttributeTableOfInteger::SwapColumns(const int theColumn1, const int theColumn2)
767 {
768   CheckLocked();  
769   for (int i = 1; i <= myNbRows; i++)
770     SwapCells(i, theColumn1, i, theColumn2);
771   // swap column titles
772   std::string tmp = myCols[theColumn1-1];
773   myCols[theColumn1-1] = myCols[theColumn2-1];
774   myCols[theColumn2-1] = tmp;
775   // no need for SetModifyFlag(), since it is done by SwapCells()
776 }
777