rgen 0.6.1 → 0.6.2

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 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.1"
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
- 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)
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
- end
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
- # prerequisits:
7
- # * containment relations must be bidirectionsl
8
- # * local name stored in single attribute +@attribute_name+ for all classes
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
- (element.is_a?(RGen::MetamodelBuilder::MMProxy) && element.targetIdentifier) || qualified_name(element)
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
- localIdent = ((element.respond_to?(@attribute_name) && element.getGeneric(@attribute_name)) || "").strip
26
- parentRef = element.class.ecore.eAllReferences.select{|r| r.eOpposite && r.eOpposite.containment}.first
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 localIdent.size > 0
30
- parentIdent = qualified_name(parent)
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 : "") + localIdent
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
- 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
-
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
- assert_raise StandardError do
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
+
data/test/rgen_test.rb CHANGED
@@ -22,4 +22,5 @@ require 'metamodel_order_test'
22
22
  require 'metamodel_from_ecore_test'
23
23
  require 'util_test'
24
24
  require 'model_fragment_test'
25
+ require 'qualified_name_provider_test'
25
26