Clean up design of ScopeQuery, throw out Iterator mixin (closes #641)

This commit is contained in:
Fischlurch 2010-06-19 05:20:34 +02:00
parent 4f6fa69f2b
commit c80b1894e6
6 changed files with 102 additions and 79 deletions

View file

@ -99,7 +99,7 @@ namespace session {
inline typename ScopeQuery<MO>::iterator
ScopeLocator::explore (Scope scope)
{
return ScopeQuery<MO> (theResolver(), scope.getTop(), CHILDREN);
return ScopeQuery<MO> (scope.getTop(), CHILDREN).resolveBy (theResolver());
}
@ -110,7 +110,7 @@ namespace session {
inline typename ScopeQuery<MO>::iterator
ScopeLocator::query (Scope scope)
{
return ScopeQuery<MO> (theResolver(), scope.getTop(), CONTENTS);
return ScopeQuery<MO> (scope.getTop(), CONTENTS).resolveBy (theResolver());
}
@ -121,7 +121,7 @@ namespace session {
inline typename ScopeQuery<MO>::iterator
ScopeLocator::locate (Scope scope)
{
return ScopeQuery<MO> (theResolver(), scope.getTop(), PATH);
return ScopeQuery<MO> (scope.getTop(), PATH).resolveBy (theResolver());
}

View file

@ -59,15 +59,16 @@ namespace session {
/**
* Mix-in ABC, combining a Query for placement-attached objects
* with an embedded result set iterator. Thus, an concrete (derived)
* DiscoveryQuery can be created by the invoking client code, and
* then immediately explored until exhaustion of the result iterator.
* ABC to build Queries for placement-attached objects.
* The Placements obtained from such a query are typed to the
* specific MObject type given as template parameter. To ensure
* this, an additional ContentFilter is applied on the yielded
* results; this filter function is constructed by a virtual
* call when actually issuing the query.
*/
template<class MO>
class DiscoveryQuery
: public Query<Placement<MO> >
, public Query<Placement<MO> >::iterator
{
typedef Query<Placement<MO> > _Query;
@ -93,7 +94,6 @@ namespace session {
DiscoveryQuery ()
: _Query (_Query::defineQueryTypeID (Goal::DISCOVERY))
, _QIter ()
{ }
private:
@ -143,7 +143,6 @@ namespace session {
typedef Query<Placement<MO> > _Query;
QueryResolver const& index_;
PlacementMO::ID startPoint_;
ScopeQueryKind to_discover_;
@ -152,24 +151,14 @@ namespace session {
typedef typename _Parent::ContentFilter ContentFilter;
ScopeQuery (QueryResolver const& resolver,
PlacementMO const& scope,
ScopeQuery (PlacementMO const& scope,
ScopeQueryKind direction)
: index_(resolver)
, startPoint_(scope)
: startPoint_(scope)
, to_discover_(direction)
{
resetResultIteration (_Query::resolveBy(index_)); ///////////////////////////////TICKET #642 this call causes the problem!!!
}
{ }
iterator
operator() () const
{
return _Query::resolveBy (index_);
}
PlacementMO::ID const&
searchScope () const
{
@ -209,9 +198,8 @@ namespace session {
struct ContentsQuery
: ScopeQuery<MO>
{
ContentsQuery (QueryResolver const& resolver,
PlacementMO const& scope)
: ScopeQuery<MO> (resolver,scope, CONTENTS)
ContentsQuery (PlacementMO const& scope)
: ScopeQuery<MO> (scope, CONTENTS)
{ }
};
@ -221,9 +209,8 @@ namespace session {
struct PathQuery
: ScopeQuery<MO>
{
PathQuery (QueryResolver const& resolver,
PlacementMO const& scope)
: ScopeQuery<MO> (resolver,scope, PARENTS)
PathQuery (PlacementMO const& scope)
: ScopeQuery<MO> (scope, PARENTS)
{ }
};
@ -233,18 +220,25 @@ namespace session {
class SpecificContentsQuery
: public ContentsQuery<MO>
{
typedef ContentsQuery<MO> _Parent;
typedef typename _Parent::ContentFilter ContentFilter;
typedef typename ContentsQuery<MO>::ContentFilter ContentFilter;
typedef Placement<MO> const& TypedPlacement;
typedef function<bool(TypedPlacement)> SpecialPredicate;
class SpecialTest
/**
* Filter functor, built on top of a predicate,
* which is provided by the client on creation of this
* SpecivicContentsQuery instance. This allows for filtering
* based on operations of the specific type MO, as opposed to
* just using the bare MObject interface.
*/
class Filter
{
SpecialPredicate predicate_;
public:
SpecialTest (SpecialPredicate const& pred)
Filter (SpecialPredicate const& pred)
: predicate_(pred)
{ }
@ -259,8 +253,14 @@ namespace session {
}
};
SpecialTest specialTest_;
Filter specialTest_;
/** using a specialised version of the filtering,
* which doesn't only check the concrete type,
* but also applies a custom filter predicate
* @return function object, embedding a copy
* of the Filter functor.
*/
ContentFilter
buildContentFilter() const
{
@ -268,10 +268,9 @@ namespace session {
}
public:
SpecificContentsQuery (QueryResolver const& resolver
,PlacementMO const& scope
SpecificContentsQuery (PlacementMO const& scope
,SpecialPredicate const& specialPred)
: ContentsQuery<MO> (resolver,scope)
: ContentsQuery<MO> (scope)
, specialTest_(specialPred)
{ }
};

View file

@ -142,17 +142,20 @@ out: Placement<.+TestSubMO1.>
out: --------------------------------Test-5: contents depth-first, filtered to TestSubMO2
out: Placement<.+TestSubMO21.>
out: Placement<.+TestSubMO2.>
out: --------------------------------Test-6: parents of the second TestSubMO2 element found
out: --------------------------------Test-6: contents depth-first, custom filtered DummyMO
out: Placement<.+TestSubMO21.>
out: Placement<.+TestSubMO2.>
out: --------------------------------Test-7: parents of the second TestSubMO2 element found
out: Placement<.+TestSubMO21.>
out: Placement<.+mobject.session.Label.>
out: --------------------------------Test-7: children of the this TestSubMO2 element
out: --------------------------------Test-8: children of the this TestSubMO2 element
out: Placement<.+TestSubMO21.>
out: --------------------------------Test-8: path from there to root
out: --------------------------------Test-9: path from there to root
out: Placement<.+TestSubMO21.>
out: Placement<.+mobject.session.Label.>
out: --------------------------------Test-9: same path, but filtered to TestSubMO2
out: --------------------------------Test-10: same path, but filtered to TestSubMO2
out: Placement<.+TestSubMO21.>
out: --------------------------------Test-10: continue exploring partially used TestSubMO2 iterator
out: --------------------------------Test-11: continue exploring partially used TestSubMO2 iterator
out: Placement<.+TestSubMO21.>
END

View file

@ -79,7 +79,7 @@ namespace test {
PlacementMO& root2 = SessionServiceExploreScope::getScopeRoot();
ASSERT (isSameObject (root1, root2));
PlacementMO& elm1 = *ContentsQuery<TestSubMO21>(resolver1,root1);
PlacementMO& elm1 = *ContentsQuery<TestSubMO21>(root1).resolveBy(resolver1);
PlacementMO& elm2 = *(index->getReferrers(root1));
ASSERT (isSameObject (elm1, elm2));
}
@ -93,12 +93,12 @@ namespace test {
PlacementIndexQueryResolver resolver(*index);
cout << "explore contents depth-first..." << endl;
discover (ContentsQuery<MObject> (resolver,root));
discover (ContentsQuery<MObject>(root).resolveBy(resolver));
PlacementMO& elm = *ContentsQuery<TestSubMO1>(resolver,root); ////////////////////// TICKET #532
PlacementMO& elm = *ContentsQuery<TestSubMO1>(root).resolveBy(resolver); ////////////////////// TICKET #532
cout << "path to root starting at " << string(elm) << endl;
discover (PathQuery<MObject> (resolver,elm));
discover (PathQuery<MObject> (elm).resolveBy(resolver));
}

View file

@ -27,6 +27,7 @@
#include "proc/mobject/session/test-scopes.hpp"
#include "proc/mobject/session/clip.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <iostream>
#include <string>
@ -41,14 +42,37 @@ namespace test {
using std::string;
using std::cout;
using std::endl;
namespace {
using util::contains;
namespace { // helpers and shortcuts....
/** a filter predicate to pick some objects from a resultset.
* @note using the specific API of DummyMO, without cast! */
bool
filterfunk (Placement<DummyMO> const& candidate)
filter (Placement<DummyMO> const& candidate)
{
string desc = candidate->operator string();
cout << "prüfe..." << desc << endl;
return desc == "TestSubMO2";
return contains(desc, "MO2");
}
template<class IT>
void
pullOut (IT const& iter)
{
for (IT elm(iter);
elm; ++elm)
cout << string(*elm) << endl;
}
void
announce (Literal description)
{
static uint nr(0);
cout << "--------------------------------Test-"<< ++nr << ": " << description << endl;
}
}
@ -74,46 +98,43 @@ namespace test {
// Prepare an (test)Index (dummy "session")
PPIdx testSession (build_testScopes());
QueryResolver const& resolver = SessionServiceExploreScope::getResolver();
PlacementMO const& scope = SessionServiceExploreScope::getScopeRoot();
PlacementMO const& scope = SessionServiceExploreScope::getScopeRoot();
discover (ScopeQuery<MObject> (resolver,scope, CONTENTS) , "contents depth-first");
discover (ScopeQuery<Clip> (resolver,scope, CONTENTS) , "contents depth-first, filtered to Clip");
discover (ScopeQuery<DummyMO> (resolver,scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532
discover (ScopeQuery<TestSubMO1> (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1");
discover (ScopeQuery<TestSubMO2> (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2");
discover (SpecificContentsQuery<DummyMO> (resolver,scope, &filterfunk) , "contents depth-first, custom filtered DummyMO");
discover (ScopeQuery<MObject> (scope, CONTENTS) , "contents depth-first");
discover (ScopeQuery<Clip> (scope, CONTENTS) , "contents depth-first, filtered to Clip");
discover (ScopeQuery<DummyMO> (scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532
discover (ScopeQuery<TestSubMO1> (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1");
discover (ScopeQuery<TestSubMO2> (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2");
ScopeQuery<TestSubMO21> specialEl(resolver,scope, CONTENTS);
discover (SpecificContentsQuery<DummyMO> (scope, filter) , "contents depth-first, custom filtered DummyMO");
ScopeQuery<TestSubMO21> allM021(scope, CONTENTS);
ScopeQuery<TestSubMO21>::iterator specialEl (issue(allM021));
++specialEl; // step in to second solution found...
ASSERT (specialEl);
discover (ScopeQuery<MObject> (resolver,*specialEl, PARENTS) , "parents of the second TestSubMO2 element found");
discover (ScopeQuery<MObject> (resolver,*specialEl, CHILDREN), "children of the this TestSubMO2 element");
discover (ScopeQuery<MObject> (resolver,*specialEl, PATH) , "path from there to root");
discover (ScopeQuery<TestSubMO2> (resolver,*specialEl, PATH) , "same path, but filtered to TestSubMO2");
discover (specialEl , "continue exploring partially used TestSubMO2 iterator");
discover (ScopeQuery<MObject> (*specialEl, PARENTS) , "parents of the second TestSubMO2 element found");
discover (ScopeQuery<MObject> (*specialEl, CHILDREN), "children of the this TestSubMO2 element");
discover (ScopeQuery<MObject> (*specialEl, PATH) , "path from there to root");
discover (ScopeQuery<TestSubMO2> (*specialEl, PATH) , "same path, but filtered to TestSubMO2");
announce ( "continue exploring partially used TestSubMO2 iterator");
pullOut (specialEl);
}
template<class MO>
void
static void
discover (ScopeQuery<MO> const& query, Literal description)
{
typedef typename ScopeQuery<MO>::iterator I;
announce (description);
for (I elm(query);
elm; ++elm)
cout << string(*elm) << endl;
pullOut (issue(query));
}
void
announce (Literal description)
template<class MO>
static typename ScopeQuery<MO>::iterator
issue (ScopeQuery<MO> const& query)
{
static uint nr(0);
cout << "--------------------------------Test-"<< ++nr << ": " << description << endl;
return query.resolveBy(SessionServiceExploreScope::getResolver());
}
};

View file

@ -78,16 +78,16 @@ namespace test {
PlacementMO&
retrieve_startElm()
{
return *ContentsQuery<TestSubMO1>(SessionServiceExploreScope::getResolver()
,SessionServiceExploreScope::getScopeRoot());
return *ContentsQuery<TestSubMO1>(SessionServiceExploreScope::getScopeRoot())
.resolveBy(SessionServiceExploreScope::getResolver());
}
ScopeQuery<MObject>::iterator
explore_testScope (PlacementMO const& scopeTop)
{
return ScopeQuery<MObject>(SessionServiceExploreScope::getResolver(),
scopeTop, CHILDREN);
return ScopeQuery<MObject>(scopeTop, CHILDREN)
.resolveBy(SessionServiceExploreScope::getResolver());
}