18#include <boost/algorithm/string.hpp>
19#include <boost/regex.hpp>
38bool doesNotContainWildCard(
const std::string &ext) {
return std::string::npos == ext.find(
'*'); }
40static const std::string
SUCCESS(
"");
43const std::string
INVALID = R
"(\+\+|,,|\+,|,\+)";
44static const boost::regex REGEX_INVALID(
INVALID);
47const std::string NUM_COMMA_ALPHA(R
"((?<=\d)\s*,\s*(?=\D))");
48const std::string ALPHA_COMMA_ALPHA(R
"((?<=\D)\s*,\s*(?=\D))");
49const std::string COMMA_OPERATORS = NUM_COMMA_ALPHA +
"|" + ALPHA_COMMA_ALPHA;
50static const boost::regex REGEX_COMMA_OPERATORS(COMMA_OPERATORS);
53const std::string NUM_PLUS_ALPHA(R
"((?<=\d)\s*\+\s*(?=\D))");
54const std::string ALPHA_PLUS_ALPHA(R
"((?<=\D)\s*\+\s*(?=\D))");
55const std::string PLUS_OPERATORS = NUM_PLUS_ALPHA +
"|" + ALPHA_PLUS_ALPHA;
56static const boost::regex REGEX_PLUS_OPERATORS(PLUS_OPERATORS, boost::regex_constants::perl);
58bool isASCII(
const std::string &str) {
59 return !std::any_of(str.cbegin(), str.cend(), [](
char c) { return static_cast<unsigned char>(c) > 127; });
74 const std::vector<std::string> &exts,
bool allowEmptyTokens)
78 m_allowEmptyTokens(allowEmptyTokens) {
81 throw std::runtime_error(
"Specified action is not supported for MultipleFileProperty");
87 std::copy_if(exts.cbegin(), exts.cend(), std::back_inserter(
m_exts), doesNotContainWildCard);
112 return "No file specified.";
133 return "No file(s) specified.";
138 g_log.
debug(
"MultiFile loading is not enabled, acting as standard FileProperty.");
145 }
catch (
const std::range_error &re) {
147 return std::string(re.what());
148 }
catch (
const std::runtime_error &re) {
149 g_log.
debug(
"MultiFile loading has failed. Trying as standard FileProperty.");
206 std::vector<std::vector<std::string>> foundFiles;
208 toValue(singleFileProperty(), foundFiles,
"",
"");
210 }
catch (std::invalid_argument &except) {
211 g_log.
debug() <<
"Could not set property " <<
name() <<
": " << except.what();
212 return except.what();
242 boost::smatch invalid_substring;
243 if (!
m_allowEmptyTokens && boost::regex_search(propValue.begin(), propValue.end(), invalid_substring, REGEX_INVALID))
244 return "Unable to parse filename due to an empty token.";
245 if (!isASCII(propValue))
246 return "Unable to parse filename due to an unsupported non-ASCII character being found.";
248 std::vector<std::vector<std::string>> fileNames;
251 boost::sregex_token_iterator end;
252 boost::sregex_token_iterator commaToken(propValue.begin(), propValue.end(), REGEX_COMMA_OPERATORS, -1);
254 for (; commaToken != end; ++commaToken) {
255 const std::string commaTokenString = commaToken->str();
258 boost::sregex_token_iterator plusToken(commaTokenString.begin(), commaTokenString.end(), REGEX_PLUS_OPERATORS, -1);
260 std::vector<std::vector<std::string>> temp;
264 std::vector<std::string> plusTokenStrings;
265 for (; plusToken != end; ++plusToken)
266 plusTokenStrings.emplace_back(plusToken->str());
269 for (
auto &plusTokenString : plusTokenStrings) {
272 }
catch (
const std::range_error &re) {
275 }
catch (
const std::runtime_error &) {
288 f.emplace_back(1, plusTokenString);
290 if (plusTokenStrings.size() > 1) {
296 return "Adding a range of files to another file(s) is not currently "
300 temp.emplace_back(f[0]);
302 for (
auto &parsedFile : f[0])
303 temp[0].emplace_back(parsedFile);
306 temp.insert(temp.end(), f.begin(), f.end());
310 fileNames.insert(fileNames.end(), std::make_move_iterator(temp.begin()), std::make_move_iterator(temp.end()));
313 std::vector<std::vector<std::string>> allUnresolvedFileNames = fileNames;
314 std::vector<std::vector<std::string>> allFullFileNames;
319 std::string defaultExt;
320 for (
const auto &unresolvedFileName : flattenedAllUnresolvedFileNames) {
323 Poco::Path path(unresolvedFileName);
324 if (!path.getExtension().empty()) {
325 defaultExt =
"." + path.getExtension();
329 }
catch (Poco::Exception &) {
337 for (
const auto &unresolvedFileNames : allUnresolvedFileNames) {
340 if (std::string::npos != boost::algorithm::join(unresolvedFileNames,
"").find(
"*"))
341 return "Searching for files by wildcards is not currently supported.";
343 std::vector<std::string> fullFileNames;
345 for (
const auto &unresolvedFileName : unresolvedFileNames) {
350 Poco::Path path(unresolvedFileName);
352 useDefaultExt = path.getExtension().empty();
353 }
catch (Poco::Exception &) {
356 useDefaultExt =
false;
359 std::string fullyResolvedFile;
361 if (!useDefaultExt) {
363 std::string
error = slaveFileProp.
setValue(unresolvedFileName);
366 if (!
error.empty()) {
367 throw std::runtime_error(
error);
370 fullyResolvedFile = slaveFileProp();
373 std::string errors =
"";
374 if (!defaultExt.empty()) {
375 auto run = FileFinder::Instance().findRun(unresolvedFileName, std::vector<std::string>(1, defaultExt));
377 fullyResolvedFile = run.result();
379 errors += run.errors();
382 auto run = FileFinder::Instance().findRun(unresolvedFileName,
m_exts);
384 fullyResolvedFile = run.result();
386 errors += run.errors();
388 if (fullyResolvedFile.empty()) {
389 bool doThrow =
false;
392 const int unresolvedInt = std::stoi(unresolvedFileName);
393 if (unresolvedInt != 0) {
396 }
catch (std::invalid_argument &) {
403 auto errorMsg =
"Unable to find file matching the string \"" + unresolvedFileName +
404 "\", please check the data search directories.";
406 errorMsg +=
" " + errors;
408 throw std::runtime_error(errorMsg);
413 fullyResolvedFile = unresolvedFileName;
419 fullFileNames.emplace_back(std::move(fullyResolvedFile));
421 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.
const 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.
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.
void toValue(const std::string &strvalue, T &value)
std::string toString(const T &value)
Convert values to strings.
Describes the direction (within an algorithm) of a Property.
@ Input
An input workspace.