lumiera_/src/steam/mobject/session/session-services.cpp
2025-06-07 23:59:57 +02:00

193 lines
6.5 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
SessionServices - accessing Steam-Layer internal session implementation services
Copyright (C)
2008, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** 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. See the file COPYING for further details.
* *****************************************************************/
/** @file session-services.cpp
** Implementation of some top-level internal services of the session.
** The Session is _the_ central interface to access the model and thus the
** edit being worked on. Behind the scenes, it needs to operate several technically
** quite involved services, which we prefer to hide away as implementation details.
** Typically, each of these services defines a dedicated interface, and is implemented
** by delegating to a set of more specialised facilities.
**
** The following services are integrated here
** - service to access a Placement by (hash) ID
** - service to attach or remove session content, while maintaining all indices
** - service to query and explore session contents
** - service to inject mock content for unit testing
** - service to manage and discover default settings by resolution query
**
** @todo WIP implementation of session core from 2010
** @todo as of 2016, this effort is considered stalled but basically valid
*/
#include "steam/mobject/session/session-service-fetch.hpp"
#include "steam/mobject/session/session-service-mutate.hpp"
#include "steam/mobject/session/session-service-explore-scope.hpp"
#include "steam/mobject/session/session-service-mock-index.hpp"
#include "steam/mobject/session/session-service-defaults.hpp"
#include "steam/mobject/session/session-services.hpp"
#include "steam/mobject/session/session-impl.hpp"
#include "steam/mobject/session/sess-manager-impl.hpp"
#include "steam/mobject/session/mobjectfactory.hpp"
#include "lib/symbol.hpp"
using lib::Symbol;
namespace steam {
namespace mobject {
namespace session {
/** is the element-fetch service usable?
* Effectively this means: is the session up?
*/
bool
SessionServiceFetch::isAccessible ()
{
return Session::initFlag
and Session::current.isUp();
}
/** verify the given placement-ID (hash) is valid,
* by checking if it refers to a Placement instance
* currently registered with the PlacementIndex of the
* active Session. */
bool
SessionServiceFetch::isRegisteredID (PlacementMO::ID const& placementID)
{
return SessionImplAPI::current->isRegisteredID (placementID);
}
/** actually retrieve a Placement tracked by the index.
* @param placementID hash-ID, typically from a PlacementRef
* @throw error::Invalid if the ID isn't resolvable
* @note the returned ref is guaranteed to be valid and usable
* only \em now, which means, by virtue of the SteamDispatcher
* and command processing, during this operation. It can be
* used to invoke an operation, but should never be stored;
* rather, client code should create an MObjectRef, if
* bound to store an reference for later.
*/
PlacementMO&
SessionServiceFetch::resolveID (PlacementMO::ID const& placementID)
{
return SessionImplAPI::current->resolveID (placementID);
}
/** attach an object by placement onto the session.
* Implemented by registering a copy of the Placement into the
* PlacementIndex in the session. This copy establishes a new kind of
* "object instance", represented by a new placement-ID, which is returned
* and can be used to refer to this "instance" within the session from now on.
* @param scope the (existing) parent scope where to attach the new element
*/
PlacementMO::ID const&
SessionServiceMutate::attach_toModel(PMO newPlacement, PID scope)
{
return SessionImplAPI::current->insertCopy (newPlacement,scope);
}
/** detach the denoted element from the model _including all children_.
* @return true if actually erased something
* @note when specifying model root, all sub-elements will be cleared,
* but model root itself will be retained.
*/
bool
SessionServiceMutate::detach_and_clear (PID scope)
{
return SessionImplAPI::current->purgeScopeRecursively (scope);
}
/** detach the denoted leaf element from the model.
* @return true if actually erased something
* @throw error::Fatal when attempting to remove the model root
* @throw error::State when the given element contains sub elements
*/
bool
SessionServiceMutate::detach (PID leafElement)
{
return SessionImplAPI::current->detachElement (leafElement);
}
namespace { // deleter function to clean up test/mock PlacementIndex
void
remove_testIndex (PlacementIndex* testIdx)
{
REQUIRE (testIdx);
SessionImplAPI::current->reset_PlacementIndex(); // restore default Index from Session
testIdx->clear();
ASSERT (0 == testIdx->size());
delete testIdx;
}
}
/** Re-define the implicit PlacementIndex temporarily, e.g. for unit tests. */
PPIdx
SessionServiceMockIndex:: install ()
{
Symbol typeID ("dummyRoot");
PMO dummyRoot (MObject::create (typeID));
PPIdx mockIndex (new PlacementIndex(dummyRoot), &remove_testIndex); // manage instance lifecycle
ENSURE (mockIndex);
ENSURE (mockIndex->isValid());
ENSURE (1 == mockIndex.use_count());
SessionImplAPI::current->reset_PlacementIndex (mockIndex.get());
return mockIndex;
}
/** @return resolver for DiscoveryQuery instances, actually backed by PlacementIndex */
QueryResolver const&
SessionServiceExploreScope::getResolver()
{
return SessionImplAPI::current->getScopeQueryResolver();
}
/** @return root scope of the current model (session datastructure) */
PlacementMO&
SessionServiceExploreScope::getScope (PlacementMO const& placementToLocate)
{
return SessionImplAPI::current->getScope(placementToLocate);
}
PlacementMO&
SessionServiceExploreScope::getScope (PlacementMO::ID const& placementToLocate)
{
return SessionImplAPI::current->getScope(placementToLocate);
}
/** @return root scope of the current model (session datastructure) */
PlacementMO&
SessionServiceExploreScope::getScopeRoot()
{
return SessionImplAPI::current->getScopeRoot();
}
}}} // namespace steam::mobject::session