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