1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef T_GENERATOR_REGISTRY_H
21 #define T_GENERATOR_REGISTRY_H
22 
23 class t_generator;
24 
25 /**
26  * A factory for producing generator classes of a particular language.
27  *
28  * This class is also responsible for:
29  *  - Registering itself with the generator registry.
30  *  - Providing documentation for the generators it produces.
31  */
32 class t_generator_factory {
33 public:
34   t_generator_factory(const std::string& short_name,
35                       const std::string& long_name,
36                       const std::string& documentation);
37 
38   virtual ~t_generator_factory() = default;
39 
40   virtual t_generator* get_generator(
41       // The program to generate.
42       t_program* program,
43       // Note: parsed_options will not exist beyond the call to get_generator.
44       const std::map<std::string, std::string>& parsed_options,
45       // Note: option_string might not exist beyond the call to get_generator.
46       const std::string& option_string) = 0;
47 
48   virtual bool is_valid_namespace(const std::string& sub_namespace) = 0;
49 
get_short_name()50   std::string get_short_name() { return short_name_; }
get_long_name()51   std::string get_long_name() { return long_name_; }
get_documentation()52   std::string get_documentation() { return documentation_; }
53 
54 private:
55   std::string short_name_;
56   std::string long_name_;
57   std::string documentation_;
58 };
59 
60 template <typename generator>
61 class t_generator_factory_impl : public t_generator_factory {
62 public:
t_generator_factory_impl(const std::string & short_name,const std::string & long_name,const std::string & documentation)63   t_generator_factory_impl(const std::string& short_name,
64                            const std::string& long_name,
65                            const std::string& documentation)
66     : t_generator_factory(short_name, long_name, documentation) {}
67 
get_generator(t_program * program,const std::map<std::string,std::string> & parsed_options,const std::string & option_string)68   t_generator* get_generator(t_program* program,
69                                      const std::map<std::string, std::string>& parsed_options,
70                                      const std::string& option_string) override {
71     return new generator(program, parsed_options, option_string);
72   }
73 
is_valid_namespace(const std::string & sub_namespace)74   bool is_valid_namespace(const std::string& sub_namespace) override {
75     return generator::is_valid_namespace(sub_namespace);
76   }
77 };
78 
79 class t_generator_registry {
80 public:
81   static void register_generator(t_generator_factory* factory);
82 
83   static t_generator* get_generator(t_program* program, const std::string& options);
84   static t_generator* get_generator(t_program* program,
85                                     const std::string& laugnage,
86                                     const std::map<std::string, std::string>& parsed_options,
87                                     const std::string& options);
88 
89   typedef std::map<std::string, t_generator_factory*> gen_map_t;
90   static gen_map_t& get_generator_map();
91 
92 private:
93   t_generator_registry();
94   t_generator_registry(const t_generator_registry&);
95 };
96 
97 #define THRIFT_REGISTER_GENERATOR(language, long_name, doc)                                        \
98   class t_##language##_generator_factory_impl                                                      \
99       : public t_generator_factory_impl<t_##language##_generator> {                                \
100   public:                                                                                          \
101     t_##language##_generator_factory_impl()                                                        \
102       : t_generator_factory_impl<t_##language##_generator>(#language, long_name, doc) {}           \
103   };                                                                                               \
104   static t_##language##_generator_factory_impl _registerer;
105 
106 #endif
107