rgen 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/MIT-LICENSE +2 -2
- data/Rakefile +2 -2
- data/lib/mmgen/templates/metamodel_generator.tpl +4 -5
- data/lib/rgen/instantiator/ecore_xml_instantiator.rb +31 -22
- data/lib/rgen/instantiator/json_instantiator.rb +79 -0
- data/lib/rgen/instantiator/json_parser.rb +326 -0
- data/lib/rgen/instantiator/json_parser.y +89 -0
- data/lib/rgen/instantiator/qualified_name_resolver.rb +93 -0
- data/lib/rgen/instantiator/reference_resolver.rb +44 -0
- data/lib/rgen/metamodel_builder.rb +12 -1
- data/lib/rgen/metamodel_builder/builder_extensions.rb +40 -11
- data/lib/rgen/metamodel_builder/builder_runtime.rb +19 -1
- data/lib/rgen/serializer/json_serializer.rb +120 -0
- data/lib/rgen/serializer/xmi20_serializer.rb +14 -3
- data/test/json_test.rb +91 -0
- data/test/metamodel_builder_test.rb +194 -0
- data/test/metamodel_roundtrip_test.rb +37 -3
- data/test/metamodel_roundtrip_test/TestModel.rb +2 -1
- data/test/metamodel_roundtrip_test/houseMetamodel.ecore +1 -0
- data/test/metamodel_roundtrip_test/houseMetamodel_from_ecore.rb +1 -0
- data/test/metamodel_roundtrip_test/using_builtin_types.ecore +8 -0
- data/test/metamodel_roundtrip_test/using_builtin_types_serialized.ecore +8 -0
- data/test/qualified_name_resolver_test.rb +102 -0
- data/test/reference_resolver_test.rb +50 -0
- data/test/rgen_test.rb +4 -0
- metadata +16 -14
@@ -7,7 +7,9 @@ module Serializer
|
|
7
7
|
class XMI20Serializer < XMLSerializer
|
8
8
|
|
9
9
|
def serialize(rootElement)
|
10
|
+
@referenceStrings = {}
|
10
11
|
buildReferenceStrings(rootElement, "#/")
|
12
|
+
addBuiltinReferenceStrings
|
11
13
|
attrs = attributeHash(rootElement)
|
12
14
|
attrs['xmi:version'] = "2.0"
|
13
15
|
attrs['xmlns:xmi'] = "http://www.omg.org/XMI"
|
@@ -36,7 +38,7 @@ class XMI20Serializer < XMLSerializer
|
|
36
38
|
val = element.getGeneric(a.name)
|
37
39
|
result[a.name] = val unless val.nil? || val == ""
|
38
40
|
end
|
39
|
-
eAllReferences(element).select{|r| !r.containment && !r.derived}.each do |r|
|
41
|
+
eAllReferences(element).select{|r| !r.containment && !(r.eOpposite && r.eOpposite.containment) && !r.derived}.each do |r|
|
40
42
|
targetElements = element.getGeneric(r.name)
|
41
43
|
targetElements = [targetElements] unless targetElements.is_a?(Array)
|
42
44
|
val = targetElements.collect{|te| @referenceStrings[te]}.compact.join(' ')
|
@@ -46,15 +48,24 @@ class XMI20Serializer < XMLSerializer
|
|
46
48
|
end
|
47
49
|
|
48
50
|
def buildReferenceStrings(element, string)
|
49
|
-
@referenceStrings ||= {}
|
50
51
|
@referenceStrings[element] = string
|
51
52
|
eachReferencedElement(element, containmentReferences(element)) do |r,te|
|
52
53
|
buildReferenceStrings(te, string+"/"+te.name) if te.respond_to?(:name)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
def addBuiltinReferenceStrings
|
58
|
+
pre = "ecore:EDataType http://www.eclipse.org/emf/2002/Ecore"
|
59
|
+
@referenceStrings[RGen::ECore::EString] = pre+"#//EString"
|
60
|
+
@referenceStrings[RGen::ECore::EInt] = pre+"#//EInt"
|
61
|
+
@referenceStrings[RGen::ECore::EFloat] = pre+"#//EFloat"
|
62
|
+
@referenceStrings[RGen::ECore::EBoolean] = pre+"#//EBoolean"
|
63
|
+
@referenceStrings[RGen::ECore::EJavaObject] = pre+"#//EJavaObject"
|
64
|
+
@referenceStrings[RGen::ECore::EJavaClass] = pre+"#//EJavaClass"
|
65
|
+
end
|
66
|
+
|
56
67
|
end
|
57
68
|
|
58
69
|
end
|
59
70
|
|
60
|
-
end
|
71
|
+
end
|
data/test/json_test.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rgen/environment'
|
5
|
+
require 'rgen/metamodel_builder'
|
6
|
+
require 'rgen/serializer/json_serializer'
|
7
|
+
require 'rgen/instantiator/json_instantiator'
|
8
|
+
|
9
|
+
class JsonTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
module TestMM
|
12
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
13
|
+
class TestNode < RGen::MetamodelBuilder::MMBase
|
14
|
+
has_attr 'text', String
|
15
|
+
has_attr 'integer', Integer
|
16
|
+
has_attr 'float', Float
|
17
|
+
contains_many 'childs', TestNode, 'parent'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class StringWriter < String
|
22
|
+
alias write concat
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_json_serializer
|
26
|
+
testModel = TestMM::TestNode.new(:text => "some text", :childs => [
|
27
|
+
TestMM::TestNode.new(:text => "child")])
|
28
|
+
|
29
|
+
output = StringWriter.new
|
30
|
+
ser = RGen::Serializer::JsonSerializer.new(output)
|
31
|
+
|
32
|
+
assert_equal %q({ "_class": "TestNode", "text": "some text", "childs": [
|
33
|
+
{ "_class": "TestNode", "text": "child" }] }), ser.serialize(testModel)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_json_instantiator
|
37
|
+
env = RGen::Environment.new
|
38
|
+
inst = RGen::Instantiator::JsonInstantiator.new(env, TestMM)
|
39
|
+
inst.instantiate(%q({ "_class": "TestNode", "text": "some text", "childs": [
|
40
|
+
{ "_class": "TestNode", "text": "child" }] }))
|
41
|
+
root = env.find(:class => TestMM::TestNode, :text => "some text").first
|
42
|
+
assert_not_nil root
|
43
|
+
assert_equal 1, root.childs.size
|
44
|
+
assert_equal TestMM::TestNode, root.childs.first.class
|
45
|
+
assert_equal "child", root.childs.first.text
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_json_serializer_escapes
|
49
|
+
testModel = TestMM::TestNode.new(:text => %q(some " \ \" text))
|
50
|
+
output = StringWriter.new
|
51
|
+
ser = RGen::Serializer::JsonSerializer.new(output)
|
52
|
+
|
53
|
+
assert_equal %q({ "_class": "TestNode", "text": "some \" \\ \\\" text" }), ser.serialize(testModel)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_json_instantiator_escapes
|
57
|
+
env = RGen::Environment.new
|
58
|
+
inst = RGen::Instantiator::JsonInstantiator.new(env, TestMM)
|
59
|
+
inst.instantiate(%q({ "_class": "TestNode", "text": "some \" \\ \\\\\" text" }))
|
60
|
+
assert_equal %q(some " \ \" text), env.elements.first.text
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_json_serializer_integer
|
64
|
+
testModel = TestMM::TestNode.new(:integer => 7)
|
65
|
+
output = StringWriter.new
|
66
|
+
ser = RGen::Serializer::JsonSerializer.new(output)
|
67
|
+
assert_equal %q({ "_class": "TestNode", "integer": 7 }), ser.serialize(testModel)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_json_instantiator_integer
|
71
|
+
env = RGen::Environment.new
|
72
|
+
inst = RGen::Instantiator::JsonInstantiator.new(env, TestMM)
|
73
|
+
inst.instantiate(%q({ "_class": "TestNode", "integer": 7 }))
|
74
|
+
assert_equal 7, env.elements.first.integer
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_json_serializer_float
|
78
|
+
testModel = TestMM::TestNode.new(:float => 1.23)
|
79
|
+
output = StringWriter.new
|
80
|
+
ser = RGen::Serializer::JsonSerializer.new(output)
|
81
|
+
assert_equal %q({ "_class": "TestNode", "float": 1.23 }), ser.serialize(testModel)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_json_instantiator_float
|
85
|
+
env = RGen::Environment.new
|
86
|
+
inst = RGen::Instantiator::JsonInstantiator.new(env, TestMM)
|
87
|
+
inst.instantiate(%q({ "_class": "TestNode", "float": 1.23 }))
|
88
|
+
assert_equal 1.23, env.elements.first.float
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -73,6 +73,76 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
73
73
|
assert_equal ["extended", "simple"], enum.eLiterals.name.sort
|
74
74
|
end
|
75
75
|
|
76
|
+
class ManyAttrClass < RGen::MetamodelBuilder::MMBase
|
77
|
+
has_many_attr 'literals', String
|
78
|
+
has_many_attr 'bools', Boolean
|
79
|
+
has_many_attr 'integers', Integer
|
80
|
+
has_many_attr 'enums', RGen::MetamodelBuilder::DataTypes::Enum.new([:a, :b, :c])
|
81
|
+
has_many_attr 'limitTest', Integer, :upperBound => 2
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_many_attr
|
85
|
+
o = ManyAttrClass.new
|
86
|
+
|
87
|
+
assert_respond_to o, :literals
|
88
|
+
assert_respond_to o, :addLiterals
|
89
|
+
assert_respond_to o, :removeLiterals
|
90
|
+
|
91
|
+
assert_raise(StandardError) do
|
92
|
+
o.addLiterals(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_equal [], o.literals
|
96
|
+
o.addLiterals("a")
|
97
|
+
assert_equal ["a"], o.literals
|
98
|
+
o.addLiterals("b")
|
99
|
+
assert_equal ["a", "b"], o.literals
|
100
|
+
# check for duplicates works by object identity, so there can be two strings "b"
|
101
|
+
o.addLiterals("b")
|
102
|
+
assert_equal ["a", "b", "b"], o.literals
|
103
|
+
# but the same string object "a" can only occur once
|
104
|
+
o.addLiterals(o.literals.first)
|
105
|
+
assert_equal ["a", "b", "b"], o.literals
|
106
|
+
# removing works by object identity, so providing a new string won't delete an existing one
|
107
|
+
o.removeLiterals("a")
|
108
|
+
assert_equal ["a", "b", "b"], o.literals
|
109
|
+
theA = o.literals.first
|
110
|
+
o.removeLiterals(theA)
|
111
|
+
assert_equal ["b", "b"], o.literals
|
112
|
+
# removing something which is not present has no effect
|
113
|
+
o.removeLiterals(theA)
|
114
|
+
assert_equal ["b", "b"], o.literals
|
115
|
+
o.removeLiterals(o.literals.first)
|
116
|
+
assert_equal ["b"], o.literals
|
117
|
+
o.removeLiterals(o.literals.first)
|
118
|
+
assert_equal [], o.literals
|
119
|
+
|
120
|
+
# setting multiple elements at a time
|
121
|
+
o.literals = ["a", "b", "c"]
|
122
|
+
assert_equal ["a", "b", "c"], o.literals
|
123
|
+
# can only take arrays
|
124
|
+
assert_raise(StandardError) do
|
125
|
+
o.literals = "a"
|
126
|
+
end
|
127
|
+
|
128
|
+
o.bools = [true, false, true, false]
|
129
|
+
assert_equal [true, false], o.bools
|
130
|
+
|
131
|
+
o.integers = [1, 2, 2, 3, 3]
|
132
|
+
assert_equal [1, 2, 3], o.integers
|
133
|
+
|
134
|
+
o.enums = [:a, :a, :b, :c, :c]
|
135
|
+
assert_equal [:a, :b, :c], o.enums
|
136
|
+
|
137
|
+
lit = ManyAttrClass.ecore.eAttributes.find{|a| a.name == "literals"}
|
138
|
+
assert lit.is_a?(RGen::ECore::EAttribute)
|
139
|
+
assert lit.many
|
140
|
+
|
141
|
+
lim = ManyAttrClass.ecore.eAttributes.find{|a| a.name == "limitTest"}
|
142
|
+
assert lit.many
|
143
|
+
assert_equal 2, lim.upperBound
|
144
|
+
end
|
145
|
+
|
76
146
|
class ClassA < RGen::MetamodelBuilder::MMBase
|
77
147
|
# metamodel accessors must work independent of the ==() method
|
78
148
|
module ClassModule
|
@@ -493,5 +563,129 @@ class MetamodelBuilderTest < Test::Unit::TestCase
|
|
493
563
|
somePackage = SomePackage.ecore
|
494
564
|
assert_equal somePackage.eSubpackages.first.object_id, subPackage.object_id
|
495
565
|
end
|
566
|
+
|
567
|
+
def test_proxy
|
568
|
+
p = RGen::MetamodelBuilder::MMProxy.new("test")
|
569
|
+
assert_equal "test", p.targetIdentifier
|
570
|
+
p.targetIdentifier = 123
|
571
|
+
assert_equal 123, p.targetIdentifier
|
572
|
+
end
|
573
|
+
|
574
|
+
def test_proxies_has_one
|
575
|
+
e = HasOneTestClass.new
|
576
|
+
proxy = RGen::MetamodelBuilder::MMProxy.new
|
577
|
+
e.classA = proxy
|
578
|
+
assert_equal proxy, e.classA
|
579
|
+
a = ClassA.new
|
580
|
+
# displace proxy
|
581
|
+
e.classA = a
|
582
|
+
assert_equal a, e.classA
|
583
|
+
# displace by proxy
|
584
|
+
e.classA = proxy
|
585
|
+
assert_equal proxy, e.classA
|
586
|
+
end
|
587
|
+
|
588
|
+
def test_proxies_has_many
|
589
|
+
e = HasManyTestClass.new
|
590
|
+
proxy = RGen::MetamodelBuilder::MMProxy.new
|
591
|
+
e.addClassA(proxy)
|
592
|
+
assert_equal [proxy], e.classA
|
593
|
+
# again
|
594
|
+
e.addClassA(proxy)
|
595
|
+
assert_equal [proxy], e.classA
|
596
|
+
proxy2 = RGen::MetamodelBuilder::MMProxy.new
|
597
|
+
e.addClassA(proxy2)
|
598
|
+
assert_equal [proxy, proxy2], e.classA
|
599
|
+
e.removeClassA(proxy)
|
600
|
+
assert_equal [proxy2], e.classA
|
601
|
+
# again
|
602
|
+
e.removeClassA(proxy)
|
603
|
+
assert_equal [proxy2], e.classA
|
604
|
+
e.removeClassA(proxy2)
|
605
|
+
assert_equal [], e.classA
|
606
|
+
end
|
607
|
+
|
608
|
+
def test_proxies_one_to_one
|
609
|
+
ea = AClassOO.new
|
610
|
+
eb = BClassOO.new
|
611
|
+
proxy1 = RGen::MetamodelBuilder::MMProxy.new
|
612
|
+
proxy2 = RGen::MetamodelBuilder::MMProxy.new
|
613
|
+
ea.bClass = proxy1
|
614
|
+
eb.aClass = proxy2
|
615
|
+
assert_equal proxy1, ea.bClass
|
616
|
+
assert_equal proxy2, eb.aClass
|
617
|
+
# displace proxies
|
618
|
+
ea.bClass = eb
|
619
|
+
assert_equal eb, ea.bClass
|
620
|
+
assert_equal ea, eb.aClass
|
621
|
+
# displace by proxy
|
622
|
+
ea.bClass = proxy1
|
623
|
+
assert_equal proxy1, ea.bClass
|
624
|
+
assert_nil eb.aClass
|
625
|
+
end
|
626
|
+
|
627
|
+
def test_proxies_one_to_many
|
628
|
+
eo = OneClass.new
|
629
|
+
em = ManyClass.new
|
630
|
+
proxy1 = RGen::MetamodelBuilder::MMProxy.new
|
631
|
+
proxy2 = RGen::MetamodelBuilder::MMProxy.new
|
632
|
+
eo.addManyClasses(proxy1)
|
633
|
+
assert_equal [proxy1], eo.manyClasses
|
634
|
+
em.oneClass = proxy2
|
635
|
+
assert_equal proxy2, em.oneClass
|
636
|
+
# displace proxies at many side
|
637
|
+
# adding em will set em.oneClass to eo and displace the proxy from em.oneClass
|
638
|
+
eo.addManyClasses(em)
|
639
|
+
assert_equal [proxy1, em], eo.manyClasses
|
640
|
+
assert_equal eo, em.oneClass
|
641
|
+
eo.removeManyClasses(proxy1)
|
642
|
+
assert_equal [em], eo.manyClasses
|
643
|
+
assert_equal eo, em.oneClass
|
644
|
+
# displace by proxy
|
645
|
+
em.oneClass = proxy2
|
646
|
+
assert_equal [], eo.manyClasses
|
647
|
+
assert_equal proxy2, em.oneClass
|
648
|
+
# displace proxies at one side
|
649
|
+
em.oneClass = eo
|
650
|
+
assert_equal [em], eo.manyClasses
|
651
|
+
assert_equal eo, em.oneClass
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_proxies_many_to_many
|
655
|
+
e1 = AClassMM.new
|
656
|
+
e2 = BClassMM.new
|
657
|
+
proxy1 = RGen::MetamodelBuilder::MMProxy.new
|
658
|
+
proxy2 = RGen::MetamodelBuilder::MMProxy.new
|
659
|
+
e1.addBClasses(proxy1)
|
660
|
+
e2.addAClasses(proxy2)
|
661
|
+
assert_equal [proxy1], e1.bClasses
|
662
|
+
assert_equal [proxy2], e2.aClasses
|
663
|
+
e1.addBClasses(e2)
|
664
|
+
assert_equal [proxy1, e2], e1.bClasses
|
665
|
+
assert_equal [proxy2, e1], e2.aClasses
|
666
|
+
e1.removeBClasses(proxy1)
|
667
|
+
e2.removeAClasses(proxy2)
|
668
|
+
assert_equal [e2], e1.bClasses
|
669
|
+
assert_equal [e1], e2.aClasses
|
670
|
+
end
|
496
671
|
|
672
|
+
def test_genericAccess
|
673
|
+
e1 = OneClass.new
|
674
|
+
e2 = ManyClass.new
|
675
|
+
e3 = OneClass.new
|
676
|
+
e4 = ManyClass.new
|
677
|
+
# use on "many" feature
|
678
|
+
e1.setOrAddGeneric("manyClasses", e2)
|
679
|
+
assert_equal [e2], e1.manyClasses
|
680
|
+
assert_equal [e2], e1.getGeneric("manyClasses")
|
681
|
+
assert_equal [e2], e1.getGenericAsArray("manyClasses")
|
682
|
+
# use on "one" feature
|
683
|
+
e2.setOrAddGeneric("oneClass", e3)
|
684
|
+
assert_equal e3, e2.oneClass
|
685
|
+
assert_equal e3, e2.getGeneric("oneClass")
|
686
|
+
assert_equal [e3], e2.getGenericAsArray("oneClass")
|
687
|
+
assert_nil e4.getGeneric("oneClass")
|
688
|
+
assert_equal [], e4.getGenericAsArray("oneClass")
|
689
|
+
end
|
690
|
+
|
497
691
|
end
|
@@ -7,7 +7,7 @@ require 'mmgen/metamodel_generator'
|
|
7
7
|
require 'rgen/instantiator/ecore_xml_instantiator'
|
8
8
|
require 'rgen/serializer/xmi20_serializer'
|
9
9
|
|
10
|
-
class
|
10
|
+
class MetamodelRoundtripTest < Test::Unit::TestCase
|
11
11
|
|
12
12
|
TEST_DIR = File.dirname(__FILE__)+"/metamodel_roundtrip_test"
|
13
13
|
|
@@ -57,5 +57,39 @@ class MetamodelGeneratorTest < Test::Unit::TestCase
|
|
57
57
|
ser.serialize(HouseMetamodel.ecore)
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
61
|
-
|
60
|
+
|
61
|
+
BuiltinTypesTestEcore = TEST_DIR+"/using_builtin_types.ecore"
|
62
|
+
|
63
|
+
def test_ecore_serializer_builtin_types
|
64
|
+
mm = RGen::ECore::EPackage.new(:name => "P1", :eClassifiers => [
|
65
|
+
RGen::ECore::EClass.new(:name => "C1", :eStructuralFeatures => [
|
66
|
+
RGen::ECore::EAttribute.new(:name => "a1", :eType => RGen::ECore::EString),
|
67
|
+
RGen::ECore::EAttribute.new(:name => "a2", :eType => RGen::ECore::EInt),
|
68
|
+
RGen::ECore::EAttribute.new(:name => "a3", :eType => RGen::ECore::EFloat),
|
69
|
+
RGen::ECore::EAttribute.new(:name => "a4", :eType => RGen::ECore::EBoolean)
|
70
|
+
])
|
71
|
+
])
|
72
|
+
outfile = TEST_DIR+"/using_builtin_types_serialized.ecore"
|
73
|
+
File.open(outfile, "w") do |f|
|
74
|
+
ser = RGen::Serializer::XMI20Serializer.new(f)
|
75
|
+
ser.serialize(mm)
|
76
|
+
end
|
77
|
+
assert_equal(File.read(BuiltinTypesTestEcore), File.read(outfile))
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_ecore_instantiator_builtin_types
|
81
|
+
env = RGen::Environment.new
|
82
|
+
File.open(BuiltinTypesTestEcore) { |f|
|
83
|
+
ECoreXMLInstantiator.new(env).instantiate(f.read)
|
84
|
+
}
|
85
|
+
a1 = env.find(:class => RGen::ECore::EAttribute, :name => "a1").first
|
86
|
+
assert_equal(RGen::ECore::EString, a1.eType)
|
87
|
+
a2 = env.find(:class => RGen::ECore::EAttribute, :name => "a2").first
|
88
|
+
assert_equal(RGen::ECore::EInt, a2.eType)
|
89
|
+
a3 = env.find(:class => RGen::ECore::EAttribute, :name => "a3").first
|
90
|
+
assert_equal(RGen::ECore::EFloat, a3.eType)
|
91
|
+
a4 = env.find(:class => RGen::ECore::EAttribute, :name => "a4").first
|
92
|
+
assert_equal(RGen::ECore::EBoolean, a4.eType)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -15,6 +15,7 @@ module HouseMetamodel
|
|
15
15
|
class Person < RGen::MetamodelBuilder::MMBase
|
16
16
|
annotation 'complexity' => '1', 'date_created' => '2006-06-27 08:34:23', 'date_modified' => '2006-06-27 08:34:26', 'ea_ntype' => '0', 'ea_stype' => 'Class', 'gentype' => 'Java', 'isSpecification' => 'false', 'package' => 'EAPK_A1B83D59_CAE1_422c_BA5F_D3624D7156AD', 'package_name' => 'HouseMetamodel', 'phase' => '1.0', 'status' => 'Proposed', 'style' => 'BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=0;HSwimLanes=0;BorderStyle=0;', 'tagged' => '0', 'version' => '1.0'
|
17
17
|
has_attr 'sex', SexEnum
|
18
|
+
has_many_attr 'nicknames', String
|
18
19
|
end
|
19
20
|
|
20
21
|
class House < RGen::MetamodelBuilder::MMBase
|
@@ -65,4 +66,4 @@ end
|
|
65
66
|
HouseMetamodel::House.contains_many 'room', HouseMetamodel::Rooms::Room, 'house', :lowerBound => 1 do
|
66
67
|
# only an opposite annotation
|
67
68
|
opposite_annotation 'containment' => 'Unspecified'
|
68
|
-
end
|
69
|
+
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
<eStructuralFeatures xsi:type="ecore:EReference" name="house" upperBound="-1"
|
21
21
|
eType="#//House"/>
|
22
22
|
<eStructuralFeatures xsi:type="ecore:EAttribute" name="sex" eType="#//SexEnum"/>
|
23
|
+
<eStructuralFeatures xsi:type="ecore:EAttribute" name="nicknames" upperBound="-1" eType="#//String"/>
|
23
24
|
</eClassifiers>
|
24
25
|
<eClassifiers xsi:type="ecore:EDataType" name="String" instanceClassName="java.lang.String"/>
|
25
26
|
<eClassifiers xsi:type="ecore:EEnum" name="SexEnum">
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<ecore:EPackage xmi:version="2.0" name="P1" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore">
|
2
|
+
<eClassifiers name="C1" xsi:type="ecore:EClass">
|
3
|
+
<eStructuralFeatures name="a1" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" unique="true"/>
|
4
|
+
<eStructuralFeatures name="a2" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" unique="true"/>
|
5
|
+
<eStructuralFeatures name="a3" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat" unique="true"/>
|
6
|
+
<eStructuralFeatures name="a4" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean" unique="true"/>
|
7
|
+
</eClassifiers>
|
8
|
+
</ecore:EPackage>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<ecore:EPackage xmi:version="2.0" name="P1" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore">
|
2
|
+
<eClassifiers name="C1" xsi:type="ecore:EClass">
|
3
|
+
<eStructuralFeatures name="a1" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" unique="true"/>
|
4
|
+
<eStructuralFeatures name="a2" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" unique="true"/>
|
5
|
+
<eStructuralFeatures name="a3" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat" unique="true"/>
|
6
|
+
<eStructuralFeatures name="a4" derived="false" transient="false" changeable="true" unsettable="false" iD="false" xsi:type="ecore:EAttribute" upperBound="1" ordered="true" volatile="false" lowerBound="0" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean" unique="true"/>
|
7
|
+
</eClassifiers>
|
8
|
+
</ecore:EPackage>
|
@@ -0,0 +1,102 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rgen/metamodel_builder'
|
5
|
+
require 'rgen/instantiator/qualified_name_resolver'
|
6
|
+
|
7
|
+
class QualifiedNameResolverTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
class TestNode < RGen::MetamodelBuilder::MMBase
|
10
|
+
has_attr 'name', String
|
11
|
+
has_one 'nextSibling', TestNode
|
12
|
+
contains_many 'children', TestNode, "parent"
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestNode2 < RGen::MetamodelBuilder::MMBase
|
16
|
+
has_attr 'cname', String
|
17
|
+
has_one 'nextSibling', TestNode2
|
18
|
+
contains_many 'children', TestNode2, "parent"
|
19
|
+
end
|
20
|
+
|
21
|
+
class TestNode3 < RGen::MetamodelBuilder::MMBase
|
22
|
+
has_attr 'name', String
|
23
|
+
contains_one 'child', TestNode3, "parent"
|
24
|
+
end
|
25
|
+
|
26
|
+
def testModel
|
27
|
+
[TestNode.new(:name => "Root1", :children => [
|
28
|
+
TestNode.new(:name => "Sub11"),
|
29
|
+
TestNode.new(:name => "Sub12", :children => [
|
30
|
+
TestNode.new(:name => "Sub121")])]),
|
31
|
+
TestNode.new(:name => "Root2", :children => [
|
32
|
+
TestNode.new(:name => "Sub21", :children => [
|
33
|
+
TestNode.new(:name => "Sub211")])]),
|
34
|
+
TestNode.new(:name => "Root3"),
|
35
|
+
TestNode.new(:name => "Root3")
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
def testModel2
|
40
|
+
[TestNode2.new(:cname => "Root1", :children => [
|
41
|
+
TestNode2.new(:cname => "Sub11")])]
|
42
|
+
end
|
43
|
+
|
44
|
+
def testModel3
|
45
|
+
[TestNode3.new(:name => "Root1", :child =>
|
46
|
+
TestNode3.new(:name => "Sub11", :child =>
|
47
|
+
TestNode3.new(:name => "Sub111")))]
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_customNameAttribute
|
51
|
+
model = testModel2
|
52
|
+
res = RGen::Instantiator::QualifiedNameResolver.new(model, :nameAttribute => "cname")
|
53
|
+
assert_equal model[0], res.resolveIdentifier("/Root1")
|
54
|
+
assert_equal model[0].children[0], res.resolveIdentifier("/Root1/Sub11")
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_customSeparator
|
58
|
+
model = testModel
|
59
|
+
res = RGen::Instantiator::QualifiedNameResolver.new(model, :separator => "|")
|
60
|
+
assert_equal model[0], res.resolveIdentifier("|Root1")
|
61
|
+
assert_nil res.resolveIdentifier("/Root1")
|
62
|
+
assert_equal model[0].children[0], res.resolveIdentifier("|Root1|Sub11")
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_noLeadingSeparator
|
66
|
+
model = testModel
|
67
|
+
res = RGen::Instantiator::QualifiedNameResolver.new(model, :leadingSeparator => false)
|
68
|
+
assert_equal model[0], res.resolveIdentifier("Root1")
|
69
|
+
assert_nil res.resolveIdentifier("/Root1")
|
70
|
+
assert_equal model[0].children[0], res.resolveIdentifier("Root1/Sub11")
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_resolve
|
74
|
+
model = testModel
|
75
|
+
res = RGen::Instantiator::QualifiedNameResolver.new(model)
|
76
|
+
assert_equal model[0], res.resolveIdentifier("/Root1")
|
77
|
+
# again
|
78
|
+
assert_equal model[0], res.resolveIdentifier("/Root1")
|
79
|
+
assert_equal model[0].children[0], res.resolveIdentifier("/Root1/Sub11")
|
80
|
+
# again
|
81
|
+
assert_equal model[0].children[0], res.resolveIdentifier("/Root1/Sub11")
|
82
|
+
assert_equal model[0].children[1], res.resolveIdentifier("/Root1/Sub12")
|
83
|
+
assert_equal model[0].children[1].children[0], res.resolveIdentifier("/Root1/Sub12/Sub121")
|
84
|
+
assert_equal model[1], res.resolveIdentifier("/Root2")
|
85
|
+
assert_equal model[1].children[0], res.resolveIdentifier("/Root2/Sub21")
|
86
|
+
assert_equal model[1].children[0].children[0], res.resolveIdentifier("/Root2/Sub21/Sub211")
|
87
|
+
# duplicate name yields two result elements
|
88
|
+
assert_equal [model[2], model[3]], res.resolveIdentifier("/Root3")
|
89
|
+
assert_equal nil, res.resolveIdentifier("/RootX")
|
90
|
+
assert_equal nil, res.resolveIdentifier("/Root1/SubX")
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_oneChild
|
94
|
+
model = testModel3
|
95
|
+
res = RGen::Instantiator::QualifiedNameResolver.new(model)
|
96
|
+
assert_equal model[0], res.resolveIdentifier("/Root1")
|
97
|
+
assert_equal model[0].child, res.resolveIdentifier("/Root1/Sub11")
|
98
|
+
assert_equal model[0].child.child, res.resolveIdentifier("/Root1/Sub11/Sub111")
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|