Reranker Framework (ReFr)
Reranking framework for structure prediction and discriminative language modeling
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
factory.H
Go to the documentation of this file.
1 // Copyright 2012, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // -----------------------------------------------------------------------------
30 //
31 //
35 
36 #ifndef RERANKER_FACTORY_H_
37 #define RERANKER_FACTORY_H_
38 
39 #include <iostream>
40 #include <sstream>
41 #include <memory>
42 #include <unordered_map>
43 #include <unordered_set>
44 #include <vector>
45 #include <stdexcept>
46 
47 #include "stream-tokenizer.H"
48 #include "environment.H"
49 
50 namespace reranker {
51 
52 using std::cerr;
53 using std::endl;
54 using std::ostream;
55 using std::ostringstream;
56 using std::shared_ptr;
57 using std::unordered_map;
58 using std::unordered_set;
59 using std::vector;
60 
76 template <typename T>
77 class TypeName {
78  public:
79  string ToString() {
80  return Factory<T>().BaseName();
81  }
82 };
83 
86 template <>
87 class TypeName<bool> {
88  public:
89  string ToString() {
90  return "bool";
91  }
92 };
93 
96 template <>
97 class TypeName<int> {
98  public:
99  string ToString() {
100  return "int";
101  }
102 };
103 
106 template <>
107 class TypeName<double> {
108  public:
109  string ToString() {
110  return "double";
111  }
112 };
113 
116 template <>
117 class TypeName<string> {
118  public:
119  string ToString() {
120  return "string";
121  }
122 };
123 
128 template <typename T>
129 class TypeName<shared_ptr<T> > {
130  public:
131  string ToString() {
132  return TypeName<T>().ToString();
133  }
134 };
135 
143 template <typename T>
144 class TypeName<vector<T> > {
145  public:
146  string ToString() {
147  return TypeName<T>().ToString() + "[]";
148  }
149 };
150 
156  public:
157  MemberInitializer(const string &name, bool required) :
158  name_(name), initialized_(0), required_(required) { }
159  virtual ~MemberInitializer() { }
160  virtual string Name() { return name_; }
161  virtual void Init(StreamTokenizer &st, Environment *env) = 0;
164  virtual int Initialized() const { return initialized_; }
165  virtual bool Required() const { return required_; }
166  protected:
168  string name_;
173  bool required_;
174 };
175 
176 template <typename T>
178  public:
179  TypedMemberInitializer(const string &name, T *member, bool required = false) :
180  MemberInitializer(name, required), member_(member) { }
182  virtual void Init(StreamTokenizer &st, Environment *env) {
183  env->ReadAndSet(Name(), st, TypeName<T>().ToString());
184  VarMapBase *var_map = env->GetVarMap(Name());
185  VarMap<T> *typed_var_map = dynamic_cast<VarMap<T> *>(var_map);
186  if (typed_var_map != NULL) {
187  bool success = typed_var_map->Get(Name(), member_);
188  if (success) {
189  ++(initialized_);
190  }
191  }
192  }
193  protected:
195 };
196 
204  public:
207  typedef unordered_map<string, MemberInitializer *>::const_iterator
211  typedef unordered_map<string, MemberInitializer *>::iterator iterator;
212 
216  virtual ~Initializers() {
217  for (iterator init_it = initializers_.begin();
218  init_it != initializers_.end();
219  ++init_it) {
220  delete init_it->second;
221  }
222  }
223 
224  template<typename T>
225  void Add(const string &name, T *member, bool required = false) {
226  initializers_[name] = new TypedMemberInitializer<T>(name, member, required);
227  }
228 
232  const_iterator begin() const { return initializers_.begin(); }
237  const_iterator end() const { return initializers_.end(); }
238 
243  iterator begin() { return initializers_.begin(); }
247  iterator end() { return initializers_.end(); }
248 
254  const_iterator find(const string &name) const {
255  return initializers_.find(name);
256  }
262  iterator find(const string &name) {
263  return initializers_.find(name);
264  }
265  private:
266  unordered_map<string, MemberInitializer *> initializers_;
267 };
268 
271 class FactoryBase {
272  public:
273  virtual ~FactoryBase() { }
279  virtual void Clear() = 0;
281  virtual const string BaseName() const = 0;
288  virtual void CollectRegistered(unordered_set<string> &registered) const = 0;
289 
290  virtual VarMapBase *CreateVarMap(Environment *env) const = 0;
291 
292  virtual VarMapBase *CreateVectorVarMap(Environment *env) const = 0;
293 };
294 
297  public:
298  typedef vector<FactoryBase *>::iterator iterator;
299 
303  static void Add(FactoryBase *factory) {
304  if (!initialized_) {
305  factories_ = new vector<FactoryBase *>();
306  initialized_ = 1;
307  }
308  factories_->push_back(factory);
309  }
311  static void Clear() {
312  if (initialized_) {
313  for (vector<FactoryBase *>::iterator it = factories_->begin();
314  it != factories_->end();
315  ++it) {
316  (*it)->Clear();
317  delete *it;
318  }
319  delete factories_;
320  }
321  }
322 
323  // Provide two methods to iterate over the FactoryBase instances
324  // held by this FactoryContainer.
325  static iterator begin() {
326  if (factories_ == NULL) {
327  cerr << "FactoryContainer::begin: error: no FactoryBase instances!"
328  << endl;
329  }
330  return factories_->begin();
331  }
332  static iterator end() {
333  if (factories_ == NULL) {
334  cerr << "FactoryContainer::begin: error: no FactoryBase instances!"
335  << endl;
336  }
337  return factories_->end();
338  }
339 
343  static void Print(ostream &os) {
344  if (!initialized_) {
345  return;
346  }
347  cerr << "Number of factories: " << factories_->size() << "." << endl;
348  for (vector<FactoryBase *>::iterator factory_it = factories_->begin();
349  factory_it != factories_->end();
350  ++factory_it) {
351  unordered_set<string> registered;
352  (*factory_it)->CollectRegistered(registered);
353  os << "Factory<" << (*factory_it)->BaseName() << "> can construct:\n";
354  for (unordered_set<string>::const_iterator it = registered.begin();
355  it != registered.end();
356  ++it) {
357  os << "\t" << *it << "\n";
358  }
359  }
360  os.flush();
361  }
362  private:
363  static int initialized_;
364  static vector<FactoryBase *> *factories_;
365 };
366 
372 // \tparam T the abstract type that this <tt>Constructor</tt> constructs
373 template <typename T>
374 class Constructor {
375  public:
376  virtual ~Constructor() { }
377  virtual T *NewInstance() const = 0;
378 };
379 
383  public:
384  virtual ~FactoryConstructible() { }
385  virtual void RegisterInitializers(Initializers &initializers) { }
386  virtual void Init(const Environment *env, const string &arg) { }
387 };
388 
395 template <typename T>
396 class Factory : public FactoryBase {
397  public:
399  Factory() { }
400 
406  virtual void Clear() {
407  ClearStatic();
408  }
409 
562  shared_ptr<T> CreateOrDie(StreamTokenizer &st, Environment *env = NULL) {
563  shared_ptr<Environment> env_ptr(env == NULL ?
564  Environment::CreateEmpty() : env->Copy());
565  size_t start = st.PeekTokenStart();
566  StreamTokenizer::TokenType token_type = st.PeekTokenType();
567  if (token_type == StreamTokenizer::RESERVED_WORD &&
568  (st.Peek() == "nullptr" || st.Peek() == "NULL")) {
569  return shared_ptr<T>();
570  }
571  if (token_type != StreamTokenizer::IDENTIFIER) {
572  ostringstream err_ss;
573  err_ss << "Factory<" << BaseName() << ">: "
574  << "error: expected type specifier token but found "
575  << StreamTokenizer::TypeName(token_type);
576  throw std::runtime_error(err_ss.str());
577  }
578 
579  // Read the concrete type of object to be created.
580  string type = st.Next();
581 
582  // Read the open parenthesis token.
583  if (st.Peek() != "(") {
584  ostringstream err_ss;
585  err_ss << "Factory<" << BaseName() << ">: "
586  << "error: expected '(' at stream position "
587  << st.PeekTokenStart() << " but found \"" << st.Peek() << "\"";
588  throw std::runtime_error(err_ss.str());
589  }
590  st.Next();
591 
592  // Attempt to create an instance of type.
593  typename unordered_map<string, const Constructor<T> *>::iterator cons_it =
594  cons_table_->find(type);
595  if (cons_it == cons_table_->end()) {
596  ostringstream err_ss;
597  err_ss << "Factory<" << BaseName() << ">: "
598  << "error: unknown type: \"" << type << "\"";
599  throw std::runtime_error(err_ss.str());
600  }
601  shared_ptr<T> instance(cons_it->second->NewInstance());
602 
603  // Ask new instance to set up member initializers.
604  Initializers initializers;
605  instance->RegisterInitializers(initializers);
606 
607  // Parse initializer list.
608  while (st.Peek() != ")") {
609  token_type = st.PeekTokenType();
610  if (token_type != StreamTokenizer::IDENTIFIER) {
611  ostringstream err_ss;
612  err_ss << "Factory<" << BaseName() << ">: "
613  << "error: expected token of type IDENTIFIER at "
614  << "stream position " << st.PeekTokenStart() << " but found "
615  << StreamTokenizer::TypeName(token_type) << ": \""
616  << st.Peek() << "\"";
617  throw std::runtime_error(err_ss.str());
618  }
619  size_t member_name_start = st.PeekTokenStart();
620  string member_name = st.Next();
621  typename Initializers::iterator init_it = initializers.find(member_name);
622  if (init_it == initializers.end()) {
623  ostringstream err_ss;
624  err_ss << "Factory<" << BaseName() << ">: "
625  << "error: unknown member name \"" << member_name
626  << "\" in initializer list for type " << type << " at stream "
627  << "position " << member_name_start;
628  throw std::runtime_error(err_ss.str());
629  }
630  MemberInitializer *member_initializer = init_it->second;
631 
632  // Read open parenthesis.
633  if (st.Peek() != "(") {
634  ostringstream err_ss;
635  err_ss << "Factory<" << BaseName() << ">: "
636  << "error: expected '(' at stream position "
637  << st.PeekTokenStart() << " but found \"" << st.Peek() << "\"";
638  throw std::runtime_error(err_ss.str());
639  }
640  st.Next();
641 
642  // Initialize member based on following token(s).
643  member_initializer->Init(st, env_ptr.get());
644 
645  // Read close parenthesis for current member initializer.
646  if (st.Peek() != ")") {
647  ostringstream err_ss;
648  err_ss << "Factory<" << BaseName() << ">: "
649  << "error: expected ')' at stream position "
650  << st.PeekTokenStart() << " but found \"" << st.Peek() << "\"";
651  throw std::runtime_error(err_ss.str());
652  }
653  st.Next();
654 
655  // Each member initializer must be followed by a comma or the final
656  // closing parenthesis.
657  if (st.Peek() != "," && st.Peek() != ")") {
658  ostringstream err_ss;
659  err_ss << "Factory<" << BaseName() << ">: "
660  << "error: expected ',' or ')' at stream position "
661  << st.PeekTokenStart() << " but found \"" << st.Peek() << "\"";
662  throw std::runtime_error(err_ss.str());
663  }
664  // Read comma, if present.
665  if (st.Peek() == ",") {
666  st.Next();
667  }
668  }
669 
670  // Read the close parenthesis token for this factory type specification.
671  if (st.Peek() != ")") {
672  ostringstream err_ss;
673  err_ss << "Factory<" << BaseName() << ">: "
674  << "error: expected ')' at stream position "
675  << st.PeekTokenStart() << " but found \"" << st.Peek() << "\"";
676  throw std::runtime_error(err_ss.str());
677  }
678  st.Next();
679 
680  // Run through all member initializers: if any are required but haven't
681  // been invoked, it is an error.
682  for (typename Initializers::const_iterator init_it = initializers.begin();
683  init_it != initializers.end();
684  ++init_it) {
685  MemberInitializer *member_initializer = init_it->second;
686  if (member_initializer->Required() &&
687  member_initializer->Initialized() == 0) {
688  ostringstream err_ss;
689  err_ss << "Factory<" << BaseName() << ">: "
690  << "error: initialization for member with name \""
691  << init_it->first << "\" required but not found (current "
692  << "stream position: " << st.tellg() << ")";
693  throw std::runtime_error(err_ss.str());
694  }
695  }
696 
697  size_t end = st.tellg();
698  // Invoke new instance's Init method.
699  string stream_str = st.str();
700  //cerr << "Full stream string is: \"" << stream_str << "\"" << endl;
701  string init_str = stream_str.substr(start, end - start);
702  //cerr << "Init string is: \"" << init_str << "\"" << endl;
703  instance->Init(env_ptr.get(), init_str);
704 
705  return instance;
706  }
707 
708  shared_ptr<T> CreateOrDie(const string &spec, const string err_msg,
709  Environment *env = NULL) {
710  StreamTokenizer st(spec);
711  return CreateOrDie(st, env);
712  }
713 
714 
716  virtual const string BaseName() const { return base_name_; }
717 
725  static bool IsRegistered(const string &type) {
726  return initialized_ && cons_table_->find(type) != cons_table_->end();
727  }
728 
730  virtual void CollectRegistered(unordered_set<string> &registered) const {
731  if (initialized_) {
732  for (typename unordered_map<string, const Constructor<T> *>::iterator it =
733  cons_table_->begin();
734  it != cons_table_->end();
735  ++it) {
736  registered.insert(it->first);
737  }
738  }
739  }
740 
741  virtual VarMapBase *CreateVarMap(Environment *env) const {
742  bool is_primitive = false;
743  return new VarMap<shared_ptr<T> >(BaseName(), env, is_primitive);
744  }
745 
747  string name = BaseName() + "[]";
748  bool is_primitive = false;
749  return new VarMap<vector<shared_ptr<T> > >(name, env, is_primitive);
750  }
751 
757  static const Constructor<T> *Register(const string &type,
758  const Constructor<T> *p) {
759  if (!initialized_) {
760  cons_table_ = new unordered_map<string, const Constructor<T> *>();
761  initialized_ = 1;
763  }
764  (*cons_table_)[type] = p;
765  return p;
766  }
767 
773  static void ClearStatic() {
774  if (initialized_) {
775  for (typename unordered_map<string, const Constructor<T> *>::iterator it =
776  cons_table_->begin();
777  it != cons_table_->end();
778  ++it) {
779  delete it->second;
780  }
781  delete cons_table_;
782  initialized_ = 0;
783  }
784  }
785  private:
786  // data members
788  static int initialized_;
790  static unordered_map<string, const Constructor<T> *> *cons_table_;
791  static const char *base_name_;
792 };
793 
800 #define DEFINE_CONS_CLASS(TYPE,NAME,BASE) \
801  class NAME ## Constructor : public Constructor<BASE> { \
802  public: virtual BASE *NewInstance() const { return new TYPE(); } };
803 
814 #define REGISTER_NAMED(TYPE,NAME,BASE) \
815  DEFINE_CONS_CLASS(TYPE,NAME,BASE) \
816  const Constructor<BASE> *NAME ## _my_protoype = \
817  Factory<BASE>::Register(string(#NAME), new NAME ## Constructor());
818 
821 #define IMPLEMENT_FACTORY(BASE) \
822  template<> int Factory<BASE>::initialized_ = 0; \
823  template<> unordered_map<string, const Constructor<BASE> *> * \
824  Factory<BASE>::cons_table_ = 0; \
825  template<> const char *Factory<BASE>::base_name_ = #BASE;
826 
827 } // namespace reranker
828 
829 #endif
virtual VarMapBase * CreateVectorVarMap(Environment *env) const =0
virtual Environment * Copy() const =0
Returns a copy of this environment.
A container to hold the mapping between named variables of a specific type and their values...
Definition: environment.H:256
static iterator begin()
Definition: factory.H:325
unordered_map< string, MemberInitializer * >::const_iterator const_iterator
Forward the const_iterator typedef of the internal data structure, to make code compact and readable...
Definition: factory.H:208
static void Add(FactoryBase *factory)
Adds the specified factory to this container of factories.
Definition: factory.H:303
string name_
The name of this member.
Definition: factory.H:168
iterator end()
Returns an iterator pointing to the end of the map from member names to pointers to TypedMemberInitia...
Definition: factory.H:247
virtual VarMapBase * CreateVarMap(Environment *env) const
Definition: factory.H:741
A simple class for tokenizing a stream of tokens for the formally specified language used to construc...
Initializers()
Constructs a new instance.
Definition: factory.H:214
string ToString()
Definition: factory.H:79
int initialized_
The number of times this member initializer’s Init method has been invoked.
Definition: factory.H:171
bool Get(const string &varname, T *value) const
Assigns the value of the specified variable to the object pointed to by the value parameter...
Definition: environment.H:277
string str()
Returns the entire sequence of characters read so far by this stream tokenizer as a newly constructed...
An interface for initializers of members of a Factory-constructible object.
Definition: factory.H:155
virtual void Clear()
Clears this factory of all (possibly static) data.
Definition: factory.H:406
virtual T * NewInstance() const =0
virtual bool Required() const
Definition: factory.H:165
bool required_
Whether this member is required to be initialized.
Definition: factory.H:173
A base class for a mapping from variables of a specific type to their values.
Definition: environment.H:65
virtual void CollectRegistered(unordered_set< string > &registered) const
Collects the names of types registered with this factory.
Definition: factory.H:730
virtual const string BaseName() const =0
Returns the name of the base type of objects constructed by this factory.
size_t PeekTokenStart() const
Returns the next token’s start position, or the byte position of the underlying byte stream if there ...
virtual ~Constructor()
Definition: factory.H:376
virtual void Clear()=0
Clears the (possibly static) data of this factory.
virtual void Init(StreamTokenizer &st, Environment *env)
Definition: factory.H:182
Factory()
Constructs a new factory.
Definition: factory.H:399
Provides an interface for an Environment, which contains a map from variables of a specific type (pri...
A class to hold all Factory instances that have been created.
Definition: factory.H:296
static const char * TypeName(TokenType token_type)
Returns a string type name for the specified TokenType constant.
void Add(const string &name, T *member, bool required=false)
Definition: factory.H:225
static bool IsRegistered(const string &type)
Returns whether the specified type has been registered with this factory (where registration happens ...
Definition: factory.H:725
Factory for dynamically created instance of the specified type.
Definition: factory.H:396
static const Constructor< T > * Register(const string &type, const Constructor< T > *p)
The method used by the REGISTER_NAMED macro to ensure that subclasses add themselves to the factory...
Definition: factory.H:757
Provides the StreamTokenizer class.
static void Print(ostream &os)
Prints the base typenames for all factories along with a list of all concrete subtypes those factorie...
Definition: factory.H:343
string Next()
Returns the next token in the token stream.
const_iterator end() const
Returns a const iterator pointing to the end of the map from member names to pointers to TypedMemberI...
Definition: factory.H:237
virtual void Init(StreamTokenizer &st, Environment *env)=0
size_t tellg() const
Returns the number of bytes read from the underlying byte stream just after scanning the most recent ...
virtual VarMapBase * CreateVarMap(Environment *env) const =0
virtual void ReadAndSet(const string &varname, StreamTokenizer &st, const string type="")=0
Sets the specified variable to the value obtained from the following tokens available from the specif...
We use the templated class TypeName to be able to take an actual C++ type and get the type name strin...
Definition: factory.H:77
unordered_map< string, MemberInitializer * >::iterator iterator
Forward the iterator typedef of the internal data structure, to make code compact and readable...
Definition: factory.H:211
virtual const string BaseName() const
Returns the name of the base type of objects constructed by this factory.
Definition: factory.H:716
TypedMemberInitializer(const string &name, T *member, bool required=false)
Definition: factory.H:179
virtual ~FactoryBase()
Definition: factory.H:273
shared_ptr< T > CreateOrDie(StreamTokenizer &st, Environment *env=NULL)
Dynamically creates an object, whose type and initialization are contained in a specification string...
Definition: factory.H:562
An interface with a single virtual method that constructs a concrete instance of the abstract type T...
Definition: factory.H:374
An interface for an environment in which variables of various types are mapped to their values...
Definition: environment.H:125
virtual void RegisterInitializers(Initializers &initializers)
Definition: factory.H:385
shared_ptr< T > CreateOrDie(const string &spec, const string err_msg, Environment *env=NULL)
Definition: factory.H:708
static iterator end()
Definition: factory.H:332
virtual void Init(const Environment *env, const string &arg)
Definition: factory.H:386
vector< FactoryBase * >::iterator iterator
Definition: factory.H:298
MemberInitializer(const string &name, bool required)
Definition: factory.H:157
const_iterator find(const string &name) const
Returns a const_iterator pointing to the MemberInitializer associated with the specified name...
Definition: factory.H:254
virtual void CollectRegistered(unordered_set< string > &registered) const =0
Collects the names of types registered with this factory.
virtual ~Initializers()
Destroys this instance.
Definition: factory.H:216
An interface for all Factory instances, specifying a few pure virtual methods.
Definition: factory.H:271
TokenType
The set of types of tokens read by this stream tokenizer.
string Peek() const
Returns the next token that would be returned by the Next method.
An interface to make it easier to implement Factory-constructible types by implementing both required...
Definition: factory.H:382
virtual VarMapBase * CreateVectorVarMap(Environment *env) const
Definition: factory.H:746
static void ClearStatic()
Clears all static data associated with this class.
Definition: factory.H:773
static Environment * CreateEmpty()
A static factory method to create a new, empty Environment instance.
Definition: environment.C:43
virtual ~MemberInitializer()
Definition: factory.H:159
virtual int Initialized() const
Returns the number of times this member initializer’s Init method has been invoked.
Definition: factory.H:164
virtual string Name()
Definition: factory.H:160
static void Clear()
Clears this container of factories.
Definition: factory.H:311
virtual VarMapBase * GetVarMap(const string &varname)=0
Retrieves the VarMap instance for the specified variable.
iterator begin()
Returns an iterator pointing to the beginning of the map from member names to pointers to TypedMember...
Definition: factory.H:243
iterator find(const string &name)
Returns an iterator pointing to the MemberInitializer associated with the specified name...
Definition: factory.H:262
const_iterator begin() const
Returns a const iterator pointing to the beginning of the map from member names to pointers to TypedM...
Definition: factory.H:232
A container for all the member initializers for a particular Factory-constructible instance...
Definition: factory.H:203
TokenType PeekTokenType() const
Returns the type of the next token, or EOF_TYPE if there is no next token.