SpatialOps
OperatorDatabase.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2017 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  << __FILE__ ":" << __LINE__ << std::endl;
207  throw std::runtime_error( msg.str() );
208  }
209  return store->get(id);
210 }
211 
212 //--------------------------------------------------------------------
213 
214 void
216 {
217  store_.clear();
218 }
219 
220 //--------------------------------------------------------------------
221 
222 template<typename OpT>
223 OperatorDatabase::OpStore<OpT>::OpStore()
224  : idCounter_(0)
225 {}
226 
227 template<typename OpT>
228 OperatorDatabase::OpStore<OpT>::~OpStore()
229 {
230  for( typename IDOpMap::iterator i=opMap_.begin(); i!=opMap_.end(); ++i ){
231  delete i->second;
232  }
233 }
234 
235 //--------------------------------------------------------------------
236 
237 template<typename OpT>
238 int
239 OperatorDatabase::OpStore<OpT>::add( OpT* const op )
240 {
241  opMap_.insert( std::make_pair( ++idCounter_, op ) );
242  return idCounter_;
243 }
244 
245 //--------------------------------------------------------------------
246 
247 template<typename OpT>
248 OpT*
249 OperatorDatabase::OpStore<OpT>::get( const int id ) const
250 {
251  typename IDOpMap::const_iterator iop = opMap_.begin();
252  if( id==-1 ){
253  if( opMap_.size() > 1 ){
254  std::ostringstream msg;
255  msg << "ERROR! You must provide a unique identifier, since multiple operators have been registered." << std::endl
256  << " registered ids:" << std::endl;
257  for( iop=opMap_.begin(); iop!=opMap_.end(); ++iop ){
258  msg << " " << iop->first << std::endl;
259  }
260  throw std::runtime_error(msg.str());
261  }
262  }
263  else{
264  iop = opMap_.find( id );
265  }
266  if( iop == opMap_.end() ){
267  std::ostringstream msg;
268  msg << "ERROR! Attempted to retrieve an operator that does not exist." << std::endl
269  << " Operator type name: " << type_name<OpT>() << std::endl
270  << " Registered ids:" << std::endl;
271  for( iop=opMap_.begin(); iop!=opMap_.end(); ++iop ){
272  msg << " " << iop->first << std::endl;
273  }
274  throw std::runtime_error( msg.str() );
275  }
276  return iop->second;
277 }
278 
279 //--------------------------------------------------------------------
280 
281 } // Namespace SpatialOps
282 
283 #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.