19#include <boost/algorithm/string.hpp>
20#include <boost/regex.hpp>
39bool doesNotContainWildCard(
const std::string &ext) {
return std::string::npos == ext.find(
'*'); }
41static const std::string
SUCCESS(
"");
44const std::string
INVALID = R
"(\+\+|,,|\+,|,\+)";
45static const boost::regex REGEX_INVALID(
INVALID);
48const std::string NUM_COMMA_ALPHA(R
"((?<=\d)\s*,\s*(?=\D))");
49const std::string ALPHA_COMMA_ALPHA(R
"((?<=\D)\s*,\s*(?=\D))");
50const std::string COMMA_OPERATORS = NUM_COMMA_ALPHA +
"|" + ALPHA_COMMA_ALPHA;
51static const boost::regex REGEX_COMMA_OPERATORS(COMMA_OPERATORS);
54const std::string NUM_PLUS_ALPHA(R
"((?<=\d)\s*\+\s*(?=\D))");
55const std::string ALPHA_PLUS_ALPHA(R
"((?<=\D)\s*\+\s*(?=\D))");
56const std::string PLUS_OPERATORS = NUM_PLUS_ALPHA +
"|" + ALPHA_PLUS_ALPHA;
57static const boost::regex REGEX_PLUS_OPERATORS(PLUS_OPERATORS, boost::regex_constants::perl);
59bool isASCII(
const std::string &str) {
60 return !std::any_of(str.cbegin(), str.cend(), [](
char c) { return static_cast<unsigned char>(c) > 127; });
75 const std::vector<std::string> &exts,
bool allowEmptyTokens)
77 name,
std::vector<
std::vector<
std::string>>(),
79 m_allowEmptyTokens(allowEmptyTokens) {
82 throw std::runtime_error(
"Specified action is not supported for MultipleFileProperty");
88 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(
m_exts), doesNotContainWildCard);
113 return "No file specified.";
134 return "No file(s) specified.";
139 g_log.
debug(
"MultiFile loading is not enabled, acting as standard FileProperty.");
146 }
catch (
const std::range_error &re) {
148 return std::string(re.what());
149 }
catch (
const std::runtime_error &re) {
150 g_log.
debug(
"MultiFile loading has failed. Trying as standard FileProperty.");
166 return toString(
m_value,
"",
"");
207 std::vector<std::vector<std::string>> foundFiles;
209 toValue(slaveFileProp(), foundFiles,
"",
"");
211 }
catch (std::invalid_argument &except) {
212 g_log.
debug() <<
"Could not set property " <<
name() <<
": " << except.what();
213 return except.what();
243 boost::smatch invalid_substring;
244 if (!
m_allowEmptyTokens && boost::regex_search(propValue.begin(), propValue.end(), invalid_substring, REGEX_INVALID))
245 return "Unable to parse filename due to an empty token.";
246 if (!isASCII(propValue))
247 return "Unable to parse filename due to an unsupported non-ASCII character being found.";
249 std::vector<std::vector<std::string>> fileNames;
252 boost::sregex_token_iterator end;
253 boost::sregex_token_iterator commaToken(propValue.begin(), propValue.end(), REGEX_COMMA_OPERATORS, -1);
255 for (; commaToken != end; ++commaToken) {
256 const std::string commaTokenString = commaToken->str();
259 boost::sregex_token_iterator plusToken(commaTokenString.begin(), commaTokenString.end(), REGEX_PLUS_OPERATORS, -1);
261 std::vector<std::vector<std::string>> temp;
265 std::vector<std::string> plusTokenStrings;
266 for (; plusToken != end; ++plusToken)
267 plusTokenStrings.emplace_back(plusToken->str());
270 for (
auto &plusTokenString : plusTokenStrings) {
273 }
catch (
const std::range_error &re) {
276 }
catch (
const std::runtime_error &) {
289 f.emplace_back(1, plusTokenString);
291 if (plusTokenStrings.size() > 1) {
297 return "Adding a range of files to another file(s) is not currently "
301 temp.emplace_back(f[0]);
303 for (
auto &parsedFile : f[0])
304 temp[0].emplace_back(parsedFile);
307 temp.insert(temp.end(), f.begin(), f.end());
311 fileNames.insert(fileNames.end(), std::make_move_iterator(temp.begin()), std::make_move_iterator(temp.end()));
314 std::vector<std::vector<std::string>> allUnresolvedFileNames = fileNames;
315 std::vector<std::vector<std::string>> allFullFileNames;
320 std::string defaultExt;
321 for (
const auto &unresolvedFileName : flattenedAllUnresolvedFileNames) {
324 Poco::Path path(unresolvedFileName);
325 if (!path.getExtension().empty()) {
326 defaultExt =
"." + path.getExtension();
330 }
catch (Poco::Exception &) {
338 for (
const auto &unresolvedFileNames : allUnresolvedFileNames) {
341 if (std::string::npos != boost::algorithm::join(unresolvedFileNames,
"").find(
"*"))
342 return "Searching for files by wildcards is not currently supported.";
344 std::vector<std::string> fullFileNames;
346 for (
const auto &unresolvedFileName : unresolvedFileNames) {
351 Poco::Path path(unresolvedFileName);
353 useDefaultExt = path.getExtension().empty();
354 }
catch (Poco::Exception &) {
357 useDefaultExt =
false;
360 std::string fullyResolvedFile;
362 if (!useDefaultExt) {
364 std::string
error = slaveFileProp.
setValue(unresolvedFileName);
367 if (!
error.empty()) {
368 throw std::runtime_error(
error);
371 fullyResolvedFile = slaveFileProp();
374 if (!defaultExt.empty()) {
380 if (fullyResolvedFile.empty()) {
381 bool doThrow =
false;
384 const int unresolvedInt = std::stoi(unresolvedFileName);
385 if (unresolvedInt != 0) {
388 }
catch (std::invalid_argument &) {
395 throw std::runtime_error(
"Unable to find file matching the string \"" + unresolvedFileName +
396 "\", please check the data search directories.");
401 fullyResolvedFile = unresolvedFileName;
407 fullFileNames.emplace_back(std::move(fullyResolvedFile));
409 allFullFileNames.emplace_back(std::move(fullFileNames));
A specialized class for dealing with file properties.
std::string setValue(const std::string &propValue) override
Overridden setValue method.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Load
allowed here which will be passed to the algorithm
A property to allow a user to specify multiple files to load.
unsigned int m_action
The action type of this property Load (dafault) or OptionalLoad are supported.
std::string setValueAsSingleFile(const std::string &propValue)
Called by setValue in the case where a user has disabled multiple file loading.
std::string getDefault() const override
Get the value the property was initialised with -its default value.
bool isOptional() const
Check if this property is optional.
std::string value() const override
Returns the value of the property as a string.
std::string isEmptyValueValid() const
Returns a string depending on whether an empty value is valid.
std::vector< std::string > m_exts
Suggested extensions.
std::string setValueAsMultipleFiles(const std::string &propValue)
Called by setValue in the case where multiple file loading is enabled.
std::vector< std::vector< std::string > > m_oldFoundValue
Last value of the found files used in MultipleFileProperty::setValueAsMultipleFiles and MultipleFileP...
std::string setValue(const std::string &propValue) override
Convert the given propValue into a comma and plus separated list of full filenames,...
MultipleFileProperty(const std::string &name, unsigned int action, const std::vector< std::string > &exts=std::vector< std::string >(), bool allowEmptyTokens=false)
Alternative constructor with action.
std::string m_oldPropValue
Last value of propValue used in MultipleFileProperty::setValueAsMultipleFiles and MultipleFilePropert...
bool m_multiFileLoadingEnabled
Whether or not the user has turned on multifile loading.
bool m_allowEmptyTokens
Whether to allow for empty tokens.
Kernel::MultiFileNameParsing::Parser m_parser
Parser used to parse multi-file strings.
Loads a workspace from a data file.
The Logger class is in charge of the publishing messages from the framework through various channels.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void setTrimWhiteSpaces(const bool &setting)
Set the flag for trimming whitespaces in run string.
std::vector< std::vector< std::string > > fileNames() const
Return the vector of vectors of parsed file names.
void parse(const std::string &multiFileName)
Parse the given multiFileNameString.
The MultiFileValidator validates a MultiFileProperty, which contains a vector of vectors* of filename...
The concrete, templated class for properties.
std::vector< std::vector< std::string > > m_initialValue
the property's default value which is also its initial value
std::vector< std::vector< std::string > > m_value
The value of the property.
bool autoTrim() const
Returns if the property is set to automatically trim string unput values of whitespace.
const std::string & name() const
Get the property's name.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::vector< T > flattenVector(const std::vector< std::vector< T > > &v)
A convenience function to "flatten" the given vector of vectors into a single vector.
Describes the direction (within an algorithm) of a Property.
@ Input
An input workspace.