rgen 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/MIT-LICENSE +20 -0
- data/README +73 -0
- data/lib/ea/xmi_class_instantiator.rb +45 -0
- data/lib/ea/xmi_helper.rb +26 -0
- data/lib/ea/xmi_metamodel.rb +19 -0
- data/lib/ea/xmi_object_instantiator.rb +42 -0
- data/lib/ea/xmi_to_classmodel.rb +78 -0
- data/lib/ea/xmi_to_objectmodel.rb +89 -0
- data/lib/mmgen/metamodel_generator.rb +19 -0
- data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +71 -0
- data/lib/mmgen/mmgen.rb +21 -0
- data/lib/mmgen/templates/uml_classmodel.tpl +63 -0
- data/lib/rgen/array_extensions.rb +23 -0
- data/lib/rgen/auto_class_creator.rb +56 -0
- data/lib/rgen/environment.rb +57 -0
- data/lib/rgen/metamodel_builder.rb +102 -0
- data/lib/rgen/metamodel_builder/build_helper.rb +29 -0
- data/lib/rgen/metamodel_builder/builder_extensions.rb +191 -0
- data/lib/rgen/metamodel_builder/builder_runtime.rb +67 -0
- data/lib/rgen/name_helper.rb +18 -0
- data/lib/rgen/template_language.rb +169 -0
- data/lib/rgen/template_language/directory_template_container.rb +51 -0
- data/lib/rgen/template_language/output_handler.rb +84 -0
- data/lib/rgen/template_language/template_container.rb +153 -0
- data/lib/rgen/template_language/template_helper.rb +26 -0
- data/lib/rgen/transformer.rb +316 -0
- data/lib/rgen/xml_instantiator/dependency_resolver.rb +23 -0
- data/lib/rgen/xml_instantiator/xml_instantiator.rb +78 -0
- data/lib/rgen/xml_instantiator/xml_parser.rb +39 -0
- data/lib/uml/objectmodel_instantiator.rb +53 -0
- data/lib/uml/uml_classmodel.rb +92 -0
- data/lib/uml/uml_objectmodel.rb +65 -0
- data/test/array_extensions_test.rb +54 -0
- data/test/environment_test.rb +47 -0
- data/test/metamodel_builder_test.rb +175 -0
- data/test/metamodel_generator_test.rb +45 -0
- data/test/metamodel_generator_test/TestModel.rb +40 -0
- data/test/metamodel_generator_test/expected_result.txt +40 -0
- data/test/output_handler_test.rb +40 -0
- data/test/rgen_test.rb +13 -0
- data/test/template_language_test.rb +46 -0
- data/test/template_language_test/expected_result.txt +10 -0
- data/test/template_language_test/templates/content/chapter.tpl +5 -0
- data/test/template_language_test/templates/index/c/cmod.tpl +1 -0
- data/test/template_language_test/templates/index/chapter.tpl +3 -0
- data/test/template_language_test/templates/root.tpl +22 -0
- data/test/template_language_test/testout.txt +10 -0
- data/test/transformer_test.rb +176 -0
- data/test/xmi_class_instantiator_test.rb +107 -0
- data/test/xmi_instantiator_test/testmodel.eap +0 -0
- data/test/xmi_instantiator_test/testmodel.xml +962 -0
- data/test/xmi_object_instantiator_test.rb +65 -0
- 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
|
data/test/rgen_test.rb
ADDED
@@ -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 @@
|
|
1
|
+
<% define 'cmod' do %>Module C is special !<% 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,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
|