Lumiera  0.pre.03
»edit your freedom«
placement-index-query-resolver.cpp
Go to the documentation of this file.
1 /*
2  placementIndexQueryResolver - using PlacementIndex to resolve scope queries
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
35 
37 
38 #include <memory>
39 #include <stack>
40 
41 
42 namespace steam {
43 namespace mobject {
44 namespace session {
45 
46  using std::unique_ptr;
47 
48  using lumiera::Goal;
49  using lumiera::Query;
50  using lumiera::Resolution;
51  using lumiera::getResultTypeID;
52 
53 
54  typedef PlacementIndex::ID PID;
55  typedef Goal::QueryID QueryID;
56  typedef QueryID const& QID;
57 
58  typedef PlacementIndex& PIdx;
59  typedef PlacementIndex::iterator PIter;
60 
69  typedef PlacementMO Pla;
70 
71 
72 
74  class Explorer
75  {
76  public:
77  virtual ~Explorer() { };
78  virtual bool exhausted () =0;
79  virtual Pla& step () =0;
80  };
81 
82 
83 
84  /* ==== special strategies to choose from ==== */
85 
92  : public Explorer
93  {
94  PIter tip_;
95 
96  bool
97  exhausted()
98  {
99  return !tip_;
100  }
101 
102  Pla&
103  step ()
104  {
105  REQUIRE (tip_);
106  Pla& pos = *tip_;
107  ++tip_;
108  return pos;
109  }
110 
111  public:
112  ChildExplorer(PIter start)
113  : tip_(start)
114  { }
115  };
116 
123  : public Explorer
124  {
125  PIdx index_;
126  std::stack<PIter> scopes_;
127 
128  bool
129  exhausted()
130  {
131  while (!scopes_.empty() && !scopes_.top())
132  scopes_.pop();
133  return scopes_.empty();
134  }
135 
136  Pla&
137  step ()
138  {
139  REQUIRE (!scopes_.empty() && scopes_.top());
140  Pla& pos = *scopes_.top();
141  ++scopes_.top();
142  scopes_.push(index_.getReferrers(pos.getID()));
143  return pos;
144  }
145 
146  public:
147  DeepExplorer(PIter start, PIdx idx)
148  : index_(idx)
149  {
150  scopes_.push(start);
151  }
152  };
153 
154 
160  : public Explorer
161  {
162  PIdx index_;
163  Pla* tip_;
164 
165  bool
166  exhausted()
167  {
168  return !tip_;
169  }
170 
171  Pla&
172  step ()
173  {
174  REQUIRE (tip_);
175  Pla& pos = *tip_;
176  tip_ = &index_.getScope(*tip_);
177  if (tip_ == &pos)
178  tip_ = 0;
179  return pos;
180  }
181 
182  public:
183  UpExplorer(Pla& start, PIdx idx)
184  : index_(idx)
185  , tip_(&start)
186  { }
187  };
188 
189 
190  typedef function<bool(Pla const&)> ContentFilter;
191  typedef function<Explorer*()> ExplorerBuilder;
192 
193 
202  class ResultSet
203  : public lumiera::Resolution
204  {
205  ContentFilter acceptable_;
206  ExplorerBuilder buildExploartion_;
207  unique_ptr<Explorer> explore_;
208 
209 
210  virtual Result
211  prepareResolution()
212  {
213  explore_.reset (buildExploartion_());
214 
215  Result cursor;
216  exploreNext (cursor);
217  return cursor;
218  }
219 
220  virtual void
221  nextResult(Result& pos)
222  {
223  exploreNext (pos);
224  }
225 
226  void
227  exploreNext (Result& res)
228  {
229  typedef Query<Pla>::Cursor Cursor;
230  Cursor& cursor = static_cast<Cursor&> (res);
231 
232  while (!explore_->exhausted() )
233  {
234  Pla& elm (explore_->step());
235  if (acceptable_(elm))
236  {
237  cursor.point_at (elm);
238  return;
239  }
240  }
241 
242  ASSERT (explore_->exhausted());
243  cursor.point_at (0);
244  }
245 
246  public:
247  ResultSet (ExplorerBuilder b
248  ,ContentFilter a)
249  : acceptable_(a)
250  , buildExploartion_(b)
251  , explore_()
252  { }
253  };
254 
255 
256 
257 
258  namespace { // Helpers for wiring up a suitable resolutionFunction....
259 
260 
261  bool acceptAllObjects_(Pla) { return true; }
262 
264  template<typename QUERY>
265  ContentFilter
266  getContentFilter (QUERY const& query)
267  {
268  return query.contentFilter();
269  }
270 
272  ContentFilter
274  {
275  static ContentFilter acceptAllObjects = bind (&acceptAllObjects_, _1);
276  return acceptAllObjects;
277  }
278 
280  template<typename MO>
281  QueryID
283  {
284  QueryID qID(Goal::DISCOVERY, getResultTypeID<Placement<MO>>());
285  return qID;
286  }
287 
288  struct
290  {
291  UseThisIndex (PlacementIndex& idx) : refIndex_(idx) {}
292 
293  PlacementIndex& refIndex_;
294  PlacementIndex& operator() (void) { return refIndex_; }
295  };
296  } //(END) Helpers
297 
298 
299 
300 
301  PlacementIndexQueryResolver::PlacementIndexQueryResolver (PlacementIndex& theIndex)
302  : _getIndex(UseThisIndex (theIndex))
303  {
304  preGenerateInvocationContext();
305  }
306 
307 
308  PlacementIndexQueryResolver::PlacementIndexQueryResolver (function<IndexLink> const& accessIndex)
309  : _getIndex(accessIndex)
310  {
311  preGenerateInvocationContext();
312  }
313 
314 
315  void
316  PlacementIndexQueryResolver::preGenerateInvocationContext()
317  {
318  defineHandling<MObject>();
319  defineHandling<Clip>();
320  defineHandling<Effect>();
322 
323  defineHandling<mobject::test::DummyMO >();
324  defineHandling<mobject::test::TestSubMO1 >();
325  defineHandling<mobject::test::TestSubMO2 >();
326  defineHandling<mobject::test::TestSubMO21>();
328  }
329 
330 
331  bool
332  PlacementIndexQueryResolver::canHandleQuery(QID qID) const
333  {
334  return qID.kind == Goal::DISCOVERY
335  &&( qID.type == getResultTypeID<Placement<MObject>>()
336  ||qID.type == getResultTypeID<Placement<Clip>>()
337  ||qID.type == getResultTypeID<Placement<Effect>>()
339 
340  ||qID.type == getResultTypeID<Placement<mobject::test::DummyMO >>()
341  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO1 >>()
342  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO2 >>()
343  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO21>>()
345  );
346  }
347 
348 
349  template<typename MO>
350  void
351  PlacementIndexQueryResolver::defineHandling()
352  {
353  installResolutionCase( whenQueryingFor<MO>()
354  , bind (&PlacementIndexQueryResolver::resolutionFunction<MO>,
355  this, _1 )
356  );
357  }
358 
359 
368  template<typename MO>
369  Resolution*
370  PlacementIndexQueryResolver::resolutionFunction (Goal const& goal)
371  {
372  QID qID = goal.getQID();
373  REQUIRE (qID == whenQueryingFor<MO>());
374  REQUIRE (INSTANCEOF(ScopeQuery<MO>, &goal));
375 
376  ScopeQuery<MO> const& query = static_cast<ScopeQuery<MO> const&> (goal);
377  ScopeQueryKind direction = query.searchDirection();
378  PID scopeID = query.searchScope();
379 
381  this, scopeID, direction)
382  , getContentFilter(query)
383  );
384  }
385 
386 
392  Explorer*
394  {
395  PIdx index = _getIndex(); // access the currently configured PlacementIndex (Session)
396  switch (direction)
397  {
398  case CONTENTS: return new DeepExplorer(index.getReferrers(startID), index);
399  case CHILDREN: return new ChildExplorer(index.getReferrers(startID));
400  case PARENTS: return new UpExplorer(index.getScope(startID),index);
401  case PATH: return new UpExplorer(index.find(startID),index);
402 
403  default:
404  throw lumiera::error::Invalid("unknown query direction");
405  }
406  }
407 
408 
409 
410 }}} // namespace steam::mobject::session
Query ABC: unspecific goal for resolution or retrieval.
Definition: query.hpp:125
A refcounting Handle to an MObject of type MO, used to constrain or explicitly specify the location w...
Definition: trait.hpp:91
Query a scope to discover it&#39;s contents or location.
ABC representing the result set of an individual query resolution.
on query, an individual result set is prepared to be explored by the invoking client code...
Core abstraction: placement of a media object into session context.
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:492
MObject in the Session to represent a clip on the timeline.
Strategy: explore the structure just by following the given iterator; usually this yields an element&#39;...
discover any contained objects depth-first
Steam-Layer implementation namespace root.
Namespace of Session and user visible high-level objects.
Definition: sequence.hpp:74
discover the path to root
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
discover the enclosing scopes
A hierarchy of simple dummy-Media-Objects for easy unit testing.
Structured compound of Placement instances with lookup capabilities.
Strategy: explore the structure upwards, ascending until reaching the root element.
iterator getReferrers(ID) const
Retrieve all the elements attached to the given entry (scope) Each element (Placement) can act as a s...
Specific queries to explore contents of a scope within the high-level model.
Explorer * setupExploration(PlacementIndex::ID startID, ScopeQueryKind direction)
the builder function used to set up an concrete result set object when issuing the query...
ContentFilter getContentFilter(ScopeQuery< MObject > const &)
especially queries for MObjects need not be filtered
Implementing resolution of "discover contents"-queries based on PlacementIndex.
discover the immediate children
Strategy: explore the structure depth first.
Interface: strategy for exploring the structure.
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:279
Single Solution, possibly part of a result set.
Definition: query.hpp:163