Salome HOME
22aedb9059a89f33b0af1d1e2f06eab09c2a30d8
[tools/simanio.git] / src / SimanIO_Configuration.cxx
1 #include <SimanIO_Configuration.hxx>
2
3 #include <stdlib.h>
4
5 // maximum length of the line in the parsed conf file
6 const int MAX_BUFFER_SIZE=10000;
7
8 using namespace std;
9
10 SimanIO_Configuration::SimanIO_Configuration()
11 {
12 }
13
14 ///! Returns true is the given symbol is white space
15 static bool IsWhite(const char theSym) {
16   return theSym == ' ' || theSym == '\t';
17 }
18
19 ///! Returns true if theLine starts with theCommand, returns in theVal rest part of the line in this case
20 static bool IsCommand(const char* theCommand, char* theLine, char*& theVal) {
21   string aLine(theLine);
22   char* aComPtr = (char*)theCommand;
23   theVal = theLine;
24   while(*aComPtr != 0 && *theVal != 0) {
25     if (IsWhite(*aComPtr)) { // skip white spaces in the command line
26       aComPtr++;
27       continue;
28     }
29     if (IsWhite(*theVal)) { // skip white spaces in the processed line
30       theVal++;
31       continue;
32     }
33      //cout<<"Compare symbols "<<tolower(*aComPtr)<<" and "<<tolower(*theVal)<<endl;
34     if (tolower(*aComPtr) != tolower(*theVal)) // symbols are not match (case is not significant)
35       break;
36     aComPtr++;
37     theVal++;
38   }
39   if (*aComPtr == 0) { // command has been found
40     while(*theVal != 0 && IsWhite(*theVal)) { // skip white spaces in the processed line
41       theVal++;
42     }
43     return true;
44   }
45   return false;
46 }
47
48 ///! Returns true if theText1 fully equal to theText2
49 static bool IsValue(const char* theText1, const char* theText2) {
50   int a;
51   for(a = 0; theText1[a] != 0 && theText2[a] != 0; a++)
52     if (theText1[a] != theText2[a]) return false;
53   return theText1[a] == 0 && theText2[a] == 0;
54 }
55
56 ///! Converts string to the integer value, or returns the default vaule if failed
57 static int toInt(const char* theStr, int theDefault) {
58   int aResult;
59   try {
60     aResult = atol(theStr);
61   } catch(...) {
62     aResult = theDefault;
63   }
64   return aResult;
65 }
66
67 // unification of the error handling in the Parse method
68 #define PARSE_ERROR(condition, message) if (condition) {cerr<<message<<endl; return false;}
69
70 bool SimanIO_Configuration::Parse(const char* theConfFileName)
71 {
72   ifstream f(theConfFileName);
73   myF = &f;
74   PARSE_ERROR(!f.good(), "Can not read conf file "<<theConfFileName)
75   char aBuffer[MAX_BUFFER_SIZE];
76   myBuffer = aBuffer; // buffer for one line reading
77   myReuseLine = false; // to read current line from the file
78   char* aVal; // value in line, that is located after the identifier of the command
79   while(!f.eof()) {
80     ReadLine();
81     if (IsCommand("Study ID :", myBuffer, aVal)) {
82       // skip study ID: this info is known in Link
83     } else if (IsCommand("Scenario ID :", myBuffer, aVal)) {
84       // skip scenario ID: this info is known in Link
85     } else if (IsCommand("User ID :", myBuffer, aVal)) {
86       // skip user ID: this info is known in Link
87     } else if (IsCommand("Activity", myBuffer, aVal)) {
88       if (!ParseActivity(aVal)) return false;
89     } else {
90       PARSE_ERROR(true, "Invalid line of conf file: '"<<myBuffer<<"'");
91     }
92   }
93   return true;
94 }
95
96 bool SimanIO_Configuration::ParseActivity(char* aName)
97 {
98   SimanIO_Activity aNewActivity;
99   aNewActivity.SetName(aName);
100   int activityID = -1; // to be imported later
101   char* aVal; // value in line, that is located after the identifier of the command
102   while(!myF->eof()) {
103     ReadLine();
104     if (IsCommand("Activity ID :", myBuffer, aVal)) {
105       PARSE_ERROR(activityID != -1, "Duplicated activity identifier '"<<myBuffer<<"'");
106       activityID = toInt(aVal, -1);
107       PARSE_ERROR(activityID < 1, "Invalid activity identifier '"<<aVal<<"'");
108     } else if (IsCommand("Module :", myBuffer, aVal) || IsCommand("SALOME Module :", myBuffer, aVal)) { // read only if module not yet imported before
109       char* aVal2;
110       PARSE_ERROR(aNewActivity.Module()[0] != 0, "Duplicated module name in '"<<myBuffer<<"'")
111       PARSE_ERROR(aVal[0] == 0, "Invalid module name in '"<<myBuffer<<"'")
112       aNewActivity.SetModule(aVal);
113     } else if (IsCommand("Document :", myBuffer, aVal)) {
114       if (!ParseDocument(aVal, aNewActivity)) return false;
115     } else { // unknown command will be processed in higher level method
116       myReuseLine = true;
117       break;
118     }
119   }
120   PARSE_ERROR(activityID == -1, "Activity '"<<aNewActivity.Name()<<"' ID is not defined");
121   PARSE_ERROR(aNewActivity.Module()[0] == 0, "Module of the activity '"<<aNewActivity.Name()<<"' is not defined");
122   if (!IsValue("null", aNewActivity.Module())) // skip activities with module name "null"
123     AddActivity(aNewActivity, activityID);
124   return true;
125 }
126
127 bool SimanIO_Configuration::ParseDocument(char* aName, SimanIO_Activity& theActivity)
128 {
129   SimanIO_Document aNewDocument;
130   aNewDocument.SetName(aName);
131   int aDocID = -1; // to be imported later
132   char* aVal; // value in line, that is located after the identifier of the command
133   while(!myF->eof()) {
134     ReadLine();
135     if (IsCommand("Document ID :", myBuffer, aVal)) {
136       PARSE_ERROR(aDocID != -1, "Duplicated document identifier '"<<myBuffer<<"'");
137       aDocID = toInt(aVal, -1);
138       PARSE_ERROR(aDocID < 1, "Invalid document identifier '"<<aVal<<"'");
139     } else if (IsCommand("Source file:", myBuffer, aVal) || IsCommand("Result file:", myBuffer, aVal)) {
140       if (!ParseFile(aNewDocument)) return false;
141     } else { // unknown command will be processed in higher level method
142       myReuseLine = true;
143       break;
144     }
145   }
146   PARSE_ERROR(aDocID == -1, "Document '"<<aNewDocument.Name()<<"' ID is not defined");
147   theActivity.AddDocument(aDocID, aNewDocument);
148   return true;
149 }
150
151 bool SimanIO_Configuration::ParseFile(SimanIO_Document& theDocument)
152 {
153   SimanIO_File aNewFile;
154   aNewFile.id = -1;
155   int aDocID = -1; // to be imported later
156   char* aVal; // value in line, that is located after the identifier of the command
157   
158   // current line contains one of the next two commands
159   if (IsCommand("Result file :", myBuffer, aVal)) {
160     aNewFile.result = true;
161     aNewFile.url = aVal;
162   } else if (IsCommand("Source file :", myBuffer, aVal)) {
163     aNewFile.result = false;
164     aNewFile.url = aVal;
165   }
166   PARSE_ERROR(aNewFile.url.empty(), "File '"<<myBuffer<<"' has invalid URL");
167   while(!myF->eof()) {
168     ReadLine();
169     if (IsCommand("Automatic processing :", myBuffer, aVal)) {
170       char* aVal2;
171       if (IsCommand("file-download", aVal, aVal2)) aNewFile.proc = FILE_DOWNLOAD;
172       else if (IsCommand("file-import", aVal, aVal2)) aNewFile.proc = FILE_IMPORT;
173       else PARSE_ERROR(true, "Invalid automatic processing value '"<<aVal<<"'");
174     } else if (IsCommand("State :", myBuffer, aVal)) {
175       char* aVal2;
176       if (IsCommand("file-actual", aVal, aVal2)) aNewFile.state = FILE_ACTUAL;
177       else if (IsCommand("file-outdated", aVal, aVal2)) aNewFile.state = FILE_OUTDATED;
178       else PARSE_ERROR(true, "Invalid state value '"<<aVal<<"'");
179     } else if (IsCommand("File ID :", myBuffer, aVal)) {
180       PARSE_ERROR(aNewFile.id != -1, "Duplicated file identifier '"<<myBuffer<<"'");
181       aNewFile.id = toInt(aVal, -1);
182       PARSE_ERROR(aNewFile.id < 0, "Invalid file identifier '"<<aVal<<"'");
183     } else { // unknown command will be processed in higher level method
184       myReuseLine = true;
185       break;
186     }
187   }
188   PARSE_ERROR(aNewFile.id < 0, "File '"<<aNewFile.url<<"' ID is not defined");
189   theDocument.AddFile(aNewFile);
190   return true;
191 }
192
193 int SimanIO_Configuration::AddActivity(const SimanIO_Activity& theActivity, const int theId)
194 {
195   int anId = theId;
196   if (theId < 0) { // generate the maximum unique Id
197     if (myActivities.empty()) anId = 1; // the first
198     else {
199       anId = myActivities.rbegin()->first + 1; // take the maximum Id plus one (in map integers are ordered)
200     }
201   }
202   myActivities[anId] = theActivity;
203 }
204
205 SimanIO_Activity& SimanIO_Configuration::GetOrCreateActivity(const int theId)
206 {
207   if (myActivities.find(theId) == myActivities.end()) {
208     myActivities[theId] = SimanIO_Activity();
209   }
210   return myActivities[theId];
211 }
212
213 void SimanIO_Configuration::ReadLine() {
214   if (myReuseLine) { // reuse current line
215     myReuseLine = false;
216     return;
217   }
218   do {
219     myF->getline(myBuffer, MAX_BUFFER_SIZE - 1);
220   } while(!myF->eof() && myBuffer[0] == 0); // continue if there is empty line
221 }
222
223 /////////////////////////////////// iterator methods ///////////////////////////
224
225 SimanIO_Configuration::ActivitiesIterator::ActivitiesIterator(SimanIO_Configuration& theConf)
226 {
227   myIter = theConf.myActivities.begin();
228   myEnd = theConf.myActivities.end();
229 }
230
231 void SimanIO_Configuration::ActivitiesIterator::Next()
232 {
233   myIter++;
234 }
235
236 bool SimanIO_Configuration::ActivitiesIterator::More()
237 {
238   return myIter != myEnd;
239 }
240
241 const int SimanIO_Configuration::ActivitiesIterator::ActivityId()
242 {
243   return myIter->first;
244 }
245
246 SimanIO_Activity& SimanIO_Configuration::ActivitiesIterator::Activity()
247 {
248   return myIter->second;
249 }