rtext 0.8.1 → 0.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG +120 -89
- data/Project.yaml +15 -0
- data/RText_Protocol +47 -4
- data/lib/rtext/context_builder.rb +49 -8
- data/lib/rtext/default_completer.rb +212 -163
- data/lib/rtext/default_service_provider.rb +3 -3
- data/lib/rtext/frontend/connector.rb +130 -56
- data/lib/rtext/instantiator.rb +11 -3
- data/lib/rtext/language.rb +5 -5
- data/lib/rtext/serializer.rb +3 -3
- data/lib/rtext/service.rb +281 -253
- data/lib/rtext/tokenizer.rb +2 -2
- metadata +33 -33
- data/Rakefile +0 -46
- data/test/completer_test.rb +0 -606
- data/test/context_builder_test.rb +0 -948
- data/test/frontend/context_test.rb +0 -301
- data/test/instantiator_test.rb +0 -1704
- data/test/integration/backend.out +0 -13
- data/test/integration/crash_on_request_editor.rb +0 -12
- data/test/integration/ecore_editor.rb +0 -50
- data/test/integration/frontend.log +0 -38203
- data/test/integration/model/invalid_encoding.invenc +0 -2
- data/test/integration/model/test.crash_on_request +0 -18
- data/test/integration/model/test.crashing_backend +0 -18
- data/test/integration/model/test.dont_open_socket +0 -0
- data/test/integration/model/test.invalid_cmd_line +0 -0
- data/test/integration/model/test.not_in_rtext +0 -0
- data/test/integration/model/test_large_with_errors.ect3 +0 -43523
- data/test/integration/model/test_metamodel.ect +0 -24
- data/test/integration/model/test_metamodel2.ect +0 -5
- data/test/integration/model/test_metamodel3.ect4 +0 -7
- data/test/integration/model/test_metamodel_error.ect2 +0 -3
- data/test/integration/model/test_metamodel_ok.ect2 +0 -18
- data/test/integration/test.rb +0 -966
- data/test/link_detector_test.rb +0 -287
- data/test/message_helper_test.rb +0 -118
- data/test/rtext_test.rb +0 -11
- data/test/serializer_test.rb +0 -1004
- data/test/tokenizer_test.rb +0 -173
data/test/serializer_test.rb
DELETED
@@ -1,1004 +0,0 @@
|
|
1
|
-
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
|
-
|
3
|
-
require 'test/unit'
|
4
|
-
require 'bigdecimal'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'stringio'
|
7
|
-
require 'rgen/environment'
|
8
|
-
require 'rgen/metamodel_builder'
|
9
|
-
require 'rtext/serializer'
|
10
|
-
require 'rtext/language'
|
11
|
-
|
12
|
-
class SerializerTest < Test::Unit::TestCase
|
13
|
-
TestOutputFile = ".serializer_test_file"
|
14
|
-
|
15
|
-
def teardown
|
16
|
-
FileUtils.rm_f TestOutputFile
|
17
|
-
end
|
18
|
-
|
19
|
-
class StringWriter < String
|
20
|
-
alias write concat
|
21
|
-
end
|
22
|
-
|
23
|
-
module TestMM
|
24
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
25
|
-
SomeEnum = RGen::MetamodelBuilder::DataTypes::Enum.new(
|
26
|
-
:name => "SomeEnum", :literals => [:A, :B, :'non-word*chars', :'2you'])
|
27
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
28
|
-
has_attr 'text', String
|
29
|
-
has_many_attr 'texts', String
|
30
|
-
has_many_attr 'more_texts', String
|
31
|
-
has_attr 'unlabled', String
|
32
|
-
has_attr 'unquoted', String
|
33
|
-
has_attr 'both', String
|
34
|
-
has_attr 'none', String
|
35
|
-
has_attr 'comment', String
|
36
|
-
has_attr 'integer', Integer
|
37
|
-
has_attr 'float', Float
|
38
|
-
has_attr 'enum', SomeEnum
|
39
|
-
has_attr 'boolean', Boolean
|
40
|
-
contains_many 'childs', TestNode, 'parent'
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_simple
|
45
|
-
testModel = TestMM::TestNode.new(:text => "some text", :childs => [
|
46
|
-
TestMM::TestNode.new(:text => "child")])
|
47
|
-
|
48
|
-
output = StringWriter.new
|
49
|
-
serialize(testModel, TestMM, output)
|
50
|
-
|
51
|
-
assert_equal %Q(\
|
52
|
-
TestNode text: "some text" {
|
53
|
-
TestNode text: "child"
|
54
|
-
}
|
55
|
-
), output
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_many_attr
|
59
|
-
testModel = TestMM::TestNode.new(:texts => ["a", "b", "c"])
|
60
|
-
|
61
|
-
output = StringWriter.new
|
62
|
-
serialize(testModel, TestMM, output)
|
63
|
-
|
64
|
-
assert_equal %Q(\
|
65
|
-
TestNode texts: ["a", "b", "c"]
|
66
|
-
), output
|
67
|
-
end
|
68
|
-
|
69
|
-
module TestMMFeatureProvider
|
70
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
71
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
72
|
-
has_attr 'attr1', String
|
73
|
-
has_attr 'attr2', String
|
74
|
-
has_attr 'attr3', String
|
75
|
-
contains_many 'childs1', TestNode, 'parent1'
|
76
|
-
contains_many 'childs2', TestNode, 'parent2'
|
77
|
-
contains_many 'childs3', TestNode, 'parent3'
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_feature_provider
|
82
|
-
testModel = TestMMFeatureProvider::TestNode.new(
|
83
|
-
:attr1 => "attr1",
|
84
|
-
:attr2 => "attr2",
|
85
|
-
:attr3 => "attr3",
|
86
|
-
:childs1 => [TestMMFeatureProvider::TestNode.new(:attr1 => "child1")],
|
87
|
-
:childs2 => [TestMMFeatureProvider::TestNode.new(:attr1 => "child2")],
|
88
|
-
:childs3 => [TestMMFeatureProvider::TestNode.new(:attr1 => "child3")])
|
89
|
-
|
90
|
-
output = StringWriter.new
|
91
|
-
serialize(testModel, TestMMFeatureProvider, output,
|
92
|
-
:feature_provider => proc {|clazz|
|
93
|
-
clazz.eAllStructuralFeatures.reject{|f| f.name =~ /parent|2$/}.reverse})
|
94
|
-
|
95
|
-
assert_equal %Q(\
|
96
|
-
TestNode attr3: "attr3", attr1: "attr1" {
|
97
|
-
childs3:
|
98
|
-
TestNode attr1: "child3"
|
99
|
-
childs1:
|
100
|
-
TestNode attr1: "child1"
|
101
|
-
}
|
102
|
-
), output
|
103
|
-
end
|
104
|
-
|
105
|
-
module TestMMUnlabledUnquoted
|
106
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
107
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
108
|
-
has_attr 'unlabled', String
|
109
|
-
has_attr 'unquoted', String
|
110
|
-
has_attr 'both', String
|
111
|
-
has_attr 'none', String
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_unlabled_unquoted
|
116
|
-
testModel = [
|
117
|
-
TestMMUnlabledUnquoted::TestNode.new(:unlabled => "unlabled", :unquoted => "unquoted", :both => "both", :none => "none"),
|
118
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "no identifier"),
|
119
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "true"),
|
120
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "333"),
|
121
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "33.3"),
|
122
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "5x"),
|
123
|
-
TestMMUnlabledUnquoted::TestNode.new(:unquoted => "//")
|
124
|
-
]
|
125
|
-
|
126
|
-
output = StringWriter.new
|
127
|
-
serialize(testModel, TestMMUnlabledUnquoted, output,
|
128
|
-
:unlabled_arguments => proc {|clazz| ["unlabled", "both"]},
|
129
|
-
:unquoted_arguments => proc {|clazz| ["unquoted", "both"]}
|
130
|
-
)
|
131
|
-
|
132
|
-
assert_equal %Q(\
|
133
|
-
TestNode "unlabled", both, unquoted: unquoted, none: "none"
|
134
|
-
TestNode unquoted: "no identifier"
|
135
|
-
TestNode unquoted: "true"
|
136
|
-
TestNode unquoted: "333"
|
137
|
-
TestNode unquoted: "33.3"
|
138
|
-
TestNode unquoted: "5x"
|
139
|
-
TestNode unquoted: "//"
|
140
|
-
), output
|
141
|
-
end
|
142
|
-
|
143
|
-
module TestMMComment
|
144
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
145
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
146
|
-
has_attr 'comment', String
|
147
|
-
contains_many 'childs', TestNode, 'parent'
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_comment_provider
|
152
|
-
testModel = TestMMComment::TestNode.new(
|
153
|
-
:comment => "this is a comment",
|
154
|
-
:childs => [
|
155
|
-
TestMMComment::TestNode.new(:comment => "\n\ncomment of a child node\n multiline\n\n\nanother\n\n\n"),
|
156
|
-
TestMMComment::TestNode.new(:comment => "don't show"),
|
157
|
-
TestMMComment::TestNode.new(:comment => "")])
|
158
|
-
|
159
|
-
output = StringWriter.new
|
160
|
-
serialize(testModel, TestMMComment, output,
|
161
|
-
:comment_provider => proc { |e|
|
162
|
-
if e.comment != "don't show"
|
163
|
-
c = e.comment
|
164
|
-
e.comment = nil
|
165
|
-
c
|
166
|
-
else
|
167
|
-
nil
|
168
|
-
end
|
169
|
-
})
|
170
|
-
|
171
|
-
assert_equal %Q(\
|
172
|
-
#this is a comment
|
173
|
-
TestNode {
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#comment of a child node
|
177
|
-
# multiline
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#another
|
181
|
-
TestNode
|
182
|
-
TestNode comment: "don't show"
|
183
|
-
TestNode
|
184
|
-
}
|
185
|
-
), output
|
186
|
-
end
|
187
|
-
|
188
|
-
module TestMMAnnotation
|
189
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
190
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
191
|
-
has_attr 'annotation', String
|
192
|
-
contains_many 'childs', TestNode, 'parent'
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def test_annotation_provider
|
197
|
-
testModel = TestMMAnnotation::TestNode.new(
|
198
|
-
:annotation => "this is an annotation",
|
199
|
-
:childs => [
|
200
|
-
TestMMAnnotation::TestNode.new(:annotation => "annotation of a child node\n multiline"),
|
201
|
-
TestMMAnnotation::TestNode.new(:annotation => "don't show")])
|
202
|
-
|
203
|
-
output = StringWriter.new
|
204
|
-
serialize(testModel, TestMMAnnotation, output,
|
205
|
-
:annotation_provider => proc { |e|
|
206
|
-
if e.annotation != "don't show"
|
207
|
-
a = e.annotation
|
208
|
-
e.annotation = nil
|
209
|
-
a
|
210
|
-
else
|
211
|
-
nil
|
212
|
-
end
|
213
|
-
})
|
214
|
-
|
215
|
-
assert_equal %Q(\
|
216
|
-
@this is an annotation
|
217
|
-
TestNode {
|
218
|
-
@annotation of a child node
|
219
|
-
@ multiline
|
220
|
-
TestNode
|
221
|
-
TestNode annotation: "don't show"
|
222
|
-
}
|
223
|
-
), output
|
224
|
-
end
|
225
|
-
|
226
|
-
def test_indent_string
|
227
|
-
testModel = TestMM::TestNode.new(:childs => [
|
228
|
-
TestMM::TestNode.new(:text => "child")])
|
229
|
-
|
230
|
-
output = StringWriter.new
|
231
|
-
serialize(testModel, TestMM, output, :indent_string => "____")
|
232
|
-
|
233
|
-
assert_equal %Q(\
|
234
|
-
TestNode {
|
235
|
-
____TestNode text: "child"
|
236
|
-
}
|
237
|
-
), output
|
238
|
-
end
|
239
|
-
|
240
|
-
module TestMMRef
|
241
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
242
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
243
|
-
has_attr 'name', String
|
244
|
-
contains_many 'childs', TestNode, 'parent'
|
245
|
-
has_many 'refMany', TestNode
|
246
|
-
has_one 'refOne', TestNode
|
247
|
-
one_to_many 'refManyBi', TestNode, 'refManyBack'
|
248
|
-
one_to_one 'refOneBi', TestNode, 'refOneBack'
|
249
|
-
many_to_many 'refManyMany', TestNode, 'refManyManyBack'
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def test_identifier_provider
|
254
|
-
testModel = [
|
255
|
-
TestMMRef::TestNode.new(:name => "Source"),
|
256
|
-
TestMMRef::TestNode.new(:name => "Target")]
|
257
|
-
testModel[0].refOne = testModel[1]
|
258
|
-
|
259
|
-
output = StringWriter.new
|
260
|
-
serialize(testModel, TestMMRef, output,
|
261
|
-
:identifier_provider => proc{|e, context, feature, index|
|
262
|
-
assert_equal testModel[0], context
|
263
|
-
assert_equal "refOne", feature.name
|
264
|
-
assert_equal 0, index
|
265
|
-
"/target/ref"
|
266
|
-
}
|
267
|
-
)
|
268
|
-
|
269
|
-
assert_equal %Q(\
|
270
|
-
TestNode name: "Source", refOne: /target/ref
|
271
|
-
TestNode name: "Target"
|
272
|
-
),output
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_identifier_provider_many
|
276
|
-
testModel = [
|
277
|
-
TestMMRef::TestNode.new(:name => "Source"),
|
278
|
-
TestMMRef::TestNode.new(:name => "Target1"),
|
279
|
-
TestMMRef::TestNode.new(:name => "Target2")]
|
280
|
-
testModel[0].addRefMany(testModel[1])
|
281
|
-
testModel[0].addRefMany(testModel[2])
|
282
|
-
|
283
|
-
output = StringWriter.new
|
284
|
-
call_index = 0
|
285
|
-
serialize(testModel, TestMMRef, output,
|
286
|
-
:identifier_provider => proc{|e, context, feature, index|
|
287
|
-
assert_equal testModel[0], context
|
288
|
-
assert_equal "refMany", feature.name
|
289
|
-
if call_index == 0
|
290
|
-
call_index += 1
|
291
|
-
assert_equal 0, index
|
292
|
-
"/target/ref1"
|
293
|
-
else
|
294
|
-
assert_equal 1, index
|
295
|
-
"/target/ref2"
|
296
|
-
end
|
297
|
-
}
|
298
|
-
)
|
299
|
-
assert_equal %Q(\
|
300
|
-
TestNode name: "Source", refMany: [/target/ref1, /target/ref2]
|
301
|
-
TestNode name: "Target1"
|
302
|
-
TestNode name: "Target2"
|
303
|
-
),output
|
304
|
-
end
|
305
|
-
|
306
|
-
def test_identifier_provider_nil
|
307
|
-
testModel = [
|
308
|
-
TestMMRef::TestNode.new(:name => "Source"),
|
309
|
-
TestMMRef::TestNode.new(:name => "Target")]
|
310
|
-
testModel[0].refOne = testModel[1]
|
311
|
-
|
312
|
-
output = StringWriter.new
|
313
|
-
serialize(testModel, TestMMRef, output,
|
314
|
-
:identifier_provider => proc{|e, context, feature, index|
|
315
|
-
nil
|
316
|
-
}
|
317
|
-
)
|
318
|
-
|
319
|
-
assert_equal %Q(\
|
320
|
-
TestNode name: "Source"
|
321
|
-
TestNode name: "Target"
|
322
|
-
),output
|
323
|
-
end
|
324
|
-
|
325
|
-
def test_references
|
326
|
-
testModel = [
|
327
|
-
TestMMRef::TestNode.new(:name => "Source"),
|
328
|
-
TestMMRef::TestNode.new(:name => "Target",
|
329
|
-
:childs => [
|
330
|
-
TestMMRef::TestNode.new(:name => "A",
|
331
|
-
:childs => [
|
332
|
-
TestMMRef::TestNode.new(:name => "A1")
|
333
|
-
]),
|
334
|
-
TestMMRef::TestNode.new(:name => "B"),
|
335
|
-
])
|
336
|
-
]
|
337
|
-
testModel[0].refOne = testModel[1].childs[0].childs[0]
|
338
|
-
testModel[0].refOneBi = testModel[1].childs[0].childs[0]
|
339
|
-
testModel[0].refMany = [testModel[1].childs[0], testModel[1].childs[1]]
|
340
|
-
testModel[0].refManyBi = [testModel[1].childs[0], testModel[1].childs[1]]
|
341
|
-
testModel[0].refManyMany = [testModel[1].childs[0], testModel[1].childs[1]]
|
342
|
-
testModel[0].addRefMany(RGen::MetamodelBuilder::MMProxy.new("/some/ref"))
|
343
|
-
|
344
|
-
output = StringWriter.new
|
345
|
-
serialize(testModel, TestMMRef, output)
|
346
|
-
|
347
|
-
assert_equal %Q(\
|
348
|
-
TestNode name: "Source", refMany: [/Target/A, /Target/B, /some/ref], refOne: /Target/A/A1, refOneBi: /Target/A/A1
|
349
|
-
TestNode name: "Target" {
|
350
|
-
TestNode name: "A", refManyBack: /Source, refManyManyBack: /Source {
|
351
|
-
TestNode name: "A1"
|
352
|
-
}
|
353
|
-
TestNode name: "B", refManyBack: /Source, refManyManyBack: /Source
|
354
|
-
}
|
355
|
-
), output
|
356
|
-
end
|
357
|
-
|
358
|
-
module TestMMChildRole
|
359
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
360
|
-
class TestNodeA < RGen::MetamodelBuilder::MMBase
|
361
|
-
has_attr 'text', String
|
362
|
-
end
|
363
|
-
class TestNodeB < RGen::MetamodelBuilder::MMBase
|
364
|
-
has_attr 'text', String
|
365
|
-
end
|
366
|
-
class TestNodeC < RGen::MetamodelBuilder::MMBase
|
367
|
-
has_attr 'text', String
|
368
|
-
end
|
369
|
-
class TestNodeD < RGen::MetamodelBuilder::MMBase
|
370
|
-
has_attr 'text3', String
|
371
|
-
end
|
372
|
-
class TestNodeE < RGen::MetamodelBuilder::MMMultiple(TestNodeC, TestNodeD)
|
373
|
-
has_attr 'text2', String
|
374
|
-
end
|
375
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
376
|
-
has_attr 'text', String
|
377
|
-
has_many_attr 'texts', String
|
378
|
-
contains_one 'child1', TestNode, 'parent1'
|
379
|
-
contains_many 'childs2', TestNode, 'parent2'
|
380
|
-
contains_one 'child3', TestNodeA, 'parent3'
|
381
|
-
contains_many 'childs4', TestNodeB, 'parent4'
|
382
|
-
contains_one 'child5', TestNodeC, 'parent5'
|
383
|
-
contains_many 'childs6', TestNodeD, 'parent6'
|
384
|
-
contains_one 'child7', TestNodeE, 'parent7'
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
def test_child_role
|
389
|
-
testModel = TestMMChildRole::TestNode.new(
|
390
|
-
:child1 => TestMMChildRole::TestNode.new(:text => "child1"),
|
391
|
-
:childs2 => [
|
392
|
-
TestMMChildRole::TestNode.new(:text => "child2a"),
|
393
|
-
TestMMChildRole::TestNode.new(:text => "child2b")
|
394
|
-
],
|
395
|
-
:child3 => TestMMChildRole::TestNodeA.new(:text => "child3"),
|
396
|
-
:childs4 => [TestMMChildRole::TestNodeB.new(:text => "child4")],
|
397
|
-
:child5 => TestMMChildRole::TestNodeC.new(:text => "child5"),
|
398
|
-
:childs6 => [TestMMChildRole::TestNodeD.new(:text3 => "child6"), TestMMChildRole::TestNodeE.new(:text => "child6.1")],
|
399
|
-
:child7 => TestMMChildRole::TestNodeE.new(:text2 => "child7")
|
400
|
-
)
|
401
|
-
|
402
|
-
output = StringWriter.new
|
403
|
-
serialize(testModel, TestMMChildRole, output)
|
404
|
-
|
405
|
-
assert_equal %Q(\
|
406
|
-
TestNode {
|
407
|
-
child1:
|
408
|
-
TestNode text: "child1"
|
409
|
-
childs2: [
|
410
|
-
TestNode text: "child2a"
|
411
|
-
TestNode text: "child2b"
|
412
|
-
]
|
413
|
-
TestNodeA text: "child3"
|
414
|
-
TestNodeB text: "child4"
|
415
|
-
TestNodeC text: "child5"
|
416
|
-
childs6: [
|
417
|
-
TestNodeD text3: "child6"
|
418
|
-
TestNodeE text: "child6.1"
|
419
|
-
]
|
420
|
-
child7:
|
421
|
-
TestNodeE text2: "child7"
|
422
|
-
}
|
423
|
-
), output
|
424
|
-
end
|
425
|
-
|
426
|
-
module TestMMLabeledContainment
|
427
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
428
|
-
class TestNode < RGen::MetamodelBuilder::MMBase
|
429
|
-
abstract
|
430
|
-
has_attr 'text', String
|
431
|
-
contains_many 'childs', TestNode, 'parent'
|
432
|
-
end
|
433
|
-
class TestNode1 < TestNode
|
434
|
-
end
|
435
|
-
class TestNode2 < TestNode
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
def test_labeled_containment
|
440
|
-
testModel = TestMMLabeledContainment::TestNode1.new(:text => "some text", :childs => [
|
441
|
-
TestMMLabeledContainment::TestNode2.new(:text => "child", :childs => [
|
442
|
-
TestMMLabeledContainment::TestNode1.new(:text => "nested child")
|
443
|
-
])])
|
444
|
-
|
445
|
-
output = StringWriter.new
|
446
|
-
serialize(testModel, TestMMLabeledContainment, output, :labeled_containments => proc {|c|
|
447
|
-
if c == TestMMLabeledContainment::TestNode2.ecore
|
448
|
-
["childs"]
|
449
|
-
else
|
450
|
-
[]
|
451
|
-
end
|
452
|
-
})
|
453
|
-
|
454
|
-
assert_equal %Q(\
|
455
|
-
TestNode1 text: "some text" {
|
456
|
-
TestNode2 text: "child" {
|
457
|
-
childs:
|
458
|
-
TestNode1 text: "nested child"
|
459
|
-
}
|
460
|
-
}
|
461
|
-
), output
|
462
|
-
end
|
463
|
-
|
464
|
-
def test_escapes
|
465
|
-
testModel = TestMM::TestNode.new(:text => %Q(some " \\ \\" text \r xx \n xx \r\n xx \t xx \b xx \f))
|
466
|
-
output = StringWriter.new
|
467
|
-
serialize(testModel, TestMM, output)
|
468
|
-
|
469
|
-
assert_equal %q(TestNode text: "some \" \\\\ \\\\\" text \r xx \n xx \r\n xx \t xx \b xx \f")+"\n", output
|
470
|
-
end
|
471
|
-
|
472
|
-
def test_integer
|
473
|
-
testModel = TestMM::TestNode.new(:integer => 7)
|
474
|
-
output = StringWriter.new
|
475
|
-
serialize(testModel, TestMM, output)
|
476
|
-
assert_equal %q(TestNode integer: 7)+"\n", output
|
477
|
-
end
|
478
|
-
|
479
|
-
def test_integer_big
|
480
|
-
testModel = TestMM::TestNode.new(:integer => 12345678901234567890)
|
481
|
-
output = StringWriter.new
|
482
|
-
serialize(testModel, TestMM, output)
|
483
|
-
assert_equal %q(TestNode integer: 12345678901234567890)+"\n", output
|
484
|
-
end
|
485
|
-
|
486
|
-
def test_integer_format_spec
|
487
|
-
testModel = TestMM::TestNode.new(:integer => 10)
|
488
|
-
output = StringWriter.new
|
489
|
-
serialize(testModel, TestMM, output, :argument_format_provider => proc {|a|
|
490
|
-
if a.name == "integer"
|
491
|
-
"0x%02X"
|
492
|
-
else
|
493
|
-
nil
|
494
|
-
end})
|
495
|
-
assert_equal %q(TestNode integer: 0x0A)+"\n", output
|
496
|
-
end
|
497
|
-
|
498
|
-
def test_integer_format_spec_big
|
499
|
-
testModel = TestMM::TestNode.new(:integer => 0xabcdefabcdefabcdef)
|
500
|
-
output = StringWriter.new
|
501
|
-
serialize(testModel, TestMM, output, :argument_format_provider => proc {|a|
|
502
|
-
if a.name == "integer"
|
503
|
-
"0x%x"
|
504
|
-
else
|
505
|
-
nil
|
506
|
-
end})
|
507
|
-
assert_equal %q(TestNode integer: 0xabcdefabcdefabcdef)+"\n", output
|
508
|
-
end
|
509
|
-
|
510
|
-
def test_float
|
511
|
-
testModel = TestMM::TestNode.new(:float => 1.23)
|
512
|
-
output = StringWriter.new
|
513
|
-
serialize(testModel, TestMM, output)
|
514
|
-
assert_equal %q(TestNode float: 1.23)+"\n", output
|
515
|
-
end
|
516
|
-
|
517
|
-
def test_float2
|
518
|
-
testModel = TestMM::TestNode.new(:float => 1.23e-08)
|
519
|
-
output = StringWriter.new
|
520
|
-
serialize(testModel, TestMM, output)
|
521
|
-
assert output =~ /TestNode float: 1.23e-0?08\n/
|
522
|
-
end
|
523
|
-
|
524
|
-
def test_float_format_spec
|
525
|
-
testModel = TestMM::TestNode.new(:float => 1.23)
|
526
|
-
output = StringWriter.new
|
527
|
-
serialize(testModel, TestMM, output, :argument_format_provider => proc {|a|
|
528
|
-
if a.name == "float"
|
529
|
-
"%1.1f"
|
530
|
-
else
|
531
|
-
nil
|
532
|
-
end})
|
533
|
-
assert_equal %q(TestNode float: 1.2)+"\n", output
|
534
|
-
end
|
535
|
-
|
536
|
-
def test_float_big_decimal
|
537
|
-
begin
|
538
|
-
testModel = TestMM::TestNode.new(:float => BigDecimal.new("1234567890.123456789"))
|
539
|
-
rescue StandardError
|
540
|
-
return
|
541
|
-
end
|
542
|
-
output = StringWriter.new
|
543
|
-
serialize(testModel, TestMM, output)
|
544
|
-
assert_equal %q(TestNode float: 1234567890.123456789)+"\n", output
|
545
|
-
end
|
546
|
-
|
547
|
-
def test_enum
|
548
|
-
testModel = [
|
549
|
-
TestMM::TestNode.new(:enum => :A),
|
550
|
-
TestMM::TestNode.new(:enum => :B),
|
551
|
-
TestMM::TestNode.new(:enum => :'non-word*chars'),
|
552
|
-
TestMM::TestNode.new(:enum => :'2you')
|
553
|
-
]
|
554
|
-
output = StringWriter.new
|
555
|
-
serialize(testModel, TestMM, output)
|
556
|
-
assert_equal %Q(\
|
557
|
-
TestNode enum: A
|
558
|
-
TestNode enum: B
|
559
|
-
TestNode enum: "non-word*chars"
|
560
|
-
TestNode enum: "2you"
|
561
|
-
), output
|
562
|
-
end
|
563
|
-
|
564
|
-
def test_generic
|
565
|
-
testModel = [
|
566
|
-
TestMM::TestNode.new(:text => RText::Generic.new("some text angel >bracket")),
|
567
|
-
TestMM::TestNode.new(:text => RText::Generic.new("some text percent angel %>bracket")),
|
568
|
-
TestMM::TestNode.new(:text => RText::Generic.new("some text > percent angel%>bracket")),
|
569
|
-
TestMM::TestNode.new(:integer => RText::Generic.new("a number: 1")),
|
570
|
-
TestMM::TestNode.new(:float => RText::Generic.new("precision")),
|
571
|
-
TestMM::TestNode.new(:enum => RText::Generic.new("an option")),
|
572
|
-
TestMM::TestNode.new(:boolean => RText::Generic.new("falsy"))
|
573
|
-
]
|
574
|
-
output = StringWriter.new
|
575
|
-
serialize(testModel, TestMM, output)
|
576
|
-
assert_equal %Q(\
|
577
|
-
TestNode text: <%some text angel >bracket%>
|
578
|
-
TestNode text: <some text percent angel >
|
579
|
-
TestNode text: <%some text > percent angel%>
|
580
|
-
TestNode integer: <a number: 1>
|
581
|
-
TestNode float: <precision>
|
582
|
-
TestNode enum: <an option>
|
583
|
-
TestNode boolean: <falsy>
|
584
|
-
), output
|
585
|
-
end
|
586
|
-
|
587
|
-
module TestMMData
|
588
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
589
|
-
# class "Data" exists in the standard Ruby namespace
|
590
|
-
class Data < RGen::MetamodelBuilder::MMBase
|
591
|
-
has_attr 'notTheBuiltin', String
|
592
|
-
end
|
593
|
-
end
|
594
|
-
|
595
|
-
module TestMMSubpackage
|
596
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
597
|
-
module SubPackage
|
598
|
-
extend RGen::MetamodelBuilder::ModuleExtension
|
599
|
-
class Data < RGen::MetamodelBuilder::MMBase
|
600
|
-
has_attr 'notTheBuiltin', String
|
601
|
-
end
|
602
|
-
class Data2 < RGen::MetamodelBuilder::MMBase
|
603
|
-
has_attr 'data2', String
|
604
|
-
end
|
605
|
-
end
|
606
|
-
end
|
607
|
-
|
608
|
-
def test_subpackage
|
609
|
-
testModel = TestMMSubpackage::SubPackage::Data2.new(:data2 => "xxx")
|
610
|
-
output = StringWriter.new
|
611
|
-
serialize(testModel, TestMMSubpackage, output)
|
612
|
-
assert_equal %q(Data2 data2: "xxx")+"\n", output
|
613
|
-
end
|
614
|
-
|
615
|
-
def test_command_name_provider
|
616
|
-
testModel = TestMM::TestNode.new(:text => "some text", :childs => [
|
617
|
-
TestMM::TestNode.new(:text => "child")])
|
618
|
-
|
619
|
-
output = StringWriter.new
|
620
|
-
serialize(testModel, TestMM, output, :command_name_provider => proc do |c|
|
621
|
-
c.name + "X"
|
622
|
-
end)
|
623
|
-
|
624
|
-
assert_equal %Q(\
|
625
|
-
TestNodeX text: "some text" {
|
626
|
-
TestNodeX text: "child"
|
627
|
-
}
|
628
|
-
), output
|
629
|
-
end
|
630
|
-
|
631
|
-
def test_file_output
|
632
|
-
testModel = TestMM::TestNode.new(:text => "some text")
|
633
|
-
|
634
|
-
File.open(TestOutputFile, "w") do |f|
|
635
|
-
serialize(testModel, TestMM, f)
|
636
|
-
end
|
637
|
-
|
638
|
-
assert_equal %Q(\
|
639
|
-
TestNode text: "some text"
|
640
|
-
), File.read(TestOutputFile)
|
641
|
-
end
|
642
|
-
|
643
|
-
def test_stringio_output
|
644
|
-
testModel = TestMM::TestNode.new(:text => "some text")
|
645
|
-
|
646
|
-
output = StringIO.new
|
647
|
-
serialize(testModel, TestMM, output)
|
648
|
-
|
649
|
-
assert_equal %Q(\
|
650
|
-
TestNode text: "some text"
|
651
|
-
), output.string
|
652
|
-
end
|
653
|
-
|
654
|
-
#
|
655
|
-
# line breaks
|
656
|
-
#
|
657
|
-
All_features = proc {|clazz|
|
658
|
-
res = []
|
659
|
-
clazz.eAllStructuralFeatures.reject{|f| f.name =~ /parent|2$/}.each{|f| res << f.name}
|
660
|
-
res
|
661
|
-
}
|
662
|
-
|
663
|
-
def test_linebreak
|
664
|
-
testModel = TestMM::TestNode.new(
|
665
|
-
:text => "some text",
|
666
|
-
:texts => ["some more text", "some more text", "some more text"])
|
667
|
-
|
668
|
-
output = StringWriter.new
|
669
|
-
serialize(testModel, TestMM, output,
|
670
|
-
:newline_arguments => All_features,
|
671
|
-
:newline_arrays => All_features)
|
672
|
-
|
673
|
-
assert_equal %Q(\
|
674
|
-
TestNode \\
|
675
|
-
text: "some text",
|
676
|
-
texts: [
|
677
|
-
"some more text",
|
678
|
-
"some more text",
|
679
|
-
"some more text"
|
680
|
-
]
|
681
|
-
), output
|
682
|
-
end
|
683
|
-
|
684
|
-
def test_linebreak_child
|
685
|
-
testModel1 = TestMM::TestNode.new(
|
686
|
-
:text => "some text1",
|
687
|
-
:texts => ["some more text", "some more text", "some more text"])
|
688
|
-
testModel0 = TestMM::TestNode.new(
|
689
|
-
:text => "some text0",
|
690
|
-
:integer => 10,
|
691
|
-
:childs => [testModel1])
|
692
|
-
|
693
|
-
output = StringWriter.new
|
694
|
-
serialize(testModel0, TestMM, output,
|
695
|
-
:newline_arguments => All_features,
|
696
|
-
:newline_arrays => All_features)
|
697
|
-
|
698
|
-
assert_equal %Q(\
|
699
|
-
TestNode \\
|
700
|
-
text: "some text0",
|
701
|
-
integer: 10 {
|
702
|
-
TestNode \\
|
703
|
-
text: "some text1",
|
704
|
-
texts: [
|
705
|
-
"some more text",
|
706
|
-
"some more text",
|
707
|
-
"some more text"
|
708
|
-
]
|
709
|
-
}
|
710
|
-
), output
|
711
|
-
end
|
712
|
-
|
713
|
-
def test_linebreak_child_no_arguments
|
714
|
-
testModel1 = TestMM::TestNode.new(
|
715
|
-
:text => "some text1",
|
716
|
-
:texts => ["some more text", "some more text", "some more text"])
|
717
|
-
testModel0 = TestMM::TestNode.new(:childs => [testModel1])
|
718
|
-
|
719
|
-
output = StringWriter.new
|
720
|
-
serialize(testModel0, TestMM, output,
|
721
|
-
:newline_arguments => All_features,
|
722
|
-
:newline_arrays => All_features)
|
723
|
-
|
724
|
-
assert_equal %Q(\
|
725
|
-
TestNode {
|
726
|
-
TestNode \\
|
727
|
-
text: "some text1",
|
728
|
-
texts: [
|
729
|
-
"some more text",
|
730
|
-
"some more text",
|
731
|
-
"some more text"
|
732
|
-
]
|
733
|
-
}
|
734
|
-
), output
|
735
|
-
end
|
736
|
-
|
737
|
-
def test_linebreak_unlabled_array_arguments
|
738
|
-
testModel = TestMM::TestNode.new(
|
739
|
-
:none => "some text",
|
740
|
-
:texts => ["some more text", "some more text", "some more text"])
|
741
|
-
|
742
|
-
output = StringWriter.new
|
743
|
-
serialize(testModel, TestMM, output,
|
744
|
-
:unlabled_arguments => proc {|clazz| ["texts"]},
|
745
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["texts"]},
|
746
|
-
:newline_arrays => All_features)
|
747
|
-
|
748
|
-
assert_equal %Q(\
|
749
|
-
TestNode [
|
750
|
-
"some more text",
|
751
|
-
"some more text",
|
752
|
-
"some more text"
|
753
|
-
],
|
754
|
-
none: "some text"
|
755
|
-
), output
|
756
|
-
end
|
757
|
-
|
758
|
-
def test_linebreak_unlabled_array_arguments_sameline
|
759
|
-
testModel = TestMM::TestNode.new(
|
760
|
-
:none => "some text",
|
761
|
-
:texts => ["some more text", "some more text", "some more text"])
|
762
|
-
|
763
|
-
output = StringWriter.new
|
764
|
-
serialize(testModel, TestMM, output,
|
765
|
-
:unlabled_arguments => proc {|clazz| ["texts"]},
|
766
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["texts"]},
|
767
|
-
:newline_arrays => proc {|clazz| All_features.call(clazz) - ["texts"]})
|
768
|
-
|
769
|
-
assert_equal %Q(\
|
770
|
-
TestNode ["some more text", "some more text", "some more text"],
|
771
|
-
none: "some text"
|
772
|
-
), output
|
773
|
-
end
|
774
|
-
|
775
|
-
def test_linebreak_unlabled_both_arguments_and_child
|
776
|
-
testModel1 = TestMM::TestNode.new(
|
777
|
-
:texts => ["some more text", "some more text", "some more text"])
|
778
|
-
testModel0 = TestMM::TestNode.new(
|
779
|
-
:unlabled => "unlabled",
|
780
|
-
:both => "both",
|
781
|
-
:childs => [testModel1])
|
782
|
-
|
783
|
-
output = StringWriter.new
|
784
|
-
serialize(testModel0, TestMM, output,
|
785
|
-
:unlabled_arguments => proc {|clazz| ["unlabled", "both"]},
|
786
|
-
:unquoted_arguments => proc {|clazz| ["both"]},
|
787
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["unlabled"]},
|
788
|
-
:newline_arrays => All_features)
|
789
|
-
|
790
|
-
assert_equal %Q(\
|
791
|
-
TestNode "unlabled",
|
792
|
-
both {
|
793
|
-
TestNode \\
|
794
|
-
texts: [
|
795
|
-
"some more text",
|
796
|
-
"some more text",
|
797
|
-
"some more text"
|
798
|
-
]
|
799
|
-
}
|
800
|
-
), output
|
801
|
-
end
|
802
|
-
|
803
|
-
def test_linebreak_child_two_attributes
|
804
|
-
testModel1 = TestMM::TestNode.new(
|
805
|
-
:text => "some text1",
|
806
|
-
:texts => ["some more text", "some more text", "some more text"],
|
807
|
-
:more_texts => ["even more text", "even more text"])
|
808
|
-
testModel0 = TestMM::TestNode.new(:text => "some text0", :childs => [testModel1])
|
809
|
-
|
810
|
-
output = StringWriter.new
|
811
|
-
serialize(testModel0, TestMM, output,
|
812
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["text"]},
|
813
|
-
:newline_arrays => proc {|clazz| All_features.call(clazz) - ["text"]})
|
814
|
-
|
815
|
-
assert_equal %Q(\
|
816
|
-
TestNode text: "some text0" {
|
817
|
-
TestNode text: "some text1",
|
818
|
-
texts: [
|
819
|
-
"some more text",
|
820
|
-
"some more text",
|
821
|
-
"some more text"
|
822
|
-
],
|
823
|
-
more_texts: [
|
824
|
-
"even more text",
|
825
|
-
"even more text"
|
826
|
-
]
|
827
|
-
}
|
828
|
-
), output
|
829
|
-
end
|
830
|
-
|
831
|
-
def test_linebreak_child_two_attributes_one_sameline
|
832
|
-
testModel1 = TestMM::TestNode.new(
|
833
|
-
:text => "some text1",
|
834
|
-
:texts => ["some more text", "some more text", "some more text"],
|
835
|
-
:more_texts => ["even more text", "even more text"])
|
836
|
-
testModel0 = TestMM::TestNode.new(:text => "some text0", :childs => [testModel1])
|
837
|
-
|
838
|
-
output = StringWriter.new
|
839
|
-
serialize(testModel0, TestMM, output,
|
840
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["more_texts"]},
|
841
|
-
:newline_arrays => proc {|clazz| All_features.call(clazz) - ["more_texts"]})
|
842
|
-
|
843
|
-
assert_equal %Q(\
|
844
|
-
TestNode \\
|
845
|
-
text: "some text0" {
|
846
|
-
TestNode \\
|
847
|
-
text: "some text1",
|
848
|
-
texts: [
|
849
|
-
"some more text",
|
850
|
-
"some more text",
|
851
|
-
"some more text"
|
852
|
-
], more_texts: ["even more text", "even more text"]
|
853
|
-
}
|
854
|
-
), output
|
855
|
-
end
|
856
|
-
|
857
|
-
def test_linebreak_two_children
|
858
|
-
testModel2 = TestMM::TestNode.new(:text => "some text2", :texts => ["some more text"])
|
859
|
-
testModel1 = TestMM::TestNode.new(:text => "some text1", :texts => ["some more text", "some more text", "some more text"])
|
860
|
-
testModel0 = TestMM::TestNode.new(:text => "some text0", :childs => [testModel1, testModel2])
|
861
|
-
|
862
|
-
output = StringWriter.new
|
863
|
-
serialize(testModel0, TestMM, output,
|
864
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["text"]},
|
865
|
-
:newline_arrays => All_features)
|
866
|
-
|
867
|
-
assert_equal %Q(\
|
868
|
-
TestNode text: "some text0" {
|
869
|
-
TestNode text: "some text1",
|
870
|
-
texts: [
|
871
|
-
"some more text",
|
872
|
-
"some more text",
|
873
|
-
"some more text"
|
874
|
-
]
|
875
|
-
TestNode text: "some text2",
|
876
|
-
texts: "some more text"
|
877
|
-
}
|
878
|
-
), output
|
879
|
-
end
|
880
|
-
|
881
|
-
def test_linebreak_nested_children
|
882
|
-
testModel2 = TestMM::TestNode.new(
|
883
|
-
:text => "some text2",
|
884
|
-
:texts => ["some more text", "some more text", "some more text"])
|
885
|
-
testModel1 = TestMM::TestNode.new(
|
886
|
-
:text => "some text1",
|
887
|
-
:childs => [testModel2])
|
888
|
-
testModel0 = TestMM::TestNode.new(
|
889
|
-
:text => "some text0",
|
890
|
-
:integer => 10,
|
891
|
-
:childs => [testModel1])
|
892
|
-
|
893
|
-
output = StringWriter.new
|
894
|
-
serialize(testModel0, TestMM, output,
|
895
|
-
:newline_arguments => All_features,
|
896
|
-
:newline_arrays => All_features)
|
897
|
-
|
898
|
-
assert_equal %Q(\
|
899
|
-
TestNode \\
|
900
|
-
text: "some text0",
|
901
|
-
integer: 10 {
|
902
|
-
TestNode \\
|
903
|
-
text: "some text1" {
|
904
|
-
TestNode \\
|
905
|
-
text: "some text2",
|
906
|
-
texts: [
|
907
|
-
"some more text",
|
908
|
-
"some more text",
|
909
|
-
"some more text"
|
910
|
-
]
|
911
|
-
}
|
912
|
-
}
|
913
|
-
), output
|
914
|
-
end
|
915
|
-
|
916
|
-
def test_linebreak_no_break
|
917
|
-
testModel = TestMM::TestNode.new(:text => "some text", :texts => ["some more text", "some more text", "some more text"])
|
918
|
-
|
919
|
-
output = StringWriter.new
|
920
|
-
serialize(testModel, TestMM, output)
|
921
|
-
|
922
|
-
assert_equal %Q(\
|
923
|
-
TestNode text: "some text", texts: ["some more text", "some more text", "some more text"]
|
924
|
-
), output
|
925
|
-
end
|
926
|
-
|
927
|
-
def test_linebreak_child_role
|
928
|
-
testModel = TestMMChildRole::TestNode.new(
|
929
|
-
:child1 => TestMMChildRole::TestNode.new(:text => "child1"),
|
930
|
-
:childs2 => [
|
931
|
-
TestMMChildRole::TestNode.new(
|
932
|
-
:text => "child2a",
|
933
|
-
:texts => ["some more text", "some more text"]),
|
934
|
-
TestMMChildRole::TestNode.new(
|
935
|
-
:text => "child2b",
|
936
|
-
:texts => ["some more text", "some more text"])
|
937
|
-
])
|
938
|
-
|
939
|
-
output = StringWriter.new
|
940
|
-
serialize(testModel, TestMMChildRole, output,
|
941
|
-
:newline_arguments => proc {|clazz| All_features.call(clazz) - ["text"]},
|
942
|
-
:newline_arrays => proc {|clazz| All_features.call(clazz) - ["text"]})
|
943
|
-
|
944
|
-
assert_equal %Q(\
|
945
|
-
TestNode {
|
946
|
-
child1:
|
947
|
-
TestNode text: "child1"
|
948
|
-
childs2: [
|
949
|
-
TestNode text: "child2a",
|
950
|
-
texts: [
|
951
|
-
"some more text",
|
952
|
-
"some more text"
|
953
|
-
]
|
954
|
-
TestNode text: "child2b",
|
955
|
-
texts: [
|
956
|
-
"some more text",
|
957
|
-
"some more text"
|
958
|
-
]
|
959
|
-
]
|
960
|
-
}
|
961
|
-
), output
|
962
|
-
end
|
963
|
-
|
964
|
-
def test_linebreak_comment
|
965
|
-
testModel = TestMM::TestNode.new(
|
966
|
-
:text => "some text",
|
967
|
-
:comment => "this is a comment",
|
968
|
-
:childs => [
|
969
|
-
TestMM::TestNode.new(:comment => "\n\ncomment of a child node\n multiline\n\n\nanother\n\n\n")
|
970
|
-
])
|
971
|
-
|
972
|
-
output = StringWriter.new
|
973
|
-
serialize(testModel, TestMM, output,
|
974
|
-
:newline_arguments => All_features,
|
975
|
-
:comment_provider => proc { |e|
|
976
|
-
c = e.comment
|
977
|
-
e.comment = nil
|
978
|
-
c
|
979
|
-
})
|
980
|
-
|
981
|
-
assert_equal %Q(\
|
982
|
-
#this is a comment
|
983
|
-
TestNode \\
|
984
|
-
text: "some text" {
|
985
|
-
#
|
986
|
-
#
|
987
|
-
#comment of a child node
|
988
|
-
# multiline
|
989
|
-
#
|
990
|
-
#
|
991
|
-
#another
|
992
|
-
TestNode
|
993
|
-
}
|
994
|
-
), output
|
995
|
-
end
|
996
|
-
|
997
|
-
def serialize(model, mm, output, options={})
|
998
|
-
lang = RText::Language.new(mm.ecore, options)
|
999
|
-
ser = RText::Serializer.new(lang)
|
1000
|
-
ser.serialize(model, output)
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
end
|
1004
|
-
|