Skip to content
Snippets Groups Projects
Commit 52b5f1a5 authored by Gigg, Martyn Anthony's avatar Gigg, Martyn Anthony
Browse files

FileLoaderRegistry now subscribes algorithms to factory

and also defines two types of loader, NonHDF and HDF.
Refs #7263
parent 885088de
No related branches found
No related tags found
No related merge requests found
......@@ -2,9 +2,11 @@
#define MANTID_API_FILELOADERREGISTRY_H_
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/AlgorithmFactory.h"
#include <set>
#include <string>
#include <vector>
namespace Mantid
{
......@@ -45,20 +47,42 @@ namespace Mantid
*/
class MANTID_API_DLL FileLoaderRegistry
{
public:
/// Defines types of possible file
enum LoaderFormat { NonHDF, HDF };
public:
/// Default constructor
FileLoaderRegistry();
/// @returns the number of entries in the registry
inline size_t size() const { return m_names.size(); }
/// Adds an entry
void subscribe(const std::string & name);
/// Pick the best loader for the given filename
std::string findLoader(const std::string & filename) const;
inline size_t size() const { return m_totalSize; }
/**
* Registers a loader whose format is one of the known formats given in LoaderFormat. It
* also passes this registration on to the AlgorithmFactory so that it can be created.
* The template type should be the class being registered. The name is taken from the string
* returned by the name() method on the object.
* @param format The type of loader being subscribed, see LoaderFormat
* @throws std::invalid_argument if an entry with this name already exists
*/
template<typename Type>
void subscribe(LoaderFormat format)
{
const std::string name = AlgorithmFactory::Instance().subscribe<Type>();
// If the factory didn't throw then the name is valid
m_names[format].insert(name);
m_totalSize += 1;
m_log.debug() << "Registered '" << name << "' as file loader\n";
}
private:
/// The registered names
std::set<std::string> m_names;
/// The list of names. The index pointed to by LoaderFormat defines a set for that format
std::vector<std::set<std::string> > m_names;
/// Total number of names registered
size_t m_totalSize;
/// Reference to a logger
Kernel::Logger & m_log;
};
......
......@@ -6,15 +6,33 @@
/**
* DECLARE_FILELOADER_ALGORITHM should be used in place of the standard
* DECLARE_ALGORITHM macro that both registers the algorithm as usual and subscribes it to the
* DECLARE_ALGORITHM macro when writing a file loading algorithm that
* loads data from a non-hierarchical format.
* It both registers the algorithm as usual and subscribes it to the
* registry held in the FrameworkManager
*/
#define DECLARE_FILELOADER_ALGORITHM(classname) \
DECLARE_ALGORITHM(classname) \
namespace \
{\
Mantid::Kernel::RegistrationHelper \
reg_loader_##classname((Mantid::API::FrameworkManager::Instance().fileLoaderRegistry().subscribe(#classname), 0));\
reg_loader_##classname((Mantid::API::\
FrameworkManager::Instance().fileLoaderRegistry().subscribe<classname>(Mantid::API::FileLoaderRegistry::NonHDF), 0));\
}
/**
* DECLARE_HDF_FILELOADER_ALGORITHM should be used in place of the standard
* DECLARE_ALGORITHM macro when writing a file loading algorithm that
* loads data from a hierarchical format, e.g. NeXus, HDF.
* It both registers the algorithm as usual and subscribes it to the
* registry held in the FrameworkManager
*/
#define DECLARE_HDF_FILELOADER_ALGORITHM(classname) \
namespace \
{\
Mantid::Kernel::RegistrationHelper \
reg_hdf_loader_##classname((Mantid::API::\
FrameworkManager::Instance().fileLoaderRegistry().subscribe<classname>(Mantid::API::FileLoaderRegistry::HDF), 0)); \
}
#endif /* MANTID_API_REGISTERFILELOADER_H_ */
......@@ -14,41 +14,12 @@ namespace Mantid
/**
* Creates an empty registry
*/
FileLoaderRegistry::FileLoaderRegistry() : m_log(Kernel::Logger::get("FileLoaderRegistry"))
FileLoaderRegistry::FileLoaderRegistry() :
m_names(2, std::set<std::string>()), m_totalSize(0),
m_log(Kernel::Logger::get("FileLoaderRegistry"))
{
}
/**
* @param name The string name of the entry
* @throws std::invalid_argument if an entry with this name already exists
*/
void FileLoaderRegistry::subscribe(const std::string & name)
{
auto insertionResult = m_names.insert(name);
if(!insertionResult.second)
{
throw std::invalid_argument("FileLoaderRegistry::subscribe - Cannot subscribe '"
+ name + "'. An entry with that name already exists");
}
m_log.debug() << "Registered '" << name << "' as file loader\n";
}
/**
* Attempts to pick the best suited loader for the given file name from those in the registry
* @param filename A string that should point to an existing file
* @throws std::invalid_argument if the filename does not point to an existing file or an empty string is given
* @throws Exception::NotFoundError if a loader could not be found
*/
std::string FileLoaderRegistry::findLoader(const std::string & filename) const
{
if(filename.empty() || !Poco::File(filename).exists())
{
throw std::invalid_argument("FileLoaderRegistry::chooserLoader - Cannot open file '" + filename + "'");
}
m_log.debug() << "Attempting to find loader for '" << filename << "'\n";
throw std::runtime_error("not implemented yet");
}
//----------------------------------------------------------------------------------------------
// Private members
//----------------------------------------------------------------------------------------------
......
......@@ -2,6 +2,7 @@
#define MANTID_API_FILELOADERREGISTRYTEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/FileLoaderRegistry.h"
using Mantid::API::FileLoaderRegistry;
......@@ -25,27 +26,35 @@ public:
{
FileLoaderRegistry registry;
TS_ASSERT_THROWS_NOTHING(registry.subscribe("LoadEventNexus"));
TS_ASSERT_THROWS_NOTHING(registry.subscribe<StubAlgorithm>(FileLoaderRegistry::NonHDF));
TS_ASSERT_EQUALS(1, registry.size());
// We can't mock the factory as it's a singleton so make sure we clean up
Mantid::API::AlgorithmFactory::Instance().unsubscribe("StubAlgorithm", 1);
}
// ======================== Failure cases ===================================
void test_Adding_Entry_That_Already_Exists_Throws_Error_And_Keeps_The_Size_The_Same()
{
FileLoaderRegistry registry;
registry.subscribe("LoadEventNexus");
registry.subscribe<StubAlgorithm>(FileLoaderRegistry::NonHDF);
TS_ASSERT_THROWS(registry.subscribe("LoadEventNexus"), std::invalid_argument);
TS_ASSERT_THROWS(registry.subscribe<StubAlgorithm>(FileLoaderRegistry::NonHDF), std::runtime_error);
TS_ASSERT_EQUALS(1, registry.size());
// We can't mock the factory as it's a singleton so make sure we clean up
Mantid::API::AlgorithmFactory::Instance().unsubscribe("StubAlgorithm", 1);
}
void test_Finding_A_Loader_Throws_Invalid_Argument_If_Filename_Does_Not_Point_To_Valid_File()
private:
// Stub algorithm for test
struct StubAlgorithm : Mantid::API::Algorithm
{
FileLoaderRegistry registry;
TS_ASSERT_THROWS(registry.findLoader(""), std::invalid_argument);
TS_ASSERT_THROWS(registry.findLoader("__notafile.txt__"), std::invalid_argument);
}
const std::string name() const { return "StubAlgorithm"; }
int version() const { return 1; }
void init() {};
void exec() {};
};
};
......
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