/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /** \file FormatParserStorage.cpp * * date: Jun, 22 2010 * author: heber * */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include #include #include #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "molecule.hpp" #include "FormatParserStorage.hpp" #include "ParserTypes.hpp" #include "MpqcParser.hpp" #include "PcpParser.hpp" #include "PdbParser.hpp" #include "Psi3Parser.hpp" #include "TremoloParser.hpp" #include "XmlParser.hpp" #include "XyzParser.hpp" #include "CodePatterns/Singleton_impl.hpp" const std::string FormatParserStorage::unknownTypeString("unknown"); /** Constructor of class FormatParserStorage. */ FormatParserStorage::FormatParserStorage() { ParserList.resize(ParserTypes_end, NULL); ParserStream.resize(ParserTypes_end, NULL); ParserPresent.resize(ParserTypes_end, false); ParserDesiredOutputFormat.resize(ParserTypes_end, false); #include "ParserTypes.def" #define insert_print(z,n,seq,map, before, after) \ map .insert( std::make_pair( \ BOOST_PP_SEQ_ELEM(n, seq) \ , before < \ BOOST_PP_SEQ_ELEM(n, seq) \ > after \ ) ); #define insert_invert_print(z,n,seq,map, before, after) \ map .insert( std::make_pair( before < \ BOOST_PP_SEQ_ELEM(n, seq) \ > after, \ BOOST_PP_SEQ_ELEM(n, seq) \ ) ); // fill ParserNames #if defined ParserTypes_END // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserNames, FormatParserTrait, ::name) #define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1) #include BOOST_PP_LOCAL_ITERATE() #endif // fill ParserLookupNames #if defined ParserTypes_END // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupNames, FormatParserTrait, ::name) #define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1) #include BOOST_PP_LOCAL_ITERATE() #endif // fill ParserSuffixes #if defined ParserTypes_END // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserSuffixes, FormatParserTrait, ::suffix) #define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1) #include BOOST_PP_LOCAL_ITERATE() #endif // fill ParserLookupSuffixes #if defined ParserTypes_END // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupSuffixes, FormatParserTrait, ::suffix) #define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1) #include BOOST_PP_LOCAL_ITERATE() #endif // fill ParserAddFunction #if defined ParserTypes_END // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserAddFunction, &FormatParserStorage::addParser, ) #define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1) #include BOOST_PP_LOCAL_ITERATE() #endif #undef insert_print #undef insert_invert_print #include "ParserTypes.undef" //std::cout << "ParserNames:" << std::endl << ParserNames << std::endl; //std::cout << "ParserSuffixes:" << std::endl << ParserSuffixes << std::endl; //std::cout << "ParserLookupNames:" << std::endl << ParserLookupNames << std::endl; //std::cout << "ParserLookupSuffixes:" << std::endl << ParserLookupSuffixes << std::endl; //std::cout << "ParserAddFunction:" << std::endl << ParserAddFunction << std::endl; } /** Destructor of class FormatParserStorage. * Free all stored FormatParsers. * Save on Exit. */ FormatParserStorage::~FormatParserStorage() { for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter) if (ParserPresent[iter]) { // this will also flush the ParserStream delete ParserList[iter]; // then we remove the stream itself if (ParserStream[iter] != NULL) { if (ParserStream[iter]->is_open()) ParserStream[iter]->close(); delete ParserStream[iter]; } } } /** Tests whether a file and parsers are selected for saving. */ bool FormatParserStorage::isAbleToSave() { if (prefix.empty()) return false; for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter) if (ParserPresent[iter] && ParserDesiredOutputFormat[iter]) return true; return false; } /** Sets the filename of all current parsers in storage to prefix.suffix. * \param &prefix prefix to use. */ void FormatParserStorage::SetOutputPrefixForAll(std::string &_prefix) { prefix=_prefix; }; /** Sets \a type as a format to be stored on call of SaveAll. * * @param type type to add to desired output formats */ void FormatParserStorage::setOutputFormat(ParserTypes type) { LOG(0, "STATUS: Adding " << ParserNames[type] << " type to output."); ParserDesiredOutputFormat[type] = true; } /** Sets \a type as a format to be stored on call of SaveAll. * * @param type type to add to desired output formats */ void FormatParserStorage::setOutputFormat(std::string type) { std::map::const_iterator iter = ParserLookupNames.find(type); ASSERT(iter != ParserLookupNames.end(), "FormatParserStorage::setOutputFormat() - output format "+type+" is unknown."); setOutputFormat(iter->second); } /** Saves the world in the desired output formats. * */ void FormatParserStorage::SaveAll() { std::string filename; for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter) if (ParserPresent[iter] && ParserDesiredOutputFormat[iter]) { filename = prefix; filename += "."; filename += ParserSuffixes[iter]; ParserStream[iter] = new std::ofstream(filename.c_str()); ParserList[iter]->setOstream((std::ostream *)ParserStream[iter]); } } ParserTypes FormatParserStorage::getTypeFromName(std::string type) { if (ParserLookupNames.find(type) == ParserLookupNames.end()) { ELOG(1, "Unknown type " << type << "."); return ParserTypes_end; } else return ParserLookupNames[type]; } ParserTypes FormatParserStorage::getTypeFromSuffix(std::string type) { if (ParserLookupSuffixes.find(type) == ParserLookupSuffixes.end()) { ELOG(1, "Unknown type " << type << "."); return ParserTypes_end; } else return ParserLookupSuffixes[type]; } const std::string &FormatParserStorage::getNameFromType(ParserTypes type) { if (ParserNames.find(type) == ParserNames.end()) { ELOG(1, "Unknown type " << type << "."); return unknownTypeString; } else return ParserNames[type]; } const std::string &FormatParserStorage::getSuffixFromType(ParserTypes type) { if (ParserSuffixes.find(type) == ParserSuffixes.end()) { ELOG(1, "Unknown type " << type << "."); return unknownTypeString; } else return ParserSuffixes[type]; } bool FormatParserStorage::add(ParserTypes ptype) { if (ptype != ParserTypes_end) { if (ParserAddFunction.find(ptype) != ParserAddFunction.end()) { (getInstance().*(ParserAddFunction[ptype]))(); // we still need an object to work on ... return true; } else { ELOG(1, "No parser to add for this known type " << ParserNames[ptype] << ", not implemented?"); return false; } } else { return false; } } bool FormatParserStorage::add(std::string type) { enum ParserTypes Ptype = getTypeFromName(type); return add(Ptype); } /** Recognizes type of file and parse via FormatParserStorage::load(). * \param filename path and filename * \return true - parsing ok, false - suffix unknown */ bool FormatParserStorage::load(boost::filesystem::path filename) { return load(filename.string()); } /** Recognizes type of file and parse via FormatParserStorage::load(). * \param filename path and filename * \return true - parsing ok, false - suffix unknown */ bool FormatParserStorage::load(std::string &filename) { std::string FilenameSuffix = filename.substr(filename.find_last_of('.')+1, filename.length()); ifstream input; LOG(0, "STATUS: Loading filler molecule " << filename << " of suffix " << FilenameSuffix << "."); input.open(filename.c_str()); const bool status = load(input, FilenameSuffix); input.close(); return status; } /** Parses an istream depending on its suffix * \param &input input stream * \param suffix * \return true - parsing ok, false - suffix unknown */ bool FormatParserStorage::load(std::istream &input, std::string &suffix) { enum ParserTypes type = getTypeFromSuffix(suffix); if (type != ParserTypes_end) get(type).load(&input); else return false; return true; } /** Stores all selected atoms in an ostream depending on its suffix * \param &output output stream * \param suffix * \return true - storing ok, false - suffix unknown */ bool FormatParserStorage::saveSelectedAtoms(std::ostream &output, std::string suffix) { const std::vector atoms = const_cast(World::getInstance()).getSelectedAtoms(); return save(output, suffix, atoms); } /** Stores all selected atoms in an ostream depending on its suffix * We store in the order of the atomic ids, not in the order they appear in the molecules. * Hence, we first create a vector from all selected molecules' atoms. * * TODO: Change here atom * to const atom * when FormatParserStorage::save() uses vector * * \param &output output stream * \param suffix * \return true - storing ok, false - suffix unknown */ bool FormatParserStorage::saveSelectedMolecules(std::ostream &output, std::string suffix) { const std::vector molecules = const_cast(World::getInstance()).getSelectedMolecules(); std::map IdAtoms; for (std::vector::const_iterator MolIter = molecules.begin(); MolIter != molecules.end(); ++MolIter) { for(molecule::const_iterator AtomIter = (*MolIter)->begin(); AtomIter != (*MolIter)->end(); ++AtomIter) { IdAtoms.insert( make_pair((*AtomIter)->getId(), (*AtomIter)) ); } } std::vector atoms; atoms.reserve(IdAtoms.size()); for (std::map::const_iterator iter = IdAtoms.begin(); iter != IdAtoms.end(); ++iter) { atoms.push_back(iter->second); } return save(output, suffix, atoms); } /** Stores world in an ostream depending on its suffix * \param &output output stream * \param suffix * \return true - storing ok, false - suffix unknown */ bool FormatParserStorage::saveWorld(std::ostream &output, std::string suffix) { const std::vector atoms = const_cast(World::getInstance()).getAllAtoms(); return save(output, suffix, atoms); } /** Stores a given vector of \a atoms in an ostream depending on its suffix * \param &output output stream * \param suffix * \return true - storing ok, false - suffix unknown */ bool FormatParserStorage::save( std::ostream &output, std::string suffix, const std::vector &atoms) { enum ParserTypes type = getTypeFromSuffix(suffix); if (type != ParserTypes_end) get(type).save(&output, atoms); else return false; return true; } /** Returns reference to the desired output parser as FormatParser, adds if not present. * \param _type type of desired parser * \return reference to the output FormatParser with desired type */ FormatParserInterface &FormatParserStorage::get(ParserTypes _type) { if (!ParserPresent[_type]) { add(_type); } return *ParserList[_type]; } CONSTRUCT_SINGLETON(FormatParserStorage)