2009-11-07 02:49:55 +01:00
|
|
|
/*
|
2009-11-09 07:35:08 +01:00
|
|
|
PLACEMENT-INDEX-QUERY-RESOLVER.hpp - using PlacementIndex to resolve scope queries
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2009-11-09 07:35:08 +01:00
|
|
|
/** @file placement-index-query-resolver.hpp
|
|
|
|
|
** TODO WIP-WIP
|
2009-11-07 02:49:55 +01:00
|
|
|
**
|
|
|
|
|
** @see PlacementRef
|
|
|
|
|
** @see PlacementIndex_test
|
|
|
|
|
**
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-11-09 07:35:08 +01:00
|
|
|
#ifndef MOBJECT_SESSION_PLACEMENT_INDEX_QUERY_RESOLVER_H
|
|
|
|
|
#define MOBJECT_SESSION_PLACEMENT_INDEX_QUERY_RESOLVER_H
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
//#include "pre.hpp"
|
|
|
|
|
//#include "proc/mobject/session/locatingpin.hpp"
|
|
|
|
|
//#include "proc/asset/pipe.hpp"
|
2009-11-09 07:35:08 +01:00
|
|
|
//#include "lib/util.hpp"
|
|
|
|
|
//#include "lib/factory.hpp"
|
|
|
|
|
//#include "proc/mobject/placement.hpp"
|
|
|
|
|
#include "proc/mobject/session/placement-index.hpp"
|
2009-11-07 02:49:55 +01:00
|
|
|
#include "proc/mobject/session/query-resolver.hpp"
|
2009-11-13 16:32:22 +01:00
|
|
|
#include "proc/mobject/session/scope-query.hpp"
|
2009-11-07 02:49:55 +01:00
|
|
|
|
2009-11-09 07:35:08 +01:00
|
|
|
//#include <tr1/memory>
|
|
|
|
|
//#include <boost/noncopyable.hpp>
|
2009-11-15 01:08:29 +01:00
|
|
|
#include <boost/scoped_ptr.hpp>
|
2009-11-09 07:35:08 +01:00
|
|
|
//#include <vector>
|
2009-11-15 01:08:29 +01:00
|
|
|
#include <stack>
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace mobject {
|
|
|
|
|
|
2009-11-09 07:35:08 +01:00
|
|
|
// class MObject; /////////////////////////////////////????
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
namespace session {
|
|
|
|
|
|
2009-11-09 07:35:08 +01:00
|
|
|
// using lib::factory::RefcountFac;
|
|
|
|
|
// using std::tr1::shared_ptr;
|
2009-11-15 01:08:29 +01:00
|
|
|
using boost::scoped_ptr;
|
2009-11-09 07:35:08 +01:00
|
|
|
// using std::vector;
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-11-09 07:35:08 +01:00
|
|
|
* TODO type comment
|
2009-11-07 02:49:55 +01:00
|
|
|
*/
|
2009-11-09 07:35:08 +01:00
|
|
|
class PlacementIndexQueryResolver
|
|
|
|
|
: public session::QueryResolver
|
2009-11-07 02:49:55 +01:00
|
|
|
{
|
2009-11-13 16:32:22 +01:00
|
|
|
PPIdx index_;
|
|
|
|
|
|
|
|
|
|
typedef PlacementIndex::ID PID;
|
2009-11-15 01:08:29 +01:00
|
|
|
////////////////////////////////////////////////////////////////TODO: moved in from PlacementIndex
|
|
|
|
|
typedef Goal::QueryID QueryID;
|
|
|
|
|
typedef QueryID const& QID;
|
2009-11-13 04:52:48 +01:00
|
|
|
|
2009-11-12 20:15:52 +01:00
|
|
|
template<class MO>
|
|
|
|
|
typename session::Query<Placement<MO> >::iterator
|
|
|
|
|
query (PlacementMO& scope) const;
|
|
|
|
|
|
|
|
|
|
operator string() const { return "PlacementIndex"; }
|
|
|
|
|
|
|
|
|
|
bool canHandleQuery(QID) const;
|
2009-11-13 16:32:22 +01:00
|
|
|
////////////////////////////////////////////////////////////////TODO:
|
2009-11-15 01:08:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef PlacementIndex::iterator PIter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Interface: strategy for exploring the structure */
|
|
|
|
|
class Explorer
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual ~Explorer() { };
|
|
|
|
|
virtual bool exhausted () =0;
|
|
|
|
|
virtual PlacementMO& operator() () =0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Strategy: explore the structure
|
|
|
|
|
* just by following the given iterator;
|
|
|
|
|
* usually this yields an element's children
|
|
|
|
|
*/
|
|
|
|
|
class ChildExplorer
|
|
|
|
|
{
|
|
|
|
|
PIter tip_;
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
exhausted()
|
|
|
|
|
{
|
|
|
|
|
return !tip_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlacementMO&
|
|
|
|
|
operator() ()
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (tip_);
|
|
|
|
|
PlacementMO& pos = *tip_;
|
|
|
|
|
++tip_;
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
ChildExplorer(PIter start)
|
|
|
|
|
: tip_(start)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Strategy: explore the structure depth first.
|
|
|
|
|
* After returning an element, delve into the scope
|
|
|
|
|
* defined by this element and so on recursively.
|
|
|
|
|
*/
|
|
|
|
|
class DeepExplorer
|
|
|
|
|
{
|
|
|
|
|
PPIdx index_;
|
|
|
|
|
std::stack<PIter> scopes_;
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
exhausted()
|
|
|
|
|
{
|
|
|
|
|
while (!scopes_.empty() && !scopes_.top())
|
|
|
|
|
scopes_.pop();
|
|
|
|
|
return scopes_.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlacementMO&
|
|
|
|
|
operator() ()
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (!scopes_.empty() && scopes_.top());
|
|
|
|
|
PlacementMO& pos = *scopes_.top();
|
|
|
|
|
++scopes_.top();
|
|
|
|
|
scopes_.push(index_->getReferrers(pos.getID()));
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
DeepExplorer(PIter start, PPIdx idx)
|
|
|
|
|
: index_(idx)
|
|
|
|
|
{
|
|
|
|
|
scopes_.push(start);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Strategy: explore the structure upwards,
|
|
|
|
|
* ascending until reaching the root element.
|
|
|
|
|
*/
|
|
|
|
|
class UpExplorer
|
|
|
|
|
{
|
|
|
|
|
PPIdx index_;
|
|
|
|
|
PlacementMO* tip_;
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
exhausted()
|
|
|
|
|
{
|
|
|
|
|
return !tip_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlacementMO&
|
|
|
|
|
operator() ()
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (tip_);
|
|
|
|
|
PlacementMO& pos = *tip_;
|
|
|
|
|
tip_ = &index_->getScope(*tip_);
|
|
|
|
|
if (tip_ == &pos)
|
|
|
|
|
tip_ = 0;
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
UpExplorer(PlacementMO& start, PPIdx idx)
|
|
|
|
|
: index_(idx)
|
|
|
|
|
, tip_(&start)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef function<bool(Val const&)> ContentFilter;
|
|
|
|
|
typedef function<Explorer*()> ExplorerBuilder;
|
|
|
|
|
|
|
|
|
|
|
2009-11-13 16:32:22 +01:00
|
|
|
/**
|
|
|
|
|
* on query, an individual result set is prepared
|
|
|
|
|
* to be explored by the invoking client code.
|
|
|
|
|
* It is built wrapping the low-level scope iterator
|
|
|
|
|
* obtained from the index, controlled by an
|
|
|
|
|
* exploration strategy.
|
|
|
|
|
*/
|
|
|
|
|
struct ResultSet
|
|
|
|
|
: Resolution
|
|
|
|
|
{
|
2009-11-15 01:08:29 +01:00
|
|
|
typedef PlacementMO Val;
|
2009-11-13 16:32:22 +01:00
|
|
|
|
2009-11-15 01:08:29 +01:00
|
|
|
ContentFilter acceptable_;
|
|
|
|
|
ExplorerBuilder buildExploartion_;
|
|
|
|
|
scoped_ptr<Explorer> explore_;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
exploreNext (Result& res)
|
|
|
|
|
{
|
|
|
|
|
typedef typename Query<Val>::Cursor Cursor;
|
|
|
|
|
Cursor& cursor = static_cast<Cursor&> (res);
|
|
|
|
|
|
|
|
|
|
while (!explore_->exhausted() )
|
|
|
|
|
{
|
|
|
|
|
Val& elm (*explore_());
|
|
|
|
|
if (acceptable_(elm))
|
|
|
|
|
{
|
|
|
|
|
cursor.point_at (elm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT (explore_->exhausted());
|
|
|
|
|
cursor.point_at (0);
|
|
|
|
|
}
|
2009-11-13 16:32:22 +01:00
|
|
|
|
|
|
|
|
Result
|
|
|
|
|
prepareResolution()
|
|
|
|
|
{
|
2009-11-15 01:08:29 +01:00
|
|
|
explore_.reset (buildExploartion_());
|
|
|
|
|
|
|
|
|
|
Result cursor;
|
|
|
|
|
exploreNext (cursor);
|
2009-11-13 16:32:22 +01:00
|
|
|
return cursor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nextResult(Result& pos)
|
|
|
|
|
{
|
2009-11-15 01:08:29 +01:00
|
|
|
exploreNext (pos);
|
|
|
|
|
return pos;
|
2009-11-13 16:32:22 +01:00
|
|
|
}
|
2009-11-15 01:08:29 +01:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
ResultSet (ExplorerBuilder b
|
|
|
|
|
,ContentFilter a)
|
|
|
|
|
: acceptable_(a)
|
|
|
|
|
, buildExploartion_(b)
|
|
|
|
|
, explore_()
|
|
|
|
|
{ }
|
2009-11-13 16:32:22 +01:00
|
|
|
};
|
|
|
|
|
|
2009-11-15 01:08:29 +01:00
|
|
|
Explorer*
|
|
|
|
|
setupExploration (PID startID, Literal direction)
|
|
|
|
|
{
|
|
|
|
|
if (direction == "contents")
|
|
|
|
|
return new DeepExplorer(index_->getReferrers(startID), index_);
|
|
|
|
|
|
|
|
|
|
else if (direction == "children")
|
|
|
|
|
return new ChildExplorer(index_->getReferrers(startID));
|
|
|
|
|
|
|
|
|
|
else if (direction == "parents")
|
|
|
|
|
return new UpExplorer(index_->getScope(startID),index_);
|
|
|
|
|
|
|
|
|
|
else if (direction == "path")
|
|
|
|
|
return new UpExplorer(index_->find(startID),index_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename MO>
|
|
|
|
|
void
|
|
|
|
|
defineHandling()
|
|
|
|
|
{
|
|
|
|
|
installResolutionCase( whenQueryingFor<MO>()
|
|
|
|
|
, bind (&PlacementIndexQueryResolver::resolutionFunction<MO>,
|
|
|
|
|
this, _1 )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 16:32:22 +01:00
|
|
|
template<typename MO>
|
2009-11-15 01:08:29 +01:00
|
|
|
Resolution*
|
2009-11-13 16:32:22 +01:00
|
|
|
resolutionFunction (Goal const& goal)
|
|
|
|
|
{
|
|
|
|
|
QID qID = goal.getQID();
|
|
|
|
|
REQUIRE (qID.kind == Goal::DISCOVERY
|
|
|
|
|
&& qID.type == getResultTypeID<Placement<MO> >()); /////////////////////////////TODO
|
|
|
|
|
REQUIRE (INSTANCEOF(ScopeQuery<MO>, &goal));
|
|
|
|
|
ScopeQuery<MO> const& query = static_cast<ScopeQuery<MO> const&> (goal);
|
|
|
|
|
|
|
|
|
|
Literal direction = query.searchDirection();
|
|
|
|
|
PID scopeID = query.searchScope().getID(); //////////TICKET #411
|
|
|
|
|
|
2009-11-15 01:08:29 +01:00
|
|
|
return new ResultSet( bind (&PlacementIndexQueryResolver::setupExploration,
|
|
|
|
|
this, scopeID, direction)
|
|
|
|
|
, getContentFilter(query)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename QUERY>
|
|
|
|
|
ContentFilter
|
|
|
|
|
getContentFilter (QUERY query)
|
|
|
|
|
{
|
|
|
|
|
return query.contentFilter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ContentFilter
|
|
|
|
|
getContentFilter (ScopeQuery<MObject>) ///< especially queries for MObjects need not be filtered
|
|
|
|
|
{
|
|
|
|
|
ContentFilter acceptAllObjects = bind (val(true), _1);
|
|
|
|
|
return acceptAllObjects;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename MO>
|
|
|
|
|
static QueryID
|
|
|
|
|
whenQueryingFor()
|
|
|
|
|
{
|
|
|
|
|
QueryID qID = {Goal::DISCOVERY, getResultTypeID<Placement<MO> >()};
|
|
|
|
|
return qID;
|
2009-11-13 16:32:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
PlacementIndexQueryResolver (PPIdx theIndex)
|
|
|
|
|
: index_(theIndex)
|
|
|
|
|
{
|
2009-11-15 01:08:29 +01:00
|
|
|
defineHandling<MObject>();
|
|
|
|
|
defineHandling<Clip>();
|
|
|
|
|
defineHandling<Effect>();
|
2009-11-15 01:09:21 +01:00
|
|
|
///////////////////////////////////////TICKET #414
|
2009-11-13 16:32:22 +01:00
|
|
|
}
|
2009-11-09 07:35:08 +01:00
|
|
|
};
|
2009-11-07 02:49:55 +01:00
|
|
|
|
|
|
|
|
|
2009-11-12 20:15:52 +01:00
|
|
|
|
2009-11-13 04:52:48 +01:00
|
|
|
bool
|
|
|
|
|
PlacementIndexQueryResolver::canHandleQuery (QID qID) const
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED ("decide by hard-wired check if the given Query can be resolved by PlacementIndex");
|
|
|
|
|
return session::Goal::GENERIC == qID.kind;
|
|
|
|
|
// thats not enough! need to check the typeID (match to Placement<MOX>, with some fixed MOX values)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-11-12 20:15:52 +01:00
|
|
|
////////////////////////////////////////////////////////////////TODO:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-11-07 02:49:55 +01:00
|
|
|
}} // namespace mobject::session
|
|
|
|
|
#endif
|