SpatialOps
OperatorDatabase.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 The University of Utah
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 
28 #ifndef SpatialOpDatabase_h
29 #define SpatialOpDatabase_h
30 
31 #include <spatialops/SpatialOpsConfigure.h>
32 #include <spatialops/Nebo.h>
33 #include "util/TypeName.h"
34 
35 #include <boost/any.hpp>
36 #include <boost/shared_ptr.hpp>
37 
38 #include <map>
39 #include <typeinfo>
40 #include <stdexcept>
41 #include <sstream>
42 
43 namespace SpatialOps{
44 
59 {
60 
61  template<typename OpT> class OpStore
62  {
63  typedef std::map<int,OpT*> IDOpMap;
64  IDOpMap opMap_;
65  int idCounter_;
66  public:
67  OpStore();
68  ~OpStore();
69  int add( OpT* const op );
70  OpT* get( const int id=-1 ) const;
71  }; // class OpStore
72 
73  typedef std::map< const std::type_info*, boost::any > Store;
74  Store store_;
75 
76  template<typename OpT>
77  OpStore<OpT>* find() const;
78 
79 public:
80 
82  ~OperatorDatabase(){}
83 
91  template<typename OpT>
92  int register_new_operator( OpT* const op );
93 
94  template<typename OpT>
95  int register_new_operator( typename OpT::Assembler assembler );
96 
107  template<typename OpT>
109 
118  template<typename OpT>
119  inline OpT* retrieve_operator( const int id=-1 ) const;
120 
124  inline void empty_database();
125 
126 }; // class OperatorDatabase
127 
128 
129 //====================================================================
130 
131 
132 
133 
134 
135 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 //
137 // Implementation
138 //
139 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 
141 
142 
143 
144 
145 //====================================================================
146 
147 
148 template<typename OpT>
149 typename OperatorDatabase::OpStore<OpT>*
150 OperatorDatabase::find() const
151 {
152  typedef boost::shared_ptr< OpStore<OpT> > PtrT;
153  const std::type_info& info = typeid(OpT);
154  const Store::const_iterator istor = store_.find( &info );
155  if( istor == store_.end() ) return NULL;
156  return boost::any_cast<PtrT>(istor->second).get();
157 }
158 
159 //--------------------------------------------------------------------
160 
161 template<typename OpT>
162 int
164 {
165  // see if we have a store built for this yet.
166  OpStore<OpT>* store = this->find<OpT>();
167  if( store==NULL ){
168  typedef boost::shared_ptr< OpStore<OpT> > PtrT;
169  store = new OpStore<OpT>();
170  const std::type_info& info = typeid(OpT);
171  store_.insert( make_pair( &info, PtrT( store ) ) );
172  }
173  // add the operator
174  return store->add(op);
175 }
176 
177 //--------------------------------------------------------------------
178 
179 template<typename OpT>
180 int
181 OperatorDatabase::register_new_operator( typename OpT::Assembler assembler )
182 {
183  return register_new_operator( new OpT(assembler) );
184 }
185 
186 //--------------------------------------------------------------------
187 
188 template<typename OpT>
189 int
191 {
192  return register_new_operator( new NeboBoundaryConditionBuilder<OpT>( *retrieve_operator<OpT>() ) );
193 }
194 
195 //--------------------------------------------------------------------
196 
197 template<typename OpT>
198 OpT*
200 {
201  const OpStore<OpT>* const store = this->find<OpT>();
202  if( store==NULL ){
203  std::ostringstream msg;
204  msg << "ERROR! Attempted to retrieve an operator that does not exist." << std::endl
205  << " Operator type name: " << type_name<OpT>() << std::endl;
206  throw std::runtime_error( msg.str() );
207  }
208  return store->get(id);
209 }
210 
211 //--------------------------------------------------------------------
212 
213 void
215 {
216  store_.clear();
217 }
218 
219 //--------------------------------------------------------------------
220 
221 template<typename OpT>
222 OperatorDatabase::OpStore<OpT>::OpStore()
223  : idCounter_(0)
224 {}
225 
226 template<typename OpT>
227 OperatorDatabase::OpStore<OpT>::~OpStore()
228 {
229  for( typename IDOpMap::iterator i=opMap_.begin(); i!=opMap_.end(); ++i ){
230  delete i->second;
231  }
232 }
233 
234 //--------------------------------------------------------------------
235 
236 template<typename OpT>
237 int
238 OperatorDatabase::OpStore<OpT>::add( OpT* const op )
239 {
240  opMap_.insert( std::make_pair( ++idCounter_, op ) );
241  return idCounter_;
242 }
243 
244 //--------------------------------------------------------------------
245 
246 template<typename OpT>
247 OpT*
248 OperatorDatabase::OpStore<OpT>::get( const int id ) const
249 {
250  typename IDOpMap::const_iterator iop = opMap_.begin();
251  if( id==-1 ){
252  if( opMap_.size() > 1 ){
253  std::ostringstream msg;
254  msg << "ERROR! You must provide a unique identifier, since multiple operators have been registered." << std::endl
255  << " registered ids:" << std::endl;
256  for( iop=opMap_.begin(); iop!=opMap_.end(); ++iop ){
257  msg << " " << iop->first << std::endl;
258  }
259  throw std::runtime_error(msg.str());
260  }
261  }
262  else{
263  iop = opMap_.find( id );
264  }
265  if( iop == opMap_.end() ){
266  std::ostringstream msg;
267  msg << "ERROR! Attempted to retrieve an operator that does not exist." << std::endl
268  << " Operator type name: " << type_name<OpT>() << std::endl
269  << " Registered ids:" << std::endl;
270  for( iop=opMap_.begin(); iop!=opMap_.end(); ++iop ){
271  msg << " " << iop->first << std::endl;
272  }
273  throw std::runtime_error( msg.str() );
274  }
275  return iop->second;
276 }
277 
278 //--------------------------------------------------------------------
279 
280 } // Namespace SpatialOps
281 
282 #endif
void empty_database()
Remove all operators of all types.
OpT * retrieve_operator(const int id=-1) const
Retrieve an operator of the requested type.
int register_new_operator(OpT *const op)
Register a new operator of the given type.
Supports definition of new Nebo boundary condition.
Provides a database to hold operators of any type.