rgen 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/CHANGELOG +6 -0
  2. data/lib/mmgen/metamodel_generator.rb +2 -1
  3. data/lib/mmgen/mm_ext/{ecore_ext.rb → ecore_mmgen_ext.rb} +3 -7
  4. data/lib/mmgen/templates/metamodel_generator.tpl +10 -8
  5. data/lib/rgen/ecore/ecore_ext.rb +69 -0
  6. data/lib/rgen/ecore/ecore_transformer.rb +1 -1
  7. data/lib/rgen/metamodel_builder/builder_extensions.rb +10 -2
  8. data/lib/rgen/serializer/xmi11_serializer.rb +101 -0
  9. data/lib/rgen/serializer/xmi20_serializer.rb +7 -7
  10. data/lib/rgen/serializer/xml_serializer.rb +47 -14
  11. data/test/ea_serializer_test.rb +29 -0
  12. data/test/ea_serializer_test/ea_testmodel_regenerated.xml +821 -0
  13. data/test/metamodel_roundtrip_test.rb +1 -2
  14. data/test/metamodel_roundtrip_test/TestModel.rb +1 -0
  15. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +34 -35
  16. data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +128 -236
  17. data/test/rgen_test.rb +1 -0
  18. metadata +93 -95
  19. data/lib/rgen/metamodel_builder.rb.bak +0 -196
  20. data/lib/rgen/metamodel_builder/builder_extensions.rb.bak +0 -437
  21. data/lib/rgen/metamodel_builder/builder_runtime.rb.bak +0 -73
  22. data/lib/rgen/name_helper.rb.bak +0 -37
  23. data/lib/rgen/template_language.rb.bak +0 -289
  24. data/lib/rgen/template_language/directory_template_container.rb.bak +0 -69
  25. data/lib/rgen/template_language/output_handler.rb.bak +0 -88
  26. data/lib/rgen/template_language/template_container.rb.bak +0 -196
  27. data/lib/rgen/transformer.rb.bak +0 -381
  28. data/test/environment_test.rb.bak +0 -52
  29. data/test/metamodel_builder_test.rb.bak +0 -443
  30. data/test/output_handler_test.rb.bak +0 -50
  31. data/test/template_language_test.rb.bak +0 -72
  32. data/test/transformer_test.rb.bak +0 -223
