source: src/Parser/FormatParserStorage.cpp@ 463bfb

Candidate_v1.7.0 stable
Last change on this file since 463bfb was 780bfa, checked in by Frederik Heber <frederik.heber@…>, 2 months ago

FIX: FormatParserStorage did not add parser instance on SetOutput.

  • using the InputAction on an empty file would not write that file using the desired parser (judged from suffix) on exit because the respective was set as desired output but not instantiated (ParserPresent).
  • Property mode set to 100644
File size: 12.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/** \file FormatParserStorage.cpp
24 *
25 * date: Jun, 22 2010
26 * author: heber
27 *
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include <iostream>
38#include <fstream>
39
40#include <boost/preprocessor/iteration/local.hpp>
41
42#include "CodePatterns/Assert.hpp"
43#include "CodePatterns/Log.hpp"
44
45#include "molecule.hpp"
46#include "FormatParserStorage.hpp"
47#include "ParserTypes.hpp"
48
49#include "MpqcParser.hpp"
50#include "PcpParser.hpp"
51#include "PdbParser.hpp"
52#include "Psi3Parser.hpp"
53#include "TremoloParser.hpp"
54#include "XmlParser.hpp"
55#include "XyzParser.hpp"
56
57#include "CodePatterns/Singleton_impl.hpp"
58
59const std::string FormatParserStorage::unknownTypeString("unknown");
60
61/** Constructor of class FormatParserStorage.
62 */
63FormatParserStorage::FormatParserStorage()
64{
65 ParserList.resize(ParserTypes_end, NULL);
66 ParserStream.resize(ParserTypes_end, NULL);
67 ParserPresent.resize(ParserTypes_end, false);
68 ParserDesiredOutputFormat.resize(ParserTypes_end, false);
69
70#include "ParserTypes.def"
71
72#define insert_print(z,n,seq,map, before, after) \
73 map .insert( std::make_pair( \
74 BOOST_PP_SEQ_ELEM(n, seq) \
75 , before < \
76 BOOST_PP_SEQ_ELEM(n, seq) \
77 > after \
78 ) );
79
80#define insert_invert_print(z,n,seq,map, before, after) \
81 map .insert( std::make_pair( before < \
82 BOOST_PP_SEQ_ELEM(n, seq) \
83 > after, \
84 BOOST_PP_SEQ_ELEM(n, seq) \
85 ) );
86
87 // fill ParserNames
88#if defined ParserTypes_END // do we have parameters at all?
89#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserNames, FormatParserTrait, ::name)
90#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
91#include BOOST_PP_LOCAL_ITERATE()
92#endif
93
94 // fill ParserLookupNames
95#if defined ParserTypes_END // do we have parameters at all?
96#define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupNames, FormatParserTrait, ::name)
97#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
98#include BOOST_PP_LOCAL_ITERATE()
99#endif
100
101 // fill ParserSuffixes
102#if defined ParserTypes_END // do we have parameters at all?
103#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserSuffixes, FormatParserTrait, ::suffix)
104#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
105#include BOOST_PP_LOCAL_ITERATE()
106#endif
107
108 // fill ParserLookupSuffixes
109#if defined ParserTypes_END // do we have parameters at all?
110#define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupSuffixes, FormatParserTrait, ::suffix)
111#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
112#include BOOST_PP_LOCAL_ITERATE()
113#endif
114
115 // fill ParserAddFunction
116#if defined ParserTypes_END // do we have parameters at all?
117#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserAddFunction, &FormatParserStorage::addParser, )
118#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
119#include BOOST_PP_LOCAL_ITERATE()
120#endif
121
122#undef insert_print
123#undef insert_invert_print
124#include "ParserTypes.undef"
125
126 //std::cout << "ParserNames:" << std::endl << ParserNames << std::endl;
127 //std::cout << "ParserSuffixes:" << std::endl << ParserSuffixes << std::endl;
128 //std::cout << "ParserLookupNames:" << std::endl << ParserLookupNames << std::endl;
129 //std::cout << "ParserLookupSuffixes:" << std::endl << ParserLookupSuffixes << std::endl;
130 //std::cout << "ParserAddFunction:" << std::endl << ParserAddFunction << std::endl;
131
132}
133
134/** Destructor of class FormatParserStorage.
135 * Free all stored FormatParsers.
136 * Save on Exit.
137 */
138FormatParserStorage::~FormatParserStorage()
139{
140 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter)
141 if (ParserPresent[iter]) {
142 // this will also flush the ParserStream
143 delete ParserList[iter];
144 // then we remove the stream itself
145 if (ParserStream[iter] != NULL) {
146 if (ParserStream[iter]->is_open())
147 ParserStream[iter]->close();
148 delete ParserStream[iter];
149 }
150 }
151}
152
153
154/** Tests whether a file and parsers are selected for saving.
155 */
156bool FormatParserStorage::isAbleToSave()
157{
158 if (prefix.empty())
159 return false;
160
161 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter)
162 if (ParserPresent[iter] && ParserDesiredOutputFormat[iter])
163 return true;
164 return false;
165}
166
167/** Sets the filename of all current parsers in storage to prefix.suffix.
168 * \param &prefix prefix to use.
169 */
170void FormatParserStorage::SetOutputPrefixForAll(std::string &_prefix)
171{
172 prefix=_prefix;
173};
174
175/** Sets \a type as a format to be stored on call of SaveAll.
176 *
177 * @param type type to add to desired output formats
178 */
179void FormatParserStorage::setOutputFormat(ParserTypes type)
180{
181 LOG(0, "STATUS: Adding " << ParserNames[type] << " type to output.");
182 ParserDesiredOutputFormat[type] = true;
183 add(type);
184}
185
186/** Sets \a type as a format to be stored on call of SaveAll.
187 *
188 * @param type type to add to desired output formats
189 */
190void FormatParserStorage::setOutputFormat(std::string type)
191{
192 std::map<std::string, ParserTypes>::const_iterator iter = ParserLookupNames.find(type);
193 ASSERT(iter != ParserLookupNames.end(),
194 "FormatParserStorage::setOutputFormat() - output format "+type+" is unknown.");
195 setOutputFormat(iter->second);
196}
197
198/** Saves the world in the desired output formats.
199 *
200 */
201void FormatParserStorage::SaveAll()
202{
203 std::string filename;
204 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter) {
205 // open a new stream, if parser is desired. Reopen such stream if already present
206 if (ParserPresent[iter] && ParserDesiredOutputFormat[iter]) {
207 if (ParserStream[iter] != NULL) {
208 if (ParserStream[iter]->is_open()) {
209 ParserStream[iter]->flush();
210 ParserStream[iter]->close();
211 }
212 delete ParserStream[iter];
213 ParserStream[iter] = NULL;
214 ParserList[iter]->setOstream(ParserStream[iter]);
215 }
216 filename = prefix;
217 filename += ".";
218 filename += ParserSuffixes[iter];
219 ParserStream[iter] = new std::ofstream(filename.c_str());
220 ParserList[iter]->setOstream((std::ostream *)ParserStream[iter]);
221 }
222 }
223}
224
225
226ParserTypes FormatParserStorage::getTypeFromName(std::string type)
227{
228 if (ParserLookupNames.find(type) == ParserLookupNames.end()) {
229 ELOG(1, "Unknown type " << type << ".");
230 return ParserTypes_end;
231 } else
232 return ParserLookupNames[type];
233}
234
235ParserTypes FormatParserStorage::getTypeFromSuffix(std::string type)
236{
237 if (ParserLookupSuffixes.find(type) == ParserLookupSuffixes.end()) {
238 ELOG(1, "Unknown type " << type << ".");
239 return ParserTypes_end;
240 } else
241 return ParserLookupSuffixes[type];
242}
243
244const std::string &FormatParserStorage::getNameFromType(ParserTypes type)
245{
246 if (ParserNames.find(type) == ParserNames.end()) {
247 ELOG(1, "Unknown type " << type << ".");
248 return unknownTypeString;
249 } else
250 return ParserNames[type];
251}
252
253const std::string &FormatParserStorage::getSuffixFromType(ParserTypes type)
254{
255 if (ParserSuffixes.find(type) == ParserSuffixes.end()) {
256 ELOG(1, "Unknown type " << type << ".");
257 return unknownTypeString;
258 } else
259 return ParserSuffixes[type];
260}
261
262bool FormatParserStorage::add(ParserTypes ptype)
263{
264 if (ptype != ParserTypes_end) {
265 if (ParserAddFunction.find(ptype) != ParserAddFunction.end()) {
266 (getInstance().*(ParserAddFunction[ptype]))(); // we still need an object to work on ...
267 return true;
268 } else {
269 ELOG(1, "No parser to add for this known type " << ParserNames[ptype] << ", not implemented?");
270 return false;
271 }
272 } else {
273 return false;
274 }
275}
276
277bool FormatParserStorage::add(std::string type)
278{
279 enum ParserTypes Ptype = getTypeFromName(type);
280 return add(Ptype);
281}
282
283/** Recognizes type of file and parse via FormatParserStorage::load().
284 * \param filename path and filename
285 * \return true - parsing ok, false - suffix unknown
286 */
287bool FormatParserStorage::load(boost::filesystem::path filename)
288{
289 return load(filename.string());
290}
291
292/** Recognizes type of file and parse via FormatParserStorage::load().
293 * \param filename path and filename
294 * \return true - parsing ok, false - suffix unknown
295 */
296bool FormatParserStorage::load(std::string &filename)
297{
298 std::string FilenameSuffix = filename.substr(filename.find_last_of('.')+1, filename.length());
299 ifstream input;
300 LOG(0, "STATUS: Loading filler molecule " << filename
301 << " of suffix " << FilenameSuffix << ".");
302 input.open(filename.c_str());
303 const bool status = load(input, FilenameSuffix);
304 input.close();
305
306 return status;
307}
308
309/** Parses an istream depending on its suffix
310 * \param &input input stream
311 * \param suffix
312 * \return true - parsing ok, false - suffix unknown
313 */
314bool FormatParserStorage::load(std::istream &input, std::string &suffix)
315{
316 enum ParserTypes type = getTypeFromSuffix(suffix);
317 if (type != ParserTypes_end)
318 get(type).load(&input);
319 else
320 return false;
321 return true;
322}
323
324/** Stores all selected atoms in an ostream depending on its suffix
325 * \param &output output stream
326 * \param suffix
327 * \return true - storing ok, false - suffix unknown
328 */
329bool FormatParserStorage::saveSelectedAtoms(std::ostream &output, std::string suffix)
330{
331 const std::vector<const atom *> atoms =
332 const_cast<const World &>(World::getInstance()).getSelectedAtoms();
333 return save(output, suffix, atoms);
334}
335
336/** Stores all selected atoms in an ostream depending on its suffix
337 * We store in the order of the atomic ids, not in the order they appear in the molecules.
338 * Hence, we first create a vector from all selected molecules' atoms.
339 *
340 * TODO: Change here atom * to const atom * when FormatParserStorage::save() uses vector<const atom *>
341 *
342 * \param &output output stream
343 * \param suffix
344 * \return true - storing ok, false - suffix unknown
345 */
346bool FormatParserStorage::saveSelectedMolecules(std::ostream &output, std::string suffix)
347{
348 const std::vector<const molecule *> molecules =
349 const_cast<const World &>(World::getInstance()).getSelectedMolecules();
350 std::map<size_t, const atom *> IdAtoms;
351 for (std::vector<const molecule *>::const_iterator MolIter = molecules.begin();
352 MolIter != molecules.end();
353 ++MolIter) {
354 for(molecule::const_iterator AtomIter = (*MolIter)->begin();
355 AtomIter != (*MolIter)->end();
356 ++AtomIter) {
357 IdAtoms.insert( make_pair((*AtomIter)->getId(), (*AtomIter)) );
358 }
359 }
360 std::vector<const atom *> atoms;
361 atoms.reserve(IdAtoms.size());
362 for (std::map<size_t, const atom *>::const_iterator iter = IdAtoms.begin();
363 iter != IdAtoms.end();
364 ++iter) {
365 atoms.push_back(iter->second);
366 }
367 return save(output, suffix, atoms);
368}
369
370/** Stores world in an ostream depending on its suffix
371 * \param &output output stream
372 * \param suffix
373 * \return true - storing ok, false - suffix unknown
374 */
375bool FormatParserStorage::saveWorld(std::ostream &output, std::string suffix)
376{
377 const std::vector<const atom *> atoms =
378 const_cast<const World &>(World::getInstance()).getAllAtoms();
379 return save(output, suffix, atoms);
380}
381
382/** Stores a given vector of \a atoms in an ostream depending on its suffix
383 * \param &output output stream
384 * \param suffix
385 * \return true - storing ok, false - suffix unknown
386 */
387bool FormatParserStorage::save(
388 std::ostream &output,
389 std::string suffix,
390 const std::vector<const atom *> &atoms)
391{
392 enum ParserTypes type = getTypeFromSuffix(suffix);
393 if (type != ParserTypes_end)
394 get(type).save(&output, atoms);
395 else
396 return false;
397 return true;
398}
399
400/** Returns reference to the desired output parser as FormatParser, adds if not present.
401 * \param _type type of desired parser
402 * \return reference to the output FormatParser with desired type
403 */
404FormatParserInterface &FormatParserStorage::get(ParserTypes _type)
405{
406 if (!ParserPresent[_type]) {
407 add(_type);
408 }
409 return *ParserList[_type];
410}
411
412CONSTRUCT_SINGLETON(FormatParserStorage)
Note: See TracBrowser for help on using the repository browser.