"Framework/Kernel/test/NexusDescriptorTest.h" did not exist on "5a1a53c2c09e4b07f288cf35a32850492dd1e785"
Newer
Older
#include "MantidAPI/FileLoaderRegistry.h"
#include "MantidAPI/IFileLoader.h"
#include <Poco/File.h>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
namespace Mantid {
namespace API {
namespace {
//----------------------------------------------------------------------------------------------
// Anonymous namespace helpers
//----------------------------------------------------------------------------------------------
/// @cond
template <typename T> struct DescriptorCallback {
void apply(T &) {} // general one does nothing
};
template <> struct DescriptorCallback<Kernel::FileDescriptor> {
void apply(Kernel::FileDescriptor &descriptor) {
descriptor.resetStreamToStart();
}
};
/// @endcond
/**
* @param filename A string giving a filename
* @param names The collection of names to search through
* @param logger A reference to a Mantid Logger object
* @return A string containing the name of an algorithm to load the file, or an
* empty string if nothing
* was found
*/
template <typename DescriptorType, typename FileLoaderType>
const IAlgorithm_sptr
searchForLoader(const std::string &filename,
const std::multimap<std::string, int> &names,
Kernel::Logger &logger) {
const auto &factory = AlgorithmFactory::Instance();
IAlgorithm_sptr bestLoader;
int maxConfidence(0);
DescriptorType descriptor(filename);
DescriptorCallback<DescriptorType> callback;
auto iend = names.end();
for (auto it = names.begin(); it != iend; ++it) {
const std::string &name = it->first;
const int version = it->second;
logger.debug() << "Checking " << name << " version " << version
<< std::endl;
// Use static cast for speed. Checks have been done at registration to check
// the types
auto alg = boost::static_pointer_cast<FileLoaderType>(
factory.create(name, version)); // highest version
try {
const int confidence = alg->confidence(descriptor);
logger.debug() << name << " returned with confidence=" << confidence
<< std::endl;
if (confidence > maxConfidence) // strictly greater
bestLoader = alg;
maxConfidence = confidence;
} catch (std::exception &exc) {
logger.warning() << "Checking loader '" << name << "' raised an error: '"
<< exc.what() << "'. Loader skipped." << std::endl;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
callback.apply(descriptor);
}
return bestLoader;
}
} // end anonymous
//----------------------------------------------------------------------------------------------
// Public members
//----------------------------------------------------------------------------------------------
/**
* If the name does not exist then it does nothing
* @param name Name of the algorithm to remove from the search list
* @param version An optional version to remove. -1 indicates remove all
* (Default=-1)
*/
void FileLoaderRegistryImpl::unsubscribe(const std::string &name,
const int version) {
auto iend = m_names.end();
for (auto it = m_names.begin(); it != iend; ++it) {
removeAlgorithm(name, version, *it);
}
}
/**
* Queries each registered algorithm and asks it how confident it is that it can
* load the given file. The name of the one with the highest confidence is
* returned.
* @param filename A full file path pointing to an existing file
* @return A string containing the name of an algorithm to load the file
* @throws Exception::NotFoundError if an algorithm cannot be found
*/
const boost::shared_ptr<IAlgorithm>
FileLoaderRegistryImpl::chooseLoader(const std::string &filename) const {
using Kernel::FileDescriptor;
using Kernel::NexusDescriptor;
m_log.debug() << "Trying to find loader for '" << filename << "'"
<< std::endl;
IAlgorithm_sptr bestLoader;
if (NexusDescriptor::isHDF(filename)) {
m_log.debug()
<< filename
<< " looks like a Nexus file. Checking registered Nexus loaders\n";
bestLoader = searchForLoader<NexusDescriptor, IFileLoader<NexusDescriptor>>(
filename, m_names[Nexus], m_log);
} else {
m_log.debug() << "Checking registered non-HDF loaders\n";
bestLoader = searchForLoader<FileDescriptor, IFileLoader<FileDescriptor>>(
filename, m_names[Generic], m_log);
}
if (!bestLoader) {
throw Kernel::Exception::NotFoundError(filename, "Unable to find loader");
}
m_log.debug() << "Found loader " << bestLoader->name() << " for file '"
<< filename << "'" << std::endl;
return bestLoader;
}
/**
* Perform a check that that the given algorithm can load the file
* @param algorithmName The name of the algorithm to check
* @param filename The name of file to check
* @returns True if the algorithm can load the file, false otherwise
* @throws std::invalid_argument if the loader does not exist
*/
bool FileLoaderRegistryImpl::canLoad(const std::string &algorithmName,
const std::string &filename) const {
using Kernel::FileDescriptor;
using Kernel::NexusDescriptor;
// Check if it is in one of our lists
bool nexus(false), nonHDF(false);
if (m_names[Nexus].find(algorithmName) != m_names[Nexus].end())
nexus = true;
else if (m_names[Generic].find(algorithmName) != m_names[Generic].end())
nonHDF = true;
if (!nexus && !nonHDF)
throw std::invalid_argument(
"FileLoaderRegistryImpl::canLoad - Algorithm '" + algorithmName +
"' is not registered as a loader.");
std::multimap<std::string, int> names{{algorithmName, -1}};
if (nexus) {
if (NexusDescriptor::isHDF(filename)) {
loader = searchForLoader<NexusDescriptor, IFileLoader<NexusDescriptor>>(
filename, names, m_log);
}
} else {
loader = searchForLoader<FileDescriptor, IFileLoader<FileDescriptor>>(
filename, names, m_log);
}
return static_cast<bool>(loader);
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
}
//----------------------------------------------------------------------------------------------
// Private members
//----------------------------------------------------------------------------------------------
/**
* Creates an empty registry
*/
FileLoaderRegistryImpl::FileLoaderRegistryImpl()
: m_names(2, std::multimap<std::string, int>()), m_totalSize(0),
m_log("FileLoaderRegistry") {}
/**
*/
FileLoaderRegistryImpl::~FileLoaderRegistryImpl() {}
/**
* @param name A string containing the algorithm name
* @param version The version to remove. -1 indicates all instances
* @param typedLoaders A map of names to version numbers
**/
void FileLoaderRegistryImpl::removeAlgorithm(
const std::string &name, const int version,
std::multimap<std::string, int> &typedLoaders) {
if (version == -1) // remove all
{
typedLoaders.erase(name);
} else // find the right version
{
auto range = typedLoaders.equal_range(name);
for (auto ritr = range.first; ritr != range.second; ++ritr) {
if (ritr->second == version) {
typedLoaders.erase(ritr);
break;
}
}
} // namespace Mantid