1 /* massXpert - the true massist's program. 2 -------------------------------------- 3 Copyright(C) 2006,2007 Filippo Rusconi 4 5 http://www.massxpert.org/massXpert 6 7 This file is part of the massXpert project. 8 9 The massxpert project is the successor to the "GNU polyxmass" 10 project that is an official GNU project package(see 11 www.gnu.org). The massXpert project is not endorsed by the GNU 12 project, although it is released ---in its entirety--- under the 13 GNU General Public License. A huge part of the code in massXpert 14 is actually a C++ rewrite of code in GNU polyxmass. As such 15 massXpert was started at the Centre National de la Recherche 16 Scientifique(FRANCE), that granted me the formal authorization to 17 publish it under this Free Software License. 18 19 This software is free software; you can redistribute it and/or 20 modify it under the terms of the GNU General Public 21 License version 3, as published by the Free Software Foundation. 22 23 24 This software is distributed in the hope that it will be useful, 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 General Public License for more details. 28 29 You should have received a copy of the GNU General Public License 30 along with this software; if not, write to the 31 32 Free Software Foundation, Inc., 33 34 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 35 */ 36 37 38 /////////////////////// Qt includes 39 #include<QFile> 40 #include<QDir> 41 #include<QDebug> 42 43 44 /////////////////////// Local includes 45 #include "polChemDefCatParser.hpp" 46 #include "configSettings.hpp" 47 48 49 namespace massXpert 50 { 51 PolChemDefCatParser()52 PolChemDefCatParser::PolChemDefCatParser() 53 { 54 mp_configSettings = 0; 55 m_pendingMode = 0; 56 m_configSysUser = 0; 57 58 return ; 59 } 60 61 ~PolChemDefCatParser()62 PolChemDefCatParser::~PolChemDefCatParser() 63 { 64 return; 65 } 66 67 68 void setFilePath(const QString & filePath)69 PolChemDefCatParser::setFilePath(const QString &filePath) 70 { 71 m_filePath = filePath; 72 } 73 74 75 const QString & getFilePath()76 PolChemDefCatParser::getFilePath() 77 { 78 return m_filePath; 79 } 80 81 82 void setPendingMode(int pendingMode)83 PolChemDefCatParser::setPendingMode(int pendingMode) 84 { 85 m_pendingMode = pendingMode; 86 } 87 88 89 int getPendingMode()90 PolChemDefCatParser::getPendingMode() 91 { 92 return m_pendingMode; 93 } 94 95 96 void setConfigSysUser(int configSysUser)97 PolChemDefCatParser::setConfigSysUser(int configSysUser) 98 { 99 m_configSysUser = configSysUser; 100 } 101 102 103 int getConfigSysUser()104 PolChemDefCatParser::getConfigSysUser() 105 { 106 return m_configSysUser; 107 } 108 109 110 int parseFiles(const ConfigSettings & configSettings,QList<PolChemDefSpec * > * polChemDefSpecList)111 PolChemDefCatParser::parseFiles(const ConfigSettings &configSettings, 112 QList<PolChemDefSpec *> 113 *polChemDefSpecList) 114 { 115 mp_configSettings = &configSettings; 116 117 QDir dir; 118 119 int count = 0; 120 int totCount = 0; 121 122 // Polymer chemistry definition catalogue files are located in 123 // pol-chem-defs directories that are located in turn in either 124 // system-wide configuration places, like 125 // /etc/massxpert/pol-chem-defs, for example on UNIX-like systems, 126 // and/or in private user locations, like 127 // $HOME/.massxpert/pol-chem-defs. 128 129 Q_ASSERT(polChemDefSpecList); 130 131 // Depending on m_configSysUser, we are going to get all the files 132 // that are polymer chemistry def catalogues in the different 133 // locations and parse these files one after the other. 134 135 if (m_configSysUser & POLCHEMDEF_CAT_PARSE_SYSTEM_CONFIG) 136 { 137 // We have to parse all the catalogue files in the system 138 // configuration directory. 139 140 dir.setPath(configSettings.systemPolChemDefCatDir()); 141 142 if(dir.exists()) 143 { 144 // All the polchem definition catalogues must have the 145 // "pol-chem-defs-cat" filename suffix. So we filter the list of 146 // files in the directory according to that wildcard expression. 147 148 QStringList filters; 149 filters << "*pol-chem-defs-cat"; 150 dir.setNameFilters(filters); 151 152 dir.setFilter(QDir::Files | QDir::NoSymLinks); 153 154 QFileInfoList list = dir.entryInfoList(); 155 156 for (int iter = 0; iter < list.size(); ++iter) 157 { 158 QFileInfo fileInfo = list.at(iter); 159 160 m_filePath = fileInfo.absoluteFilePath(); 161 count = parse(polChemDefSpecList, 162 POLCHEMDEF_CAT_PARSE_SYSTEM_CONFIG); 163 164 if(count == -1) 165 return -1; 166 else 167 totCount += count; 168 } 169 } 170 } 171 172 if (m_configSysUser & POLCHEMDEF_CAT_PARSE_USER_CONFIG) 173 { 174 // We have to parse all the catalogue files in the user 175 // configuration directory. 176 177 dir.setPath(configSettings.userPolChemDefCatDir()); 178 179 if(dir.exists()) 180 { 181 // All the atom definition catalogues must have the 182 // "atom-defs-cat" filename suffix. So we filter the list of 183 // files in the directory according to that wildcard expression. 184 185 QStringList filters; 186 filters << "*pol-chem-defs-cat"; 187 dir.setNameFilters(filters); 188 189 dir.setFilter(QDir::Files | QDir::NoSymLinks); 190 191 QFileInfoList list = dir.entryInfoList(); 192 193 for (int iter = 0; iter < list.size(); ++iter) 194 { 195 QFileInfo fileInfo = list.at(iter); 196 197 m_filePath = fileInfo.absoluteFilePath(); 198 count = parse(polChemDefSpecList, 199 POLCHEMDEF_CAT_PARSE_USER_CONFIG); 200 201 if(count == -1) 202 return -1; 203 else 204 totCount += count; 205 } 206 } 207 } 208 209 return totCount; 210 } 211 212 213 int parse(QList<PolChemDefSpec * > * polChemDefSpecList,int forSystemOrUser)214 PolChemDefCatParser::parse(QList<PolChemDefSpec *> 215 *polChemDefSpecList, 216 int forSystemOrUser) 217 { 218 qint64 lineLength; 219 220 QString line; 221 222 char buffer [1024]; 223 224 int equalSignIdx = 0; 225 int count = 0; 226 227 PolChemDefSpec *polChemDefSpec = 0; 228 229 // We are given a QList in which to store all the 230 // PolChemDefSpec* instances that we create by parsing the 231 // catalogue files. 232 // 233 // Each line in the catalogue(s) that we may have to parse gives the 234 // name of a polymer chemistry definition, like "protein", and the 235 // full pathname of the file in which that definition is stored and 236 // the full pathname to the directory where all its corresponding 237 // stuff is stored. Example: 238 // protein=/some/dir/protein/protein.xml 239 // 240 // All we have to do is parse each line and for each valid one 241 // create a PolChemDefSpec item that we append/prepend to the 242 // QList passed as parameter. 243 244 Q_ASSERT(polChemDefSpecList); 245 246 QFile file(m_filePath); 247 248 if (! file.open(QFile::ReadOnly)) 249 return -1; 250 251 //qDebug() << "Begin file:" << m_filePath.toAscii(); 252 253 254 // Get the first line of the file. Next we enter in to a 255 // while loop. 256 257 lineLength = file.readLine(buffer, sizeof(buffer)); 258 259 while(lineLength != -1) 260 { 261 // The line is now in buffer, and we want to convert 262 // it to Unicode by setting it in a QString. 263 line = buffer; 264 265 // Remove all the spaces from the borders: Whitespace means any 266 // character for which QChar::isSpace() returns true. This 267 // includes the ASCII characters '\t', '\n', '\v', '\f', '\r', 268 // and ' '. 269 270 line = line.trimmed(); 271 272 // The line that is in line should contain something like: 273 274 // protein=protein/protein.xml(relative path) 275 276 // or: 277 278 // protein=/some/dir/protein/protein.xml(absolute path) 279 // 280 // Note, however that lines beginning with either ' '(space) or 281 // '\n'(newline) or '#' are comments. 282 283 if(line.isEmpty() || line.startsWith('#', Qt::CaseInsensitive)) 284 { 285 lineLength = file.readLine(buffer, sizeof(buffer)); 286 continue; 287 } 288 289 // Now some other checks. 290 equalSignIdx = line.indexOf('=', 0, Qt::CaseInsensitive); 291 292 if(equalSignIdx == -1 || line.count('=', Qt::CaseInsensitive) > 1) 293 return -1; 294 295 // Ok at this point, we might have a nicely parseable line, it 296 // makes sens to allocate a new AtomDefSpec object. 297 polChemDefSpec = new(PolChemDefSpec); 298 299 polChemDefSpec->setName(line.left(equalSignIdx)); 300 301 // Of course we have to make sure that we are getting 302 // a file path corresponding to something we actually 303 // can use. 304 305 QString polChemDefFile = line.right(line.length() 306 - equalSignIdx - 1); 307 308 QFileInfo fileInfo(polChemDefFile); 309 310 if(fileInfo.isRelative()) 311 { 312 // The polymer chemistry definition file is not an 313 // absolute filePath. We have to change it into an 314 // absolute filePath by prepending the directory path 315 // where it is located. 316 317 if (forSystemOrUser == POLCHEMDEF_CAT_PARSE_SYSTEM_CONFIG) 318 { 319 QFile file(mp_configSettings->systemPolChemDefCatDir() + 320 QDir::separator() + polChemDefFile); 321 322 if(!file.exists()) 323 { 324 delete polChemDefSpec; 325 return -1; 326 } 327 328 polChemDefSpec->setFilePath(file.fileName()); 329 } 330 else if (forSystemOrUser == POLCHEMDEF_CAT_PARSE_USER_CONFIG) 331 { 332 QFile file(mp_configSettings->userPolChemDefCatDir() + 333 QDir::separator() + polChemDefFile); 334 335 if(!file.exists()) 336 { 337 delete polChemDefSpec; 338 return -1; 339 } 340 341 polChemDefSpec->setFilePath(file.fileName()); 342 } 343 else 344 qFatal("%s@%d: Failed to parse polymer chemistry definition " 345 "catalogues.", __FILE__, __LINE__); 346 } 347 else 348 { 349 if (!fileInfo.exists()) 350 { 351 delete polChemDefSpec; 352 return -1; 353 } 354 355 polChemDefSpec->setFilePath(polChemDefFile); 356 } 357 358 359 // OK, the file exists, and thus we can set the newly allocated 360 // polChemDefSpec object to the QList passed as parameter. 361 362 if(m_pendingMode == POLCHEMDEF_CAT_PARSE_APPEND_CONFIG) 363 polChemDefSpecList->append(polChemDefSpec); 364 else 365 polChemDefSpecList->prepend(polChemDefSpec); 366 367 ++count; 368 369 //qDebug() << "Parsed line: " << line.toAscii(); 370 371 lineLength = file.readLine(buffer, sizeof(buffer)); 372 } 373 // while(lineLength != -1) 374 375 file.close(); 376 377 //qDebug() << "Endfile:" << m_filePath.toAscii(); 378 379 return count; 380 } 381 382 } // namespace massXpert 383