LUMIERA.clone/src/common/query/query-resolver.hpp

174 lines
4.8 KiB
C++
Raw Normal View History

/*
QUERY-RESOLVER.hpp - framework for resolving generic queries
2010-12-17 23:28:49 +01:00
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
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.
2010-12-17 23:28:49 +01:00
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.
2010-12-17 23:28:49 +01:00
*/
/** @file §§§
** TODO §§§
*/
#ifndef LUMIERA_QUERY_RESOLVER_H
#define LUMIERA_QUERY_RESOLVER_H
#include "lib/iter-adapter.hpp"
#include "common/query.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <functional>
#include <memory>
#include <string>
using std::function;
namespace lumiera {
using boost::noncopyable;
using boost::scoped_ptr;
using std::string;
2009-10-24 00:23:22 +02:00
class Resolution;
2009-10-24 00:23:22 +02:00
class QueryResolver;
class QueryDispatcher;
2009-10-24 00:23:22 +02:00
/** Allow to take and transfer ownership of a result set */
typedef std::shared_ptr<Resolution> PReso;
/**
* ABC representing the result set
* of an individual query resolution
*/
class Resolution
: boost::noncopyable
{
2009-10-29 21:59:02 +01:00
public:
typedef Goal::Result Result;
virtual ~Resolution();
/** IterAdapter attached here */
2009-10-29 21:59:02 +01:00
friend bool
checkPoint (PReso const&, Result const& pos)
{
return bool(pos);
}
2009-10-29 21:59:02 +01:00
friend void
iterNext (PReso& resultSet, Result& pos)
{
resultSet->nextResult(pos);
}
2009-10-29 21:59:02 +01:00
virtual Result prepareResolution() =0;
protected:
virtual void nextResult(Result& pos) =0;
};
/**
* Interface: a facility for resolving (some kind of) queries
* A concrete subclass has the ability to create Resolution instances
* in response to specific queries of some kind, \link #canHandle if applicable \endlink.
* Every resolution mechanism is expected to enrol by calling #installResolutionCase.
* Such a registration is considered permanent; a factory function gets stored,
* assuming that the entity to implement this function remains available
* up to the end of Lumiera main(). The kind of query and a suitable
* resolver is determined by the QueryID, which includes a type-ID.
* Thus the implementation might downcast query and resultset.
*/
class QueryResolver
: noncopyable
{
scoped_ptr<QueryDispatcher> dispatcher_;
public:
2009-10-24 00:23:22 +02:00
virtual ~QueryResolver() ;
virtual operator string () const =0; ///< short characterisation of the actual facility
/** issue a query to retrieve contents
2009-10-24 00:23:22 +02:00
* The query is handed over internally to a suitable resolver implementation.
* @return concrete Resolution of the query (ResultSet), \em managed by smart-pointer.
2009-10-24 00:23:22 +02:00
* @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;
using ResolutionMechanism = function<Resolution*(Goal const&)>;
void installResolutionCase (Goal::QueryID const&,
ResolutionMechanism);
2009-10-24 00:23:22 +02:00
QueryResolver();
};
2009-10-24 00:23:22 +02:00
template<typename RES>
inline typename Query<RES>::iterator
Query<RES>::resolveBy (QueryResolver const& resolver) const
{
PReso resultSet = resolver.issue (*this);
Result first = resultSet->prepareResolution();
Cursor& start = static_cast<Cursor&> (first); // note: type RES must be compatible!
return iterator (resultSet, start);
}
/** notational convenience shortcut,
* synonymous to #resolveBy */
template<typename RES>
inline typename Query<RES>::iterator
Query<RES>::operator() (QueryResolver const& resolver) const
{
return resolveBy (resolver);
}
2009-10-24 00:23:22 +02:00
inline bool
2009-11-13 04:52:48 +01:00
QueryResolver::canHandle(Goal const& query) const
{
return canHandleQuery (query.getQID());
}
} // namespace lumiera
#endif