Clean up design of ScopeQuery, throw out Iterator mixin (closes #641)
This commit is contained in:
parent
4f6fa69f2b
commit
c80b1894e6
6 changed files with 102 additions and 79 deletions
|
|
@ -99,7 +99,7 @@ namespace session {
|
||||||
inline typename ScopeQuery<MO>::iterator
|
inline typename ScopeQuery<MO>::iterator
|
||||||
ScopeLocator::explore (Scope scope)
|
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
|
inline typename ScopeQuery<MO>::iterator
|
||||||
ScopeLocator::query (Scope scope)
|
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
|
inline typename ScopeQuery<MO>::iterator
|
||||||
ScopeLocator::locate (Scope scope)
|
ScopeLocator::locate (Scope scope)
|
||||||
{
|
{
|
||||||
return ScopeQuery<MO> (theResolver(), scope.getTop(), PATH);
|
return ScopeQuery<MO> (scope.getTop(), PATH).resolveBy (theResolver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,15 +59,16 @@ namespace session {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mix-in ABC, combining a Query for placement-attached objects
|
* ABC to build Queries for placement-attached objects.
|
||||||
* with an embedded result set iterator. Thus, an concrete (derived)
|
* The Placements obtained from such a query are typed to the
|
||||||
* DiscoveryQuery can be created by the invoking client code, and
|
* specific MObject type given as template parameter. To ensure
|
||||||
* then immediately explored until exhaustion of the result iterator.
|
* 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>
|
template<class MO>
|
||||||
class DiscoveryQuery
|
class DiscoveryQuery
|
||||||
: public Query<Placement<MO> >
|
: public Query<Placement<MO> >
|
||||||
, public Query<Placement<MO> >::iterator
|
|
||||||
{
|
{
|
||||||
typedef Query<Placement<MO> > _Query;
|
typedef Query<Placement<MO> > _Query;
|
||||||
|
|
||||||
|
|
@ -93,7 +94,6 @@ namespace session {
|
||||||
|
|
||||||
DiscoveryQuery ()
|
DiscoveryQuery ()
|
||||||
: _Query (_Query::defineQueryTypeID (Goal::DISCOVERY))
|
: _Query (_Query::defineQueryTypeID (Goal::DISCOVERY))
|
||||||
, _QIter ()
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -143,7 +143,6 @@ namespace session {
|
||||||
typedef Query<Placement<MO> > _Query;
|
typedef Query<Placement<MO> > _Query;
|
||||||
|
|
||||||
|
|
||||||
QueryResolver const& index_;
|
|
||||||
PlacementMO::ID startPoint_;
|
PlacementMO::ID startPoint_;
|
||||||
ScopeQueryKind to_discover_;
|
ScopeQueryKind to_discover_;
|
||||||
|
|
||||||
|
|
@ -152,24 +151,14 @@ namespace session {
|
||||||
typedef typename _Parent::ContentFilter ContentFilter;
|
typedef typename _Parent::ContentFilter ContentFilter;
|
||||||
|
|
||||||
|
|
||||||
ScopeQuery (QueryResolver const& resolver,
|
ScopeQuery (PlacementMO const& scope,
|
||||||
PlacementMO const& scope,
|
|
||||||
ScopeQueryKind direction)
|
ScopeQueryKind direction)
|
||||||
: index_(resolver)
|
: startPoint_(scope)
|
||||||
, startPoint_(scope)
|
|
||||||
, to_discover_(direction)
|
, to_discover_(direction)
|
||||||
{
|
{ }
|
||||||
resetResultIteration (_Query::resolveBy(index_)); ///////////////////////////////TICKET #642 this call causes the problem!!!
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
iterator
|
|
||||||
operator() () const
|
|
||||||
{
|
|
||||||
return _Query::resolveBy (index_);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlacementMO::ID const&
|
PlacementMO::ID const&
|
||||||
searchScope () const
|
searchScope () const
|
||||||
{
|
{
|
||||||
|
|
@ -209,9 +198,8 @@ namespace session {
|
||||||
struct ContentsQuery
|
struct ContentsQuery
|
||||||
: ScopeQuery<MO>
|
: ScopeQuery<MO>
|
||||||
{
|
{
|
||||||
ContentsQuery (QueryResolver const& resolver,
|
ContentsQuery (PlacementMO const& scope)
|
||||||
PlacementMO const& scope)
|
: ScopeQuery<MO> (scope, CONTENTS)
|
||||||
: ScopeQuery<MO> (resolver,scope, CONTENTS)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -221,9 +209,8 @@ namespace session {
|
||||||
struct PathQuery
|
struct PathQuery
|
||||||
: ScopeQuery<MO>
|
: ScopeQuery<MO>
|
||||||
{
|
{
|
||||||
PathQuery (QueryResolver const& resolver,
|
PathQuery (PlacementMO const& scope)
|
||||||
PlacementMO const& scope)
|
: ScopeQuery<MO> (scope, PARENTS)
|
||||||
: ScopeQuery<MO> (resolver,scope, PARENTS)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -233,18 +220,25 @@ namespace session {
|
||||||
class SpecificContentsQuery
|
class SpecificContentsQuery
|
||||||
: public ContentsQuery<MO>
|
: public ContentsQuery<MO>
|
||||||
{
|
{
|
||||||
typedef ContentsQuery<MO> _Parent;
|
typedef typename ContentsQuery<MO>::ContentFilter ContentFilter;
|
||||||
typedef typename _Parent::ContentFilter ContentFilter;
|
|
||||||
|
|
||||||
typedef Placement<MO> const& TypedPlacement;
|
typedef Placement<MO> const& TypedPlacement;
|
||||||
|
|
||||||
typedef function<bool(TypedPlacement)> SpecialPredicate;
|
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_;
|
SpecialPredicate predicate_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpecialTest (SpecialPredicate const& pred)
|
Filter (SpecialPredicate const& pred)
|
||||||
: predicate_(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
|
ContentFilter
|
||||||
buildContentFilter() const
|
buildContentFilter() const
|
||||||
{
|
{
|
||||||
|
|
@ -268,10 +268,9 @@ namespace session {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpecificContentsQuery (QueryResolver const& resolver
|
SpecificContentsQuery (PlacementMO const& scope
|
||||||
,PlacementMO const& scope
|
|
||||||
,SpecialPredicate const& specialPred)
|
,SpecialPredicate const& specialPred)
|
||||||
: ContentsQuery<MO> (resolver,scope)
|
: ContentsQuery<MO> (scope)
|
||||||
, specialTest_(specialPred)
|
, specialTest_(specialPred)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -142,17 +142,20 @@ out: Placement<.+TestSubMO1.>
|
||||||
out: --------------------------------Test-5: contents depth-first, filtered to TestSubMO2
|
out: --------------------------------Test-5: contents depth-first, filtered to TestSubMO2
|
||||||
out: Placement<.+TestSubMO21.>
|
out: Placement<.+TestSubMO21.>
|
||||||
out: Placement<.+TestSubMO2.>
|
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<.+TestSubMO21.>
|
||||||
out: Placement<.+mobject.session.Label.>
|
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: Placement<.+TestSubMO21.>
|
||||||
out: --------------------------------Test-8: path from there to root
|
out: --------------------------------Test-9: path from there to root
|
||||||
out: Placement<.+TestSubMO21.>
|
out: Placement<.+TestSubMO21.>
|
||||||
out: Placement<.+mobject.session.Label.>
|
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: Placement<.+TestSubMO21.>
|
||||||
out: --------------------------------Test-10: continue exploring partially used TestSubMO2 iterator
|
out: --------------------------------Test-11: continue exploring partially used TestSubMO2 iterator
|
||||||
out: Placement<.+TestSubMO21.>
|
out: Placement<.+TestSubMO21.>
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ namespace test {
|
||||||
PlacementMO& root2 = SessionServiceExploreScope::getScopeRoot();
|
PlacementMO& root2 = SessionServiceExploreScope::getScopeRoot();
|
||||||
ASSERT (isSameObject (root1, root2));
|
ASSERT (isSameObject (root1, root2));
|
||||||
|
|
||||||
PlacementMO& elm1 = *ContentsQuery<TestSubMO21>(resolver1,root1);
|
PlacementMO& elm1 = *ContentsQuery<TestSubMO21>(root1).resolveBy(resolver1);
|
||||||
PlacementMO& elm2 = *(index->getReferrers(root1));
|
PlacementMO& elm2 = *(index->getReferrers(root1));
|
||||||
ASSERT (isSameObject (elm1, elm2));
|
ASSERT (isSameObject (elm1, elm2));
|
||||||
}
|
}
|
||||||
|
|
@ -93,12 +93,12 @@ namespace test {
|
||||||
PlacementIndexQueryResolver resolver(*index);
|
PlacementIndexQueryResolver resolver(*index);
|
||||||
|
|
||||||
cout << "explore contents depth-first..." << endl;
|
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;
|
cout << "path to root starting at " << string(elm) << endl;
|
||||||
discover (PathQuery<MObject> (resolver,elm));
|
discover (PathQuery<MObject> (elm).resolveBy(resolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "proc/mobject/session/test-scopes.hpp"
|
#include "proc/mobject/session/test-scopes.hpp"
|
||||||
#include "proc/mobject/session/clip.hpp"
|
#include "proc/mobject/session/clip.hpp"
|
||||||
#include "lib/symbol.hpp"
|
#include "lib/symbol.hpp"
|
||||||
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -41,14 +42,37 @@ namespace test {
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
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
|
bool
|
||||||
filterfunk (Placement<DummyMO> const& candidate)
|
filter (Placement<DummyMO> const& candidate)
|
||||||
{
|
{
|
||||||
string desc = candidate->operator string();
|
string desc = candidate->operator string();
|
||||||
cout << "prüfe..." << desc << endl;
|
return contains(desc, "MO2");
|
||||||
return desc == "TestSubMO2";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
// Prepare an (test)Index (dummy "session")
|
||||||
PPIdx testSession (build_testScopes());
|
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<MObject> (scope, CONTENTS) , "contents depth-first");
|
||||||
discover (ScopeQuery<Clip> (resolver,scope, CONTENTS) , "contents depth-first, filtered to Clip");
|
discover (ScopeQuery<Clip> (scope, CONTENTS) , "contents depth-first, filtered to Clip");
|
||||||
discover (ScopeQuery<DummyMO> (resolver,scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532
|
discover (ScopeQuery<DummyMO> (scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532
|
||||||
discover (ScopeQuery<TestSubMO1> (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1");
|
discover (ScopeQuery<TestSubMO1> (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1");
|
||||||
discover (ScopeQuery<TestSubMO2> (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2");
|
discover (ScopeQuery<TestSubMO2> (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2");
|
||||||
|
|
||||||
discover (SpecificContentsQuery<DummyMO> (resolver,scope, &filterfunk) , "contents depth-first, custom filtered DummyMO");
|
discover (SpecificContentsQuery<DummyMO> (scope, filter) , "contents depth-first, custom filtered DummyMO");
|
||||||
|
|
||||||
ScopeQuery<TestSubMO21> specialEl(resolver,scope, CONTENTS);
|
ScopeQuery<TestSubMO21> allM021(scope, CONTENTS);
|
||||||
|
ScopeQuery<TestSubMO21>::iterator specialEl (issue(allM021));
|
||||||
++specialEl; // step in to second solution found...
|
++specialEl; // step in to second solution found...
|
||||||
ASSERT (specialEl);
|
ASSERT (specialEl);
|
||||||
|
|
||||||
discover (ScopeQuery<MObject> (resolver,*specialEl, PARENTS) , "parents of the second TestSubMO2 element found");
|
discover (ScopeQuery<MObject> (*specialEl, PARENTS) , "parents of the second TestSubMO2 element found");
|
||||||
discover (ScopeQuery<MObject> (resolver,*specialEl, CHILDREN), "children of the this TestSubMO2 element");
|
discover (ScopeQuery<MObject> (*specialEl, CHILDREN), "children of the this TestSubMO2 element");
|
||||||
discover (ScopeQuery<MObject> (resolver,*specialEl, PATH) , "path from there to root");
|
discover (ScopeQuery<MObject> (*specialEl, PATH) , "path from there to root");
|
||||||
discover (ScopeQuery<TestSubMO2> (resolver,*specialEl, PATH) , "same path, but filtered to TestSubMO2");
|
discover (ScopeQuery<TestSubMO2> (*specialEl, PATH) , "same path, but filtered to TestSubMO2");
|
||||||
discover (specialEl , "continue exploring partially used TestSubMO2 iterator");
|
announce ( "continue exploring partially used TestSubMO2 iterator");
|
||||||
|
pullOut (specialEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class MO>
|
template<class MO>
|
||||||
void
|
static void
|
||||||
discover (ScopeQuery<MO> const& query, Literal description)
|
discover (ScopeQuery<MO> const& query, Literal description)
|
||||||
{
|
{
|
||||||
typedef typename ScopeQuery<MO>::iterator I;
|
|
||||||
|
|
||||||
announce (description);
|
announce (description);
|
||||||
for (I elm(query);
|
pullOut (issue(query));
|
||||||
elm; ++elm)
|
|
||||||
cout << string(*elm) << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
template<class MO>
|
||||||
announce (Literal description)
|
static typename ScopeQuery<MO>::iterator
|
||||||
|
issue (ScopeQuery<MO> const& query)
|
||||||
{
|
{
|
||||||
static uint nr(0);
|
return query.resolveBy(SessionServiceExploreScope::getResolver());
|
||||||
cout << "--------------------------------Test-"<< ++nr << ": " << description << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,16 @@ namespace test {
|
||||||
PlacementMO&
|
PlacementMO&
|
||||||
retrieve_startElm()
|
retrieve_startElm()
|
||||||
{
|
{
|
||||||
return *ContentsQuery<TestSubMO1>(SessionServiceExploreScope::getResolver()
|
return *ContentsQuery<TestSubMO1>(SessionServiceExploreScope::getScopeRoot())
|
||||||
,SessionServiceExploreScope::getScopeRoot());
|
.resolveBy(SessionServiceExploreScope::getResolver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScopeQuery<MObject>::iterator
|
ScopeQuery<MObject>::iterator
|
||||||
explore_testScope (PlacementMO const& scopeTop)
|
explore_testScope (PlacementMO const& scopeTop)
|
||||||
{
|
{
|
||||||
return ScopeQuery<MObject>(SessionServiceExploreScope::getResolver(),
|
return ScopeQuery<MObject>(scopeTop, CHILDREN)
|
||||||
scopeTop, CHILDREN);
|
.resolveBy(SessionServiceExploreScope::getResolver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue