rgen 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/Rakefile +1 -1
- data/lib/rgen/array_extensions.rb +35 -23
- data/lib/rgen/serializer/qualified_name_provider.rb +14 -12
- data/test/array_extensions_test.rb +50 -46
- data/test/metamodel_builder_test.rb +38 -19
- data/test/qualified_name_provider_test.rb +48 -0
- data/test/rgen_test.rb +1 -0
- data/test/testmodel/ea_testmodel_regenerated.xml +583 -583
- metadata +4 -3
data/CHANGELOG
CHANGED
@@ -161,3 +161,8 @@
|
|
161
161
|
* Fixed ModelFragment#elements not containing root elements
|
162
162
|
* Added optional output of invalidation reason to FileCacheMap#load_data
|
163
163
|
|
164
|
+
=0.6.2
|
165
|
+
|
166
|
+
* Made qualified name provider work with unidirectional containment references
|
167
|
+
* Fixed array_extension breaking the Hash[] method
|
168
|
+
|
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rdoc/task'
|
|
3
3
|
|
4
4
|
RGenGemSpec = Gem::Specification.new do |s|
|
5
5
|
s.name = %q{rgen}
|
6
|
-
s.version = "0.6.
|
6
|
+
s.version = "0.6.2"
|
7
7
|
s.date = Time.now.strftime("%Y-%m-%d")
|
8
8
|
s.summary = %q{Ruby Modelling and Generator Framework}
|
9
9
|
s.email = %q{martin dot thiede at gmx de}
|
@@ -5,27 +5,39 @@ require 'rgen/metamodel_builder'
|
|
5
5
|
|
6
6
|
class Array
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
super unless size == 0 or compact.any?{|e| e.is_a? RGen::MetamodelBuilder::MMBase}
|
14
|
-
# use an array to build the result to achiev similar ordering
|
15
|
-
result = []
|
16
|
-
inResult = {}
|
17
|
-
compact.each do |e|
|
18
|
-
if e.is_a? RGen::MetamodelBuilder::MMBase
|
19
|
-
((o=e.send(m)).is_a?(Array) ? o : [o] ).each do |v|
|
20
|
-
next if inResult[v.object_id]
|
21
|
-
inResult[v.object_id] = true
|
22
|
-
result << v
|
23
|
-
end
|
24
|
-
else
|
25
|
-
raise StandardError.new("Trying to call a method on an array element not a RGen MMBase")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
result.compact
|
29
|
-
end
|
8
|
+
def >>(method)
|
9
|
+
compact.inject([]) { |r,e| r | ( (o=e.send(method)).is_a?(Array) ? o : [o] ) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(m, *args)
|
30
13
|
|
31
|
-
|
14
|
+
# This extensions has the side effect that it allows to call any method on any
|
15
|
+
# empty array with an empty array as the result. This behavior is required for
|
16
|
+
# navigating models.
|
17
|
+
#
|
18
|
+
# This is a problem for Hash[] called with an (empty) array of tupels.
|
19
|
+
# It will call to_hash expecting a Hash as the result. When it gets an array instead,
|
20
|
+
# it fails with an exception. Make sure it gets a NoMethodException as without this
|
21
|
+
# extension and it will catch that and return an empty hash as expected.
|
22
|
+
#
|
23
|
+
return super unless (size == 0 &&
|
24
|
+
m != :to_hash) ||
|
25
|
+
compact.any?{|e| e.is_a? RGen::MetamodelBuilder::MMBase}
|
26
|
+
# use an array to build the result to achiev similar ordering
|
27
|
+
result = []
|
28
|
+
inResult = {}
|
29
|
+
compact.each do |e|
|
30
|
+
if e.is_a? RGen::MetamodelBuilder::MMBase
|
31
|
+
((o=e.send(m)).is_a?(Array) ? o : [o] ).each do |v|
|
32
|
+
next if inResult[v.object_id]
|
33
|
+
inResult[v.object_id] = true
|
34
|
+
result << v
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise StandardError.new("Trying to call a method on an array element not a RGen MMBase")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -2,10 +2,10 @@ module RGen
|
|
2
2
|
|
3
3
|
module Serializer
|
4
4
|
|
5
|
-
# simple identifier calculation based on qualified names
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
5
|
+
# simple identifier calculation based on qualified names.
|
6
|
+
# as a prerequisit, elements must have a local name stored in single attribute +attribute_name+.
|
7
|
+
# there may be classes without the name attribute though and there may be elements without a
|
8
|
+
# local name. in both cases the element will have the same qualified name as its container.
|
9
9
|
#
|
10
10
|
class QualifiedNameProvider
|
11
11
|
|
@@ -17,23 +17,25 @@ class QualifiedNameProvider
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def identifier(element)
|
20
|
-
|
20
|
+
if element.is_a?(RGen::MetamodelBuilder::MMProxy)
|
21
|
+
element.targetIdentifier
|
22
|
+
else
|
23
|
+
qualified_name(element)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
def qualified_name(element)
|
24
28
|
return @qualified_name_cache[element] if @qualified_name_cache[element]
|
25
|
-
|
26
|
-
|
27
|
-
parent = parentRef && element.getGeneric(parentRef.name)
|
29
|
+
local_ident = ((element.respond_to?(@attribute_name) && element.getGeneric(@attribute_name)) || "").strip
|
30
|
+
parent = element.eContainer
|
28
31
|
if parent
|
29
|
-
if
|
30
|
-
|
31
|
-
result = parentIdent + @separator + localIdent
|
32
|
+
if local_ident.size > 0
|
33
|
+
result = qualified_name(parent) + @separator + local_ident
|
32
34
|
else
|
33
35
|
result = qualified_name(parent)
|
34
36
|
end
|
35
37
|
else
|
36
|
-
result = (@leading_separator ? @separator : "") +
|
38
|
+
result = (@leading_separator ? @separator : "") + local_ident
|
37
39
|
end
|
38
40
|
@qualified_name_cache[element] = result
|
39
41
|
end
|
@@ -5,50 +5,54 @@ require 'rgen/array_extensions'
|
|
5
5
|
|
6
6
|
class ArrayExtensionsTest < Test::Unit::TestCase
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
8
|
+
def test_element_methods
|
9
|
+
c = Struct.new("SomeClass",:name,:age)
|
10
|
+
a = []
|
11
|
+
a << c.new('MyName',33)
|
12
|
+
a << c.new('YourName',22)
|
13
|
+
assert_equal ["MyName", "YourName"], a >> :name
|
14
|
+
assert_raise NoMethodError do
|
15
|
+
a.name
|
16
|
+
end
|
17
|
+
assert_equal [33, 22], a>>:age
|
18
|
+
assert_raise NoMethodError do
|
19
|
+
a.age
|
20
|
+
end
|
21
|
+
# unfortunately, any method can be called on an empty array
|
22
|
+
assert_equal [], [].age
|
23
|
+
end
|
24
|
+
|
25
|
+
class MMBaseClass < RGen::MetamodelBuilder::MMBase
|
26
|
+
has_attr 'name'
|
27
|
+
has_attr 'age', Integer
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_with_mmbase
|
31
|
+
e1 = MMBaseClass.new
|
32
|
+
e1.name = "MyName"
|
33
|
+
e1.age = 33
|
34
|
+
e2 = MMBaseClass.new
|
35
|
+
e2.name = "YourName"
|
36
|
+
e2.age = 22
|
37
|
+
a = [e1, e2]
|
38
|
+
assert_equal ["MyName", "YourName"], a >> :name
|
39
|
+
assert_equal ["MyName", "YourName"], a.name
|
40
|
+
assert_equal [33, 22], a>>:age
|
41
|
+
assert_equal [33, 22], a.age
|
42
|
+
# put something into the array that is not an MMBase
|
43
|
+
a << "not a MMBase"
|
44
|
+
# the dot operator will tell that there is something not a MMBase
|
45
|
+
assert_raise StandardError do
|
46
|
+
a.age
|
47
|
+
end
|
48
|
+
# the >> operator will try to call the method anyway
|
49
|
+
assert_raise NoMethodError do
|
50
|
+
a >> :age
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_hash_square
|
55
|
+
assert_equal({}, Hash[[]])
|
56
|
+
end
|
57
|
+
|
54
58
|
end
|
@@ -167,9 +167,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
167
167
|
assert_equal "TestName", sc.name
|
168
168
|
sc.name = nil
|
169
169
|
assert_equal nil, sc.name
|
170
|
-
assert_raise StandardError do
|
170
|
+
err = assert_raise StandardError do
|
171
171
|
sc.name = 5
|
172
172
|
end
|
173
|
+
assert_match /In (\w+::)+SimpleClass : Can not use a Fixnum where a String is expected/, err.message
|
173
174
|
assert_equal "EString", mm::SimpleClass.ecore.eAttributes.find{|a| a.name=="name"}.eType.name
|
174
175
|
|
175
176
|
assert_equal "xtest", sc.stringWithDefault
|
@@ -195,12 +196,14 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
195
196
|
assert_equal false, sc.allowed
|
196
197
|
sc.allowed = nil
|
197
198
|
assert_equal nil, sc.allowed
|
198
|
-
assert_raise StandardError do
|
199
|
+
err = assert_raise StandardError do
|
199
200
|
sc.allowed = :someSymbol
|
200
201
|
end
|
201
|
-
|
202
|
+
assert_match /In (\w+::)+SimpleClass : Can not use a Symbol\(:someSymbol\) where a \[true,false\] is expected/, err.message
|
203
|
+
err = assert_raise StandardError do
|
202
204
|
sc.allowed = "a string"
|
203
205
|
end
|
206
|
+
assert_match /In (\w+::)+SimpleClass : Can not use a String where a \[true,false\] is expected/, err.message
|
204
207
|
assert_equal "EBoolean", mm::SimpleClass.ecore.eAttributes.find{|a| a.name=="allowed"}.eType.name
|
205
208
|
|
206
209
|
assert_respond_to sc, :kind
|
@@ -211,12 +214,14 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
211
214
|
assert_equal :extended, sc.kind
|
212
215
|
sc.kind = nil
|
213
216
|
assert_equal nil, sc.kind
|
214
|
-
assert_raise StandardError do
|
217
|
+
err = assert_raise StandardError do
|
215
218
|
sc.kind = :false
|
216
219
|
end
|
217
|
-
|
220
|
+
assert_match /In (\w+::)+SimpleClass : Can not use a Symbol\(:false\) where a \[:simple,:extended\] is expected/, err.message
|
221
|
+
err = assert_raise StandardError do
|
218
222
|
sc.kind = "a string"
|
219
223
|
end
|
224
|
+
assert_match /In (\w+::)+SimpleClass : Can not use a String where a \[:simple,:extended\] is expected/, err.message
|
220
225
|
|
221
226
|
enum = mm::SimpleClass.ecore.eAttributes.find{|a| a.name=="kind"}.eType
|
222
227
|
assert_equal ["extended", "simple"], enum.eLiterals.name.sort
|
@@ -229,9 +234,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
229
234
|
assert_respond_to o, :addLiterals
|
230
235
|
assert_respond_to o, :removeLiterals
|
231
236
|
|
232
|
-
assert_raise(StandardError) do
|
237
|
+
err = assert_raise(StandardError) do
|
233
238
|
o.addLiterals(1)
|
234
239
|
end
|
240
|
+
assert_match /In (\w+::)+ManyAttrClass : Can not use a Fixnum where a String is expected/, err.message
|
235
241
|
|
236
242
|
assert_equal [], o.literals
|
237
243
|
o.addLiterals("a")
|
@@ -263,9 +269,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
263
269
|
o.literals = ["a", "b", "c"]
|
264
270
|
assert_equal ["a", "b", "c"], o.literals
|
265
271
|
# can only take enumerables
|
266
|
-
assert_raise(StandardError) do
|
272
|
+
err = assert_raise(StandardError) do
|
267
273
|
o.literals = 1
|
268
274
|
end
|
275
|
+
assert_match /In (\w+::)+ManyAttrClass : Can not use a Fixnum where a Enumerable is expected/, err.message
|
269
276
|
|
270
277
|
o.bools = [true, false, true, false]
|
271
278
|
assert_equal [true, false, true, false], o.bools
|
@@ -309,9 +316,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
309
316
|
sc.classB = cb
|
310
317
|
assert_equal cb, sc.classB
|
311
318
|
|
312
|
-
assert_raise StandardError do
|
319
|
+
err = assert_raise StandardError do
|
313
320
|
sc.classB = ca
|
314
321
|
end
|
322
|
+
assert_match /In (\w+::)+HasOneTestClass : Can not use a (\w+::)+ClassA where a (\w+::)+ClassB is expected/, err.message
|
315
323
|
|
316
324
|
assert_equal [], mm::ClassA.ecore.eReferences
|
317
325
|
assert_equal [], mm::ClassB.ecore.eReferences
|
@@ -335,9 +343,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
335
343
|
assert_equal [ca1, ca2], o.classA
|
336
344
|
o.removeClassA(ca2)
|
337
345
|
assert_equal [ca1], o.classA
|
338
|
-
assert_raise StandardError do
|
346
|
+
err = assert_raise StandardError do
|
339
347
|
o.addClassA(mm::ClassB.new)
|
340
348
|
end
|
349
|
+
assert_match /In (\w+::)+HasManyTestClass : Can not use a (\w+::)+ClassB where a (\w+::)+ClassA is expected/, err.message
|
341
350
|
assert_equal [], mm::HasManyTestClass.ecore.eReferences.select{|r| r.many == false}
|
342
351
|
assert_equal ["classA"], mm::HasManyTestClass.ecore.eReferences.select{|r| r.many == true}.name
|
343
352
|
end
|
@@ -543,9 +552,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
543
552
|
assert ac.bClasses.include?(bc)
|
544
553
|
|
545
554
|
# put something else into the BClass
|
546
|
-
assert_raise StandardError do
|
555
|
+
err = assert_raise StandardError do
|
547
556
|
bc.addAClasses :notaaclass
|
548
557
|
end
|
558
|
+
assert_match /In (\w+::)+BClassMM : Can not use a Symbol\(:notaaclass\) where a (\w+::)+AClassMM is expected/, err.message
|
549
559
|
|
550
560
|
# remove the AClass from the BClass
|
551
561
|
bc.removeAClasses ac
|
@@ -558,9 +568,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
558
568
|
assert bc.aClasses.include?(ac)
|
559
569
|
|
560
570
|
# put something else into the AClass
|
561
|
-
assert_raise StandardError do
|
571
|
+
err = assert_raise StandardError do
|
562
572
|
ac.addBClasses :notabclass
|
563
573
|
end
|
574
|
+
assert_match /In (\w+::)+AClassMM : Can not use a Symbol\(:notabclass\) where a (\w+::)+BClassMM is expected/, err.message
|
564
575
|
|
565
576
|
# remove the BClass from the AClass
|
566
577
|
ac.removeBClasses bc
|
@@ -789,9 +800,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
789
800
|
end
|
790
801
|
|
791
802
|
def test_abstract
|
792
|
-
assert_raise StandardError do
|
803
|
+
err = assert_raise StandardError do
|
793
804
|
mm::AbstractClass.new
|
794
805
|
end
|
806
|
+
assert_match /Class (\w+::)+AbstractClass is abstract/, err.message
|
795
807
|
end
|
796
808
|
|
797
809
|
module BadDefaultValueLiteralContainer
|
@@ -835,27 +847,34 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
835
847
|
end
|
836
848
|
|
837
849
|
def test_bad_default_value_literal
|
838
|
-
assert_raise StandardError do
|
850
|
+
err = assert_raise StandardError do
|
839
851
|
BadDefaultValueLiteralContainer::Test1.call
|
840
852
|
end
|
841
|
-
|
853
|
+
assert_equal "Property integerWithDefault can not take value 1.1, expected an Integer", err.message
|
854
|
+
err = assert_raise StandardError do
|
842
855
|
BadDefaultValueLiteralContainer::Test2.call
|
843
856
|
end
|
844
|
-
|
857
|
+
assert_equal "Property integerWithDefault can not take value x, expected an Integer", err.message
|
858
|
+
err = assert_raise StandardError do
|
845
859
|
BadDefaultValueLiteralContainer::Test3.call
|
846
860
|
end
|
847
|
-
|
861
|
+
assert_equal "Property boolWithDefault can not take value 1, expected true or false", err.message
|
862
|
+
err = assert_raise StandardError do
|
848
863
|
BadDefaultValueLiteralContainer::Test4.call
|
849
864
|
end
|
850
|
-
|
865
|
+
assert_equal "Property floatWithDefault can not take value 1, expected a Float", err.message
|
866
|
+
err = assert_raise StandardError do
|
851
867
|
BadDefaultValueLiteralContainer::Test5.call
|
852
868
|
end
|
853
|
-
|
869
|
+
assert_equal "Property floatWithDefault can not take value true, expected a Float", err.message
|
870
|
+
err = assert_raise StandardError do
|
854
871
|
BadDefaultValueLiteralContainer::Test6.call
|
855
872
|
end
|
856
|
-
|
873
|
+
assert_equal "Property enumWithDefault can not take value xxx, expected one of :simple, :extended", err.message
|
874
|
+
err = assert_raise StandardError do
|
857
875
|
BadDefaultValueLiteralContainer::Test7.call
|
858
876
|
end
|
877
|
+
assert_equal "Property enumWithDefault can not take value 7, expected one of :simple, :extended", err.message
|
859
878
|
end
|
860
879
|
|
861
880
|
def test_isset_set_to_nil
|
@@ -0,0 +1,48 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rgen/metamodel_builder'
|
5
|
+
require 'rgen/serializer/qualified_name_provider'
|
6
|
+
|
7
|
+
class QualifiedNameProviderTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
class AbstractTestNode < RGen::MetamodelBuilder::MMBase
|
10
|
+
contains_many 'children', AbstractTestNode, "parent"
|
11
|
+
end
|
12
|
+
|
13
|
+
class NamedNode < AbstractTestNode
|
14
|
+
has_attr 'n', String
|
15
|
+
end
|
16
|
+
|
17
|
+
class UnnamedNode < AbstractTestNode
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_simple
|
21
|
+
root = NamedNode.new(:n => "root", :children => [
|
22
|
+
NamedNode.new(:n => "a", :children => [
|
23
|
+
NamedNode.new(:n => "a1")
|
24
|
+
]),
|
25
|
+
UnnamedNode.new(:children => [
|
26
|
+
NamedNode.new(:n => "b1")
|
27
|
+
])
|
28
|
+
])
|
29
|
+
|
30
|
+
qnp = RGen::Serializer::QualifiedNameProvider.new(:attribute_name => "n")
|
31
|
+
|
32
|
+
assert_equal "/root", qnp.identifier(root)
|
33
|
+
assert_equal "/root/a", qnp.identifier(root.children[0])
|
34
|
+
assert_equal "/root/a/a1", qnp.identifier(root.children[0].children[0])
|
35
|
+
assert_equal "/root", qnp.identifier(root.children[1])
|
36
|
+
assert_equal "/root/b1", qnp.identifier(root.children[1].children[0])
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_unnamed_root
|
40
|
+
root = UnnamedNode.new
|
41
|
+
|
42
|
+
qnp = RGen::Serializer::QualifiedNameProvider.new(:attribute_name => "n")
|
43
|
+
|
44
|
+
assert_equal "/", qnp.identifier(root)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|