VariableController2.cpp
190 lines
| 6.6 KiB
| text/x-c
|
CppLexer
r0 | #include "Variable/VariableController2.h" | |||
r6 | #include "Variable/VariableSynchronizationGroup2.h" | |||
r2 | #include <Common/containers.h> | |||
#include <Common/debug.h> | ||||
#include <Data/DataProviderParameters.h> | ||||
r9 | #include <Data/DateTimeRangeHelper.h> | |||
#include <Variable/VariableCacheStrategyFactory.h> | ||||
r0 | ||||
r2 | class VariableController2::VariableController2Private | |||
r0 | { | |||
r9 | QMap<QUuid,std::shared_ptr<Variable>> _variables; | |||
r2 | QMap<QUuid,std::shared_ptr<IDataProvider>> _providers; | |||
r6 | QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups; | |||
r9 | std::unique_ptr<VariableCacheStrategy> _cacheStrategy; | |||
r8 | bool p_contains(std::shared_ptr<Variable> variable) | |||
{ | ||||
return _providers.contains(variable->ID()); | ||||
} | ||||
bool v_contains(std::shared_ptr<Variable> variable) | ||||
{ | ||||
return SciQLop::containers::contains(this->_variables, variable); | ||||
} | ||||
bool sg_contains(std::shared_ptr<Variable> variable) | ||||
{ | ||||
return _synchronizationGroups.contains(variable->ID()); | ||||
} | ||||
r9 | ||||
void _changeRange(std::shared_ptr<Variable> var, DateTimeRange r) | ||||
{ | ||||
auto provider = _providers[var->ID()]; | ||||
r10 | DateTimeRange newCacheRange; | |||
std::vector<DateTimeRange> missingRanges; | ||||
if(DateTimeRangeHelper::hasnan(var->cacheRange())) | ||||
{ | ||||
newCacheRange = _cacheStrategy->computeRange(r,r); | ||||
missingRanges = {newCacheRange}; | ||||
} | ||||
else | ||||
{ | ||||
newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r); | ||||
missingRanges = newCacheRange - var->cacheRange(); | ||||
} | ||||
r9 | for(auto range:missingRanges) | |||
{ | ||||
auto data = provider->getData(DataProviderParameters{{range},var->metadata()}); | ||||
var->mergeDataSeries(data); | ||||
} | ||||
r12 | var->setCacheRange(newCacheRange); | |||
r9 | var->setRange(r); | |||
} | ||||
r0 | public: | |||
VariableController2Private(QObject* parent=Q_NULLPTR) | ||||
r12 | :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold)) | |||
r2 | { | |||
Q_UNUSED(parent); | ||||
} | ||||
r0 | ~VariableController2Private() = default; | |||
r2 | ||||
r10 | std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider) | |||
r0 | { | |||
r2 | auto newVar = std::make_shared<Variable>(name,metadata); | |||
r9 | this->_variables[newVar->ID()] = newVar; | |||
r2 | this->_providers[newVar->ID()] = provider; | |||
r6 | this->_synchronizationGroups[newVar->ID()] = std::make_shared<VariableSynchronizationGroup2>(newVar->ID()); | |||
r2 | return newVar; | |||
} | ||||
void deleteVariable(std::shared_ptr<Variable> variable) | ||||
{ | ||||
r8 | /* | |||
* Removing twice a var is ok but a var without provider has to be a hard error | ||||
* this means we got the var controller in an inconsistent state | ||||
*/ | ||||
if(v_contains(variable)) | ||||
r9 | this->_variables.remove(variable->ID()); | |||
r8 | if(p_contains(variable)) | |||
this->_providers.remove(variable->ID()); | ||||
else | ||||
r9 | SCIQLOP_ERROR(VariableController2Private, "No provider found for given variable"); | |||
r2 | } | |||
void changeRange(std::shared_ptr<Variable> variable, DateTimeRange r) | ||||
{ | ||||
r8 | if(p_contains(variable)) | |||
r2 | { | |||
r10 | if(!DateTimeRangeHelper::hasnan(r)) | |||
r9 | { | |||
auto transformation = DateTimeRangeHelper::computeTransformation(variable->range(),r); | ||||
auto group = _synchronizationGroups[variable->ID()]; | ||||
if(std::holds_alternative<DateTimeRangeTransformation>(transformation)) | ||||
{ | ||||
for(auto varId:group->variables()) | ||||
{ | ||||
auto var = _variables[varId]; | ||||
auto newRange = var->range().transform(std::get<DateTimeRangeTransformation>(transformation)); | ||||
_changeRange(var,newRange); | ||||
} | ||||
} | ||||
else // force new range to all variables -> may be weird if more than one var in the group | ||||
// @TODO ensure that there is no side effects | ||||
{ | ||||
for(auto varId:group->variables()) | ||||
{ | ||||
auto var = _variables[varId]; | ||||
_changeRange(var,r); | ||||
} | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN"); | ||||
} | ||||
r2 | } | |||
else | ||||
{ | ||||
r9 | SCIQLOP_ERROR(VariableController2Private, "No provider found for given variable"); | |||
r2 | } | |||
} | ||||
r8 | void synchronize(std::shared_ptr<Variable> var, std::shared_ptr<Variable> with) | |||
{ | ||||
if(v_contains(var) && v_contains(with)) | ||||
{ | ||||
if(sg_contains(var) && sg_contains(with)) | ||||
{ | ||||
auto dest_group = this->_synchronizationGroups[with->ID()]; | ||||
this->_synchronizationGroups[var->ID()] = dest_group; | ||||
dest_group->addVariable(var->ID()); | ||||
} | ||||
else | ||||
{ | ||||
r9 | SCIQLOP_ERROR(VariableController2Private, "At least one of the given variables isn't in a sync group"); | |||
r8 | } | |||
} | ||||
else | ||||
{ | ||||
r9 | SCIQLOP_ERROR(VariableController2Private, "At least one of the given variables is not found"); | |||
r8 | } | |||
} | ||||
r2 | ||||
r9 | const std::set<std::shared_ptr<Variable>> variables() | |||
r2 | { | |||
r9 | std::set<std::shared_ptr<Variable>> vars; | |||
for(auto var:_variables.values()) | ||||
{ | ||||
vars.insert(var); | ||||
} | ||||
return vars; | ||||
r0 | } | |||
r2 | ||||
r0 | }; | |||
VariableController2::VariableController2() | ||||
:impl{spimpl::make_unique_impl<VariableController2Private>()} | ||||
{} | ||||
std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider, const DateTimeRange &range) | ||||
{ | ||||
r10 | auto var = impl->createVariable(name, metadata, provider); | |||
r2 | emit variableAdded(var); | |||
r10 | if(!DateTimeRangeHelper::hasnan(range)) | |||
r9 | impl->changeRange(var,range); | |||
else | ||||
SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error"); | ||||
r2 | return var; | |||
} | ||||
void VariableController2::deleteVariable(std::shared_ptr<Variable> variable) | ||||
{ | ||||
impl->deleteVariable(variable); | ||||
emit variableDeleted(variable); | ||||
} | ||||
void VariableController2::changeRange(std::shared_ptr<Variable> variable, DateTimeRange r) | ||||
{ | ||||
impl->changeRange(variable, r); | ||||
} | ||||
r9 | const std::set<std::shared_ptr<Variable> > VariableController2::variables() | |||
r2 | { | |||
return impl->variables(); | ||||
r0 | } | |||
r8 | void VariableController2::synchronize(std::shared_ptr<Variable> var, std::shared_ptr<Variable> with) | |||
{ | ||||
impl->synchronize(var, with); | ||||
} | ||||