diff --git a/src/proc/mobject/placement-index.hpp b/src/proc/mobject/placement-index.hpp index 553419d32..55f1f52ec 100644 --- a/src/proc/mobject/placement-index.hpp +++ b/src/proc/mobject/placement-index.hpp @@ -62,7 +62,7 @@ namespace mobject { ///////////////////////////////////////////TODO: shouldn't t */ class PlacementIndex : public session::QueryResolver ////////TODO: really inherit here? - , boost::noncopyable +// , boost::noncopyable ////////TODO : where to put the "noncopyable" base { class Table; diff --git a/src/proc/mobject/session/query-resolver.cpp b/src/proc/mobject/session/query-resolver.cpp index bd30d4e54..8bfb65eb3 100644 --- a/src/proc/mobject/session/query-resolver.cpp +++ b/src/proc/mobject/session/query-resolver.cpp @@ -22,45 +22,91 @@ #include "proc/mobject/session/query-resolver.hpp" -//#include "proc/mobject/session/track.hpp" -//#include "proc/mobject/placement.hpp" -//#include "proc/mobject/session/mobjectfactory.hpp" -//#include "proc/asset/track.hpp" +#include "lib/multifact-arg.hpp" namespace mobject { namespace session { + using lib::factory::MultiFact; + using lib::factory::BuildRefcountPtr; - /* generate vtables here */ - + /* generate vtables here... */ + Goal::~Goal() { } - - QueryResolver::~QueryResolver() { } Resolution::~Resolution() { } + QueryResolver::~QueryResolver() { } + + + + + typedef Goal::QueryID const& QID; + + /** we're going to use QueryID as Map key... */ + inline bool + operator< (QID q1, QID q2) + { + return (q1.kind < q2.kind) + || (q1.kind == q2.kind + && q1.type < q2.type + ); + } + + + + + + /* == dispatch to resolve typed queries == */ + + /** factory used as dispatcher table + * for resolving typed queries */ + typedef MultiFact< Resolution(Goal&) // nominal signature of fabrication + , Goal::QueryID // select resolution function by kind-of-Query + , BuildRefcountPtr // wrapper: manage result set by smart-ptr + > DispatcherTable; // struct QueryDispatcher + : DispatcherTable { + PReso + handle (Goal& query) + { + QID qID = query.getQID(); + ENSURE (contains (qID)); + + return (*this) (qID, query); + } //qID picks the resolution function }; + QueryResolver::QueryResolver () : dispatcher_(new QueryDispatcher) { } - /** TODO??? */ + /** @par implementation + * For actually building a result set, the QueryResolver base implementation + * uses an embedded dispatcher table. The concrete query resolving facilities, + * when implementing the QueryResolver interface, are expected to register + * individual resolution functions into this QueryDispatcher table. + * Whenever issuing a Goal, a suitable resolution function is picked + * based on the Goal::QueryID, which contains an embedded type code. + * Thus, the individual resolution function can (re)establish a + * typed context and downcast the Goal appropriately + */ PReso QueryResolver::issue (Goal& query) const { + TODO ("ensure proper initialisation"); + if (!canHandleQuery (query.getQID())) throw lumiera::error::Invalid ("unable to resolve this kind of query"); ////TICKET #197 - UNIMPLEMENTED ("dispatch-mechanism for re-discovering specific type-context"); - + return dispatcher_->handle(query); } diff --git a/src/proc/mobject/session/query-resolver.hpp b/src/proc/mobject/session/query-resolver.hpp index 8d3ccf1c2..6c0d295c5 100644 --- a/src/proc/mobject/session/query-resolver.hpp +++ b/src/proc/mobject/session/query-resolver.hpp @@ -31,6 +31,7 @@ #include "lib/iter-adapter.hpp" #include "lib/util.hpp" +#include #include #include //#include @@ -43,6 +44,7 @@ namespace mobject { namespace session { using util::unConst; + using boost::noncopyable; class Goal; @@ -60,6 +62,7 @@ namespace session { * Query ABC */ class Goal + : noncopyable { public: virtual ~Goal() ; @@ -78,6 +81,12 @@ namespace session { QueryID getQID() { 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 { @@ -117,6 +126,15 @@ namespace session { * 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 @@ -129,7 +147,7 @@ namespace session { static QueryID defineQueryTypeID () { - QueryID id = {Goal::GENERIC, ResultType::ID::get()}; + QueryID id = {Goal::GENERIC, getResultTypeID() }; return id; } @@ -138,6 +156,7 @@ namespace session { : Goal (defineQueryTypeID()) { } + /* results retrieval */ class Cursor : public Goal::Result @@ -156,7 +175,8 @@ namespace session { typedef lib::IterAdapter iterator; - iterator operator() (QueryResolver const& resolver); + iterator + operator() (QueryResolver const& resolver); }; @@ -166,6 +186,7 @@ namespace session { * of an individual query resolution */ class Resolution + : noncopyable { public: typedef Goal::Result Result; @@ -195,9 +216,11 @@ namespace session { /** + * Interface: a facility for resolving (some) queries * TODO type comment */ class QueryResolver + : noncopyable { boost::scoped_ptr dispatcher_; diff --git a/tests/components/proc/mobject/session/query-resolver-test.cpp b/tests/components/proc/mobject/session/query-resolver-test.cpp index 9775caccb..9f5f7e186 100644 --- a/tests/components/proc/mobject/session/query-resolver-test.cpp +++ b/tests/components/proc/mobject/session/query-resolver-test.cpp @@ -54,23 +54,23 @@ namespace test { template - class DummySolution; + class DummySolutions; template<> - class DummySolution + class DummySolutions { int resNr_; public: - DummySolution() : resNr_(7) {} + DummySolutions() : resNr_(7) {} int* next () { --resNr_; return &resNr_; } bool exhausted() { return bool(resNr_); } }; template<> - class DummySolution - : DummySolution + class DummySolutions + : DummySolutions { string currentText_; @@ -79,7 +79,7 @@ namespace test { next () { static const char* lumi ="Lumiera"; - currentText_ = string (lumi + *DummySolution::next()); + currentText_ = string (lumi + *DummySolutions::next()); return ¤tText_; } }; @@ -88,7 +88,7 @@ namespace test { struct DummyResultSet : Resolution { - DummySolution solution_; + DummySolutions solutions_; typedef typename Query::Cursor Cursor; @@ -96,7 +96,7 @@ namespace test { prepareResolution() { Cursor cursor; - cursor.pointAt (solution_.next()); + cursor.pointAt (solutions_.next()); return cursor; } @@ -105,10 +105,10 @@ namespace test { { Cursor& cursor = static_cast (pos); - if (solution_.exhausted()) + if (solutions_.exhausted()) cursor.point_at (0); else - cursor.point_at (solution_.next()); + cursor.point_at (solutions_.next()); } }; @@ -127,7 +127,7 @@ namespace test { bool wantResultType (Goal::QueryID qID) const { - return qID.type == ResultType::ID::get(); + return qID.type == getResultTypeID(); } }; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index df0a49d38..423409a94 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -5562,9 +5562,9 @@ Using transitions is a very basic task and thus needs viable support by the GUI. Because of this experience, ichthyo wants to support a more general case of transitions, which have N output connections, behave similar to their "simple" counterpart, but leave out the mixing step. As a plus, such transitions can be inserted at the source ports of N clips or between any intermediary or final output pipes as well. Any transition processor capable of handling this situation should provide some flag, in order to decide if he can be placed in such a manner. (wichin the builder, encountering a inconsistently placed transition is just an [[building error|BuildingError]]) -
+
//the problem of processing specifically typed queries without tying query and QueryResolver.//<br/>This problem can be seen as a instance of the problematic situation encountered with most visitation schemes: we want entities and tools (visitors) to work together, without being forced to commit to a pre-defined table of operations. In the situation at hand here, we want //some entities// &mdash; which we don't know &mdash; to issue //some queries// &mdash; which we don't know either. Obviously, such a problem can be solved only by controlling the scope of this incomplete knowledge, and the sequence in time of building it.
-Thus, to re-state the problem more specifically, we want the //definition//&nbsp; of the entities to be completely separate of those concerning the details of the query resolution mechanism, so to be able to design, reason, verify and extend each one without being forced into concern about the details of the respective other side. So, the buildup of the combined structure has to be postponed &mdash; assuring it //has//&nbsp; happened at the point it's operations are required.
+Thus, to re-state the problem more specifically, we want the //definition//&nbsp; of the entities to be completely separate of those definitions concerning the details of the query resolution mechanism, so to be able to design, reason, verify and extend each one without being forced into concern about the details of the respective other side. So, the buildup of the combined structure has to be postponed &mdash; assuring it //has//&nbsp; happened at the point it's operations are required.
 
 !Solution Stages
 * in ''static scope'' (while compiling), just a {{{Query<TY>}}} gets mentioned.<br/>As this is the only chance for driving a specifically typed context, we need to prepare a registration mechanism, to allow for //remembering//&nbsp; this context later.