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

178 lines
5.1 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 query-resolver.hpp
** framework and to resolve logical queries.
** This header defines a family of interfaces and classes
** to integrate resolution of logical, rules based queries into generic
** implementation code. The concrete facility actually to resolve such queries
** is abstracted away as QueryResolver. A prominent usage example is the session,
** which allows to query for elements "somewhere within the model"
**
*/
#ifndef LUMIERA_QUERY_RESOLVER_H
#define LUMIERA_QUERY_RESOLVER_H
#include "lib/iter-adapter.hpp"
#include "common/query.hpp"
#include "lib/nocopy.hpp"
#include <functional>
#include <memory>
#include <string>
using std::function;
namespace lumiera {
using std::unique_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
: util::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, [if applicable](QueryResolver::canHandle).
* 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
: util::NonCopyable
{
unique_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 Query<RES>::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