Newer
Older
Steve Williams
committed
#include "MantidKernel/FileValidator.h"
#include <algorithm>
#include <iostream>
Gigg, Martyn Anthony
committed
namespace
{
/// Functor object to supply to for_each
struct lowercase
Gigg, Martyn Anthony
committed
void operator()(std::string s)
Gigg, Martyn Anthony
committed
std::transform(s.begin(), s.end(), s.begin(), tolower);
Gigg, Martyn Anthony
committed
};
Steve Williams
committed
namespace Mantid
{
namespace Kernel
{
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
Logger& FileValidator::g_log = Logger::get("FileValidator");
/// Default constructor.
Gigg, Martyn Anthony
committed
FileValidator::FileValidator() : IValidator<std::string>(), m_extensions(), m_fullTest(true)
{}
/** Constructor
Janik Zikovsky
committed
* @param extensions :: The permitted file extensions (e.g. .RAW)
* @param testFileExists :: Flag indicating whether to test for existence of file (default: yes)
*/
FileValidator::FileValidator(const std::vector<std::string>& extensions, bool testFileExists) :
IValidator<std::string>(),
m_extensions(extensions.begin(),extensions.end()),
m_fullTest(testFileExists)
{
Gigg, Martyn Anthony
committed
for_each(m_extensions.begin(), m_extensions.end(), lowercase());
Peterson, Peter
committed
/// Destructor
FileValidator::~FileValidator() {}
/// Returns the set of valid values
std::set<std::string> FileValidator::allowedValues() const
{
return m_extensions;
}
/**
* Clone the validator
* @returns A pointer to a new validator with the same properties as this one
*/
IValidator<std::string>* FileValidator::clone()
{
return new FileValidator(*this);
}
Steve Williams
committed
Gigg, Martyn Anthony
committed
/** If m_fullTest=true if checks that the files exists, otherwise just that path syntax looks valid
Janik Zikovsky
committed
* @param value :: file name
* @returns An error message to display to users or an empty string on no error
*/
std::string FileValidator::checkValidity(const std::string &value) const
Gigg, Martyn Anthony
committed
{
// Check if the path is syntactically valid
if( !Poco::Path().tryParse(value) )
{
return "Error in path syntax: \"" + value + "\".";
}
//Check the extension but just issue a warning if it is not one of the suggested values
Peterson, Peter
committed
if (!(value.empty()))
Gigg, Martyn Anthony
committed
{
Peterson, Peter
committed
if (!(this->endswith(value)))
{
Peterson, Peter
committed
g_log.warning() << "Unrecognised extension in file \"" << value << "\"";
if (!this->m_extensions.empty()) {
this->g_log.warning() << " [ ";
for (std::set<std::string>::const_iterator it = this->m_extensions.begin(); it != this->m_extensions.end(); ++it)
g_log.warning() << *it << " ";
this->g_log.warning() << "]";
}
g_log.warning() << "\"." << std::endl;
Peterson, Peter
committed
}
Gigg, Martyn Anthony
committed
//If the file is required to exist check it is there
if ( m_fullTest && ( value.empty() || !Poco::File(value).exists() ) )
Gigg, Martyn Anthony
committed
{
Steve Williams
committed
return "File \"" + Poco::Path(value).getFileName() + "\" not found";
Gigg, Martyn Anthony
committed
}
//Otherwise we are okay, file extensions are just a suggestion so no validation on them is necessary
return "";
}
Peterson, Peter
committed
/**
* Confirm that the value string ends with then ending string.
Janik Zikovsky
committed
* @param value :: The string to check the ending for.
* @param ending :: The ending the string should have.
Peterson, Peter
committed
*/
bool has_ending(const std::string &value, const std::string & ending)
Peterson, Peter
committed
{
if (ending.empty()) // always match against an empty extension
return true;
if (value.length() < ending.length()) // filename is not long enough
return false;
int result = value.compare(value.length() - ending.length(), ending.length(), ending);
return (result == 0); // only care if it matches
}
/**
* Checks the extension of a filename
Janik Zikovsky
committed
* @param value :: the filename to check
* @return flag that true if the extension matches in the filename
*/
Peterson, Peter
committed
bool FileValidator::endswith(const std::string &value) const
{
if (m_extensions.empty()) // automatically match a lack of extensions
return true;
Peterson, Peter
committed
if ((m_extensions.size() == 1) && (m_extensions.begin()->empty()))
return true;
Peterson, Peter
committed
// create a lowercase copy of the filename
std::string value_copy(value);
std::transform(value_copy.begin(), value_copy.end(), value_copy.begin(), tolower);
// check for the ending
for (std::set<std::string>::const_iterator it = m_extensions.begin();
it != m_extensions.end(); it++) {
Peterson, Peter
committed
if (has_ending(value, *it)) // original case
return true;
if (has_ending(value_copy, *it)) // lower case
Peterson, Peter
committed
return true;
}
return false;
}
Steve Williams
committed
} // namespace Kernel
} // namespace Mantid