Skip to content
Snippets Groups Projects
Commit 9877c796 authored by Simon Heybrock's avatar Simon Heybrock
Browse files

Re #17859. Moved WorkspaceProperty implementation out of header.

parent e70b9401
No related branches found
No related tags found
No related merge requests found
......@@ -320,6 +320,7 @@ set ( INC_FILES
inc/MantidAPI/WorkspaceHistory.h
inc/MantidAPI/WorkspaceOpOverloads.h
inc/MantidAPI/WorkspaceProperty.h
inc/MantidAPI/WorkspaceProperty.tcc
inc/MantidAPI/WorkspaceUnitValidator.h
inc/MantidAPI/Workspace_fwd.h
)
......
#ifndef MANTID_API_WORKSPACEPROPERTY_H_
#define MANTID_API_WORKSPACEPROPERTY_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/PropertyWithValue.h"
#include "MantidAPI/IWorkspaceProperty.h"
#include "MantidAPI/AnalysisDataService.h"
......@@ -77,430 +74,70 @@ class WorkspaceProperty
: public Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>,
public IWorkspaceProperty {
public:
/** Constructor.
* Sets the property and workspace names but initializes the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
explicit WorkspaceProperty(
const std::string &name, const std::string &wsName,
const unsigned int direction,
Kernel::IValidator_sptr validator =
Kernel::IValidator_sptr(new Kernel::NullValidator))
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName),
m_optional(PropertyMode::Mandatory), m_locking(LockMode::Lock) {}
/** Constructor.
* Sets the property and workspace names but initialises the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param optional :: If true then the property is optional
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
Kernel::IValidator_sptr(new Kernel::NullValidator));
explicit WorkspaceProperty(
const std::string &name, const std::string &wsName,
const unsigned int direction, const PropertyMode::Type optional,
Kernel::IValidator_sptr validator =
Kernel::IValidator_sptr(new Kernel::NullValidator))
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional),
m_locking(LockMode::Lock) {}
/** Constructor.
* Sets the property and workspace names but initialises the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param optional :: A boolean indicating whether the property is mandatory
* or not. Only matters
* for input properties
* @param locking :: A boolean indicating whether the workspace should read or
* write-locked when an algorithm begins. Default=true.
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
Kernel::IValidator_sptr(new Kernel::NullValidator));
explicit WorkspaceProperty(
const std::string &name, const std::string &wsName,
const unsigned int direction, const PropertyMode::Type optional,
const LockMode::Type locking,
Kernel::IValidator_sptr validator =
Kernel::IValidator_sptr(new Kernel::NullValidator))
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional),
m_locking(locking) {}
/// Copy constructor, the default name stored in the new object is the same as
/// the default name from the original object
WorkspaceProperty(const WorkspaceProperty &right)
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(right),
m_workspaceName(right.m_workspaceName),
m_initialWSName(right.m_initialWSName), m_optional(right.m_optional),
m_locking(right.m_locking) {}
/// Copy assignment operator. Only copies the value (i.e. the pointer to the
/// workspace)
WorkspaceProperty &operator=(const WorkspaceProperty &right) {
if (&right == this)
return *this;
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::operator=(right);
return *this;
}
/** Bring in the PropertyWithValue assignment operator explicitly (avoids
* VSC++ warning)
* @param value :: The value to set to
* @return assigned PropertyWithValue
*/
Kernel::IValidator_sptr(new Kernel::NullValidator));
WorkspaceProperty(const WorkspaceProperty &right);
WorkspaceProperty &operator=(const WorkspaceProperty &right);
boost::shared_ptr<TYPE> &
operator=(const boost::shared_ptr<TYPE> &value) override {
std::string wsName = value->name();
if (this->direction() == Kernel::Direction::Input && !wsName.empty()) {
m_workspaceName = wsName;
}
return Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::operator=(value);
}
//--------------------------------------------------------------------------------------
/// Add the value of another property
WorkspaceProperty &operator+=(Kernel::Property const *) override {
throw Kernel::Exception::NotImplementedError(
"+= operator is not implemented for WorkspaceProperty.");
return *this;
}
/// 'Virtual copy constructor'
WorkspaceProperty<TYPE> *clone() const override {
return new WorkspaceProperty<TYPE>(*this);
}
/** Get the name of the workspace
* @return The workspace's name
*/
std::string value() const override { return m_workspaceName; }
/** Get the value the property was initialised with -its default value
* @return The default value
*/
std::string getDefault() const override { return m_initialWSName; }
/** Set the name of the workspace.
* Also tries to retrieve it from the AnalysisDataService.
* @param value :: The new name for the workspace
* @return
*/
std::string setValue(const std::string &value) override {
m_workspaceName = value;
if (Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::autoTrim()) {
boost::trim(m_workspaceName);
}
// Try and get the workspace from the ADS, but don't worry if we can't
try {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
AnalysisDataService::Instance().retrieveWS<TYPE>(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Set to null property if not found
this->clear();
// the workspace name is not reset here, however.
}
return isValid();
}
/** Set a value from a data item
* @param value :: A shared pointer to a DataItem. If it is of the correct
* type it will set validated, if not the property's value will be cleared.
* @return
*/
operator=(const boost::shared_ptr<TYPE> &value) override;
WorkspaceProperty &operator+=(Kernel::Property const *) override;
WorkspaceProperty<TYPE> *clone() const override;
std::string value() const override;
std::string getDefault() const override;
std::string setValue(const std::string &value) override;
std::string
setDataItem(const boost::shared_ptr<Kernel::DataItem> value) override {
boost::shared_ptr<TYPE> typed = boost::dynamic_pointer_cast<TYPE>(value);
if (typed) {
std::string wsName = typed->name();
if (this->direction() == Kernel::Direction::Input && !wsName.empty()) {
m_workspaceName = wsName;
}
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value = typed;
} else {
this->clear();
}
return isValid();
}
/** Checks whether the entered workspace is valid.
* To be valid, in addition to satisfying the conditions of any validators,
* an output property must not have an empty name and an input one must point
* to
* a workspace of the correct type.
* @returns A user level description of the problem or "" if it is valid.
*/
std::string isValid() const override {
// start with the no error condition
std::string error;
// If an output workspace it must have a name, although it might not exist
// in the ADS yet
if (this->direction() == Kernel::Direction::Output) {
return isValidOutputWs();
}
// If an input (or inout) workspace, must point to something, although it
// doesn't have to have a name
// unless it's optional
if (this->direction() == Kernel::Direction::Input ||
this->direction() == Kernel::Direction::InOut) {
// Workspace groups will not have a value since they are not of type TYPE
if (!Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value) {
Mantid::API::Workspace_sptr wksp;
// if the workspace name is empty then there is no point asking the ADS
if (m_workspaceName.empty())
return isOptionalWs();
try {
wksp = AnalysisDataService::Instance().retrieve(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Check to see if the workspace is not logged with the ADS because it
// is optional.
return isOptionalWs();
}
// At this point we have a valid pointer to a Workspace so we need to
// test whether it is a group
if (boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp)) {
return isValidGroup(
boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp));
} else {
error = "Workspace " + this->value() + " is not of the correct type";
}
return error;
}
}
// Call superclass method to access any attached validators (which do their
// own logging)
return Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::isValid();
}
/** Indicates if the object is still pointing to the same workspace, using the
* workspace name
* @return true if the value is the same as the initial value or false
* otherwise
*/
bool isDefault() const override { return m_initialWSName == m_workspaceName; }
/** Is the workspace property optional
* @return true if the workspace can be blank */
bool isOptional() const override {
return (m_optional == PropertyMode::Optional);
}
/** Does the workspace need to be locked before starting an algorithm?
* @return true (default) if the workspace will be locked */
bool isLocking() const override { return (m_locking == LockMode::Lock); }
/** Returns the current contents of the AnalysisDataService for input
* workspaces.
* For output workspaces, an empty set is returned
* @return set of objects in AnalysisDataService
*/
std::vector<std::string> allowedValues() const override {
if (this->direction() == Kernel::Direction::Input ||
this->direction() == Kernel::Direction::InOut) {
// If an input workspace, get the list of workspaces currently in the ADS
auto vals = AnalysisDataService::Instance().getObjectNames(
Mantid::Kernel::DataServiceSort::Sorted);
if (isOptional()) // Insert an empty option
{
vals.push_back("");
}
// Copy-construct a temporary workspace property to test the validity of
// each workspace
WorkspaceProperty<TYPE> tester(*this);
// Remove any workspace that's not valid for this algorithm
auto eraseIter = remove_if(vals.begin(), vals.end(),
[&tester](const std::string &wsName) {
return !tester.setValue(wsName).empty();
});
// Erase everything past returned iterator afterwards for readability
vals.erase(eraseIter, vals.end());
return vals;
} else {
// For output workspaces, just return an empty set
return std::vector<std::string>();
}
}
/// Create a history record
/// @return A populated PropertyHistory for this class
const Kernel::PropertyHistory createHistory() const override {
std::string wsName = m_workspaceName;
bool isdefault = this->isDefault();
if ((wsName.empty() || this->hasTemporaryValue()) && this->operator()()) {
// give the property a temporary name in the history
std::ostringstream os;
os << "__TMP" << this->operator()().get();
wsName = os.str();
isdefault = false;
}
return Kernel::PropertyHistory(this->name(), wsName, this->type(),
isdefault, this->direction());
}
/** If this is an output workspace, store it into the AnalysisDataService
* @return True if the workspace is an output workspace and has been stored
* @throw std::runtime_error if unable to store the workspace successfully
*/
bool store() override {
bool result = false;
if (!this->operator()() && isOptional())
return result;
if (this->direction()) // Output or InOut
{
// Check that workspace exists
if (!this->operator()())
throw std::runtime_error(
"WorkspaceProperty doesn't point to a workspace");
// Note use of addOrReplace rather than add
API::AnalysisDataService::Instance().addOrReplace(m_workspaceName,
this->operator()());
result = true;
}
// always clear the internal pointer after storing
clear();
return result;
}
Workspace_sptr getWorkspace() const override { return this->operator()(); }
setDataItem(const boost::shared_ptr<Kernel::DataItem> value) override;
std::string isValid() const override;
bool isDefault() const override;
bool isOptional() const override;
bool isLocking() const override;
std::vector<std::string> allowedValues() const override;
const Kernel::PropertyHistory createHistory() const override;
bool store() override;
Workspace_sptr getWorkspace() const override;
private:
/** Checks whether the entered workspace group is valid.
* To be valid *all* members of the group have to be valid.
* @param wsGroup :: the WorkspaceGroup of which to check the validity
* @returns A user level description of the problem or "" if it is valid.
*/
std::string isValidGroup(boost::shared_ptr<WorkspaceGroup> wsGroup) const {
g_log.debug() << " Input WorkspaceGroup found \n";
std::vector<std::string> wsGroupNames = wsGroup->getNames();
std::string error;
// Cycle through each workspace in the group ...
for (const auto &memberWsName : wsGroupNames) {
boost::shared_ptr<Workspace> memberWs =
AnalysisDataService::Instance().retrieve(memberWsName);
// Table Workspaces are ignored
if ("TableWorkspace" == memberWs->id()) {
error = "Workspace " + memberWsName + " is of type TableWorkspace and "
"will therefore be ignored as "
"part of the GroupedWorkspace.";
g_log.debug() << error << '\n';
} else {
// ... and if it is a workspace of incorrect type, exclude the group by
// returning an error.
if (!boost::dynamic_pointer_cast<TYPE>(memberWs)) {
error = "Workspace " + memberWsName + " is not of type " +
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::type() +
".";
g_log.debug() << error << '\n';
return error;
}
// If it is of the correct type, it may still be invalid. Check.
else {
Mantid::API::WorkspaceProperty<TYPE> memberWsProperty(*this);
std::string memberError = memberWsProperty.setValue(memberWsName);
if (!memberError.empty())
return memberError; // Since if this member is invalid, then the
// whole group is invalid.
}
}
}
return ""; // Since all members of the group are valid.
}
/** Checks whether the entered output workspace is valid.
* To be valid the only thing it needs is a name that is allowed by the ADS,
* @see AnalysisDataServiceImpl
* @returns A user level description of the problem or "" if it is valid.
*/
std::string isValidOutputWs() const {
std::string error;
const std::string value = this->value();
if (!value.empty()) {
// Will the ADS accept it
error = AnalysisDataService::Instance().isValid(value);
} else {
if (isOptional())
error = ""; // Optional ones don't need a name
else
error = "Enter a name for the Output workspace";
}
return error;
}
/** Checks whether the entered workspace (that by this point we've found is
* not in the ADS)
* is actually an optional workspace and so still valid.
* @returns A user level description of the problem or "" if it is valid.
*/
std::string isOptionalWs() const {
std::string error;
if (m_workspaceName.empty()) {
if (isOptional()) {
error = "";
} else {
error = "Enter a name for the Input/InOut workspace";
}
} else {
error = "Workspace \"" + this->value() +
"\" was not found in the Analysis Data Service";
}
return error;
}
/// Reset the pointer to the workspace
void clear() override {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
boost::shared_ptr<TYPE>();
}
/** Attempts to retreive the data from the ADS
* if the data is not foung the internal pointer is set to null.
*/
void retrieveWorkspaceFromADS() {
// Try and get the workspace from the ADS, but don't worry if we can't
try {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
AnalysisDataService::Instance().retrieveWS<TYPE>(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Set to null property if not found
this->clear();
}
}
std::string isValidGroup(boost::shared_ptr<WorkspaceGroup> wsGroup) const;
std::string isValidOutputWs() const;
std::string isOptionalWs() const;
void clear() override;
void retrieveWorkspaceFromADS();
/// The name of the workspace (as used by the AnalysisDataService)
std::string m_workspaceName;
......
#include "MantidAPI/Workspace.h"
#include "MantidAPI/WorkspaceProperty.h"
namespace Mantid {
namespace API {
/** Constructor.
* Sets the property and workspace names but initializes the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
template <typename TYPE>
WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name,
const std::string &wsName,
const unsigned int direction,
Kernel::IValidator_sptr validator)
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName),
m_optional(PropertyMode::Mandatory), m_locking(LockMode::Lock) {}
/** Constructor.
* Sets the property and workspace names but initialises the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param optional :: If true then the property is optional
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
template <typename TYPE>
WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name,
const std::string &wsName,
const unsigned int direction,
const PropertyMode::Type optional,
Kernel::IValidator_sptr validator)
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional),
m_locking(LockMode::Lock) {}
/** Constructor.
* Sets the property and workspace names but initialises the workspace pointer
* to null.
* @param name :: The name to assign to the property
* @param wsName :: The name of the workspace
* @param direction :: Whether this is a Direction::Input, Direction::Output
* or Direction::InOut (Input & Output) workspace
* @param optional :: A boolean indicating whether the property is mandatory
* or not. Only matters
* for input properties
* @param locking :: A boolean indicating whether the workspace should read or
* write-locked when an algorithm begins. Default=true.
* @param validator :: The (optional) validator to use for this property
* @throw std::out_of_range if the direction argument is not a member of the
* Direction enum (i.e. 0-2)
*/
template <typename TYPE>
WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name,
const std::string &wsName,
const unsigned int direction,
const PropertyMode::Type optional,
const LockMode::Type locking,
Kernel::IValidator_sptr validator)
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(
name, boost::shared_ptr<TYPE>(), validator, direction),
m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional),
m_locking(locking) {}
/// Copy constructor, the default name stored in the new object is the same as
/// the default name from the original object
template <typename TYPE>
WorkspaceProperty<TYPE>::WorkspaceProperty(const WorkspaceProperty &right)
: Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>(right),
m_workspaceName(right.m_workspaceName),
m_initialWSName(right.m_initialWSName), m_optional(right.m_optional),
m_locking(right.m_locking) {}
/// Copy assignment operator. Only copies the value (i.e. the pointer to the
/// workspace)
template <typename TYPE>
WorkspaceProperty<TYPE> &WorkspaceProperty<TYPE>::
operator=(const WorkspaceProperty &right) {
if (&right == this)
return *this;
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::operator=(right);
return *this;
}
/** Bring in the PropertyWithValue assignment operator explicitly (avoids
* VSC++ warning)
* @param value :: The value to set to
* @return assigned PropertyWithValue
*/
template <typename TYPE>
boost::shared_ptr<TYPE> &WorkspaceProperty<TYPE>::
operator=(const boost::shared_ptr<TYPE> &value) {
std::string wsName = value->name();
if (this->direction() == Kernel::Direction::Input && !wsName.empty()) {
m_workspaceName = wsName;
}
return Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::operator=(value);
}
//--------------------------------------------------------------------------------------
/// Add the value of another property
template <typename TYPE>
WorkspaceProperty<TYPE> &WorkspaceProperty<TYPE>::
operator+=(Kernel::Property const *) {
throw Kernel::Exception::NotImplementedError(
"+= operator is not implemented for WorkspaceProperty.");
return *this;
}
/// 'Virtual copy constructor'
template <typename TYPE>
WorkspaceProperty<TYPE> *WorkspaceProperty<TYPE>::clone() const {
return new WorkspaceProperty<TYPE>(*this);
}
/** Get the name of the workspace
* @return The workspace's name
*/
template <typename TYPE> std::string WorkspaceProperty<TYPE>::value() const {
return m_workspaceName;
}
/** Get the value the property was initialised with -its default value
* @return The default value
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::getDefault() const {
return m_initialWSName;
}
/** Set the name of the workspace.
* Also tries to retrieve it from the AnalysisDataService.
* @param value :: The new name for the workspace
* @return
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::setValue(const std::string &value) {
m_workspaceName = value;
if (Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::autoTrim()) {
boost::trim(m_workspaceName);
}
// Try and get the workspace from the ADS, but don't worry if we can't
try {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
AnalysisDataService::Instance().retrieveWS<TYPE>(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Set to null property if not found
this->clear();
// the workspace name is not reset here, however.
}
return isValid();
}
/** Set a value from a data item
* @param value :: A shared pointer to a DataItem. If it is of the correct
* type it will set validated, if not the property's value will be cleared.
* @return
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::setDataItem(
const boost::shared_ptr<Kernel::DataItem> value) {
boost::shared_ptr<TYPE> typed = boost::dynamic_pointer_cast<TYPE>(value);
if (typed) {
std::string wsName = typed->name();
if (this->direction() == Kernel::Direction::Input && !wsName.empty()) {
m_workspaceName = wsName;
}
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value = typed;
} else {
this->clear();
}
return isValid();
}
/** Checks whether the entered workspace is valid.
* To be valid, in addition to satisfying the conditions of any validators,
* an output property must not have an empty name and an input one must point
* to
* a workspace of the correct type.
* @returns A user level description of the problem or "" if it is valid.
*/
template <typename TYPE> std::string WorkspaceProperty<TYPE>::isValid() const {
// start with the no error condition
std::string error;
// If an output workspace it must have a name, although it might not exist
// in the ADS yet
if (this->direction() == Kernel::Direction::Output) {
return isValidOutputWs();
}
// If an input (or inout) workspace, must point to something, although it
// doesn't have to have a name
// unless it's optional
if (this->direction() == Kernel::Direction::Input ||
this->direction() == Kernel::Direction::InOut) {
// Workspace groups will not have a value since they are not of type TYPE
if (!Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value) {
Mantid::API::Workspace_sptr wksp;
// if the workspace name is empty then there is no point asking the ADS
if (m_workspaceName.empty())
return isOptionalWs();
try {
wksp = AnalysisDataService::Instance().retrieve(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Check to see if the workspace is not logged with the ADS because it
// is optional.
return isOptionalWs();
}
// At this point we have a valid pointer to a Workspace so we need to
// test whether it is a group
if (boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp)) {
return isValidGroup(
boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp));
} else {
error = "Workspace " + this->value() + " is not of the correct type";
}
return error;
}
}
// Call superclass method to access any attached validators (which do their
// own logging)
return Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::isValid();
}
/** Indicates if the object is still pointing to the same workspace, using the
* workspace name
* @return true if the value is the same as the initial value or false
* otherwise
*/
template <typename TYPE> bool WorkspaceProperty<TYPE>::isDefault() const {
return m_initialWSName == m_workspaceName;
}
/** Is the workspace property optional
* @return true if the workspace can be blank */
template <typename TYPE> bool WorkspaceProperty<TYPE>::isOptional() const {
return (m_optional == PropertyMode::Optional);
}
/** Does the workspace need to be locked before starting an algorithm?
* @return true (default) if the workspace will be locked */
template <typename TYPE> bool WorkspaceProperty<TYPE>::isLocking() const {
return (m_locking == LockMode::Lock);
}
/** Returns the current contents of the AnalysisDataService for input
* workspaces.
* For output workspaces, an empty set is returned
* @return set of objects in AnalysisDataService
*/
template <typename TYPE>
std::vector<std::string> WorkspaceProperty<TYPE>::allowedValues() const {
if (this->direction() == Kernel::Direction::Input ||
this->direction() == Kernel::Direction::InOut) {
// If an input workspace, get the list of workspaces currently in the ADS
auto vals = AnalysisDataService::Instance().getObjectNames(
Mantid::Kernel::DataServiceSort::Sorted);
if (isOptional()) // Insert an empty option
{
vals.push_back("");
}
// Copy-construct a temporary workspace property to test the validity of
// each workspace
WorkspaceProperty<TYPE> tester(*this);
// Remove any workspace that's not valid for this algorithm
auto eraseIter = remove_if(vals.begin(), vals.end(),
[&tester](const std::string &wsName) {
return !tester.setValue(wsName).empty();
});
// Erase everything past returned iterator afterwards for readability
vals.erase(eraseIter, vals.end());
return vals;
} else {
// For output workspaces, just return an empty set
return std::vector<std::string>();
}
}
/// Create a history record
/// @return A populated PropertyHistory for this class
template <typename TYPE>
const Kernel::PropertyHistory WorkspaceProperty<TYPE>::createHistory() const {
std::string wsName = m_workspaceName;
bool isdefault = this->isDefault();
if ((wsName.empty() || this->hasTemporaryValue()) && this->operator()()) {
// give the property a temporary name in the history
std::ostringstream os;
os << "__TMP" << this->operator()().get();
wsName = os.str();
isdefault = false;
}
return Kernel::PropertyHistory(this->name(), wsName, this->type(), isdefault,
this->direction());
}
/** If this is an output workspace, store it into the AnalysisDataService
* @return True if the workspace is an output workspace and has been stored
* @throw std::runtime_error if unable to store the workspace successfully
*/
template <typename TYPE> bool WorkspaceProperty<TYPE>::store() {
bool result = false;
if (!this->operator()() && isOptional())
return result;
if (this->direction()) // Output or InOut
{
// Check that workspace exists
if (!this->operator()())
throw std::runtime_error(
"WorkspaceProperty doesn't point to a workspace");
// Note use of addOrReplace rather than add
API::AnalysisDataService::Instance().addOrReplace(m_workspaceName,
this->operator()());
result = true;
}
// always clear the internal pointer after storing
clear();
return result;
}
template <typename TYPE>
Workspace_sptr WorkspaceProperty<TYPE>::getWorkspace() const {
return this->operator()();
}
/** Checks whether the entered workspace group is valid.
* To be valid *all* members of the group have to be valid.
* @param wsGroup :: the WorkspaceGroup of which to check the validity
* @returns A user level description of the problem or "" if it is valid.
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::isValidGroup(
boost::shared_ptr<WorkspaceGroup> wsGroup) const {
g_log.debug() << " Input WorkspaceGroup found \n";
std::vector<std::string> wsGroupNames = wsGroup->getNames();
std::string error;
// Cycle through each workspace in the group ...
for (const auto &memberWsName : wsGroupNames) {
boost::shared_ptr<Workspace> memberWs =
AnalysisDataService::Instance().retrieve(memberWsName);
// Table Workspaces are ignored
if ("TableWorkspace" == memberWs->id()) {
error = "Workspace " + memberWsName + " is of type TableWorkspace and "
"will therefore be ignored as "
"part of the GroupedWorkspace.";
g_log.debug() << error << '\n';
} else {
// ... and if it is a workspace of incorrect type, exclude the group by
// returning an error.
if (!boost::dynamic_pointer_cast<TYPE>(memberWs)) {
error = "Workspace " + memberWsName + " is not of type " +
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::type() +
".";
g_log.debug() << error << '\n';
return error;
}
// If it is of the correct type, it may still be invalid. Check.
else {
Mantid::API::WorkspaceProperty<TYPE> memberWsProperty(*this);
std::string memberError = memberWsProperty.setValue(memberWsName);
if (!memberError.empty())
return memberError; // Since if this member is invalid, then the
// whole group is invalid.
}
}
}
return ""; // Since all members of the group are valid.
}
/** Checks whether the entered output workspace is valid.
* To be valid the only thing it needs is a name that is allowed by the ADS,
* @see AnalysisDataServiceImpl
* @returns A user level description of the problem or "" if it is valid.
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::isValidOutputWs() const {
std::string error;
const std::string value = this->value();
if (!value.empty()) {
// Will the ADS accept it
error = AnalysisDataService::Instance().isValid(value);
} else {
if (isOptional())
error = ""; // Optional ones don't need a name
else
error = "Enter a name for the Output workspace";
}
return error;
}
/** Checks whether the entered workspace (that by this point we've found is
* not in the ADS)
* is actually an optional workspace and so still valid.
* @returns A user level description of the problem or "" if it is valid.
*/
template <typename TYPE>
std::string WorkspaceProperty<TYPE>::isOptionalWs() const {
std::string error;
if (m_workspaceName.empty()) {
if (isOptional()) {
error = "";
} else {
error = "Enter a name for the Input/InOut workspace";
}
} else {
error = "Workspace \"" + this->value() +
"\" was not found in the Analysis Data Service";
}
return error;
}
/// Reset the pointer to the workspace
template <typename TYPE> void WorkspaceProperty<TYPE>::clear() {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
boost::shared_ptr<TYPE>();
}
/** Attempts to retreive the data from the ADS
* if the data is not foung the internal pointer is set to null.
*/
template <typename TYPE>
void WorkspaceProperty<TYPE>::retrieveWorkspaceFromADS() {
// Try and get the workspace from the ADS, but don't worry if we can't
try {
Kernel::PropertyWithValue<boost::shared_ptr<TYPE>>::m_value =
AnalysisDataService::Instance().retrieveWS<TYPE>(m_workspaceName);
} catch (Kernel::Exception::NotFoundError &) {
// Set to null property if not found
this->clear();
}
}
} // namespace API
} // namespace Mantid
#include "MantidAPI/Workspace.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/IEventWorkspace.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/ISplittersWorkspace.h"
// WorkspaceProperty implementation
#include "MantidAPI/WorkspaceProperty.tcc"
namespace Mantid {
namespace API {
///@cond TEMPLATE
......
......@@ -44,6 +44,7 @@ set ( SRC_FILES
src/TableWorkspace.cpp
src/VectorColumn.cpp
src/Workspace2D.cpp
src/WorkspaceProperty.cpp
src/WorkspaceSingleValue.cpp
)
......
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataObjects/WorkspaceSingleValue.h"
// WorkspaceProperty implementation
#include "MantidAPI/WorkspaceProperty.tcc"
namespace Mantid {
// Note that this file is part of DataObjects, but we are extending API
namespace API {
///@cond TEMPLATE
template class MANTID_API_DLL
Mantid::API::WorkspaceProperty<Mantid::DataObjects::EventWorkspace>;
template class MANTID_API_DLL
Mantid::API::WorkspaceProperty<Mantid::DataObjects::Workspace2D>;
template class MANTID_API_DLL
Mantid::API::WorkspaceProperty<Mantid::DataObjects::WorkspaceSingleValue>;
///@endcond TEMPLATE
} // namespace API
} // namespace Mantid
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment