Class: CrailsDataGenerator

Inherits:
GeneratorBase show all
Defined in:
lib/metarecord/generators/crails/data_generator.rb

Direct Known Subclasses

CometDataGenerator

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from GeneratorBase

_use_by_files, _use_by_models, #get_classname, #get_pluralized_name, #get_singular_name, #get_type, #get_value, #id_type, #indent, is_file_based?, #make_block, #null_id, prepare, #ptr_type, #should_generate_for, #should_generate_from_manifest, #should_skip_on_client?, sourcefile_to_destfile, #unindent, use

Instance Attribute Details

#forward_declarationsObject

Returns the value of attribute forward_declarations.



5
6
7
# File 'lib/metarecord/generators/crails/data_generator.rb', line 5

def forward_declarations
  @forward_declarations
end

Class Method Details

.extensionObject



260
# File 'lib/metarecord/generators/crails/data_generator.rb', line 260

def extension ; ".hpp" ; end

.generate_includesObject



262
263
264
265
266
267
268
269
270
271
# File 'lib/metarecord/generators/crails/data_generator.rb', line 262

def generate_includes
<<CPP
# include <vector>
# include <list>
# include <map>
# include <string>
# include <crails/datatree.hpp>
# include <crails/odb/id_type.hpp>
CPP
end

.make_file(filename, data) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/metarecord/generators/crails/data_generator.rb', line 273

def make_file filename, data
  file_define = "_#{filename[0...-3].upcase.gsub "/", "_"}_HPP"
  source = <<CPP
#ifndef  #{file_define}
# define #{file_define}
#{generate_includes}
#{collect_includes_for(filename, true).join "\n"}
namespace odb { class access; }
#{data[:headers].join ""}
namespace #{METARECORD_NAMESPACE}
{
#{data[:bodies].join "\n"}}

#endif
CPP
end

Instance Method Details

#_append(str, opts = {}) ⇒ Object



13
14
15
16
17
# File 'lib/metarecord/generators/crails/data_generator.rb', line 13

def _append str, opts = {}
  @src[@current_visibility] ||= ""
  @src[@current_visibility] += " " * (@indent * @tab_size)
  @src[@current_visibility] += str + "\n" unless opts[:no_line_return]
end

#_append_macro(str) ⇒ Object



19
20
21
22
# File 'lib/metarecord/generators/crails/data_generator.rb', line 19

def _append_macro str
  @src[@current_visibility] ||= ""
  @src[@current_visibility] += str + "\n"
end

#_id_based_has_many(list_type, name, options) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/metarecord/generators/crails/data_generator.rb', line 240

def _id_based_has_many list_type, name, options
  singular_name = get_singular_name name
  store_type = "std::vector<#{id_type}>"
  with_visibility :public do
    _append "const #{store_type}& get_#{singular_name}_ids() const { return #{singular_name}_ids; }"
    _append "const #{list_type}& get_#{name}();"
    _append "void set_#{singular_name}_ids(const #{store_type}& val) { #{singular_name}_ids = val; #{name}_fetched = false; }"
  end
  has_many_fetch list_type, name, options
  options[:db]        ||= {}
  options[:db][:type] ||= "INTEGER[]"
  make_pragma_db options[:db], [:type, :column, :null]
  _append "#{store_type} #{singular_name}_ids;"
  make_pragma_db transient: true
  _append "#{list_type} #{name};"
  make_pragma_db transient: true
  _append "bool #{name}_fetched = false;"
end

#_join_based_has_many(list_type, name, options) ⇒ Object



225
226
227
228
229
230
231
232
# File 'lib/metarecord/generators/crails/data_generator.rb', line 225

def _join_based_has_many list_type, name, options
  singular_name = get_singular_name name
  with_visibility :public do
    _append "const #{list_type}& get_#{name}() const { return #{name}; }"
    _append "std::vector<#{id_type}> get_#{singular_name}_ids() const;"
  end
  _append "#{list_type} #{name};"
end

#datatree_property(name, options) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/metarecord/generators/crails/data_generator.rb', line 126

def datatree_property name, options
  with_visibility :public do
    virt = if options[:allow_override] == true then "virtual " else "" end
    _append "#{virt}DataTree& get_#{name}() { return #{name}; }"
    _append "#{virt}const DataTree& get_#{name}() const { return #{name}; }"
    _append "#{virt}void set_#{name}(Data value) { this->#{name}.clear(); this->#{name}.as_data().merge(value); }"
  end
end

#edit_resource_declarationObject



70
71
72
73
74
75
76
77
78
# File 'lib/metarecord/generators/crails/data_generator.rb', line 70

def edit_resource_declaration
  _append "virtual std::vector<std::string> find_missing_parameters(Data) const;"
  _append "virtual void                     edit(Data);"
  _append "virtual void                     merge_data(Data) const;"
  _append "virtual std::string              to_json() const;"
  _append "virtual bool                     is_valid();"
  _append "virtual void                     on_dependent_destroy(#{id_type});"
  _append ""
end

#generate_class_head(object) ⇒ Object



43
44
45
46
# File 'lib/metarecord/generators/crails/data_generator.rb', line 43

def generate_class_head object
  _append "#pragma db object abstract"
  _append "struct #{object[:name]}"
end

#generate_for(object) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/metarecord/generators/crails/data_generator.rb', line 48

def generate_for object
  reset
  @forward_declarations << object[:classname] unless object[:classname].nil?
  @current_visibility = :_preblock
  @indent += 1
  generate_class_head object
  _append "{"
  @indent += 1
  _append "friend class odb::access;"
  _append "#pragma db transient"
  _append "DataTree errors;"
  @current_visibility = :public
  edit_resource_declaration
  prepare_order_by
  self.instance_eval &object[:block]
  @current_visibility = :_postblock
  @indent -= 1
  _append "};"
  @indent -= 1
  render
end

#get_headersObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/metarecord/generators/crails/data_generator.rb', line 24

def get_headers
  forward_source = ""
  @forward_declarations.each do |type|
    parts = type.split('::').reject {|part| part.empty?}
    last_part = parts.last
    if parts.length > 1
      parts[0...parts.size-1].each do |part|
        forward_source += "namespace #{part} { "
      end
      forward_source += "class #{last_part};"
      (parts.size - 1).times do forward_source += " } " end
      forward_source += "\n"
    else
      forward_source += "class #{last_part};\n"
    end
  end
  forward_source
end

#has_many(type, name, options = {}) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/metarecord/generators/crails/data_generator.rb', line 205

def has_many type, name, options = {}
  @forward_declarations << type
  type = get_type type
  tptr = ptr_type type
  list_type = "std::list<#{tptr} >"
  singular_name = get_singular_name name
  with_visibility :public do
    virt = if options[:allow_override] == true then "virtual " else "" end
    _append "#{virt}bool update_#{name}(Data);"
    _append "#{virt}void add_#{singular_name}(#{tptr});"
    _append "#{virt}void remove_#{singular_name}(const #{type}&);"
    _append "#{virt}void collect_#{name}(std::map<#{id_type}, #{tptr} >&);"
  end
  if options[:joined] != false
    _join_based_has_many list_type, name, options
  else
    _id_based_has_many list_type, name, options
  end
end

#has_many_fetch(list_type, name, options) ⇒ Object



234
235
236
237
238
# File 'lib/metarecord/generators/crails/data_generator.rb', line 234

def has_many_fetch list_type, name, options
  with_visibility :public do
    _append "void fetch_#{name}();"
  end
end

#has_one(type, name, options = {}) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/metarecord/generators/crails/data_generator.rb', line 166

def has_one type, name, options = {}
  @forward_declarations << type
  type = get_type type
  tptr = ptr_type type
  virt = if options[:allow_override] == true then "virtual " else "" end
  if options[:joined] != false
    with_visibility :public do
      _append "#{virt}#{tptr} get_#{name}() const { return #{name}; }"
      _append "#{virt}void set_#{name}(#{tptr} v) { this->#{name} = v; }"
      _append "#{virt}#{id_type} get_#{name}_id() const;"
    end
    _append "#{tptr} #{name};"
  else
    with_visibility :public do
      _append "#{virt}#{tptr} get_#{name}() const;"
      _append "#{virt}void set_#{name}(#{tptr} v);"
      _append "#{id_type} get_#{name}_id() const { return #{name}_id; }"
      _append "void set_#{name}_id(#{id_type} v) { #{name}_id = v; }"
    end
    make_pragma_db options[:db] unless options[:db].nil?
    _append "#{id_type} #{name}_id = #{null_id};"
  end
  with_visibility :public do
    _append <<CPP

  template<typename ARRAY>
  static void collect_#{name}(ARRAY& array, std::map<#{id_type}, #{tptr} >& results)
  {
    for (auto model : array)
    {
      if (results.find(model.get_#{name}_id()) == results.end())
        results[model.get_#{name}_id()] = model.get_#{name}();
    }
  }

CPP
  end
end

#make_pragma_db(options, authorized_options = []) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/metarecord/generators/crails/data_generator.rb', line 153

def make_pragma_db options, authorized_options = []
  is_option_available = lambda {|a|
    (not options[a].nil?) && (authorized_options.size == 0 || authorized_options.include?(a))
  }
  src  = ""
  src += "transient " if is_option_available.call(:transient) && options[:transient] == true
  src += "type(\"#{options[:type]}\") "          if is_option_available.call :type
  src += "column(\"#{options[:column]}\") "      if is_option_available.call :column
  src += "default(#{get_value options[:default]}) " if is_option_available.call :default
  src += "null " if is_option_available.call(:null) && options[:null] == true
  _append "#pragma db #{src}" if src.size > 0
end

#order_by(name, flow = nil) ⇒ Object



119
120
121
122
123
124
# File 'lib/metarecord/generators/crails/data_generator.rb', line 119

def order_by name, flow = nil
  src = "return query + \"ORDER BY\" + QUERY::#{name}"
  src += " + \"#{flow.to_s.upcase}\"" unless flow.nil?
  src += ";"
  @src[:public] = @src[:public].gsub /^(\s*).*\/\/ order_by$/, '\1' + src
end

#prepare_order_byObject



80
81
82
83
84
85
86
# File 'lib/metarecord/generators/crails/data_generator.rb', line 80

def prepare_order_by
  _append "template<typename QUERY>"
  _append "static QUERY default_order_by(QUERY query)"
  _append "{"
  _append "  return query; // order_by"
  _append "}\n"
end

#property(type, name, options = {}) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/metarecord/generators/crails/data_generator.rb', line 135

def property type, name, options = {}
  if type == 'DataTree'
    datatree_property name, options
  else
     with_visibility :public do
     virt = if options[:allow_override] == true then "virtual " else "" end
      _append "#{virt}#{type} get_#{name}() const { return #{name}; }"
      _append "#{virt}void set_#{name}(#{type} value) { this->#{name} = value; }"
    end
  end
  make_pragma_db options[:db] unless options[:db].nil?
  if options[:default].nil?
    _append "#{type} #{name};"
  else
    _append "#{type} #{name} = #{get_value options[:default]};"
  end
end

#renderObject



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/metarecord/generators/crails/data_generator.rb', line 88

def render
  @current_visibility = :_result
  result = @src[:_preblock]
  [:public, :protected, :private].each do |key|
    unless @src[key].nil?
      result += "  #{key}:\n"
      result += @src[key]
    end
  end
  result += @src[:_postblock]
  result
end

#resetObject



7
8
9
10
11
# File 'lib/metarecord/generators/crails/data_generator.rb', line 7

def reset
  super
  @forward_declarations = []
  @src = {}
end

#resource_name(name) ⇒ Object



112
113
114
115
116
117
# File 'lib/metarecord/generators/crails/data_generator.rb', line 112

def resource_name name
  visibility :public
  _append "static const std::string scope;"
  _append "static const std::string plural_scope;"
  _append "static const std::string view;"
end

#visibility(value) ⇒ Object



101
102
103
# File 'lib/metarecord/generators/crails/data_generator.rb', line 101

def visibility value
  @current_visibility = value
end

#with_visibility(value, &block) ⇒ Object



105
106
107
108
109
110
# File 'lib/metarecord/generators/crails/data_generator.rb', line 105

def with_visibility value, &block
  old_visibility = @current_visibility
  visibility value
  self.instance_eval &block
  visibility old_visibility
end