Salome HOME
Bug IPAL19426, fixed methods Save/Load
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeTableOfString.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : SALOMEDSImpl_AttributeTableOfString.cxx
21 //  Author : Sergey Ruin
22 //  Module : SALOME
23
24 #include <SALOMEDSImpl_AttributeTableOfString.hxx>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <strstream>
28
29 using namespace std;
30
31 #define SEPARATOR '\1'
32
33 typedef map<int, string>::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_AttributeTableOfString::GetID() 
53 {
54   static std::string SALOMEDSImpl_AttributeTableOfStringID ("128371A4-8F52-11d6-A8A3-0001021E8C7F");
55   return SALOMEDSImpl_AttributeTableOfStringID;
56 }
57
58 SALOMEDSImpl_AttributeTableOfString* SALOMEDSImpl_AttributeTableOfString::Set(const DF_Label& label) 
59 {
60   SALOMEDSImpl_AttributeTableOfString* A = NULL;
61   if (!(A=(SALOMEDSImpl_AttributeTableOfString*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfString::GetID()))) {
62     A = new SALOMEDSImpl_AttributeTableOfString();
63     label.AddAttribute(A);
64   }
65   return A;
66 }
67
68 SALOMEDSImpl_AttributeTableOfString::SALOMEDSImpl_AttributeTableOfString() 
69 :SALOMEDSImpl_GenericAttribute("AttributeTableOfString")
70 {
71   myNbRows = 0;
72   myNbColumns = 0;
73 }
74
75 void SALOMEDSImpl_AttributeTableOfString::SetNbColumns(const int theNbColumns)
76 {
77   CheckLocked();  
78   Backup();
79   
80   map<int, string> 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_AttributeTableOfString::SetRowTitle(const int theRow,
103                                                       const std::string& theTitle) 
104 {
105   CheckLocked();  
106   Backup();
107   std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
108   if(aUnit.size()>0) {
109     aTitle += SEPARATOR;
110     aTitle += aUnit;
111   }
112   myRows[theRow-1] = aTitle;
113   
114   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
115 }
116
117 void SALOMEDSImpl_AttributeTableOfString::SetRowUnit(const int theRow,
118                                                      const std::string& theUnit) 
119 {
120   CheckLocked();  
121   Backup();
122   std::string aTitle = GetRowTitle(theRow);
123   aTitle += SEPARATOR;
124   aTitle += theUnit;
125
126   myRows[theRow-1] = aTitle;
127   
128   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
129 }
130
131 void SALOMEDSImpl_AttributeTableOfString::SetRowUnits(const vector<string>& theUnits)
132 {
133   if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
134   int aLength = theUnits.size(), i;
135   for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
136 }
137
138 vector<string> SALOMEDSImpl_AttributeTableOfString::GetRowUnits()
139 {
140   vector<string> aSeq;
141   int aLength = myRows.size(), i;
142   for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
143   return aSeq;
144 }
145
146 void SALOMEDSImpl_AttributeTableOfString::SetRowTitles(const vector<string>& theTitles)
147 {
148   if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
149   int aLength = theTitles.size(), i;
150   for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
151   
152   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
153 }
154
155 vector<string> SALOMEDSImpl_AttributeTableOfString::GetRowTitles()
156 {
157   vector<string> aSeq;
158   int aLength = myRows.size(), i;
159   for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
160   return aSeq;
161 }
162
163
164 std::string SALOMEDSImpl_AttributeTableOfString::GetRowTitle(const int theRow) const 
165 {
166   return getTitle(myRows[theRow-1]);
167 }
168
169
170 std::string SALOMEDSImpl_AttributeTableOfString::GetRowUnit(const int theRow) const 
171 {
172   return getUnit(myRows[theRow-1]);
173 }
174
175 void SALOMEDSImpl_AttributeTableOfString::SetRowData(const int theRow,
176                                                      const vector<string>& theData) 
177 {
178   CheckLocked();  
179   if(theData.size() > myNbColumns) SetNbColumns(theData.size());
180
181   Backup();
182
183   while (myRows.size() < theRow) { // append new row titles
184     myRows.push_back(std::string(""));
185   }
186
187   int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
188   for(i = 1; i <= aLength; i++) {
189     myTable[aShift + i] = theData[i-1];
190   }
191
192   if(theRow > myNbRows) myNbRows = theRow;
193   
194   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
195 }
196
197 void SALOMEDSImpl_AttributeTableOfString::SetTitle(const std::string& theTitle) 
198 {
199   CheckLocked();  
200   Backup();
201   myTitle = theTitle;
202   
203   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
204 }
205
206 std::string SALOMEDSImpl_AttributeTableOfString::GetTitle() const 
207 {
208   return myTitle;
209 }
210
211 vector<string> SALOMEDSImpl_AttributeTableOfString::GetRowData(const int theRow)
212 {
213   vector<string> aSeq;
214   int i, aShift = (theRow-1)*myNbColumns;
215   for(i = 1; i <= myNbColumns; i++) {
216      if(myTable.find(aShift+i) != myTable.end()) 
217        aSeq.push_back(myTable[aShift+i]);
218      else
219        aSeq.push_back("");
220   }
221   
222   return aSeq;
223 }
224
225 void SALOMEDSImpl_AttributeTableOfString::SetColumnData(const int theColumn,
226                                                         const vector<string>& 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 vector<string> SALOMEDSImpl_AttributeTableOfString::GetColumnData(const int theColumn)
250 {
251   vector<string> aSeq;
252   
253   int i, anIndex;
254   for(i = 1; i <= myNbRows; i++) {
255     anIndex = myNbColumns*(i-1) + theColumn;
256     if(myTable.find(anIndex) != myTable.end()) 
257       aSeq.push_back(myTable[anIndex]);
258     else
259       aSeq.push_back("");
260   }
261   
262   return aSeq;
263 }
264
265 void SALOMEDSImpl_AttributeTableOfString::SetColumnTitle(const int theColumn,
266                                                          const std::string& theTitle) 
267 {
268   CheckLocked();  
269   Backup();
270   while(myCols.size() < theColumn) myCols.push_back(std::string(""));
271   myCols[theColumn-1] = theTitle;
272   
273   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
274 }
275
276 std::string SALOMEDSImpl_AttributeTableOfString::GetColumnTitle(const int theColumn) const 
277 {
278   if(myCols.empty()) return "";
279   if(myCols.size() < theColumn) return "";
280   return myCols[theColumn-1];
281 }
282
283
284 void SALOMEDSImpl_AttributeTableOfString::SetColumnTitles(const vector<string>& theTitles)
285 {
286   if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
287   int aLength = theTitles.size(), i;
288   for(i = 0; i < aLength; i++)  myCols[i] =  theTitles[i];
289   
290   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
291 }
292
293 vector<string> SALOMEDSImpl_AttributeTableOfString::GetColumnTitles()
294 {
295   vector<string> aSeq;
296   int aLength = myCols.size(), i;
297   for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
298   return aSeq;
299 }
300
301
302 int SALOMEDSImpl_AttributeTableOfString::GetNbRows() const
303 {
304   return myNbRows;
305 }
306
307 int SALOMEDSImpl_AttributeTableOfString::GetNbColumns() const
308 {
309   return myNbColumns;
310 }
311
312 void SALOMEDSImpl_AttributeTableOfString::PutValue(const std::string& theValue,
313                                                    const int theRow,
314                                                    const int theColumn) 
315 {
316   CheckLocked();  
317   if(theColumn > myNbColumns) SetNbColumns(theColumn);
318
319   int anIndex = (theRow-1)*myNbColumns + theColumn;
320   myTable[anIndex] = theValue;
321
322   if(theRow > myNbRows) {
323     while (myRows.size() < theRow) { // append empty row titles
324       myRows.push_back(std::string(""));
325     }
326     myNbRows = theRow;
327   }
328   
329   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
330 }
331
332 bool SALOMEDSImpl_AttributeTableOfString::HasValue(const int theRow,
333                                                    const int theColumn) 
334 {
335   if(theRow > myNbRows || theRow < 1) return false;
336   if(theColumn > myNbColumns || theColumn < 1) return false;
337
338   int anIndex = (theRow-1)*myNbColumns + theColumn;
339   return (myTable.find(anIndex) !=  myTable.end()); 
340 }
341
342 std::string SALOMEDSImpl_AttributeTableOfString::GetValue(const int theRow,
343                                                           const int theColumn) 
344 {
345   if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
346   if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
347
348   int anIndex = (theRow-1)*myNbColumns + theColumn;
349   if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
350   
351   throw DFexception("Invalid cell index");
352   return "";
353 }
354
355 const std::string& SALOMEDSImpl_AttributeTableOfString::ID() const
356 {
357   return GetID();
358 }
359
360 void SALOMEDSImpl_AttributeTableOfString::Restore(DF_Attribute* with) 
361 {
362   int anIndex;
363   SALOMEDSImpl_AttributeTableOfString* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfString*>(with);
364
365   myTable.clear();
366   myCols.clear();
367   myRows.clear();
368
369   myTable = aTable->myTable;
370   myNbRows = aTable->myNbRows;
371   myNbColumns = aTable->myNbColumns;
372   myTitle = aTable->myTitle;
373   
374   for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
375     myRows.push_back(aTable->GetRowTitle(anIndex));
376
377   for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++) 
378     myCols.push_back(aTable->GetColumnTitle(anIndex));
379 }
380
381 DF_Attribute* SALOMEDSImpl_AttributeTableOfString::NewEmpty() const
382 {
383   return new SALOMEDSImpl_AttributeTableOfString();
384 }
385
386 void SALOMEDSImpl_AttributeTableOfString::Paste(DF_Attribute* into)
387 {
388   int anIndex;
389   SALOMEDSImpl_AttributeTableOfString* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfString*>(into);
390
391   aTable->myTable.clear();
392   aTable->myCols.clear();
393   aTable->myRows.clear();
394
395   aTable->myTable = myTable;
396   aTable->myTitle = myTitle;
397   aTable->myNbRows = myNbRows;
398   aTable->myNbColumns = myNbColumns;
399
400   for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
401     aTable->myRows.push_back(GetRowTitle(anIndex));
402   for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++) 
403     aTable->myCols.push_back(GetColumnTitle(anIndex));
404 }
405
406
407 vector<int> SALOMEDSImpl_AttributeTableOfString::GetSetRowIndices(const int theRow)
408 {
409   vector<int> aSeq;
410
411   int i, aShift = myNbColumns*(theRow-1);
412   for(i = 1; i <= myNbColumns; i++) {
413     if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
414   }
415   
416   return aSeq;
417 }
418
419 vector<int> SALOMEDSImpl_AttributeTableOfString::GetSetColumnIndices(const int theColumn)
420 {
421   vector<int> aSeq;
422
423   int i, anIndex;
424   for(i = 1; i <= myNbRows; i++) {
425     anIndex = myNbColumns*(i-1)+theColumn;
426     if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
427   }
428   
429   return aSeq;
430 }
431
432
433
434 string SALOMEDSImpl_AttributeTableOfString::Save() 
435 {
436   string aString;
437   char* buffer = new char[1024];
438   int i, j, l;
439
440   //Title
441   l = myTitle.size();
442   sprintf(buffer, "%d\n", l);
443   aString+=buffer;
444   for(i=0; i<l; i++) {
445     aString += myTitle[i];
446     aString +='\n';
447   }
448   
449   //Nb rows
450   sprintf(buffer, "%d\n", myNbRows);
451   aString+=buffer;
452
453   //Row titles
454   for(i=0; i<myNbRows; i++) {
455     l = myRows[i].size();
456     sprintf(buffer, "%d\n", l);
457     aString+=buffer;
458     for(j=0; j<l; j++) {
459       aString += myRows[i][j];
460       aString += '\n';
461     }
462   }  
463
464   //Nb columns
465   sprintf(buffer, "%d\n", myNbColumns);
466   aString+=buffer;
467
468   //Columns titles
469   for(i=0; i<myNbColumns; i++) {
470     l = myCols[i].size();
471     sprintf(buffer, "%d\n", l);
472     aString+=buffer;
473     for(j=0; j<l; j++) {
474       aString += myCols[i][j];
475       aString += '\n';
476     }
477   }
478
479   //Store the table values
480   l = myTable.size();
481   sprintf(buffer, "%d\n", l);
482   aString+=buffer;
483   for(MI p = myTable.begin(); p!=myTable.end(); p++) {
484     if (p->second.size()) { // check empty string in the value table
485       sprintf(buffer, "%d\n", p->first);
486       aString += buffer;
487       unsigned long aValueSize = p->second.size();
488       sprintf(buffer, "%ld\n", aValueSize);
489       aString +=buffer;
490       aString += p->second;
491       aString += '\n';
492     } else { // write index only of kind: "0key"; "05", for an example
493       sprintf(buffer, "0%d\n", p->first);
494       aString+=buffer;
495     }
496   }
497
498   delete []buffer;
499   return aString;
500 }
501
502 void SALOMEDSImpl_AttributeTableOfString::Load(const string& value) 
503 {
504   vector<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     aStr = v[pos++]; //Ket as a string 
559     int aKey = strtol(aStr.c_str(), NULL, 10);
560     string aValue;
561     if(aStr[0] == '0') //If the first character of the key is 0, then empty value
562       aValue = "";
563     else {
564       long aSize = strtol(v[pos++].c_str(), NULL, 10);
565       aValue = v[pos++];
566     }
567     myTable[aKey] = aValue;
568   }
569 }