Salome HOME
245de358c6b933b1e3d98cee20d2705797a1b4f2
[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   ostrstream theStream;
437   int i, j, l;
438   
439   //Title
440   l = myTitle.size();
441   theStream << l << "\n";
442   for(i=0; i<l; i++)
443     theStream << myTitle[i] << "\n";
444
445   //Nb rows
446   theStream << myNbRows << "\n";
447
448   //Rows titles
449   for(i=0; i<myNbRows; i++) {
450     l = myRows[i].size();
451     theStream << l << "\n";
452     for(j=0; j<l; j++)
453       theStream << myRows[i][j] << "\n";
454   }
455
456   //Nb columns
457   theStream << myNbColumns << "\n";
458
459   //Columns titles
460   for(i=0; i<myNbColumns; i++) {
461     l = myCols[i].size();
462     theStream << l << "\n";
463     for(j=0; j<l; j++)
464       theStream << myCols[i][j] << "\n";
465   }
466
467   //Store the table values
468   l = myTable.size();
469   theStream << l << "\n";
470   for(MI p = myTable.begin(); p!=myTable.end(); p++) {
471     if (p->second.size()) { // check empty string in the value table
472       theStream << p->first << "\n";
473       unsigned long aValueSize = p->second.size();
474       theStream<<aValueSize << "\n";
475       theStream.write(p->second.c_str(),aValueSize);
476       theStream<<"\n";
477     } else { // write index only of kind: "0key"; "05", for an example
478       theStream << "0" << p->first << "\n";
479     }
480   }
481   string aString((char*)theStream.rdbuf()->str());
482   return aString;
483 }
484
485 void SALOMEDSImpl_AttributeTableOfString::Load(const string& value) 
486 {
487   istrstream theStream(value.c_str(), strlen(value.c_str()));
488   Backup();
489
490   theStream.seekg(0, ios::end);
491   long aSize = theStream.tellg();
492   theStream.seekg(0, ios::beg);
493
494   int i, j, l;
495   char *aValueString = new char[aSize];
496
497   char anExtChar;
498   std::string aStr;
499
500   //Title
501   theStream >> l;
502
503   myTitle = std::string(l, 0);
504   for(i=0; i<l; i++) {
505     theStream >> anExtChar;
506     myTitle[i] = anExtChar;
507   }
508
509   //Nb rows
510   theStream >> myNbRows;
511
512   //Rows titles
513   myRows.clear();  
514   for(i=0; i<myNbRows; i++) { 
515     theStream >> l;
516     aStr = std::string(l,0);
517     for(j=0; j<l; j++) {
518       theStream >> anExtChar;
519       aStr[j] = anExtChar;
520     }
521     myRows.push_back(aStr);
522   }
523
524   //Nb columns
525   theStream >> myNbColumns;
526
527   //Columns titles
528   myCols.clear();
529   for(i=0; i<myNbColumns; i++) {
530     theStream >> l;
531     aStr = std::string(l,0);
532     for(j=0; j<l; j++) {
533       theStream >> anExtChar;
534       aStr[j] = anExtChar;
535     }
536     myCols.push_back(aStr);
537   }
538
539   //Restore the table values
540   string aValue;
541   theStream >> l;
542   myTable.clear();
543   theStream.getline(aValueString,aSize,'\n');
544   for(i=1; i<=l; i++) {
545     int aKey;
546
547     theStream.getline(aValueString,aSize,'\n');
548     aValue = aValueString;
549     aKey = atoi(aValue.c_str());
550     if (aValue[0] == '0')
551       aValue = "";
552     else {
553       unsigned long aValueSize;
554       theStream >> aValueSize;
555       theStream.read(aValueString, 1); // an '\n' omitting
556       theStream.read(aValueString, aValueSize);
557       theStream.read(aValueString, 1); // an '\n' omitting
558       aValue = aValueString;
559     }
560     myTable[aKey] = aValue;
561   }
562   delete(aValueString);
563 }