Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/AlgorithmProxy.h"
#include "MantidAPI/AlgorithmObserver.h"
Russell Taylor
committed
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/DeprecatedAlgorithm.h"
#include <Poco/ActiveMethod.h>
#include <Poco/ActiveResult.h>
#include <Poco/Void.h>
using namespace Mantid::Kernel;
namespace Mantid
{
Gigg, Martyn Anthony
committed
namespace API
Russell Taylor
committed
{
Gigg, Martyn Anthony
committed
//----------------------------------------------------------------------
// Public methods
//----------------------------------------------------------------------
/// Constructor
AlgorithmProxy::AlgorithmProxy(Algorithm_sptr alg) :
PropertyManagerOwner(), m_executeAsync(new Poco::ActiveMethod<bool, Poco::Void, AlgorithmProxy>(this,&AlgorithmProxy::executeAsyncImpl)),
m_name(alg->name()),m_category(alg->category()), m_categorySeparator(alg->categorySeparator()),
m_alias(alg->alias()),m_summary(alg->summary()), m_version(alg->version()), m_alg(alg),
m_isExecuted(),m_isLoggingEnabled(true), m_loggingOffset(0), m_rethrow(false),
m_isChild(false)
Gigg, Martyn Anthony
committed
{
if (!alg)
{
throw std::logic_error("Unable to create a proxy algorithm.");
}
alg->initialize();
copyPropertiesFrom(*alg);
}
/// Virtual destructor
AlgorithmProxy::~AlgorithmProxy()
{
Gigg, Martyn Anthony
committed
}
/** Initialization method invoked by the framework.
* Does nothing for AlgorithmProxy as initialization is done in the constructor.
*/
void AlgorithmProxy::initialize()
{
return;
}
AlgorithmID AlgorithmProxy::getAlgorithmID() const
{
return AlgorithmID(const_cast<AlgorithmProxy*>(this));
}
/** Perform whole-input validation */
std::map<std::string, std::string> AlgorithmProxy::validateInputs()
{
if (!m_alg) createConcreteAlg();
return m_alg->validateInputs();
}
Gigg, Martyn Anthony
committed
/** The actions to be performed by the AlgorithmProxy on a dataset. This method is
* invoked for top level AlgorithmProxys by the application manager.
* This method invokes exec() method.
* For Child AlgorithmProxys either the execute() method or exec() method
Gigg, Martyn Anthony
committed
* must be EXPLICITLY invoked by the parent AlgorithmProxy.
*
* @throw runtime_error Thrown if AlgorithmProxy or Child AlgorithmProxy cannot be executed
Gigg, Martyn Anthony
committed
*/
bool AlgorithmProxy::execute()
{
createConcreteAlg();
try
{
m_alg->execute();
}
catch(...)
{
stopped();
Gigg, Martyn Anthony
committed
throw;
}
stopped();
return m_isExecuted;
}
/** Asynchronous execution of the algorithm.
* This will launch the AlgorithmProxy::executeAsyncImpl() method
* but in a separate thread.
*
* @return Poco::ActiveResult containing the result from the thread.
*/
Gigg, Martyn Anthony
committed
Poco::ActiveResult<bool> AlgorithmProxy::executeAsync()
{
Gigg, Martyn Anthony
committed
}
/** executeAsync() implementation.
* Calls execute and, when it has finished, deletes the real algorithm.
* @param dummy :: An unused dummy variable
*/
bool AlgorithmProxy::executeAsyncImpl(const Poco::Void & dummy)
{
createConcreteAlg();
// Call Algorithm::executeAsyncImpl rather than executeAsync() because the latter
// would spawn off another (3rd) thread which is unecessary.
try
{
m_alg->executeAsyncImpl(dummy); // Pass through dummy argument, though not used
}
catch(...)
{
stopped();
throw;
}
stopped();
return m_isExecuted;
}
Gigg, Martyn Anthony
committed
/// True if the algorithm is running.
bool AlgorithmProxy::isRunning() const
Gigg, Martyn Anthony
committed
{
return m_alg ? m_alg->isRunning() : false;
}
/// Has the AlgorithmProxy already been initialized
bool AlgorithmProxy::isInitialized() const
{
return true;//!!!!!!!!!
}
/// Has the AlgorithmProxy already been executed
bool AlgorithmProxy::isExecuted() const
{
return m_isExecuted;
}
///Cancel the execution of the algorithm
Gigg, Martyn Anthony
committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
{
if (m_alg)
m_alg->cancel();
}
/** Add an observer for a notification. If the real algorithm is running
* the observer is added directly. If the algorithm is not running yet
* the observer's address is added to a buffer to be used later when execute/executeAsync
* method is called.
* @param observer :: Observer
*/
void AlgorithmProxy::addObserver(const Poco::AbstractObserver& observer)const
{
const Poco::AbstractObserver* obs = &observer;
if (m_alg)
{
m_alg->addObserver(*obs);
}
// save the observer in any case because m_alg can be reset (eg in createConcreteAlg())
m_externalObservers.push_back(obs);
}
/** Remove an observer.
* @param observer :: Observer
*/
void AlgorithmProxy::removeObserver(const Poco::AbstractObserver& observer)const
{
std::vector<const Poco::AbstractObserver*>::iterator o =
std::find(m_externalObservers.begin(),m_externalObservers.end(),&observer);
if (o != m_externalObservers.end()) m_externalObservers.erase(o);
if (m_alg) m_alg->removeObserver(observer);
}
void AlgorithmProxy::setRethrows(const bool rethrow)
{
this->m_rethrow = rethrow;
if(m_alg) m_alg->setRethrows(rethrow);
}
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
* @return A string giving the method name that should be attached to a workspace
*/
const std::string AlgorithmProxy::workspaceMethodName() const
{
if(m_alg) return m_alg->workspaceMethodName();
else return "";
}
/**
* @return A set of workspace class names that should have the workspaceMethodName attached
*/
const std::vector<std::string> AlgorithmProxy::workspaceMethodOn() const
{
if(m_alg) return m_alg->workspaceMethodOn();
else return std::vector<std::string>();
}
/**
* @return The name of the property that the calling object will be passed to
*/
const std::string AlgorithmProxy::workspaceMethodInputProperty() const
{
if(m_alg) return m_alg->workspaceMethodInputProperty();
else return "";
}
Gigg, Martyn Anthony
committed
/**
* Override setPropertyValue
* @param name The name of the property
* @param value The value of the property as a string
*/
void AlgorithmProxy::setPropertyValue(const std::string &name, const std::string &value)
{
createConcreteAlg(true);
m_alg->setPropertyValue(name, value);
copyPropertiesFrom(*m_alg);
m_alg.reset();
}
/**
* Do something after a property was set
* @param name :: The name of the property
*/
void AlgorithmProxy::afterPropertySet(const std::string& name)
{
createConcreteAlg(true);
m_alg->getPointerToProperty(name)->setValueFromProperty(*this->getPointerToProperty(name));
m_alg->afterPropertySet(name);
copyPropertiesFrom(*m_alg);
m_alg.reset();
}
Gigg, Martyn Anthony
committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
//----------------------------------------------------------------------
// Private methods
//----------------------------------------------------------------------
/**
* Creates an unmanaged instance of the actual algorithm and sets its properties
* @param initOnly If true then the algorithm will only having its init step run, otherwise observers will
* also be added and rethrows will be true
*/
void AlgorithmProxy::createConcreteAlg(bool initOnly)
{
m_alg = boost::dynamic_pointer_cast<Algorithm>(AlgorithmManager::Instance().createUnmanaged(name(),version()));
m_alg->initializeFromProxy(*this);
if( !initOnly )
{
m_alg->setRethrows(this->m_rethrow);
addObservers();
}
}
/**
* Clean up when the real algorithm stops
*/
void AlgorithmProxy::stopped()
{
if(!isChild()) dropWorkspaceReferences();
Gigg, Martyn Anthony
committed
m_isExecuted = m_alg->isExecuted();
m_alg.reset();
}
/**
* Forces any workspace property to clear its internal workspace reference
*/
void AlgorithmProxy::dropWorkspaceReferences()
{
const std::vector< Property*> &props = getProperties();
for (unsigned int i = 0; i < props.size(); ++i)
{
if(auto *wsProp = dynamic_cast<IWorkspaceProperty*>(props[i]))
{
wsProp->clear();
}
}
}
Gigg, Martyn Anthony
committed
/**
* Add observers stored previously in m_externalObservers
*/
void AlgorithmProxy::addObservers()
{
if (!m_alg) return;
std::vector<const Poco::AbstractObserver*>::reverse_iterator o = m_externalObservers.rbegin();
for(;o != m_externalObservers.rend();++o)
Gigg, Martyn Anthony
committed
m_alg->addObserver(**o);
m_externalObservers.clear();
}
///setting the child start progress
void AlgorithmProxy::setChildStartProgress(const double startProgress)const
{
m_alg->setChildStartProgress(startProgress);
}
/// setting the child end progress
void AlgorithmProxy::setChildEndProgress(const double endProgress)const
{
m_alg->setChildEndProgress(endProgress);
}
/**
* Serialize this object to a string. Simple routes the call the algorithm
* @returns This object serialized as a string
*/
std::string AlgorithmProxy::toString() const
Gigg, Martyn Anthony
committed
{
const_cast<AlgorithmProxy*>(this)->createConcreteAlg();
std::string serialized = m_alg->toString();
Gigg, Martyn Anthony
committed
m_alg.reset();
return serialized;
}
/// Function to return all of the categories that contain this algorithm
const std::vector<std::string> AlgorithmProxy::categories() const
{
std::vector < std::string > res;
Poco::StringTokenizer tokenizer(category(), categorySeparator(),
Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
Poco::StringTokenizer::Iterator h = tokenizer.begin();
for (; h != tokenizer.end(); ++h)
{
res.push_back(*h);
}
const DeprecatedAlgorithm * depo = dynamic_cast<const DeprecatedAlgorithm *>(this);
if (depo != NULL)
{
res.push_back("Deprecated");
}
Gigg, Martyn Anthony
committed
} // namespace API