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)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
26 
28 
29 #include <memory>
30 #include <stack>
31 
32 
33 namespace steam {
34 namespace mobject {
35 namespace session {
36 
37  using std::unique_ptr;
38 
39  using lumiera::Goal;
40  using lumiera::Query;
41  using lumiera::Resolution;
42  using lumiera::getResultTypeID;
43 
44 
45  typedef PlacementIndex::ID PID;
46  typedef Goal::QueryID QueryID;
47  typedef QueryID const& QID;
48 
49  typedef PlacementIndex& PIdx;
50  typedef PlacementIndex::iterator PIter;
51 
60  typedef PlacementMO Pla;
61 
62 
63 
65  class Explorer
66  {
67  public:
68  virtual ~Explorer() { };
69  virtual bool exhausted () =0;
70  virtual Pla& step () =0;
71  };
72 
73 
74 
75  /* ==== special strategies to choose from ==== */
76 
83  : public Explorer
84  {
85  PIter tip_;
86 
87  bool
88  exhausted()
89  {
90  return !tip_;
91  }
92 
93  Pla&
94  step ()
95  {
96  REQUIRE (tip_);
97  Pla& pos = *tip_;
98  ++tip_;
99  return pos;
100  }
101 
102  public:
103  ChildExplorer(PIter start)
104  : tip_(start)
105  { }
106  };
107 
114  : public Explorer
115  {
116  PIdx index_;
117  std::stack<PIter> scopes_;
118 
119  bool
120  exhausted()
121  {
122  while (!scopes_.empty() && !scopes_.top())
123  scopes_.pop();
124  return scopes_.empty();
125  }
126 
127  Pla&
128  step ()
129  {
130  REQUIRE (!scopes_.empty() && scopes_.top());
131  Pla& pos = *scopes_.top();
132  ++scopes_.top();
133  scopes_.push(index_.getReferrers(pos.getID()));
134  return pos;
135  }
136 
137  public:
138  DeepExplorer(PIter start, PIdx idx)
139  : index_(idx)
140  {
141  scopes_.push(start);
142  }
143  };
144 
145 
151  : public Explorer
152  {
153  PIdx index_;
154  Pla* tip_;
155 
156  bool
157  exhausted()
158  {
159  return !tip_;
160  }
161 
162  Pla&
163  step ()
164  {
165  REQUIRE (tip_);
166  Pla& pos = *tip_;
167  tip_ = &index_.getScope(*tip_);
168  if (tip_ == &pos)
169  tip_ = 0;
170  return pos;
171  }
172 
173  public:
174  UpExplorer(Pla& start, PIdx idx)
175  : index_(idx)
176  , tip_(&start)
177  { }
178  };
179 
180 
181  typedef function<bool(Pla const&)> ContentFilter;
182  typedef function<Explorer*()> ExplorerBuilder;
183 
184 
193  class ResultSet
194  : public lumiera::Resolution
195  {
196  ContentFilter acceptable_;
197  ExplorerBuilder buildExploartion_;
198  unique_ptr<Explorer> explore_;
199 
200 
201  virtual Result
202  prepareResolution()
203  {
204  explore_.reset (buildExploartion_());
205 
206  Result cursor;
207  exploreNext (cursor);
208  return cursor;
209  }
210 
211  virtual void
212  nextResult(Result& pos)
213  {
214  exploreNext (pos);
215  }
216 
217  void
218  exploreNext (Result& res)
219  {
220  typedef Query<Pla>::Cursor Cursor;
221  Cursor& cursor = static_cast<Cursor&> (res);
222 
223  while (!explore_->exhausted() )
224  {
225  Pla& elm (explore_->step());
226  if (acceptable_(elm))
227  {
228  cursor.point_at (elm);
229  return;
230  }
231  }
232 
233  ASSERT (explore_->exhausted());
234  cursor.point_at (0);
235  }
236 
237  public:
238  ResultSet (ExplorerBuilder b
239  ,ContentFilter a)
240  : acceptable_(a)
241  , buildExploartion_(b)
242  , explore_()
243  { }
244  };
245 
246 
247 
248 
249  namespace { // Helpers for wiring up a suitable resolutionFunction....
250 
251 
252  bool acceptAllObjects_(Pla) { return true; }
253 
255  template<typename QUERY>
256  ContentFilter
257  getContentFilter (QUERY const& query)
258  {
259  return query.contentFilter();
260  }
261 
263  ContentFilter
265  {
266  static ContentFilter acceptAllObjects = bind (&acceptAllObjects_, _1);
267  return acceptAllObjects;
268  }
269 
271  template<typename MO>
272  QueryID
274  {
275  QueryID qID(Goal::DISCOVERY, getResultTypeID<Placement<MO>>());
276  return qID;
277  }
278 
279  struct
281  {
282  UseThisIndex (PlacementIndex& idx) : refIndex_(idx) {}
283 
284  PlacementIndex& refIndex_;
285  PlacementIndex& operator() (void) { return refIndex_; }
286  };
287  } //(END) Helpers
288 
289 
290 
291 
292  PlacementIndexQueryResolver::PlacementIndexQueryResolver (PlacementIndex& theIndex)
293  : _getIndex(UseThisIndex (theIndex))
294  {
295  preGenerateInvocationContext();
296  }
297 
298 
299  PlacementIndexQueryResolver::PlacementIndexQueryResolver (function<IndexLink> const& accessIndex)
300  : _getIndex(accessIndex)
301  {
302  preGenerateInvocationContext();
303  }
304 
305 
306  void
307  PlacementIndexQueryResolver::preGenerateInvocationContext()
308  {
309  defineHandling<MObject>();
310  defineHandling<Clip>();
311  defineHandling<Effect>();
313 
314  defineHandling<mobject::test::DummyMO >();
315  defineHandling<mobject::test::TestSubMO1 >();
316  defineHandling<mobject::test::TestSubMO2 >();
317  defineHandling<mobject::test::TestSubMO21>();
319  }
320 
321 
322  bool
323  PlacementIndexQueryResolver::canHandleQuery(QID qID) const
324  {
325  return qID.kind == Goal::DISCOVERY
326  &&( qID.type == getResultTypeID<Placement<MObject>>()
327  ||qID.type == getResultTypeID<Placement<Clip>>()
328  ||qID.type == getResultTypeID<Placement<Effect>>()
330 
331  ||qID.type == getResultTypeID<Placement<mobject::test::DummyMO >>()
332  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO1 >>()
333  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO2 >>()
334  ||qID.type == getResultTypeID<Placement<mobject::test::TestSubMO21>>()
336  );
337  }
338 
339 
340  template<typename MO>
341  void
342  PlacementIndexQueryResolver::defineHandling()
343  {
344  installResolutionCase( whenQueryingFor<MO>()
345  , bind (&PlacementIndexQueryResolver::resolutionFunction<MO>,
346  this, _1 )
347  );
348  }
349 
350 
359  template<typename MO>
360  Resolution*
361  PlacementIndexQueryResolver::resolutionFunction (Goal const& goal)
362  {
363  QID qID = goal.getQID();
364  REQUIRE (qID == whenQueryingFor<MO>());
365  REQUIRE (INSTANCEOF(ScopeQuery<MO>, &goal));
366 
367  ScopeQuery<MO> const& query = static_cast<ScopeQuery<MO> const&> (goal);
368  ScopeQueryKind direction = query.searchDirection();
369  PID scopeID = query.searchScope();
370 
372  this, scopeID, direction)
373  , getContentFilter(query)
374  );
375  }
376 
377 
383  Explorer*
385  {
386  PIdx index = _getIndex(); // access the currently configured PlacementIndex (Session)
387  switch (direction)
388  {
389  case CONTENTS: return new DeepExplorer(index.getReferrers(startID), index);
390  case CHILDREN: return new ChildExplorer(index.getReferrers(startID));
391  case PARENTS: return new UpExplorer(index.getScope(startID),index);
392  case PATH: return new UpExplorer(index.find(startID),index);
393 
394  default:
395  throw lumiera::error::Invalid("unknown query direction");
396  }
397  }
398 
399 
400 
401 }}} // namespace steam::mobject::session
Query ABC: unspecific goal for resolution or retrieval.
Definition: query.hpp:116
A refcounting Handle to an MObject of type MO, used to constrain or explicitly specify the location w...
Definition: trait.hpp:82
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:514
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:65
discover the path to root
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
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:270
Single Solution, possibly part of a result set.
Definition: query.hpp:154