/* QUERY-RESOLVER.hpp - interface for discovering contents of a scope Copyright (C) Lumiera.org 2009, Hermann Vosseler 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef MOBJECT_SESSION_QUERY_RESOLVER_H #define MOBJECT_SESSION_QUERY_RESOLVER_H //#include "proc/mobject/mobject.hpp" //#include "proc/mobject/placement.hpp" #include "lib/bool-checkable.hpp" #include "lib/typed-counter.hpp" #include "lib/iter-adapter.hpp" #include "lib/util.hpp" #include #include #include #include //#include #include //using std::vector; //using std::string; namespace mobject { namespace session { using util::unConst; using boost::noncopyable; using boost::scoped_ptr; using std::tr1::function; using std::string; class no_copy_by_client { protected: ~no_copy_by_client() {} no_copy_by_client() {} no_copy_by_client (no_copy_by_client const&) {} no_copy_by_client const& operator=(no_copy_by_client const&) { return *this; } }; class Goal; class Resolution; class QueryResolver; class QueryDispatcher; /** Allow for taking ownership of a result set */ typedef std::tr1::shared_ptr PReso; /** * TODO type comment * Query ABC */ class Goal : no_copy_by_client { public: virtual ~Goal() ; enum Kind { GENERIC = 0 , DISCOVERY }; struct QueryID { Kind kind; size_t type; }; QueryID const& getQID() const { return id_; } /** * Single Solution, possibly part of a result set. * A pointer-like object, usually to be down-casted * to a specifically typed Query::Cursor * @see Resolution */ class Result : public lib::BoolCheckable { void* cur_; protected: void point_at(void* p) { cur_ = p; } template RES& access() { REQUIRE (cur_); return *reinterpret_cast (cur_); } public: bool isValid() const { return bool(cur_); } Result() : cur_(0) { } ///< create an NIL result }; protected: QueryID id_; Goal (QueryID qid) : id_(qid) { } }; inline bool operator== (Goal::QueryID const& id1, Goal::QueryID const& id2) { return id1.kind == id2.kind && id1.type == id2.type; } inline bool operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2) { return ! (id1 == id2); } /** Context used for generating type-IDs to denote * the specific result types of issued queries */ typedef lib::TypedContext ResultType; template inline size_t getResultTypeID() ///< @return unique ID denoting result type RES { return ResultType::ID::get(); } /** * TODO type comment * Concrete query to yield specifically typed result elements */ template class Query : public Goal { protected: static QueryID defineQueryTypeID (Kind queryType = Goal::GENERIC) { QueryID id = {queryType, getResultTypeID() }; return id; } public: Query() : Goal (defineQueryTypeID()) { } /* results retrieval */ class Cursor : public Goal::Result { public: typedef RES value_type; typedef RES& reference; typedef RES* pointer; RES& operator* () { return access(); } RES* operator->() { return & access(); } void point_at(RES* r){ Goal::Result::point_at(r);} void point_at(RES& r){ Goal::Result::point_at(&r);} }; typedef lib::IterAdapter iterator; iterator operator() (QueryResolver const& resolver) const; iterator resolveBy (QueryResolver const& resolver) const; protected: Query (QueryID qID) : Goal (qID) { } }; /** * ABC denoting the result set * of an individual query resolution */ class Resolution : noncopyable { public: typedef Goal::Result Result; virtual ~Resolution(); friend bool hasNext (PReso const&, Result const& pos) ////TICKET #410 { return bool(pos); } friend void iterNext (PReso& resultSet, Result& pos) { resultSet->nextResult(pos); } virtual Result prepareResolution() =0; protected: virtual void nextResult(Result& pos) =0; }; /** * Interface: a facility for resolving (some) queries * TODO type comment */ class QueryResolver : noncopyable { scoped_ptr dispatcher_; public: virtual ~QueryResolver() ; virtual operator string () const =0; ///< short characterisation of the actual facility /** issue a query to retrieve contents * The query is handed over internally to a suitable resolver implementation. * @return concrete Resolution of the query (ResultSet), \em managed by smart-pointer. * @throw lumiera::Error subclass if query evaluation flounders. * This might be broken logic, invalid input, misconfiguration * or failure of an external facility used for resolution. * @note a query may yield no results, in which case the iterator is empty. */ PReso issue (Goal const& query) const; bool canHandle (Goal const&) const; protected: /* ===== API for concrete query resolvers ===== */ virtual bool canHandleQuery (Goal::QueryID const&) const =0; void installResolutionCase (Goal::QueryID const&, function); QueryResolver(); }; template inline typename Query::iterator Query::resolveBy (QueryResolver const& resolver) const { PReso resultSet = resolver.issue (*this); Result first = resultSet->prepareResolution(); Cursor& start = static_cast (first); return iterator (resultSet, start); } /** notational convenience shortcut, * synonymous to #resolveBy */ template inline typename Query::iterator Query::operator() (QueryResolver const& resolver) const { return resolveBy (resolver); } inline bool QueryResolver::canHandle(Goal const& query) const { return canHandleQuery (query.getQID()); } }} // namespace mobject::session #endif