// // Copyright (C) 2009 Alistair Riddoch // Copyright (C) 2012 Erik Ogenvik // // This program 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. // // This program 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 this program; if not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "EntityExporter.h" #include "MultiLineListFormatter.h" #include "common/serialno.h" #include "common/log.h" #include "common/compose.hpp" #include #include #include #include #include using Atlas::Objects::Root; using Atlas::Objects::smart_dynamic_cast; using Atlas::Objects::Entity::Anonymous; using Atlas::Objects::Entity::RootEntity; using Atlas::Objects::Operation::Talk; using Atlas::Objects::Operation::Get; using Atlas::Message::Element; using Atlas::Message::ListType; using Atlas::Message::MapType; EntityExporter::EntityExporter(const std::string & accountId, const std::string & avatarId) : EntityExporterBase(accountId, avatarId, getCurrentTime()), mCurrentRes( nullptr) { assert(accountId != ""); assert(avatarId != ""); } EntityExporter::~EntityExporter() { } void EntityExporter::setup(const std::string & arg, OpVector & ret) { mCurrentRes = &ret; //Start by asking the server for information about itself //so we can provide correct meta data in fillWithServerData() Get get; get->setObjtype("op"); get->setSerialno(newSerialNumber()); CallbackFunction callback = sigc::mem_fun(*this, &EntityExporter::operationGetServerInfo); sendAndAwaitResponse(get, callback); start(arg, "0"); mCurrentRes = nullptr; if (mComplete || mCancelled) { m_complete = true; } } void EntityExporter::operation(const Operation & op, OpVector & res) { mCurrentRes = &res; if (!op->isDefaultRefno()) { auto I = mCallbacks.find(op->getRefno()); if (I != mCallbacks.end()) { auto callback = I->second; mCallbacks.erase(I); callback(op); } } else { if (op->getClassNo() == Atlas::Objects::Operation::ERROR_NO) { std::string message = op->getArgs().front()->getAttr("message").asString(); log(ERROR, String::compose("Got error. Message: %1", message)); } } mCurrentRes = nullptr; if (mComplete || mCancelled) { m_complete = true; } } long int EntityExporter::newSerialNumber() { return newSerialNo(); } void EntityExporter::send(const Atlas::Objects::Operation::RootOperation& op) { if (mCurrentRes) { mCurrentRes->push_back(op); } } void EntityExporter::sendAndAwaitResponse( const Atlas::Objects::Operation::RootOperation& op, CallbackFunction& callback) { if (mCurrentRes) { mCallbacks.insert(std::make_pair(op->getSerialno(), callback)); mCurrentRes->push_back(op); } } Atlas::Formatter* EntityExporter::createMultiLineFormatter(std::iostream& s, Atlas::Bridge& b) { return new MultiLineListFormatter(s, b); } std::string EntityExporter::getCurrentTime() { boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); std::stringstream ss; ss << (boost::posix_time::microsec_clock::universal_time() - epoch).total_milliseconds(); return ss.str(); } void EntityExporter::fillWithServerData(Atlas::Message::MapType& serverMap) { Element e; if (m_server_info->copyAttr("name", e) == 0 && e.isString()) { serverMap["name"] = e.asString(); //TODO: get the hostname in a different way serverMap["host"] = e.asString(); } if (m_server_info->copyAttr("ruleset", e) == 0 && e.isString()) { serverMap["ruleset"] = e.asString(); } if (m_server_info->copyAttr("version", e) == 0 && e.isString()) { serverMap["version"] = e.asString(); } if (m_server_info->copyAttr("name", e) == 0 && e.isString()) { serverMap["name"] = e.asString(); } } void EntityExporter::operationGetServerInfo( const Atlas::Objects::Operation::RootOperation& op) { if (!op->getArgs().empty()) { m_server_info = op->getArgs().front(); } }