2 * @brief Class for looking up user subclasses during unserialisation.
4 /* Copyright (C) 2006,2007,2008,2009,2010 Olly Betts
5 * Copyright (C) 2006,2007,2009 Lemur Consulting Ltd
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "xapian/registry.h"
26 #include "xapian/error.h"
27 #include "xapian/geospatial.h"
28 #include "xapian/intrusive_ptr.h"
29 #include "xapian/matchspy.h"
30 #include "xapian/postingsource.h"
31 #include "xapian/weight.h"
41 class Xapian::Registry::Internal
: public Xapian::Internal::intrusive_base
{
42 friend class Xapian::Registry
;
44 /// Registered weighting schemes.
45 std::map
<std::string
, Xapian::Weight
*> wtschemes
;
47 /// Registered external posting sources.
48 std::map
<std::string
, Xapian::PostingSource
*> postingsources
;
50 /// Registered match spies.
51 std::map
<std::string
, Xapian::MatchSpy
*> matchspies
;
53 /// Registered lat-long metrics.
54 std::map
<std::string
, Xapian::LatLongMetric
*> lat_long_metrics
;
56 /// Add the standard subclasses provided in the API.
59 /// Clear all registered weighting schemes.
60 void clear_weighting_schemes();
62 /// Clear all registered posting sources.
63 void clear_posting_sources();
65 /// Clear all registered match spies.
66 void clear_match_spies();
68 /// Clear all registered lat-long metrics.
69 void clear_lat_long_metrics();
78 register_object(map
<string
, T
*> & registry
, const T
& obj
)
80 string name
= obj
.name();
81 if (rare(name
.empty())) {
82 throw Xapian::InvalidOperationError("Unable to register object - name() method returned empty string");
85 pair
<typename map
<string
, T
*>::iterator
, bool> r
;
86 r
= registry
.insert(make_pair(name
, static_cast<T
*>(NULL
)));
88 // Existing element with this key, so replace the pointer with NULL
89 // and delete the existing pointer.
91 // If the delete throws, this will leave a NULL entry in the map, but
92 // that won't affect behaviour as we return NULL for "not found"
93 // anyway. The memory used will be leaked if the dtor throws, but
94 // throwing exceptions from the dtor is bad form, so that's not a big
97 swap(p
, r
.first
->second
);
101 T
* clone
= obj
.clone();
103 throw Xapian::InvalidOperationError("Unable to register object - clone() method returned NULL");
106 r
.first
->second
= clone
;
110 static inline const T
*
111 lookup_object(map
<string
, T
*> registry
, const string
& name
)
113 typename map
<string
, T
*>::const_iterator i
= registry
.find(name
);
114 if (i
== registry
.end()) {
122 Registry::Internal::Internal()
127 Registry::Internal::~Internal()
129 clear_weighting_schemes();
130 clear_posting_sources();
132 clear_lat_long_metrics();
136 Registry::Internal::add_defaults()
138 Xapian::Weight
* weighting_scheme
;
139 weighting_scheme
= new Xapian::BB2Weight
;
140 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
141 weighting_scheme
= new Xapian::BM25Weight
;
142 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
143 weighting_scheme
= new Xapian::BoolWeight
;
144 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
145 weighting_scheme
= new Xapian::TradWeight
;
146 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
147 weighting_scheme
= new Xapian::TfIdfWeight
;
148 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
149 weighting_scheme
= new Xapian::InL2Weight
;
150 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
151 weighting_scheme
= new Xapian::IfB2Weight
;
152 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
153 weighting_scheme
= new Xapian::IneB2Weight
;
154 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
155 weighting_scheme
= new Xapian::DLHWeight
;
156 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
157 weighting_scheme
= new Xapian::PL2Weight
;
158 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
159 weighting_scheme
= new Xapian::DPHWeight
;
160 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
161 weighting_scheme
= new Xapian::LMWeight
;
162 wtschemes
[weighting_scheme
->name()] = weighting_scheme
;
164 Xapian::PostingSource
* source
;
165 source
= new Xapian::ValueWeightPostingSource(0);
166 postingsources
[source
->name()] = source
;
167 source
= new Xapian::DecreasingValueWeightPostingSource(0);
168 postingsources
[source
->name()] = source
;
169 source
= new Xapian::ValueMapPostingSource(0);
170 postingsources
[source
->name()] = source
;
171 source
= new Xapian::FixedWeightPostingSource(0.0);
172 postingsources
[source
->name()] = source
;
173 source
= new Xapian::LatLongDistancePostingSource(0,
174 Xapian::LatLongCoords(),
175 Xapian::GreatCircleMetric());
176 postingsources
[source
->name()] = source
;
178 Xapian::MatchSpy
* spy
;
179 spy
= new Xapian::ValueCountMatchSpy();
180 matchspies
[spy
->name()] = spy
;
182 Xapian::LatLongMetric
* metric
;
183 metric
= new Xapian::GreatCircleMetric();
184 lat_long_metrics
[metric
->name()] = metric
;
188 Registry::Internal::clear_weighting_schemes()
190 map
<string
, Xapian::Weight
*>::const_iterator i
;
191 for (i
= wtschemes
.begin(); i
!= wtschemes
.end(); ++i
) {
197 Registry::Internal::clear_posting_sources()
199 map
<string
, Xapian::PostingSource
*>::const_iterator i
;
200 for (i
= postingsources
.begin(); i
!= postingsources
.end(); ++i
) {
206 Registry::Internal::clear_match_spies()
208 map
<string
, Xapian::MatchSpy
*>::const_iterator i
;
209 for (i
= matchspies
.begin(); i
!= matchspies
.end(); ++i
) {
215 Registry::Internal::clear_lat_long_metrics()
217 map
<string
, Xapian::LatLongMetric
*>::const_iterator i
;
218 for (i
= lat_long_metrics
.begin(); i
!= lat_long_metrics
.end(); ++i
) {
223 Registry::Registry(const Registry
& other
)
224 : internal(other
.internal
)
226 LOGCALL_CTOR(API
, "Registry", other
);
230 Registry::operator=(const Registry
& other
)
232 LOGCALL(API
, Xapian::Registry
&, "Xapian::Registry::operator=", other
);
233 internal
= other
.internal
;
238 : internal(new Registry::Internal())
240 LOGCALL_CTOR(API
, "Registry", NO_ARGS
);
243 Registry::~Registry()
245 LOGCALL_DTOR(API
, "Registry");
247 // Note - we don't need to do anything special in this destructor, but it
248 // does need to be explicitly defined because the definition of the
249 // internals is not visible externally, which results in an error if the
250 // compiler tries to generate a default destructor.
254 Registry::register_weighting_scheme(const Xapian::Weight
&wt
)
256 LOGCALL_VOID(API
, "Xapian::Registry::register_weighting_scheme", wt
.name());
257 register_object(internal
->wtschemes
, wt
);
260 const Xapian::Weight
*
261 Registry::get_weighting_scheme(const string
& name
) const
263 LOGCALL(API
, const Xapian::Weight
*, "Xapian::Registry::get_weighting_scheme", name
);
264 RETURN(lookup_object(internal
->wtschemes
, name
));
268 Registry::register_posting_source(const Xapian::PostingSource
&source
)
270 LOGCALL_VOID(API
, "Xapian::Registry::register_posting_source", source
.name());
271 register_object(internal
->postingsources
, source
);
274 const Xapian::PostingSource
*
275 Registry::get_posting_source(const string
& name
) const
277 LOGCALL(API
, const Xapian::PostingSource
*, "Xapian::Registry::get_posting_source", name
);
278 RETURN(lookup_object(internal
->postingsources
, name
));
282 Registry::register_match_spy(const Xapian::MatchSpy
&spy
)
284 LOGCALL_VOID(API
, "Xapian::Registry::register_match_spy", spy
.name());
285 register_object(internal
->matchspies
, spy
);
288 const Xapian::MatchSpy
*
289 Registry::get_match_spy(const string
& name
) const
291 LOGCALL(API
, const Xapian::MatchSpy
*, "Xapian::Registry::get_match_spy", name
);
292 RETURN(lookup_object(internal
->matchspies
, name
));
296 Registry::register_lat_long_metric(const Xapian::LatLongMetric
&metric
)
298 LOGCALL_VOID(API
, "Xapian::Registry::register_lat_long_metric", metric
.name());
299 register_object(internal
->lat_long_metrics
, metric
);
302 const Xapian::LatLongMetric
*
303 Registry::get_lat_long_metric(const string
& name
) const
305 LOGCALL(API
, const Xapian::LatLongMetric
*, "Xapian::Registry::get_lat_long_metric", name
);
306 RETURN(lookup_object(internal
->lat_long_metrics
, name
));