Skip to content

Commit

Permalink
FileLoaderRegistry now subscribes algorithms to factory
Browse files Browse the repository at this point in the history
and also defines two types of loader, NonHDF and HDF.
Refs #7263
  • Loading branch information
martyngigg committed Jun 29, 2013
1 parent 2ba04b3 commit 79e6051
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 51 deletions.
38 changes: 31 additions & 7 deletions Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
};
Expand Down
24 changes: 21 additions & 3 deletions Code/Mantid/Framework/API/inc/MantidAPI/RegisterFileLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
35 changes: 3 additions & 32 deletions Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//----------------------------------------------------------------------------------------------
Expand Down
27 changes: 18 additions & 9 deletions Code/Mantid/Framework/API/test/FileLoaderRegistryTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,27 +26,35 @@ class FileLoaderRegistryTest : public CxxTest::TestSuite
{
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() {};
};

};

Expand Down

0 comments on commit 79e6051

Please sign in to comment.