rgen 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG +9 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +73 -0
  4. data/lib/ea/xmi_class_instantiator.rb +45 -0
  5. data/lib/ea/xmi_helper.rb +26 -0
  6. data/lib/ea/xmi_metamodel.rb +19 -0
  7. data/lib/ea/xmi_object_instantiator.rb +42 -0
  8. data/lib/ea/xmi_to_classmodel.rb +78 -0
  9. data/lib/ea/xmi_to_objectmodel.rb +89 -0
  10. data/lib/mmgen/metamodel_generator.rb +19 -0
  11. data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +71 -0
  12. data/lib/mmgen/mmgen.rb +21 -0
  13. data/lib/mmgen/templates/uml_classmodel.tpl +63 -0
  14. data/lib/rgen/array_extensions.rb +23 -0
  15. data/lib/rgen/auto_class_creator.rb +56 -0
  16. data/lib/rgen/environment.rb +57 -0
  17. data/lib/rgen/metamodel_builder.rb +102 -0
  18. data/lib/rgen/metamodel_builder/build_helper.rb +29 -0
  19. data/lib/rgen/metamodel_builder/builder_extensions.rb +191 -0
  20. data/lib/rgen/metamodel_builder/builder_runtime.rb +67 -0
  21. data/lib/rgen/name_helper.rb +18 -0
  22. data/lib/rgen/template_language.rb +169 -0
  23. data/lib/rgen/template_language/directory_template_container.rb +51 -0
  24. data/lib/rgen/template_language/output_handler.rb +84 -0
  25. data/lib/rgen/template_language/template_container.rb +153 -0
  26. data/lib/rgen/template_language/template_helper.rb +26 -0
  27. data/lib/rgen/transformer.rb +316 -0
  28. data/lib/rgen/xml_instantiator/dependency_resolver.rb +23 -0
  29. data/lib/rgen/xml_instantiator/xml_instantiator.rb +78 -0
  30. data/lib/rgen/xml_instantiator/xml_parser.rb +39 -0
  31. data/lib/uml/objectmodel_instantiator.rb +53 -0
  32. data/lib/uml/uml_classmodel.rb +92 -0
  33. data/lib/uml/uml_objectmodel.rb +65 -0
  34. data/test/array_extensions_test.rb +54 -0
  35. data/test/environment_test.rb +47 -0
  36. data/test/metamodel_builder_test.rb +175 -0
  37. data/test/metamodel_generator_test.rb +45 -0
  38. data/test/metamodel_generator_test/TestModel.rb +40 -0
  39. data/test/metamodel_generator_test/expected_result.txt +40 -0
  40. data/test/output_handler_test.rb +40 -0
  41. data/test/rgen_test.rb +13 -0
  42. data/test/template_language_test.rb +46 -0
  43. data/test/template_language_test/expected_result.txt +10 -0
  44. data/test/template_language_test/templates/content/chapter.tpl +5 -0
  45. data/test/template_language_test/templates/index/c/cmod.tpl +1 -0
  46. data/test/template_language_test/templates/index/chapter.tpl +3 -0
  47. data/test/template_language_test/templates/root.tpl +22 -0
  48. data/test/template_language_test/testout.txt +10 -0
  49. data/test/transformer_test.rb +176 -0
  50. data/test/xmi_class_instantiator_test.rb +107 -0
  51. data/test/xmi_instantiator_test/testmodel.eap +0 -0
  52. data/test/xmi_instantiator_test/testmodel.xml +962 -0
  53. data/test/xmi_object_instantiator_test.rb +65 -0
  54. metadata +117 -0
