prepare refactoring of the Query interface
This commit is contained in:
parent
2f1aa5ff58
commit
baefd74ae7
11 changed files with 103 additions and 34 deletions
|
|
@ -62,6 +62,7 @@ namespace lumiera {
|
|||
using proc::mobject::Session;
|
||||
using lib::meta::InstantiateChained;
|
||||
|
||||
using util::contains;
|
||||
using util::isnil;
|
||||
|
||||
using boost::any;
|
||||
|
|
@ -85,9 +86,9 @@ namespace lumiera {
|
|||
* This implementation is quite crude, of course it would be necessary actually to
|
||||
* parse and evaluate the query. @note query is modified if "default" ... */
|
||||
inline bool
|
||||
is_defaults_query (string& query)
|
||||
treat_as_defaults_query (string& querySpec)
|
||||
{
|
||||
return !isnil (removeTerm ("default", query));
|
||||
return !isnil (removeTerm ("default", querySpec));
|
||||
}
|
||||
|
||||
} // details (end)
|
||||
|
|
@ -130,7 +131,7 @@ namespace lumiera {
|
|||
|
||||
/**
|
||||
* building block defining how to do
|
||||
* the mock implementation for \e one type.
|
||||
* the mock implementation for \em one type.
|
||||
* We simply access a table holding pre-created objects.
|
||||
*/
|
||||
template<class TY, class BASE>
|
||||
|
|
@ -148,7 +149,7 @@ namespace lumiera {
|
|||
{
|
||||
Ret const& candidate (any_cast<Ret const&> (entry));
|
||||
if (! solution
|
||||
||(solution && solution == candidate) // simulates a real unification
|
||||
||(solution && solution == candidate) // simulates a real unification
|
||||
)
|
||||
return solution = candidate;
|
||||
}
|
||||
|
|
@ -159,17 +160,21 @@ namespace lumiera {
|
|||
bool
|
||||
try_special_case (Ret& solution, Query<TY> const& q)
|
||||
{
|
||||
if (solution && isFakeBypass(q)) // backdoor for tests
|
||||
if (solution && isFakeBypass(q)) // backdoor for tests
|
||||
return solution;
|
||||
|
||||
string querySpec (q);
|
||||
if (treat_as_defaults_query (querySpec))
|
||||
{
|
||||
Query<TY> defaultsQuery(querySpec);
|
||||
return solution = Session::current->defaults (defaultsQuery);
|
||||
} // may cause recursion
|
||||
|
||||
Query<TY> newQuery = q;
|
||||
if (is_defaults_query (newQuery)) // modified query..
|
||||
return solution = Session::current->defaults (newQuery);
|
||||
// may cause recursion
|
||||
if (this->detect_case (solution, newQuery))
|
||||
return resolve (solution, newQuery);
|
||||
|
||||
return solution = Ret(); // fail: return default-constructed empty smart ptr
|
||||
return solution = Ret(); // fail: return default-constructed empty smart ptr
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ namespace util {
|
|||
* used to fed parameters has a higher precedence than the
|
||||
* assignment or comparison operators, ensuring that all parameters
|
||||
* are evaluated and formatted prior to receiving the formatted result
|
||||
* @note EX_FREE
|
||||
*/
|
||||
_Fmt::operator string() const
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ namespace util {
|
|||
* @param val arbitrary value or pointer to be included into the result
|
||||
* @warning you need to provide exactly the right number of parameters,
|
||||
* i.e. matching the number of fields in the format string.
|
||||
* @note EX_FREE
|
||||
*/
|
||||
template<typename VAL>
|
||||
inline _Fmt&
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/** @file polymorphic-value.hpp
|
||||
** A mechanism to allow for opaque polymorphic value objects.
|
||||
** This template helps to overcome a problem frequently encountered in
|
||||
** This template helps to overcome a problem occasionally encountered in
|
||||
** C++ programming, based on the fundamental design of C++, which favours
|
||||
** explicit low-level control, copying of values and strict ctor-dtor pairs.
|
||||
** Many object oriented design patterns build on polymorphism, where the
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
** In C++, in order to employ many of the well known techniques, we're bound
|
||||
** more or less to explicitly put the objects somewhere in heap allocated memory
|
||||
** and then pass an interface pointer or reference into the actual algorithm.
|
||||
** Often, this hinders a design based on constant values and small descriptor
|
||||
** Sometimes, this hinders a design based on constant values and small descriptor
|
||||
** objects used inline, thus forcing into unnecessarily complex and heavyweight
|
||||
** alternatives. While it's certainly pointless to fight the fundamental nature
|
||||
** of the programming language, we may try to pull some (template based) trickery
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
** this concrete type is irrelevant after finishing the placement constructor.
|
||||
** In order to re-access this management interface, so to be able to invoke
|
||||
** the copy or clone operations, we need to do an elaborate re-cast operation,
|
||||
** first going down to the leaf type and then back up into the mixed in
|
||||
** first going down to the leaf type and then back up into the mixed-in
|
||||
** management interface. Basically this operation is performed by using
|
||||
** a \c dynamic_cast<CopyAPI&>(bufferContents)
|
||||
** - but when the used client types provide some collaboration and implement
|
||||
|
|
@ -98,6 +98,16 @@
|
|||
** to conceal the actual implementation type comes with zero runtime overhead,
|
||||
** compared with direct usage of a family of polymorphic types (with VTable).
|
||||
**
|
||||
** So, how can the implementation of copy or assignment know the actual type
|
||||
** to be copied? Basically we exploit the fact that the actual instance lives
|
||||
** in an opaque buffer within the "outer" container. More specifically, \em we
|
||||
** place it into that buffer -- thus we're able to control the actual type used.
|
||||
** This way, the actual copy operations reside in an Adapter type, which lives
|
||||
** at the absolute leaf end of the inheritance chain. It even inherits from
|
||||
** the "implementation type" specified by the client. Thus, within the
|
||||
** context of the copy operation, we know all the concrete types.
|
||||
**
|
||||
**
|
||||
** \par using polymorphic value objects
|
||||
**
|
||||
** To start with, we need a situation where polymorphic treatment and type erasure
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <boost/format.hpp> /////////////////////////////////////////TICKET #166 Oh RLY ... need to do away with this
|
||||
|
||||
#include "lib/symbol.hpp"
|
||||
|
||||
|
||||
|
|
@ -60,19 +58,26 @@ namespace lumiera {
|
|||
* of the atoms in the query.
|
||||
*/
|
||||
template<class OBJ>
|
||||
class Query : public std::string
|
||||
class Query
|
||||
{
|
||||
std::string predicateForm_;
|
||||
|
||||
public:
|
||||
explicit Query (string const& predicate="") : string(predicate) {}
|
||||
// explicit Query (format& pattern) : string(str(pattern)) {} //////////////TICKET #166 outch... that needs to disappear
|
||||
explicit Query (string const& predicate="")
|
||||
: predicateForm_(predicate)
|
||||
{ }
|
||||
|
||||
const string asKey() const
|
||||
|
||||
void
|
||||
clear()
|
||||
{
|
||||
return string(typeid(OBJ).name())+": "+*this;
|
||||
predicateForm_.clear();
|
||||
}
|
||||
|
||||
operator string& () { return *this; } //TICKET #710 : needed temporarily by fake-configrules
|
||||
}; // for calling removeTerm on the string-ref....
|
||||
operator string() const { return predicateForm_; }
|
||||
|
||||
// operator string& () { return predicateForm_; } //TICKET #710 : needed temporarily by fake-configrules
|
||||
}; // for calling removeTerm on the string-ref....
|
||||
|
||||
|
||||
namespace query {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#ifndef ASSET_PROCPATT_H
|
||||
#define ASSET_PROCPATT_H
|
||||
|
||||
#include "lib/query.hpp"
|
||||
#include "proc/asset/struct.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ namespace proc {
|
|||
namespace control {
|
||||
|
||||
// using lib::P;
|
||||
// using lumiera::Query;
|
||||
|
||||
// using std::string;
|
||||
// using boost::format;
|
||||
|
|
|
|||
|
|
@ -24,11 +24,10 @@
|
|||
#include "proc/mobject/session/defs-manager.hpp"
|
||||
#include "proc/mobject/session/defs-registry.hpp"
|
||||
#include "common/configrules.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
#include "lib/error.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using boost::format;
|
||||
using util::_Fmt;
|
||||
|
||||
using lumiera::ConfigRules;
|
||||
using lumiera::query::QueryHandler;
|
||||
|
|
@ -64,8 +63,9 @@ namespace session {
|
|||
P<TAR> res;
|
||||
QueryHandler<TAR>& typeHandler = ConfigRules::instance();
|
||||
for (DefsRegistry::Iter<TAR> i = defsRegistry->candidates(capabilities);
|
||||
res = *i ; ++i )
|
||||
bool(*i) ; ++i )
|
||||
{
|
||||
res = *i;
|
||||
typeHandler.resolve (res, capabilities);
|
||||
if (res)
|
||||
return res;
|
||||
|
|
@ -120,8 +120,8 @@ namespace session {
|
|||
res = create (capabilities); // not yet known as default, create new
|
||||
|
||||
if (!res)
|
||||
throw lumiera::error::Config ( str(format("The following Query could not be resolved: %s.")
|
||||
% capabilities.asKey())
|
||||
throw lumiera::error::Config (_Fmt("The following Query could not be resolved: %s.")
|
||||
% capabilities.asKey()
|
||||
, LUMIERA_ERROR_CAPABILITY_QUERY );
|
||||
else
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "lib/nocopy.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <tr1/functional>
|
||||
|
|
@ -177,11 +178,16 @@ namespace session {
|
|||
return id;
|
||||
}
|
||||
|
||||
class Builder;
|
||||
|
||||
public:
|
||||
Query()
|
||||
: Goal (defineQueryTypeID())
|
||||
{ }
|
||||
|
||||
static QueryBuilder
|
||||
build (Kind queryType = Goal::GENERIC);
|
||||
|
||||
|
||||
/* results retrieval */
|
||||
class Cursor
|
||||
|
|
@ -211,11 +217,33 @@ namespace session {
|
|||
: Goal (qID)
|
||||
{ }
|
||||
|
||||
friend class Builder;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper for establishing,
|
||||
* reworking and remolding queries.
|
||||
*/
|
||||
template<class RES>
|
||||
class Query<RES>::Builder
|
||||
{
|
||||
string predicateForm_;
|
||||
|
||||
public:
|
||||
|
||||
const string
|
||||
asKey() const
|
||||
{
|
||||
return "type("
|
||||
+ lexial_cast<string> (getResultTypeID<RES>())
|
||||
+ "), "+predicateForm_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ABC denoting the result set
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ namespace session {
|
|||
* object holds it's own discovery iterator and thus is completely
|
||||
* self contained. The query is issued automatically on construction,
|
||||
* thus the embedded iterator immediately points at the first result.
|
||||
* Moreover, as any Lumiera Forward Iterator is \c bool checkable,
|
||||
* Moreover, since any Lumiera Forward Iterator is \c bool checkable,
|
||||
* a ScopeQuery not yielding any results will evaluate to \c false
|
||||
* immediately after construction, allowing convenient inline checks.
|
||||
* The query can be re-issued by the function operator, and the
|
||||
|
|
|
|||
|
|
@ -1614,7 +1614,7 @@ For this to work, we need each of the //participating object types// to provide
|
|||
|
||||
@@clear(left):display(block):@@</pre>
|
||||
</div>
|
||||
<div title="ConfigRules" modifier="Ichthyostega" modified="201010280156" created="200801171352" tags="overview spec Rules" changecount="20">
|
||||
<div title="ConfigRules" modifier="Ichthyostega" modified="201210280250" created="200801171352" tags="overview spec Rules" changecount="22">
|
||||
<pre>Many features can be implemented by specifically configuring and wiring some unspecific components. Rather than tie the client code in need of some given feature to these configuration internals, in Lumiera the client can //query // for some kind of object providing the //needed capabilities. // Right from start (summer 2007), Ichthyo had the intention to implement such a feature using sort of a ''declarative database'', e.g. by embedding a Prolog system. By adding rules to the basic session configuration, users should be able to customize the semi-automatic part of Lumiera's behaviour to great extent.
|
||||
|
||||
[[Configuration Queries|ConfigQuery]] are used at various places, when creating and adding new objects, as well when building or optimizing the render engine node network.
|
||||
|
|
@ -1631,7 +1631,21 @@ Queries are represented by instantiations of the {{{Query<TYPE>}}} templat
|
|||
A special kind of configuration query includes the predicate {{{default(X)}}}, which is kind-of an existential quantisation of the variable {{{X}}}. Using this predicate states that a suitable //default-configured// object exists somehow. This behaviour could be used as an fallback within a config query, allowing us always to return a solution. The latter can be crucial when it comes to integrating the query subsystem into an existing piece of implementation logic, which requires us to give some guarantees.
|
||||
&rarr; see DefaultsManagement on details how to access these captured defaults
|
||||
|
||||
But note, the exact relation of configuration queries and query-for-default still needs to be worked out, especially when to use which flavour. {{red{WIP 10/2010 &rArr; see Ticket [[#705|http://issues.lumiera.org/ticket/705]]}}}
|
||||
But note, the exact relation of configuration queries and query-for-default still needs to be worked out, especially when to use which flavour.
|
||||
|
||||
! {{red{WIP 2012}}} front-end and integration
|
||||
The overall architecture of this rules based configuration system remains to be worked out
|
||||
* the generic front-end to unite all kinds of configuration queries
|
||||
* how to configure the various [[query resolvers|QueryResolver]]
|
||||
* how to pick and address a suitable resolver for a given query situation
|
||||
* the taxonomy of queries:
|
||||
** capability queries
|
||||
** retrieval queries
|
||||
** defaults queries
|
||||
** discovery queries
|
||||
** connection queries
|
||||
** ...
|
||||
{{red{WIP 10/2010 &rArr; see Ticket [[#705|http://issues.lumiera.org/ticket/705]]}}}
|
||||
|
||||
!executing a Configuration Query
|
||||
Actually posing such an configuration query, for example to the [[Defaults Manager in the Sessison|DefaultsManagement]], may trigger several actions: First it is checked against internal object registries (depending on the target object type), which may cause the delivery of an already existing object (as reference, clone, or smart pointer). Otherwise, the system tries to figure out an viable configuration for a newly created object instance, possibly by issuing recursive queries. In the most general case this may silently impose additional decisions onto the //execution context // of the query &mdash; by default the session.
|
||||
|
|
@ -4826,6 +4840,12 @@ See also the notes on
|
|||
&nbsp; &rarr; QueryRegistration
|
||||
</pre>
|
||||
</div>
|
||||
<div title="QueryExchange" modifier="Ichthyostega" modified="201211151656" created="201211060206" tags="Rules draft" changecount="3">
|
||||
<pre>There is a common denominator amongst all queries: they describe a pattern of relations, which can be //satisfied// by providing a //solution.// But queries can be used in a wide variety of situations, each binding them to a more specific meaning and each opening the possibility to use a specialised resolution mechanism. For example, a query //might// actually mean to fetch and filter the contents of some sub-section of the session model. Or it might cause the fabrication an registration of some new model content object. In order to tie those disjoint kinds of queries together, we need a mechanism to exchange one kind of query with another one, or to derive one from another one. This ''exchange of queries'' actually is a way of ''remoulding'' and rebuilding a query -- which is based on a common syntactic representation of all queries, cast into terms of predicate logic. Besides, there is a common, unspecific, generic resolution mechanism ({{red{planned 11/12}}}) , which can delegate to more specialised resolvers when applicable.
|
||||
|
||||
!handling of queries
|
||||
Queries are are always exposed or revealed at some point or facility allowing to pose queries. This facility remains the owner of the query instances and knows its concrete flavour (type). But queries can be referred to and exchanged through the {{{Query<TY>}}}-abstraction.</pre>
|
||||
</div>
|
||||
<div title="QueryFocus" modifier="Ichthyostega" modified="201006190505" created="200910140244" tags="def spec img" changecount="34">
|
||||
<pre>When querying contents of the session or sub-containers within the session, the QueryFocus follows the current point-of-query. As such queries can be issued to explore the content of container-like objects holding other MObjects, the focus is always attached to a container, which also acts as [[scope|PlacementScope]] for the contained objects. QueryFocus is an implicit state (the current point of interrest). This sate especially remembers the path down from the root of the HighLevelModel, which was used to access the current scope. Because this path constitutes a hierarchy of scopes, it can be relevant for querying and resolving placement properties. (&rarr; SessionStructureQuery)
|
||||
|
||||
|
|
@ -4889,9 +4909,10 @@ Then, running the goal {{{:-resolve(T, stream(T,mpeg)).}}} would search a Track
|
|||
In the design of the Lumiera Proc Layer done thus far, we provide //no possibility to introduce a new object kind// into the system via plugin interface. The system uses a fixed collection of classes intended to cover all needs (Clip, Effect, Track, Pipe, Label, Automation, ~Macro-Clips). Thus, plugins will only be able to provide new parametrisations of existing classes. This should not be any real limitation, because the whole system is designed to achieve most of its functionality by freely combining rather basic object kinds. As a plus, it plays nicely with any plain-C based plugin interface. For example, we will have C++ adapter classes for the most common sorts of effect plugin (pull system and synchronous frame-by-frame push with buffering) with a thin C adaptation layer for the specific external plugin systems used. Everything beyond this point can be considered "configuration data" (including the actual plugin implementation to be loaded)
|
||||
</pre>
|
||||
</div>
|
||||
<div title="QueryRegistration" modifier="Ichthyostega" created="201006190112" tags="Rules draft impl discuss" changecount="1">
|
||||
<div title="QueryRegistration" modifier="Ichthyostega" modified="201211151653" created="201006190112" tags="Rules draft impl discuss" changecount="4">
|
||||
<pre>//Querying for some suitable element,// instead of relying on hard wired dependencies, is considered a core pattern within Lumiera.
|
||||
But we certainly can't expect to subsume every query situation to one single umbrella interface, so we need some kind of '''query dispatch''' and a registration mechanism to support this indirection. Closely related is the &rarr; TypedQueryProblem
|
||||
But we certainly can't expect to subsume every query situation to one single umbrella interface, so we need some kind of ''query dispatch'' and a registration mechanism to support this indirection. This could lead to a situation, where the term &raquo;query&laquo; is just a vaguely defined umbrella, holding together several disjoint subsistems. Yet, while in fact this describes the situation in the code base as of this writing, {{red{11/2012}}}, actually all kinds of queries are intended to share a //common semantic space.// So, in the end, we need a mechanism to [[exchange queries|QueryExchange]] with one another, and this mechanism ought to be based on the common //syntactic representation through terms of predicate logic.//
|
||||
Closely related is the &rarr; TypedQueryProblem
|
||||
|
||||
!Plans and preliminary implementation
|
||||
As of 6/10, the intention is to be able just to //pose queries eventually.// Behind the scenes, a suitable QueryResolver should then be picked to process the query and yield a resultset. Thus the {{{Goal}}} and {{{Query<TY>}}} interfaces are to become the access point to a generic dispatching service and a bundle of specialised resolution mechanisms.
|
||||
|
|
|
|||
Loading…
Reference in a new issue