C++: Add terms to ScriptDependentPriceSpecification
[smartapi.git] / Utilities / ClassGenerator.py
1 #!/usr/bin/python
2
3 import sys
4 from simplejson import loads
5 import argparse
6
7
8 class CodeGenerator(object):
9         def __init__(self):
10                 pass
11         
12         def generate(self, spec):
13                 pass
14         
15         
16 class CsGenerator(object):
17         def __init__(self):
18                 self.code = ""
19
20         def generate(self, spec):
21                 # Write class def
22                 self.code += """using System;
23 using SmartAPI.Common;
24 using SmartAPI.Rdf;
25 using System.Collections.Generic;
26
27 namespace SmartAPI.Model
28 {"""
29
30                 # Objects that do not have a type are abstact classes
31                 if not spec.has_key('type'):
32                         self.code += "\n    public abstract class %s : %s\n    {\n"%(spec['className'], spec['inherits'])
33                 # others are concrete classes
34                 else:
35                         self.code += "\n    public class %s : %s\n    {\n"%(spec['className'], spec['inherits'])
36     
37                 if spec.has_key('properties'):
38                         # Define internal vars
39                         for p in spec['properties']:
40                                 if p.has_key('listType'):
41                                         self.code += "        private %s %s = new %s;\n"%(p['listType'], p['name'], p['listType'])
42                                 else:
43                                         self.code += "        private %s %s = null;\n"%(p['className'], p['name'])
44                                         
45                         # Define the init function
46                         self.code += "\n        private void init()\n"
47                         self.code += "        {\n"
48                         for p in spec['properties']:
49                                 if p.has_key('literalType'):
50                                         self.code += "            this.initProperty<%s>(%s, this.has%s, this.get%sVar);\n"%(p['className'], p['predicate'], p['name'][0].upper()+p['name'][1:], p['name'][0].upper()+p['name'][1:])
51                                 elif p.has_key('listType'):
52                                         self.code += "            this.initPropertListy<%s,%s>(%s, this.has%s, this.get%s);\n"%(p['listType'], p['className'], p['predicate'], p['name'][0].upper()+p['name'][1:], p['name'][0].upper()+p['name'][1:])
53                                 else:
54                                         self.code += "            this.initProperty<%s>(%s, this.has%s, this.get%s);\n"%(p['className'], p['predicate'], p['name'][0].upper()+p['name'][1:], p['name'][0].upper()+p['name'][1:])
55                         self.code += "        }\n"
56                 else: # if no properties, create an empty init
57                         self.code += "\n        private void init() {}\n"
58                         
59                 # Define standard constructions
60                 typeSetter = ""
61                 
62                 if spec.has_key('type'):
63                         typeSetter = "\n            setType(%s);"%spec['type']
64                         
65                 self.code += """
66         public %s()
67         {
68             init();%s
69         }
70
71         public %s(String uri)
72         {
73             init();%s
74             this.setIdentifierUri(uri);
75         }
76         """%(spec['className'], typeSetter ,spec['className'], typeSetter)
77         
78         # Output standard serializer
79                 self.code += """
80         public override RDFNode serialize(Rdf.Model model)
81         {
82             return base.serialize(model);
83         }
84         """
85         
86                 # If properties exits, a parser is needed. Output it
87                 if spec.has_key('properties'):
88                         self.code += """
89         public override void parse(Statement statement)
90         {\n"""
91                         for p in spec['properties']:
92                                 if p.has_key('listType'):
93                                         self.code += "            if (this.parsePropertyList<%s,%s>(statement, %s, this.set%s)) return;\n"%(p['listType'], p['className'], p['predicate'], p['name'][0].upper()+p['name'][1:])  
94                                 else:
95                                         self.code += "            if (this.parseProperty<%s>(statement, %s, this.set%s)) return;\n"%(p['className'], p['predicate'], p['name'][0].upper()+p['name'][1:])        
96                         self.code += """
97             base.parse(statement);
98         }
99         """
100                         
101                         # Output getters and setters
102                         for p in spec['properties']:
103                                 self.renderGettersSetters(p)
104            
105                 # Close class def
106                 self.code += """
107     }
108 }"""
109                 return self.code
110         
111         def renderGettersSetters(self, p):
112                 name = p['name']
113                 nameCap = p['name'][0].upper()+p['name'][1:]
114                 if p.has_key('literalType'):
115                         nativeClass = p['literalType']
116                         objectClass = p['className']
117                         if nativeClass == "String":
118                                 emptyVar = '""'
119                         elif nativeClass == "bool" or nativeClass == "Boolean":
120                                 emptyVar = "false"
121                         elif nativeClass == "DateTime":
122                                 emptyVar = "null"
123                         else:
124                                 emptyVar = "0"
125                 else:
126                         nativeClass = p['className']
127                         objectClass = None
128                         emptyVar = None
129                 
130                 nativeClassCap = nativeClass[0].upper()+nativeClass[1:]
131                 nativeClassNullable = nativeClass
132                 if nativeClassNullable == "DateTime": nativeClassNullable = "Nullable<DateTime>"
133                 
134                 # Render hasfunc
135                 if p.has_key('listType'):
136                         self.code += """
137         public bool has%s()
138         {
139             return this.%s.Count > 0;
140         }
141         """%(nameCap, name)
142                 else:
143                         self.code += """
144         public bool has%s()
145         {
146             return this.%s != null;
147         }
148         """%(nameCap, name)
149                 
150                 # Render a setter for lists
151                 if p.has_key('listType'):
152                         self.code += """
153         public void set%s(%s v)
154         {
155             this.%s = v;
156         }
157         """%(nameCap, p['listType'], name)
158         # And a basic one for others
159                 elif objectClass is None:
160                         self.code += """
161         public void set%s(%s v)
162         {
163             this.%s = v;
164         }
165         """%(nameCap, nativeClass, name)
166         
167         # Render additional setters for literal vars
168                 if objectClass is not None:
169                         self.code += """
170         public void set%s(%s v)
171         {
172             this.%s = v;
173         }
174
175         public void set%s(%s v)
176         {
177             this.set%s(new %s(v));
178         }
179                 
180         public %s get%s()
181         {
182             if (this.%s != null) return this.%s.as%s();
183             return %s;
184         }
185         
186         public %s get%sVar()
187         {
188             return this.%s;
189         }
190         """%(nameCap, objectClass, name, nameCap, nativeClass, nameCap, objectClass, nativeClassNullable, nameCap, name, name, nativeClassCap, emptyVar, objectClass, nameCap, name)
191
192                 # specific getter and adder for lists
193                 elif p.has_key('listType'):
194                         self.code += """
195         public %s get%s()
196         {
197             return this.%s;
198         }
199         
200         public void addTo%s(%s v)
201         {
202             return this.%s.Add(v);
203         }
204         """%(p['listType'], nameCap, name, nameCap, nativeClass, name)
205
206                 # just a basic getter for object classes
207                 else:
208                         self.code += """
209         public %s get%s()
210         {
211             return this.%s;
212         }
213                         """%(nativeClass, nameCap, name)
214
215         
216
217 class CppGenerator(object):
218         def __init__(self):
219                 pass
220
221
222 class JavaGenerator(object):
223         def __init__(self):
224                 pass
225
226
227 class PythonGenerator(object):
228         def __init__(self):
229                 pass
230
231         
232 class ClassGenerator(object):
233         def __init__(self, language, input_files):
234                 self.language = language
235                 self.inputs = input_files
236         
237         def run(self):
238                 generator = None
239                 if self.language == "cs":
240                         generator = CsGenerator()
241                 elif self.language == "cpp":
242                         generator = CppGenerator()
243                 elif self.language == "java":
244                         generator = JavaGenerator()
245                 elif self.language == "python":
246                         generator = PythonGenerator()
247                 
248                 if generator is not None:
249                         for input_file in self.inputs:
250                                 f = open(input_file, 'r')
251                                 spec = loads(f.read())
252                                 output = generator.generate(spec)
253                                 print output
254
255
256 def main():
257         print "\n==============================================================="
258         print "Class generator for Smart API objects"
259         print "==============================================================="
260         print
261         
262         parser = argparse.ArgumentParser(description='Subscribe to data from a gateway and listen to it over HTTP.')
263         parser.add_argument('--lang', dest='lang', type=str,
264                                         help='Target language { cpp, cs, java, python }')
265         parser.add_argument('--input', dest='inputFile', default=None, nargs="+",
266                                         help='The spec files of objects')
267         
268         args = parser.parse_args()
269         if args.lang is not None and  args.inputFile is not None:
270                 generator = ClassGenerator(args.lang, args.inputFile)
271                 generator.run()
272         else:
273                 parser.print_help()
274                 sys.exit()
275                 
276         
277 if __name__=='__main__':
278     main()