From c80b1894e6d74bd71be6f49acc279093a4f7af98 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 19 Jun 2010 05:20:34 +0200 Subject: [PATCH] Clean up design of ScopeQuery, throw out Iterator mixin (closes #641) --- src/proc/mobject/session/scope-locator.hpp | 6 +- src/proc/mobject/session/scope-query.hpp | 67 ++++++++-------- tests/43session.tests | 13 +-- .../session/placement-index-query-test.cpp | 8 +- .../proc/mobject/session/scope-query-test.cpp | 79 ++++++++++++------- .../proc/mobject/session/test-scopes.cpp | 8 +- 6 files changed, 102 insertions(+), 79 deletions(-) diff --git a/src/proc/mobject/session/scope-locator.hpp b/src/proc/mobject/session/scope-locator.hpp index c6c9aba5d..d936ae119 100644 --- a/src/proc/mobject/session/scope-locator.hpp +++ b/src/proc/mobject/session/scope-locator.hpp @@ -99,7 +99,7 @@ namespace session { inline typename ScopeQuery::iterator ScopeLocator::explore (Scope scope) { - return ScopeQuery (theResolver(), scope.getTop(), CHILDREN); + return ScopeQuery (scope.getTop(), CHILDREN).resolveBy (theResolver()); } @@ -110,7 +110,7 @@ namespace session { inline typename ScopeQuery::iterator ScopeLocator::query (Scope scope) { - return ScopeQuery (theResolver(), scope.getTop(), CONTENTS); + return ScopeQuery (scope.getTop(), CONTENTS).resolveBy (theResolver()); } @@ -121,7 +121,7 @@ namespace session { inline typename ScopeQuery::iterator ScopeLocator::locate (Scope scope) { - return ScopeQuery (theResolver(), scope.getTop(), PATH); + return ScopeQuery (scope.getTop(), PATH).resolveBy (theResolver()); } diff --git a/src/proc/mobject/session/scope-query.hpp b/src/proc/mobject/session/scope-query.hpp index c55c15482..55152b82d 100644 --- a/src/proc/mobject/session/scope-query.hpp +++ b/src/proc/mobject/session/scope-query.hpp @@ -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 DiscoveryQuery : public Query > - , public Query >::iterator { typedef Query > _Query; @@ -93,7 +94,6 @@ namespace session { DiscoveryQuery () : _Query (_Query::defineQueryTypeID (Goal::DISCOVERY)) - , _QIter () { } private: @@ -143,7 +143,6 @@ namespace session { typedef Query > _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 { - ContentsQuery (QueryResolver const& resolver, - PlacementMO const& scope) - : ScopeQuery (resolver,scope, CONTENTS) + ContentsQuery (PlacementMO const& scope) + : ScopeQuery (scope, CONTENTS) { } }; @@ -221,9 +209,8 @@ namespace session { struct PathQuery : ScopeQuery { - PathQuery (QueryResolver const& resolver, - PlacementMO const& scope) - : ScopeQuery (resolver,scope, PARENTS) + PathQuery (PlacementMO const& scope) + : ScopeQuery (scope, PARENTS) { } }; @@ -233,18 +220,25 @@ namespace session { class SpecificContentsQuery : public ContentsQuery { - typedef ContentsQuery _Parent; - typedef typename _Parent::ContentFilter ContentFilter; + typedef typename ContentsQuery::ContentFilter ContentFilter; typedef Placement const& TypedPlacement; typedef function 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 (resolver,scope) + : ContentsQuery (scope) , specialTest_(specialPred) { } }; diff --git a/tests/43session.tests b/tests/43session.tests index 45149af95..9f991c6b4 100644 --- a/tests/43session.tests +++ b/tests/43session.tests @@ -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 diff --git a/tests/components/proc/mobject/session/placement-index-query-test.cpp b/tests/components/proc/mobject/session/placement-index-query-test.cpp index c7c39753f..cb7ef3fb3 100644 --- a/tests/components/proc/mobject/session/placement-index-query-test.cpp +++ b/tests/components/proc/mobject/session/placement-index-query-test.cpp @@ -79,7 +79,7 @@ namespace test { PlacementMO& root2 = SessionServiceExploreScope::getScopeRoot(); ASSERT (isSameObject (root1, root2)); - PlacementMO& elm1 = *ContentsQuery(resolver1,root1); + PlacementMO& elm1 = *ContentsQuery(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 (resolver,root)); + discover (ContentsQuery(root).resolveBy(resolver)); - PlacementMO& elm = *ContentsQuery(resolver,root); ////////////////////// TICKET #532 + PlacementMO& elm = *ContentsQuery(root).resolveBy(resolver); ////////////////////// TICKET #532 cout << "path to root starting at " << string(elm) << endl; - discover (PathQuery (resolver,elm)); + discover (PathQuery (elm).resolveBy(resolver)); } diff --git a/tests/components/proc/mobject/session/scope-query-test.cpp b/tests/components/proc/mobject/session/scope-query-test.cpp index 8d047e906..4ef96d144 100644 --- a/tests/components/proc/mobject/session/scope-query-test.cpp +++ b/tests/components/proc/mobject/session/scope-query-test.cpp @@ -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 #include @@ -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 const& candidate) + filter (Placement const& candidate) { string desc = candidate->operator string(); - cout << "prüfe..." << desc << endl; - return desc == "TestSubMO2"; + return contains(desc, "MO2"); } + + template + 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 (resolver,scope, CONTENTS) , "contents depth-first"); - discover (ScopeQuery (resolver,scope, CONTENTS) , "contents depth-first, filtered to Clip"); - discover (ScopeQuery (resolver,scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532 - discover (ScopeQuery (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1"); - discover (ScopeQuery (resolver,scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2"); - - discover (SpecificContentsQuery (resolver,scope, &filterfunk) , "contents depth-first, custom filtered DummyMO"); + discover (ScopeQuery (scope, CONTENTS) , "contents depth-first"); + discover (ScopeQuery (scope, CONTENTS) , "contents depth-first, filtered to Clip"); + discover (ScopeQuery (scope, CONTENTS) , "contents depth-first, filtered to DummyMO"); ////////////////////// TICKET #532 + discover (ScopeQuery (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO1"); + discover (ScopeQuery (scope, CONTENTS) , "contents depth-first, filtered to TestSubMO2"); - ScopeQuery specialEl(resolver,scope, CONTENTS); + discover (SpecificContentsQuery (scope, filter) , "contents depth-first, custom filtered DummyMO"); + + ScopeQuery allM021(scope, CONTENTS); + ScopeQuery::iterator specialEl (issue(allM021)); ++specialEl; // step in to second solution found... ASSERT (specialEl); - discover (ScopeQuery (resolver,*specialEl, PARENTS) , "parents of the second TestSubMO2 element found"); - discover (ScopeQuery (resolver,*specialEl, CHILDREN), "children of the this TestSubMO2 element"); - discover (ScopeQuery (resolver,*specialEl, PATH) , "path from there to root"); - discover (ScopeQuery (resolver,*specialEl, PATH) , "same path, but filtered to TestSubMO2"); - discover (specialEl , "continue exploring partially used TestSubMO2 iterator"); + discover (ScopeQuery (*specialEl, PARENTS) , "parents of the second TestSubMO2 element found"); + discover (ScopeQuery (*specialEl, CHILDREN), "children of the this TestSubMO2 element"); + discover (ScopeQuery (*specialEl, PATH) , "path from there to root"); + discover (ScopeQuery (*specialEl, PATH) , "same path, but filtered to TestSubMO2"); + announce ( "continue exploring partially used TestSubMO2 iterator"); + pullOut (specialEl); } template - void + static void discover (ScopeQuery const& query, Literal description) { - typedef typename ScopeQuery::iterator I; - announce (description); - for (I elm(query); - elm; ++elm) - cout << string(*elm) << endl; + pullOut (issue(query)); } - void - announce (Literal description) + template + static typename ScopeQuery::iterator + issue (ScopeQuery const& query) { - static uint nr(0); - cout << "--------------------------------Test-"<< ++nr << ": " << description << endl; + return query.resolveBy(SessionServiceExploreScope::getResolver()); } }; diff --git a/tests/components/proc/mobject/session/test-scopes.cpp b/tests/components/proc/mobject/session/test-scopes.cpp index 578c7e638..8edfacc21 100644 --- a/tests/components/proc/mobject/session/test-scopes.cpp +++ b/tests/components/proc/mobject/session/test-scopes.cpp @@ -78,16 +78,16 @@ namespace test { PlacementMO& retrieve_startElm() { - return *ContentsQuery(SessionServiceExploreScope::getResolver() - ,SessionServiceExploreScope::getScopeRoot()); + return *ContentsQuery(SessionServiceExploreScope::getScopeRoot()) + .resolveBy(SessionServiceExploreScope::getResolver()); } ScopeQuery::iterator explore_testScope (PlacementMO const& scopeTop) { - return ScopeQuery(SessionServiceExploreScope::getResolver(), - scopeTop, CHILDREN); + return ScopeQuery(scopeTop, CHILDREN) + .resolveBy(SessionServiceExploreScope::getResolver()); }