@@ -1,37 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- module RGen
5
-
6
- module NameHelper
7
-
8
- def normalize(name)
9
- name.gsub(/\W/,'_')
10
- end
11
-
12
- def className(object)
13
- object.class.name =~ /::(\w+)$/; $1
14
- end
15
-
16
- def firstToUpper(str)
17
- str[0..0].upcase + ( str[1..-1] || "" )
18
- end
19
-
20
- def firstToLower(str)
21
- str[0..0].downcase + ( str[1..-1] || "" )
22
- end
23
-
24
- def saneClassName(str)
25
- firstToUpper(normalize(str)).sub(/^Class$/, 'Clazz')
26
- end
27
-
28
- def saneMethodName(str)
29
- firstToLower(normalize(str)).sub(/^class$/, 'clazz')
30
- end
31
-
32
- def camelize(str)
33
- str.split(/[\W_]/).collect{|s| firstToUpper(s.downcase)}.join
34
- end
35
- end
36
-
37
- end
@@ -1,289 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- require 'rgen/template_language/directory_template_container'
5
- require 'rgen/template_language/template_container'
6
-
7
- module RGen
8
-
9
- # The RGen template language has been designed to build complex generators.
10
- # It is very similar to the EXPAND language of the Java based
11
- # OpenArchitectureWare framework.
12
- #
13
- # =Templates
14
- #
15
- # The basic idea is to allow "templates" not only being template files
16
- # but smaller parts. Those parts can be expanded from other parts very
17
- # much like Ruby methods are called from other methods.
18
- # Thus the term "template" refers to such a part within a "template file".
19
- #
20
- # Template files used by the RGen template language should have a
21
- # filename with the postfix ".tpl". Those files can reside within (nested)
22
- # template file directories.
23
- #
24
- # As an example a template directory could look like the following:
25
- #
26
- # templates/root.tpl
27
- # templates/dbaccess/dbaccess.tpl
28
- # templates/dbaccess/schema.tpl
29
- # templates/headers/generic_headers.tpl
30
- # templates/headers/specific/component.tpl
31
- #
32
- # A template is always called for a <i>context object</i>. The context object
33
- # serves as the receiver of methods called within the template. Details are given
34
- # below.
35
- #
36
- #
37
- # =Defining Templates
38
- #
39
- # One or more templates can be defined in a template file using the +define+
40
- # keyword as in the following example:
41
- #
42
- # <% define 'GenerateDBAdapter', :for => DBDescription do |dbtype| %>
43
- # Content to be generated; use ERB syntax here
44
- # <% end %>
45
- #
46
- # The template definition takes three kinds of parameters:
47
- # 1. The name of the template within the template file as a String or Symbol
48
- # 2. An optional class object describing the class of context objects for which
49
- # this template is valid.
50
- # 3. An arbitrary number of template parameters
51
- # See RGen::TemplateLanguage::TemplateContainer for details about the syntax of +define+.
52
- #
53
- # Within a template, regular ERB syntax can be used. This is
54
- # * <code><%</code> and <code>%></code> are used to embed Ruby code
55
- # * <code><%=</code> and <code>%></code> are used to embed Ruby expressions with
56
- # the expression result being written to the template output
57
- # * <code><%#</code> and <code>%></code> are used for comments
58
- # All content not within these tags is written to the template output verbatim.
59
- # See below for details about output files and output formatting.
60
- #
61
- # All methods which are called from within the template are sent to the context
62
- # object.
63
- #
64
- # Experience shows that one easily forgets the +do+ at the end of the first
65
- # line of a template definition. This will result in an ERB parse error.
66
- #
67
- #
68
- # =Expanding Templates
69
- #
70
- # Templates are normally expanded from within other templates. The only
71
- # exception is the root template, which is expanded from the surrounding code.
72
- #
73
- # Template names can be specified in the following ways:
74
- # * Non qualified name: use the template with the given name in the current template file
75
- # * Relative qualified name: use the template within the template file specified by the relative path
76
- # * Absolute qualified name: use the template within the template file specified by the absolute path
77
- #
78
- # The +expand+ keyword is used to expand templates.
79
- #
80
- # Here are some examples:
81
- #
82
- # <% expand 'GenerateDBAdapter', dbtype, :for => dbDesc %>
83
- #
84
- # <i>Non qualified</i>. Must be called within the file where 'GenerateDBAdapter' is defined.
85
- # There is one template parameter passed in via variable +dbtype+.
86
- # The context object is provided in variable +dbDesc+.
87
- #
88
- # <% expand 'dbaccess::ExampleSQL' %>
89
- #
90
- # <i>Qualified with filename</i>. Must be called from a file in the same directory as 'dbaccess.tpl'
91
- # There are no parameters. The current context object will be used as the context
92
- # object for this template expansion.
93
- #
94
- # <% expand '../headers/generic_headers::CHeader', :foreach => modules %>
95
- #
96
- # <i>Relatively qualified</i>. Must be called from a location from which the file
97
- # 'generic_headers.tpl' is accessible via the relative path '../headers'.
98
- # The template is expanded for each module in +modules+ (which has to be an Array).
99
- # Each element of +modules+ will be the context object in turn.
100
- #
101
- # <% expand '/headers/generic_headers::CHeader', :foreach => modules %>
102
- #
103
- # Absolutely qualified: The same behaviour as before but with an absolute path from
104
- # the template directory root (which in this example is 'templates', see above)
105
- #
106
- # Sometimes it is neccessary to generate some text (e.g. a ',') in between the single
107
- # template expansion results from a <code>:foreach</code> expansion. This can be achieved by
108
- # using the <code>:separator</code> keyword:
109
- #
110
- # <% expand 'ColumnName', :foreach => column, :separator => ', ' %>
111
- #
112
- # Note that the separator may also contain newline characters (\n). See below for
113
- # details about formatting.
114
- #
115
- #
116
- # =Formatting
117
- #
118
- # For many generator tools a formatting postprocess (e.g. using a pretty printer) is
119
- # required in order to make the output readable. However, depending on the kind of
120
- # generated output, such a tool might not be available.
121
- #
122
- # The RGen template language has been design for generators which do not need a
123
- # postprocessing step. The basic idea is to eliminate all whitespace at the beginning
124
- # of template lines (the indentation that makes the _template_ readable) and output
125
- # newlines only after at least on character has been generated in the corresponding
126
- # line. This way there are no empty lines in the output and each line will start with
127
- # a non-whitspace character.
128
- #
129
- # Starting from this point one can add indentation and newlines as required by using
130
- # explicit formatting commands:
131
- # * <code><%nl%></code> (newline) starts a new line
132
- # * <code><%iinc%></code> (indentation increment) increases the current indentation
133
- # * <code><%idec%></code> (indentation decrement) decreases the current indentation
134
- # * <code><%nonl%></code> (no newline) ignore next newline
135
- # * <code><%nows%></code> (no whitespace) ignore next whitespace
136
- #
137
- # Indentation takes place for every new line in the output unless it is 0.
138
- # The initial indentation can be specified with a root +expand+ command by using
139
- # the <code>:indent</code> keyword.
140
- #
141
- # Here is an example:
142
- #
143
- # expand 'GenerateDBAdapter', dbtype, :for => dbDesc, :indent => 1
144
- #
145
- # Initial indentation defaults to 0. Normally <code><%iinc%></code> and
146
- # <code><%idec%></code> are used to change the indentation.
147
- # The current indentation is kept for expansion of subtemplates.
148
- #
149
- # Note that commands to ignore whitespace and newlines are still useful if output
150
- # generated from multiple template lines should show up in one single output line.
151
- #
152
- # Here is an example of a template generating a C program:
153
- #
154
- # #include <stdio.h>
155
- # <%nl%>
156
- # int main() {<%iinc%>
157
- # printf("Hello World\n");
158
- # return 0;<%idec>
159
- # }
160
- #
161
- # The result is:
162
- #
163
- # #include <stdio.h>
164
- #
165
- # int main() {
166
- # printf("Hello World\n");
167
- # return 0;
168
- # }
169
- #
170
- # Note that without the explicit formatting commands, the output generated from the
171
- # example above would not have any empty lines or whitespace in the beginning of lines.
172
- # This may seem like unneccessary extra work for the example above which could also
173
- # have been generated by passing the template to the output verbatimly.
174
- # However in most cases templates will contain more template specific indentation and
175
- # newlines which should be eliminated than formatting that should be visible in the
176
- # output.
177
- #
178
- # Here is a more realistic example for generating C function prototypes:
179
- #
180
- # <% define 'Prototype', :for => CFunction do %>
181
- # <%= getType.name %> <%= name %>(<%nows%>
182
- # <% expand 'Signature', :foreach => argument, :separator => ', ' %>);
183
- # <% end %>
184
- #
185
- # <% define 'Signature', :for => CFunctionArgument do %>
186
- # <%= getType.name %> <%= name%><%nows%>
187
- # <% end %>
188
- #
189
- # The result could look something like:
190
- #
191
- # void somefunc(int a, float b, int c);
192
- # int otherfunc(short x);
193
- #
194
- # In this example a separator is used to join the single arguments of the C functions.
195
- # Note that the template generating the argument type and name needs to contain
196
- # a <code><%nows%></code> if the result should consist of a single line.
197
- #
198
- # Here is one more example for generating C array initializations:
199
- #
200
- # <% define 'Array', :for => CArray do %>
201
- # <%= getType.name %> <%= name %>[<%= size %>] = {<%iinc%>
202
- # <% expand 'InitValue', :foreach => initvalue, :separator => ",\n" %><%nl%><%idec%>
203
- # };
204
- # <% end %>
205
- #
206
- # <% define 'InitValue', :for => PrimitiveInitValue do %>
207
- # <%= value %><%nows%>
208
- # <% end %>
209
- #
210
- # The result could look something like:
211
- #
212
- # int myArray[3] = {
213
- # 1,
214
- # 2,
215
- # 3
216
- # };
217
- #
218
- # Note that in this example, the separator contains a newline. The current increment
219
- # will be applied to each single expansion result since it starts in a new line.
220
- #
221
- #
222
- # =Output Files
223
- #
224
- # Normally the generated content is to be written into one or more output files.
225
- # The RGen template language facilitates this by means of the +file+ keyword.
226
- #
227
- # When the +file+ keyword is used to define a block, all output generated
228
- # from template code within this block will be written to the specified file.
229
- # This includes output generated from template expansions.
230
- # Thus all output from templates expanded within this block is written to
231
- # the same file as long as those templates do not use the +file+ keyword to
232
- # define a new file context.
233
- #
234
- # Here is an example:
235
- #
236
- # <% file 'dbadapter/'+adapter.name+'.c' do %>
237
- # all content within this block will be written to the specified file
238
- # <% end %>
239
- #
240
- # Note that the filename itself can be calculated dynamically by an arbitrary
241
- # Ruby expression.
242
- #
243
- # The absolute position where the output file is created depends on the output
244
- # root directory passed to DirectoryTemplateContainer as described below.
245
- #
246
- # =Setting up the Generator
247
- #
248
- # Setting up the generator consists of 3 steps:
249
- # * Instantiate DirectoryTemplateContainer passing one or more metamodel(s) and the output
250
- # directory to the constructor.
251
- # * Load the templates into the template container
252
- # * Expand the root template to start generation
253
- #
254
- # Here is an example:
255
- #
256
- # module MyMM
257
- # # metaclasses are defined here, e.g. using RGen::MetamodelBuilder
258
- # end
259
- #
260
- # OUTPUT_DIR = File.dirname(__FILE__)+"/output"
261
- # TEMPLATES_DIR = File.dirname(__FILE__)+"/templates"
262
- #
263
- # tc = RGen::TemplateLanguage::DirectoryTemplateContainer.new(MyMM, OUTPUT_DIR)
264
- # tc.load(TEMPLATES_DIR)
265
- # # testModel should hold an instance of the metamodel class expected by the root template
266
- # # the following line starts generation
267
- # tc.expand('root::Root', :for => testModel, :indent => 1)
268
- #
269
- # The metamodel is the Ruby module which contains the metaclasses.
270
- # This information is required for the template container in order to resolve the
271
- # metamodel classes used within the template file.
272
- # If several metamodels shall be used, an array of modules can be passed instead
273
- # of a single module.
274
- #
275
- # The output path is prepended to the relative paths provided to the +file+
276
- # definitions in the template files.
277
- #
278
- # The template directory should contain template files as described above.
279
- #
280
- # Finally the generation process is started by calling +expand+ in the same way as it
281
- # is used from within templates.
282
- #
283
- # Also see the unit tests for more examples.
284
- #
285
- module TemplateLanguage
286
-
287
- end
288
-
289
- end
@@ -1,69 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- require 'rgen/template_language/template_container'
5
- require 'rgen/template_language/template_helper'
6
-
7
- module RGen
8
-
9
- module TemplateLanguage
10
-
11
- class DirectoryTemplateContainer
12
- include TemplateHelper
13
-
14
- def initialize(metamodel=nil, output_path=nil, parent=nil)
15
- @containers = {}
16
- @parent = parent
17
- @metamodel = metamodel
18
- @output_path = output_path
19
- end
20
-
21
- def load(dir)
22
- #print "Loading templates in #{dir} ...\n"
23
- Dir.foreach(dir) { |f|
24
- qf = dir+"/"+f
25
- if !File.directory?(qf) && f =~ /^(.*)\.tpl$/
26
- (@containers[$1] = TemplateContainer.dup.new(@metamodel, @output_path, self,qf)).load
27
- elsif File.directory?(qf) && f != "." && f != ".."
28
- (@containers[f] = DirectoryTemplateContainer.new(@metamodel, @output_path, self)).load(qf)
29
- end
30
- }
31
- end
32
-
33
- def expand(template, *all_args)
34
- if template =~ /^\//
35
- if @parent
36
- # pass to parent
37
- @parent.expand(template, *all_args)
38
- else
39
- # this is root
40
- _expand(template, *all_args)
41
- end
42
- elsif template =~ /^\.\.\/(.*)/
43
- if @parent
44
- # pass to parent
45
- @parent.expand($1, *all_args)
46
- else
47
- raise "No parent directory for root"
48
- end
49
- else
50
- _expand(template, *all_args)
51
- end
52
- end
53
-
54
- private
55
-
56
- def _expand(template, *all_args)
57
- if template =~ /^\/?([^:\/]+)(?:::|\/)([^:\/].*)/
58
- raise "Template not found: #{$1}" unless @containers[$1]
59
- @containers[$1].expand($2, *all_args)
60
- else
61
- raise "Invalid template name: #{template}"
62
- end
63
- end
64
-
65
- end
66
-
67
- end
68
-
69
- end
@@ -1,88 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- module RGen
5
-
6
- module TemplateLanguage
7
-
8
- class OutputHandler
9
- attr_writer :indent
10
-
11
- def initialize(indent=0, mode=:explicit)
12
- self.mode = mode
13
- @indent = indent
14
- @state = :wait_for_nonws
15
- @output = ""
16
- end
17
-
18
- # ERB will call this method for every string s which is part of the
19
- # template file in between %> and <%. If s contains a newline, it will
20
- # call this method for every part of s which is terminated by a \n
21
- #
22
- def concat(s)
23
- return @output.concat(s) if s.is_a? OutputHandler
24
- s = s.to_str.gsub(/^[\t ]*\r?\n/,'') if @ignoreNextNL
25
- s = s.to_str.gsub(/^\s+/,'') if @ignoreNextWS
26
- @ignoreNextNL = @ignoreNextWS = false if s =~ /\S/
27
- if @mode == :direct
28
- @output.concat(s)
29
- elsif @mode == :explicit
30
- while s.size > 0
31
- if @state == :wait_for_nl
32
- if s =~ /\A([^\r\n]*\r?\n)(.*)/m
33
- rest = $2
34
- @output.concat($1.gsub(/[\t ]+(?=\r|\n)/,''))
35
- s = rest || ""
36
- @state = :wait_for_nonws
37
- else
38
- @output.concat(s)
39
- s = ""
40
- end
41
- elsif @state == :wait_for_nonws
42
- if s =~ /\A\s*(\S+.*)/m
43
- s = $1 || ""
44
- if !@noIndentNextLine && !(@output.to_s.size > 0 && @output.to_s[-1] != "\n"[0])
45
- @output.concat(" "*@indent)
46
- else
47
- @noIndentNextLine = false
48
- end
49
- @state = :wait_for_nl
50
- else
51
- s = ""
52
- end
53
- end
54
- end
55
- end
56
- end
57
- alias << concat
58
-
59
- def to_str
60
- @output
61
- end
62
- alias to_s to_str
63
-
64
- def direct_concat(s)
65
- @output.concat(s)
66
- end
67
-
68
- def ignoreNextNL
69
- @ignoreNextNL = true
70
- end
71
-
72
- def ignoreNextWS
73
- @ignoreNextWS = true
74
- end
75
-
76
- def noIndentNextLine
77
- @noIndentNextLine = true
78
- end
79
-
80
- def mode=(m)
81
- raise StandardError.new("Unknown mode: #{m}") unless [:direct, :explicit].include?(m)
82
- @mode = m
83
- end
84
- end
85
-
86
- end
87
-
88
- end