@@ -0,0 +1,45 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'ea/xmi_class_instantiator'
5
+ require 'mmgen/metamodel_generator'
6
+
7
+ class MetamodelGeneratorTest < Test::Unit::TestCase
8
+
9
+ MODEL_DIR = File.join(File.dirname(__FILE__),"xmi_instantiator_test")
10
+ OUTPUT_DIR = File.dirname(__FILE__)+"/metamodel_generator_test"
11
+ MM_FILE = OUTPUT_DIR+"/TestModel.rb"
12
+
13
+ include XMIClassInstantiator
14
+ include MMGen::MetamodelGenerator
15
+
16
+ def test_generator
17
+ envUML = RGen::Environment.new
18
+ File.open(MODEL_DIR+"/testmodel.xml") { |f|
19
+ instantiateUMLClassModel(envUML, f.read)
20
+ }
21
+
22
+ rootPackage = envUML.find(:class => UMLClassModel::UMLPackage).select{|p| p.name == "HouseMetamodel"}.first
23
+ assert_not_nil rootPackage
24
+
25
+ assert_raise StandardError do
26
+ # this will raise an exception because multiple inheritance is not resolved
27
+ generateMetamodel(rootPackage, MM_FILE)
28
+ end
29
+
30
+ # resolve multiple inheritance by specifying which class should be a module
31
+ modules = ['MeetingPlace']
32
+ generateMetamodel(rootPackage, MM_FILE, modules)
33
+
34
+ # try to use the generated metamodel
35
+ File.open(MM_FILE) { |f|
36
+ eval(f.read)
37
+ }
38
+ assert HouseMetamodel::House.new
39
+
40
+ result = expected = ""
41
+ File.open(MM_FILE) {|f| result = f.read}
42
+ File.open(OUTPUT_DIR+"/expected_result.txt") {|f| expected = f.read}
43
+ assert_equal expected, result
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ require 'rgen/metamodel_builder'
2
+ module HouseMetamodel
3
+
4
+ class Person < RGen::MetamodelBuilder::MMBase
5
+ has_one 'name', String
6
+ end
7
+
8
+ class House < RGen::MetamodelBuilder::MMBase
9
+ has_one 'name', String
10
+ has_one 'address', String
11
+ end
12
+
13
+ module MeetingPlace
14
+ extend RGen::MetamodelBuilder::BuilderExtensions
15
+ has_one 'name', String
16
+ end
17
+
18
+
19
+ module Rooms
20
+
21
+ class Room < RGen::MetamodelBuilder::MMBase
22
+ has_one 'name', String
23
+ end
24
+
25
+ class Bathroom < Room
26
+ has_one 'name', String
27
+ end
28
+
29
+ class Kitchen < Room
30
+ include MeetingPlace
31
+ has_one 'name', String
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ HouseMetamodel::Person.one_to_many 'home', HouseMetamodel::House, 'person'
38
+ HouseMetamodel::House.one_to_one 'bathroom', HouseMetamodel::Rooms::Bathroom, 'house'
39
+ HouseMetamodel::Rooms::Kitchen.one_to_one 'house', HouseMetamodel::House, 'kitchen'
40
+ HouseMetamodel::House.one_to_many 'room', HouseMetamodel::Rooms::Room, 'house'
@@ -0,0 +1,40 @@
1
+ require 'rgen/metamodel_builder'
2
+ module HouseMetamodel
3
+
4
+ class Person < RGen::MetamodelBuilder::MMBase
5
+ has_one 'name', String
6
+ end
7
+
8
+ class House < RGen::MetamodelBuilder::MMBase
9
+ has_one 'name', String
10
+ has_one 'address', String
11
+ end
12
+
13
+ module MeetingPlace
14
+ extend RGen::MetamodelBuilder::BuilderExtensions
15
+ has_one 'name', String
16
+ end
17
+
18
+
19
+ module Rooms
20
+
21
+ class Room < RGen::MetamodelBuilder::MMBase
22
+ has_one 'name', String
23
+ end
24
+
25
+ class Bathroom < Room
26
+ has_one 'name', String
27
+ end
28
+
29
+ class Kitchen < Room
30
+ include MeetingPlace
31
+ has_one 'name', String
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ HouseMetamodel::Person.one_to_many 'home', HouseMetamodel::House, 'person'
38
+ HouseMetamodel::House.one_to_one 'bathroom', HouseMetamodel::Rooms::Bathroom, 'house'
39
+ HouseMetamodel::Rooms::Kitchen.one_to_one 'house', HouseMetamodel::House, 'kitchen'
40
+ HouseMetamodel::House.one_to_many 'room', HouseMetamodel::Rooms::Room, 'house'
@@ -0,0 +1,40 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rgen/template_language/output_handler'
5
+
6
+ class MetamodelBuilderTest < Test::Unit::TestCase
7
+ def test_direct_nl
8
+ h = RGen::TemplateLanguage::OutputHandler.new
9
+ h.mode = :direct
10
+ h << "Test"
11
+ h.ignoreNextNL
12
+ h << "\nContent"
13
+ assert_equal "TestContent", h.to_s
14
+ end
15
+ def test_direct_ws
16
+ h = RGen::TemplateLanguage::OutputHandler.new
17
+ h.mode = :direct
18
+ h << "Test"
19
+ h.ignoreNextWS
20
+ h << " \n Content"
21
+ assert_equal "TestContent", h.to_s
22
+ end
23
+ def test_explicit_indent
24
+ h = RGen::TemplateLanguage::OutputHandler.new
25
+ h.mode = :explicit
26
+ h.indent = 1
27
+ h << "Start"
28
+ h << " \n "
29
+ h << "Test"
30
+ h << " \n \n Content"
31
+ assert_equal " Start\n Test\n Content", h.to_s
32
+ end
33
+ def test_explicit_endswithws
34
+ h = RGen::TemplateLanguage::OutputHandler.new
35
+ h.mode = :explicit
36
+ h.indent = 1
37
+ h << "Start \n\n"
38
+ assert_equal " Start\n", h.to_s
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'test/unit'
4
+
5
+ require 'array_extensions_test'
6
+ require 'environment_test'
7
+ require 'metamodel_builder_test'
8
+ require 'output_handler_test'
9
+ require 'template_language_test'
10
+ require 'xmi_class_instantiator_test'
11
+ require 'xmi_object_instantiator_test'
12
+ require 'metamodel_generator_test'
13
+ require 'transformer_test'
@@ -0,0 +1,46 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rgen/template_language'
5
+
6
+ class TemplateContainerTest < Test::Unit::TestCase
7
+
8
+ TEMPLATES_DIR = File.dirname(__FILE__)+"/template_language_test/templates"
9
+ OUTPUT_DIR = File.dirname(__FILE__)+"/template_language_test"
10
+
11
+ module MyMM
12
+
13
+ class Chapter
14
+ attr_reader :title
15
+ def initialize(title)
16
+ @title = title
17
+ end
18
+ end
19
+
20
+ class Document
21
+ attr_reader :title, :author, :chapters
22
+ def initialize(title, author)
23
+ @title, @author = title, author
24
+ @chapters = []
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ TEST_MODEL = MyMM::Document.new("SomeDocument","MyName")
31
+ TEST_MODEL.chapters << MyMM::Chapter.new("Intro")
32
+ TEST_MODEL.chapters << MyMM::Chapter.new("MainPart")
33
+ TEST_MODEL.chapters << MyMM::Chapter.new("Summary")
34
+
35
+ def test_with_model
36
+ tc = RGen::TemplateLanguage::DirectoryTemplateContainer.new(MyMM, OUTPUT_DIR)
37
+ tc.load(TEMPLATES_DIR)
38
+ File.delete(OUTPUT_DIR+"/testout.txt") if File.exists? OUTPUT_DIR+"/testout.txt"
39
+ tc.expand('root::Root', :for => TEST_MODEL, :indent => 1)
40
+ result = expected = ""
41
+ File.open(OUTPUT_DIR+"/testout.txt") {|f| result = f.read}
42
+ File.open(OUTPUT_DIR+"/expected_result.txt") {|f| expected = f.read}
43
+ assert_equal expected, result
44
+ end
45
+
46
+ end
@@ -0,0 +1,10 @@
1
+ Document: SomeDocument
2
+ Index:
3
+ 1 Intro in SomeDocument
4
+ 2 MainPart in SomeDocument
5
+ 3 Summary in SomeDocument
6
+ by MyName
7
+ ----------------
8
+ *** Intro ***
9
+ *** MainPart ***
10
+ *** Summary ***
@@ -0,0 +1,5 @@
1
+ <% define 'Root', :for => Chapter do %>
2
+ *** <%= title %> ***
3
+
4
+
5
+ <% end %>
@@ -0,0 +1 @@
1
+ <% define 'cmod' do %>Module C is special !<% end %>
@@ -0,0 +1,3 @@
1
+ <% define 'Root' do |idx, doc| %>
2
+ <%= idx%> <%= title %> in <%= doc.title %>
3
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <% define 'Root' do %>
2
+ <% file 'testout.txt' do %>
3
+ Document: <%= title %>
4
+
5
+ Index:<%iinc%>
6
+ <% for c in chapters %>
7
+ <% nr = (nr || 0); nr += 1 %>
8
+ <% expand 'index/chapter::Root', nr, this, :for => c %>
9
+ <% end %><%idec%>
10
+
11
+ by <%= author %>
12
+
13
+ ----------------
14
+
15
+ <% expand 'content/chapter::Root', :foreach => chapters %>
16
+
17
+ <% end %>
18
+ <% end %>
19
+
20
+ <% def MyNewMethod(arg1, arg2, arg3) %>
21
+ <% end %>
22
+
@@ -0,0 +1,10 @@
1
+ Document: SomeDocument
2
+ Index:
3
+ 1 Intro in SomeDocument
4
+ 2 MainPart in SomeDocument
5
+ 3 Summary in SomeDocument
6
+ by MyName
7
+ ----------------
8
+ *** Intro ***
9
+ *** MainPart ***
10
+ *** Summary ***
@@ -0,0 +1,176 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rgen/transformer'
5
+ require 'rgen/environment'
6
+
7
+ class TransformerTest < Test::Unit::TestCase
8
+
9
+ class ModelIn
10
+ attr_accessor :name
11
+ end
12
+
13
+ class ModelAIn
14
+ attr_accessor :name
15
+ attr_accessor :modelB
16
+ end
17
+
18
+ class ModelBIn
19
+ attr_accessor :name
20
+ attr_accessor :modelA
21
+ end
22
+
23
+ class ModelCIn
24
+ attr_accessor :number
25
+ end
26
+
27
+ class ModelOut
28
+ attr_accessor :name
29
+ end
30
+
31
+ class ModelAOut
32
+ attr_accessor :name
33
+ attr_accessor :modelB
34
+ end
35
+
36
+ class ModelBOut
37
+ attr_accessor :name
38
+ attr_accessor :modelA
39
+ end
40
+
41
+ class ModelCOut
42
+ attr_accessor :number
43
+ end
44
+
45
+ class MyTransformer < RGen::Transformer
46
+ attr_reader :modelInTrans_count
47
+ attr_reader :modelAInTrans_count
48
+ attr_reader :modelBInTrans_count
49
+
50
+ transform ModelIn, :to => ModelOut do
51
+ # aribitrary ruby code may be placed before the hash creating the output element
52
+ @modelInTrans_count ||= 0; @modelInTrans_count += 1
53
+ { :name => name }
54
+ end
55
+
56
+ transform ModelAIn, :to => ModelAOut do
57
+ @modelAInTrans_count ||= 0; @modelAInTrans_count += 1
58
+ { :name => name, :modelB => trans(modelB) }
59
+ end
60
+
61
+ transform ModelBIn, :to => ModelBOut do
62
+ @modelBInTrans_count ||= 0; @modelBInTrans_count += 1
63
+ { :name => name, :modelA => trans(modelA) }
64
+ end
65
+
66
+ transform ModelCIn, :to => ModelCOut, :if => :largeNumber do
67
+ # a method can be called anywhere in a transformer block
68
+ { :number => duplicateNumber }
69
+ end
70
+
71
+ transform ModelCIn, :to => ModelCOut, :if => :smallNumber do
72
+ { :number => number / 2 }
73
+ end
74
+
75
+ method :largeNumber do
76
+ number > 1000
77
+ end
78
+
79
+ method :smallNumber do
80
+ number < 500
81
+ end
82
+
83
+ method :duplicateNumber do
84
+ number * 2;
85
+ end
86
+
87
+ end
88
+
89
+ class MyTransformer2 < RGen::Transformer
90
+ # check that subclasses are independent (i.e. do not share the rules)
91
+ transform ModelIn, :to => ModelOut do
92
+ { :name => name }
93
+ end
94
+ end
95
+
96
+ def test_transformer
97
+ from = ModelIn.new
98
+ from.name = "TestName"
99
+ env_out = RGen::Environment.new
100
+ t = MyTransformer.new(:env_in, env_out)
101
+ assert t.trans(from).is_a?(ModelOut)
102
+ assert_equal "TestName", t.trans(from).name
103
+ assert_equal 1, env_out.elements.size
104
+ assert_equal env_out.elements.first, t.trans(from)
105
+ assert_equal 1, t.modelInTrans_count
106
+ end
107
+
108
+ def test_transformer_array
109
+ froms = [ModelIn.new, ModelIn.new]
110
+ froms[0].name = "M1"
111
+ froms[1].name = "M2"
112
+ env_out = RGen::Environment.new
113
+ t = MyTransformer.new(:env_in, env_out)
114
+ assert t.trans(froms).is_a?(Array)
115
+ assert t.trans(froms)[0].is_a?(ModelOut)
116
+ assert_equal "M1", t.trans(froms)[0].name
117
+ assert t.trans(froms)[1].is_a?(ModelOut)
118
+ assert_equal "M2", t.trans(froms)[1].name
119
+ assert_equal 2, env_out.elements.size
120
+ assert (t.trans(froms)-env_out.elements).empty?
121
+ assert_equal 2, t.modelInTrans_count
122
+ end
123
+
124
+ def test_transformer_cyclic
125
+ # setup a cyclic dependency between fromA and fromB
126
+ fromA = ModelAIn.new
127
+ fromB = ModelBIn.new
128
+ fromA.modelB = fromB
129
+ fromA.name = "ModelA"
130
+ fromB.modelA = fromA
131
+ fromB.name = "ModelB"
132
+ env_out = RGen::Environment.new
133
+ t = MyTransformer.new(:env_in, env_out)
134
+ # check that trans resolves the cycle correctly (no endless loop)
135
+ # both elements, fromA and fromB will be transformed with the transformation
136
+ # of the first element, either fromA or fromB
137
+ assert t.trans(fromA).is_a?(ModelAOut)
138
+ assert_equal "ModelA", t.trans(fromA).name
139
+ assert t.trans(fromA).modelB.is_a?(ModelBOut)
140
+ assert_equal "ModelB", t.trans(fromA).modelB.name
141
+ assert_equal t.trans(fromA), t.trans(fromA).modelB.modelA
142
+ assert_equal t.trans(fromB), t.trans(fromA).modelB
143
+ assert_equal 2, env_out.elements.size
144
+ assert (env_out.elements - [t.trans(fromA), t.trans(fromB)]).empty?
145
+ assert_equal 1, t.modelAInTrans_count
146
+ assert_equal 1, t.modelBInTrans_count
147
+ end
148
+
149
+ def test_transformer_conditional
150
+ froms = [ModelCIn.new, ModelCIn.new, ModelCIn.new]
151
+ froms[0].number = 100
152
+ froms[1].number = 1000
153
+ froms[2].number = 2000
154
+
155
+ env_out = RGen::Environment.new
156
+ t = MyTransformer.new(:env_in, env_out)
157
+
158
+ assert t.trans(froms).is_a?(Array)
159
+ assert_equal 2, t.trans(froms).size
160
+
161
+ # this one matched the smallNumber rule
162
+ assert t.trans(froms[0]).is_a?(ModelCOut)
163
+ assert_equal 50, t.trans(froms[0]).number
164
+
165
+ # this one did not match any rule
166
+ assert t.trans(froms[1]).nil?
167
+
168
+ # this one matched the largeNumber rule
169
+ assert t.trans(froms[2]).is_a?(ModelCOut)
170
+ assert_equal 4000, t.trans(froms[2]).number
171
+
172
+ # elements in environment are the same as the ones returned
173
+ assert_equal 2, env_out.elements.size
174
+ assert (t.trans(froms)-env_out.elements).empty?
175
+ end
176
+ end