rgen 0.5.1 → 0.5.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 +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
|
+
|