rubyang 0.1.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 +7 -0
- data/.codeclimate.yml +27 -0
- data/.coveralls.yml +1 -0
- data/.eslintignore +1 -0
- data/.eslintrc +213 -0
- data/.gitignore +41 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/README.md +44 -0
- data/Rakefile +6 -0
- data/lib/rubyang.rb +10 -0
- data/lib/rubyang/cli.rb +120 -0
- data/lib/rubyang/cli/parser.rb +74 -0
- data/lib/rubyang/database.rb +29 -0
- data/lib/rubyang/database/data_tree.rb +725 -0
- data/lib/rubyang/database/helper.rb +44 -0
- data/lib/rubyang/database/schema_tree.rb +1060 -0
- data/lib/rubyang/model.rb +917 -0
- data/lib/rubyang/model/parser.rb +183 -0
- data/lib/rubyang/model/parser/parser.tab.rb +3661 -0
- data/lib/rubyang/model/parser/parser.y +1454 -0
- data/lib/rubyang/restapi.rb +4 -0
- data/lib/rubyang/restapi/httpd.rb +62 -0
- data/lib/rubyang/version.rb +3 -0
- data/lib/rubyang/webui.rb +11 -0
- data/lib/rubyang/webui/app.rb +74 -0
- data/lib/rubyang/webui/make_json_schema.rb +63 -0
- data/lib/rubyang/webui/public/js/webui.js +326 -0
- data/lib/rubyang/webui/views/index.erb +48 -0
- data/lib/rubyang/webui/views/layout.erb +82 -0
- data/lib/rubyang/xpath.rb +224 -0
- data/lib/rubyang/xpath/parser.rb +146 -0
- data/lib/rubyang/xpath/parser/parser.tab.rb +2273 -0
- data/lib/rubyang/xpath/parser/parser.y +1083 -0
- data/rubyang.gemspec +38 -0
- metadata +180 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
def json_to_xml( json_str )
|
7
|
+
hash = JSON.parse( json_str )
|
8
|
+
if hash.keys.size > 1
|
9
|
+
raise 'root key size must be 1'
|
10
|
+
end
|
11
|
+
#doc_xml = REXML::Document.new( "<#{hash.keys.first} />" )
|
12
|
+
doc_xml = REXML::Document.new
|
13
|
+
json_to_xml_recursive( hash.keys.first, hash.values.first, doc_xml )
|
14
|
+
return doc_xml.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def json_to_xml_recursive( _key, _value, _doc_xml )
|
18
|
+
doc_xml = _doc_xml.add_element( _key )
|
19
|
+
case _value
|
20
|
+
when Hash
|
21
|
+
_value.each{ |key, value|
|
22
|
+
case value
|
23
|
+
when Hash
|
24
|
+
json_to_xml_recursive( key, value, doc_xml )
|
25
|
+
when Array
|
26
|
+
value.each{ |hash|
|
27
|
+
json_to_xml_recursive( key, hash, doc_xml )
|
28
|
+
}
|
29
|
+
else
|
30
|
+
doc_xml.add_element( key ).add_text value
|
31
|
+
end
|
32
|
+
}
|
33
|
+
else
|
34
|
+
raise "case value when other than Hash is not implemented"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
if __FILE__ == $0
|
40
|
+
json_str = '{"config": {"a": [{"b1": {"c1": "c1"}}, {"b2": {"c2": "c2"}}]}}'
|
41
|
+
puts json_to_xml( json_str )
|
42
|
+
json_str = '{"config":{"leaf1":"0"}}'
|
43
|
+
puts json_to_xml( json_str )
|
44
|
+
end
|
@@ -0,0 +1,1060 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
require_relative '../model'
|
7
|
+
require_relative '../xpath'
|
8
|
+
|
9
|
+
module Rubyang
|
10
|
+
class Database
|
11
|
+
class SchemaTree
|
12
|
+
class Type
|
13
|
+
attr_reader :arg
|
14
|
+
end
|
15
|
+
class IntegerType < Type
|
16
|
+
def initialize arg
|
17
|
+
@arg = arg
|
18
|
+
range = case arg
|
19
|
+
when 'int8' then '-128..127'
|
20
|
+
when 'int16' then '-32768..32767'
|
21
|
+
when 'int32' then '-2147483648..2147483647'
|
22
|
+
when 'int64' then '-9223372036854775808..9223372036854775807'
|
23
|
+
when 'uint8' then '0..255'
|
24
|
+
when 'uint16' then '0..65535'
|
25
|
+
when 'uint32' then '0..4294967295'
|
26
|
+
when 'uint64' then '0..18446744073709551615'
|
27
|
+
end
|
28
|
+
@range = Range.new range
|
29
|
+
end
|
30
|
+
def update_range arg
|
31
|
+
@range.update arg
|
32
|
+
end
|
33
|
+
def valid? value
|
34
|
+
result = true
|
35
|
+
result &&= @range.valid? value
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
class StringType < Type
|
40
|
+
attr_reader :length, :pattern
|
41
|
+
def initialize
|
42
|
+
@arg = 'string'
|
43
|
+
@length = Length.new
|
44
|
+
@pattern = Pattern.new
|
45
|
+
end
|
46
|
+
def update_length arg
|
47
|
+
@length.update arg
|
48
|
+
end
|
49
|
+
def update_pattern arg
|
50
|
+
@pattern.update arg
|
51
|
+
end
|
52
|
+
def valid? value
|
53
|
+
result = true
|
54
|
+
result &&= @length.valid? value
|
55
|
+
result &&= @pattern.valid? value
|
56
|
+
result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
class BooleanType < Type
|
60
|
+
def initialize
|
61
|
+
@arg = 'boolean'
|
62
|
+
end
|
63
|
+
def valid? value
|
64
|
+
if 'true' == value
|
65
|
+
true
|
66
|
+
elsif 'false' == value
|
67
|
+
true
|
68
|
+
else
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
class EnumerationType < Type
|
74
|
+
def initialize
|
75
|
+
@arg = 'enumeration'
|
76
|
+
@enum = Enum.new
|
77
|
+
end
|
78
|
+
def update_enum arg
|
79
|
+
@enum.update arg
|
80
|
+
end
|
81
|
+
def valid? value
|
82
|
+
result = true
|
83
|
+
result &&= @enum.valid? value
|
84
|
+
result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
class BitsType < Type
|
88
|
+
def initialize
|
89
|
+
@arg = 'bits'
|
90
|
+
@bit = Bit.new
|
91
|
+
end
|
92
|
+
def update_bit arg
|
93
|
+
@bit.update arg
|
94
|
+
end
|
95
|
+
def valid? value
|
96
|
+
result = true
|
97
|
+
result &&= @bit.valid? value
|
98
|
+
result
|
99
|
+
end
|
100
|
+
end
|
101
|
+
class BinaryType < Type
|
102
|
+
def initialize
|
103
|
+
@arg = 'binary'
|
104
|
+
@length = Length.new
|
105
|
+
end
|
106
|
+
def update_length arg
|
107
|
+
@length.update arg
|
108
|
+
end
|
109
|
+
def valid? value
|
110
|
+
result = true
|
111
|
+
result &&= @length.valid? Base64.strict_decode64( value )
|
112
|
+
result
|
113
|
+
end
|
114
|
+
end
|
115
|
+
class LeafrefType < Type
|
116
|
+
def initialize interior_schema_node, path_arg
|
117
|
+
@arg = 'leafref'
|
118
|
+
@path_arg = path_arg
|
119
|
+
@path = Path.new interior_schema_node, path_arg
|
120
|
+
end
|
121
|
+
def path
|
122
|
+
@path_arg
|
123
|
+
@path.path
|
124
|
+
end
|
125
|
+
def valid? data_tree, value
|
126
|
+
result = true
|
127
|
+
result &&= @path.valid? data_tree, true
|
128
|
+
result
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Path
|
133
|
+
attr_reader :path
|
134
|
+
|
135
|
+
def initialize interior_schema_node, arg
|
136
|
+
@path = Rubyang::Xpath::Parser.parse arg
|
137
|
+
if !(@path[0].axis.name == Rubyang::Xpath::Axis::PARENT && @path[0].node_test.node_test == Rubyang::Xpath::NodeTest::NodeType::NODE)
|
138
|
+
raise "unsupported path: #{@path}"
|
139
|
+
end
|
140
|
+
target = interior_schema_node.evaluate_xpath( @path[1..-1] )
|
141
|
+
if target.size == 0
|
142
|
+
raise ArgumentError, "#{arg} is not valid"
|
143
|
+
end
|
144
|
+
@target = target
|
145
|
+
end
|
146
|
+
def valid? data_tree, value
|
147
|
+
true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
class Range
|
151
|
+
def initialize arg
|
152
|
+
@range = [[-Float::INFINITY, Float::INFINITY]]
|
153
|
+
self.update arg
|
154
|
+
end
|
155
|
+
def valid? value
|
156
|
+
if @range.find{ |min2, max2| (min2..max2).include?( value.to_i ) }
|
157
|
+
true
|
158
|
+
else
|
159
|
+
false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
def update arg
|
163
|
+
new_range = Array.new
|
164
|
+
arg.gsub( ' ', '' ).split( '|' ).each{ |range_part|
|
165
|
+
case range_part
|
166
|
+
when /[^\.]+\.\.[^\.]+/
|
167
|
+
min, max = range_part.split('..')
|
168
|
+
else
|
169
|
+
min = max = range_part
|
170
|
+
end
|
171
|
+
case min
|
172
|
+
when /^min$/
|
173
|
+
min = @range.map{ |r| r[0] }.min
|
174
|
+
else
|
175
|
+
min = min.to_i
|
176
|
+
end
|
177
|
+
case max
|
178
|
+
when /^max$/
|
179
|
+
max = @range.map{ |r| r[1] }.max
|
180
|
+
else
|
181
|
+
max = max.to_i
|
182
|
+
end
|
183
|
+
unless @range.find{ |min2, max2| (min2..max2).include?( min ) && (min2..max2).include?( max ) }
|
184
|
+
raise ArgumentError, "#{range_part} is not valid"
|
185
|
+
end
|
186
|
+
new_range.push [min, max]
|
187
|
+
}
|
188
|
+
@range = new_range
|
189
|
+
end
|
190
|
+
def to_s
|
191
|
+
@range.map{ |l| "#{l[0]}..#{l[1]}" }.join( "|" )
|
192
|
+
end
|
193
|
+
end
|
194
|
+
class Length
|
195
|
+
def initialize
|
196
|
+
@length = [[0, 18446744073709551615]]
|
197
|
+
end
|
198
|
+
def valid? value
|
199
|
+
if @length.find{ |min2, max2| (min2..max2).include?( value.size ) }
|
200
|
+
true
|
201
|
+
else
|
202
|
+
false
|
203
|
+
end
|
204
|
+
end
|
205
|
+
def update arg
|
206
|
+
new_length = Array.new
|
207
|
+
arg.gsub( ' ', '' ).split( '|' ).each{ |length_part|
|
208
|
+
case length_part
|
209
|
+
when /[^\.]+\.\.[^\.]+/
|
210
|
+
min, max = length_part.split('..')
|
211
|
+
else
|
212
|
+
min = max = length_part
|
213
|
+
end
|
214
|
+
case min
|
215
|
+
when /^min$/
|
216
|
+
min = @length.map{ |r| r[0] }.min
|
217
|
+
else
|
218
|
+
min = min.to_i
|
219
|
+
end
|
220
|
+
case max
|
221
|
+
when /^max$/
|
222
|
+
max = @length.map{ |r| r[1] }.max
|
223
|
+
else
|
224
|
+
max = max.to_i
|
225
|
+
end
|
226
|
+
unless @length.find{ |min2, max2| (min2..max2).include?( min ) && (min2..max2).include?( max ) }
|
227
|
+
raise ArgumentError, "#{length_part} is not valid"
|
228
|
+
end
|
229
|
+
new_length.push [min, max]
|
230
|
+
}
|
231
|
+
@length = new_length
|
232
|
+
end
|
233
|
+
def to_s
|
234
|
+
@length.map{ |l| "#{l[0]}..#{l[1]}" }.join( "|" )
|
235
|
+
end
|
236
|
+
end
|
237
|
+
class Pattern
|
238
|
+
def initialize
|
239
|
+
@pattern = Regexp.new( '.*' )
|
240
|
+
end
|
241
|
+
def valid? value
|
242
|
+
if @pattern =~ value
|
243
|
+
true
|
244
|
+
else
|
245
|
+
false
|
246
|
+
end
|
247
|
+
end
|
248
|
+
def update arg
|
249
|
+
@pattern = Regexp.new( arg )
|
250
|
+
end
|
251
|
+
def to_s
|
252
|
+
@pattern.inspect
|
253
|
+
end
|
254
|
+
end
|
255
|
+
class Enum
|
256
|
+
def initialize
|
257
|
+
@enum = []
|
258
|
+
end
|
259
|
+
def valid? value
|
260
|
+
if @enum.find{ |e| e == value }
|
261
|
+
true
|
262
|
+
else
|
263
|
+
false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
def update arg
|
267
|
+
if @enum.find{ |e| e == arg }
|
268
|
+
raise ArgumentError, "#{arg} is not valid"
|
269
|
+
end
|
270
|
+
@enum.push arg
|
271
|
+
end
|
272
|
+
end
|
273
|
+
class Bit
|
274
|
+
def initialize
|
275
|
+
@bit = []
|
276
|
+
end
|
277
|
+
def valid? value
|
278
|
+
values = value.split( ' ' )
|
279
|
+
if values.inject( true ){ |result, v| result && @bit.find{ |b| b == v } }
|
280
|
+
true
|
281
|
+
else
|
282
|
+
false
|
283
|
+
end
|
284
|
+
end
|
285
|
+
def update arg
|
286
|
+
if @bit.find{ |b| b == arg }
|
287
|
+
raise ArgumentError, "#{arg} is not valid"
|
288
|
+
end
|
289
|
+
@bit.push arg
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
class SchemaNode
|
294
|
+
attr_accessor :yangs, :arg, :yang, :parent, :module
|
295
|
+
def initialize yangs, arg, yang, parent, _module
|
296
|
+
@yangs = yangs
|
297
|
+
@arg = arg
|
298
|
+
@yang = yang
|
299
|
+
@parent = parent
|
300
|
+
@module = _module
|
301
|
+
end
|
302
|
+
def model
|
303
|
+
@yang
|
304
|
+
end
|
305
|
+
def namespace
|
306
|
+
@module.substmt( 'namespace' )[0].arg
|
307
|
+
end
|
308
|
+
def prefix
|
309
|
+
@module.substmt( 'prefix' )[0].arg
|
310
|
+
end
|
311
|
+
def root
|
312
|
+
if @parent == nil
|
313
|
+
self
|
314
|
+
else
|
315
|
+
@parent.root
|
316
|
+
end
|
317
|
+
end
|
318
|
+
def to_json
|
319
|
+
h = Hash.new
|
320
|
+
self.to_json_recursive( h )
|
321
|
+
h.to_json
|
322
|
+
end
|
323
|
+
def evaluate_xpath location_steps, current=self
|
324
|
+
location_step = location_steps.first
|
325
|
+
candidates_by_axis = self.evaluate_xpath_axis( location_step, current )
|
326
|
+
candidates_by_node_test = candidates_by_axis.inject([]){ |cs, c| cs + c.evaluate_xpath_node_test( location_step, current ) }
|
327
|
+
candidates_by_predicates = candidates_by_node_test.inject([]){ |cs, c| cs + c.evaluate_xpath_predicates( location_step, current ) }
|
328
|
+
if location_steps[1..-1].size == 0
|
329
|
+
candidates_by_predicates
|
330
|
+
else
|
331
|
+
candidates_by_predicates.inject([]){ |cs, c| c.evaluate_xpath( location_steps[1..-1], current ) }
|
332
|
+
end
|
333
|
+
end
|
334
|
+
def evaluate_xpath_axis location_step, current
|
335
|
+
case location_step.axis.name
|
336
|
+
when Rubyang::Xpath::Axis::PARENT
|
337
|
+
[@parent]
|
338
|
+
when Rubyang::Xpath::Axis::CHILD
|
339
|
+
@children
|
340
|
+
else
|
341
|
+
raise "location_step.axis.name: #{location_step.axis.name} NOT implemented"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
def evaluate_xpath_node_test location_step, current
|
345
|
+
case location_step.node_test.node_test_type
|
346
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::NAME_TEST
|
347
|
+
if self.model.arg == location_step.node_test.node_test
|
348
|
+
[self]
|
349
|
+
else
|
350
|
+
[]
|
351
|
+
end
|
352
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::NODE_TYPE
|
353
|
+
case location_step.node_test.node_test
|
354
|
+
when Rubyang::Xpath::NodeTest::NodeType::COMMENT
|
355
|
+
raise "node-type: comment is not implemented"
|
356
|
+
when Rubyang::Xpath::NodeTest::NodeType::TEXT
|
357
|
+
raise "node-type: text is not implemented"
|
358
|
+
when Rubyang::Xpath::NodeTest::NodeType::NODE
|
359
|
+
[self]
|
360
|
+
else
|
361
|
+
raise "node-type not match to comment or text or node"
|
362
|
+
end
|
363
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::PROCESSING_INSTRUCTION
|
364
|
+
raise "processing-instruction is not implemented"
|
365
|
+
else
|
366
|
+
raise ""
|
367
|
+
end
|
368
|
+
end
|
369
|
+
def evaluate_xpath_predicates location_step, current
|
370
|
+
case location_step.predicates.size
|
371
|
+
when 0
|
372
|
+
[self]
|
373
|
+
else
|
374
|
+
location_step.predicates.inject([]){ |cs, predicate|
|
375
|
+
self.evaluate_xpath_predicate_expr predicate.expr, current
|
376
|
+
}
|
377
|
+
end
|
378
|
+
end
|
379
|
+
def evaluate_xpath_predicate_expr expr, current
|
380
|
+
case expr
|
381
|
+
when Rubyang::Xpath::Predicate::OrExpr
|
382
|
+
if Rubyang::Xpath::Parser::DEBUG
|
383
|
+
puts
|
384
|
+
puts "in OrExpr"
|
385
|
+
puts "op1: #{expr.op1}"
|
386
|
+
puts "op2: #{expr.op2}"
|
387
|
+
puts
|
388
|
+
end
|
389
|
+
op1 = expr.op1
|
390
|
+
op2 = expr.op2
|
391
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
392
|
+
if op2 == nil
|
393
|
+
op1_result
|
394
|
+
else
|
395
|
+
op2_result = self.evaluate_xpath_predicate_expr( op2, current )
|
396
|
+
op1_result | op2_result
|
397
|
+
end
|
398
|
+
when Rubyang::Xpath::Predicate::AndExpr
|
399
|
+
if Rubyang::Xpath::Parser::DEBUG
|
400
|
+
puts
|
401
|
+
puts "in AndExpr"
|
402
|
+
puts "op1: #{expr.op1}"
|
403
|
+
puts "op2: #{expr.op2}"
|
404
|
+
puts
|
405
|
+
end
|
406
|
+
op1 = expr.op1
|
407
|
+
op2 = expr.op2
|
408
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
409
|
+
if op2 == nil
|
410
|
+
op1_result
|
411
|
+
else
|
412
|
+
op2_result = self.evaluate_xpath_predicate_expr( op2, current )
|
413
|
+
op1_result & op2_result
|
414
|
+
end
|
415
|
+
when Rubyang::Xpath::Predicate::EqualityExpr
|
416
|
+
if Rubyang::Xpath::Parser::DEBUG
|
417
|
+
puts
|
418
|
+
puts "in EqualityExpr"
|
419
|
+
puts "op1: #{expr.op1}"
|
420
|
+
puts "op2: #{expr.op2}"
|
421
|
+
puts "operator: #{expr.operator}"
|
422
|
+
puts
|
423
|
+
end
|
424
|
+
op1 = expr.op1
|
425
|
+
op2 = expr.op2
|
426
|
+
operator = expr.operator
|
427
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
428
|
+
if op2 == nil
|
429
|
+
op1_result
|
430
|
+
else
|
431
|
+
case operator
|
432
|
+
when /^\=$/
|
433
|
+
op2_result = self.evaluate_xpath_predicate_expr( op2, current )
|
434
|
+
if op1_result.size > 0 and op2_result.size >0
|
435
|
+
[self]
|
436
|
+
else
|
437
|
+
[]
|
438
|
+
end
|
439
|
+
#op1_result.select{ |a| op2_result.map{ |b| b.value }.include? a }
|
440
|
+
when /^\!\=$/
|
441
|
+
raise "Equality Expr: '!=' not implemented"
|
442
|
+
else
|
443
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
444
|
+
end
|
445
|
+
end
|
446
|
+
when Rubyang::Xpath::Predicate::RelationalExpr
|
447
|
+
if Rubyang::Xpath::Parser::DEBUG
|
448
|
+
puts
|
449
|
+
puts "in RelationalExpr"
|
450
|
+
puts "op1: #{expr.op1}"
|
451
|
+
puts "op2: #{expr.op2}"
|
452
|
+
puts "operator: #{expr.operator}"
|
453
|
+
puts
|
454
|
+
end
|
455
|
+
op1 = expr.op1
|
456
|
+
op2 = expr.op2
|
457
|
+
operator = expr.operator
|
458
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
459
|
+
if op2 == nil
|
460
|
+
op1_result
|
461
|
+
else
|
462
|
+
case operator
|
463
|
+
when /^\>$/
|
464
|
+
raise "Relational Expr: '>' not implemented"
|
465
|
+
when /^\<$/
|
466
|
+
raise "Relational Expr: '<' not implemented"
|
467
|
+
when /^\>\=$/
|
468
|
+
raise "Relational Expr: '>=' not implemented"
|
469
|
+
when /^\<\=$/
|
470
|
+
raise "Relational Expr: '<=' not implemented"
|
471
|
+
else
|
472
|
+
raise "Relational Expr: other than '>', '<', '>=' and '<=' not implemented"
|
473
|
+
end
|
474
|
+
end
|
475
|
+
when Rubyang::Xpath::Predicate::AdditiveExpr
|
476
|
+
if Rubyang::Xpath::Parser::DEBUG
|
477
|
+
puts
|
478
|
+
puts "in AdditiveExpr"
|
479
|
+
puts "op1: #{expr.op1}"
|
480
|
+
puts "op2: #{expr.op2}"
|
481
|
+
puts "operator: #{expr.operator}"
|
482
|
+
puts
|
483
|
+
end
|
484
|
+
op1 = expr.op1
|
485
|
+
op2 = expr.op2
|
486
|
+
operator = expr.operator
|
487
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
488
|
+
if op2 == nil
|
489
|
+
op1_result
|
490
|
+
else
|
491
|
+
case operator
|
492
|
+
when /^\+$/
|
493
|
+
raise "Additive Expr: '+' not implemented"
|
494
|
+
when /^\-$/
|
495
|
+
raise "Additive Expr: '-' not implemented"
|
496
|
+
else
|
497
|
+
raise "Additive Expr: other than '+' and '-' not implemented"
|
498
|
+
end
|
499
|
+
end
|
500
|
+
when Rubyang::Xpath::Predicate::MultiplicativeExpr
|
501
|
+
if Rubyang::Xpath::Parser::DEBUG
|
502
|
+
puts
|
503
|
+
puts "in MultiplicativeExpr"
|
504
|
+
puts "op1: #{expr.op1}"
|
505
|
+
puts "op2: #{expr.op2}"
|
506
|
+
puts "operator: #{expr.operator}"
|
507
|
+
puts
|
508
|
+
end
|
509
|
+
op1 = expr.op1
|
510
|
+
op2 = expr.op2
|
511
|
+
operator = expr.operator
|
512
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
513
|
+
if op2 == nil
|
514
|
+
op1_result
|
515
|
+
else
|
516
|
+
case operator
|
517
|
+
when /^\*$/
|
518
|
+
raise "Multiplicative Expr: '*' not implemented"
|
519
|
+
when /^\/$/
|
520
|
+
raise "Multiplicative Expr: '/' not implemented"
|
521
|
+
else
|
522
|
+
raise "Multiplicative Expr: other than '*' and '/' not implemented"
|
523
|
+
end
|
524
|
+
end
|
525
|
+
when Rubyang::Xpath::Predicate::UnaryExpr
|
526
|
+
if Rubyang::Xpath::Parser::DEBUG
|
527
|
+
puts
|
528
|
+
puts "in UnaryExpr"
|
529
|
+
puts "op1: #{expr.op1}"
|
530
|
+
puts "operator: #{expr.operator}"
|
531
|
+
puts
|
532
|
+
end
|
533
|
+
op1 = expr.op1
|
534
|
+
operator = expr.operator
|
535
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
536
|
+
case operator
|
537
|
+
when nil
|
538
|
+
op1_result
|
539
|
+
when /^\-$/
|
540
|
+
raise "Unary Expr: '-' not implemented"
|
541
|
+
else
|
542
|
+
raise "Unary Expr: other than '-' not implemented"
|
543
|
+
end
|
544
|
+
when Rubyang::Xpath::Predicate::UnionExpr
|
545
|
+
if Rubyang::Xpath::Parser::DEBUG
|
546
|
+
puts
|
547
|
+
puts "in UnionExpr"
|
548
|
+
puts "op1: #{expr.op1}"
|
549
|
+
puts "op2: #{expr.op2}"
|
550
|
+
puts "operator: #{expr.operator}"
|
551
|
+
puts
|
552
|
+
end
|
553
|
+
op1 = expr.op1
|
554
|
+
op2 = expr.op2
|
555
|
+
operator = expr.operator
|
556
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
557
|
+
if op2 == nil
|
558
|
+
op1_result
|
559
|
+
else
|
560
|
+
case operator
|
561
|
+
when /^\|$/
|
562
|
+
raise "Union Expr: '|' not implemented"
|
563
|
+
else
|
564
|
+
raise "Union Expr: other than '|' not implemented"
|
565
|
+
end
|
566
|
+
end
|
567
|
+
when Rubyang::Xpath::Predicate::PathExpr
|
568
|
+
if Rubyang::Xpath::Parser::DEBUG
|
569
|
+
puts
|
570
|
+
puts "in PathExpr"
|
571
|
+
puts "op1: #{expr.op1}"
|
572
|
+
puts "op2: #{expr.op2}"
|
573
|
+
puts "operator: #{expr.operator}"
|
574
|
+
puts
|
575
|
+
end
|
576
|
+
op1 = expr.op1
|
577
|
+
op2 = expr.op2
|
578
|
+
operator = expr.operator
|
579
|
+
case op1
|
580
|
+
when Rubyang::Xpath::LocationSteps
|
581
|
+
op1_result = self.evaluate_xpath( op1, current )
|
582
|
+
when Rubyang::Xpath::Predicate::FilterExpr
|
583
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
584
|
+
if op2 == nil
|
585
|
+
op1_result
|
586
|
+
else
|
587
|
+
case operator
|
588
|
+
when /^\/$/
|
589
|
+
case op2
|
590
|
+
when Rubyang::Xpath::LocationSteps
|
591
|
+
if !(op2[0].axis.name == Rubyang::Xpath::Axis::PARENT &&
|
592
|
+
op2[0].node_test.node_test == Rubyang::Xpath::NodeTest::NodeType::NODE)
|
593
|
+
raise "unsupported path: #{op2}"
|
594
|
+
end
|
595
|
+
current.evaluate_xpath (op1_result + op2[1..-1]), current
|
596
|
+
else
|
597
|
+
raise "Path Expr: op1 is not LocationSteps"
|
598
|
+
end
|
599
|
+
when /^\/\/$/
|
600
|
+
raise "Path Expr: '//' not implemented"
|
601
|
+
else
|
602
|
+
raise "Path Expr: other than '/' and '//' not implemented"
|
603
|
+
end
|
604
|
+
end
|
605
|
+
else
|
606
|
+
raise ""
|
607
|
+
end
|
608
|
+
when Rubyang::Xpath::Predicate::FilterExpr
|
609
|
+
if Rubyang::Xpath::Parser::DEBUG
|
610
|
+
puts
|
611
|
+
puts "in FilterExpr"
|
612
|
+
puts "op1: #{expr.op1}"
|
613
|
+
puts "op2: #{expr.op2}"
|
614
|
+
puts
|
615
|
+
end
|
616
|
+
op1 = expr.op1
|
617
|
+
op2 = expr.op2
|
618
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
619
|
+
if op2 == nil
|
620
|
+
op1_result
|
621
|
+
else
|
622
|
+
op2_result = self.evaluate_xpath_predicate_expr( op2.expr, current )
|
623
|
+
raise "Filter Expr: Filter Predicate not implemented"
|
624
|
+
end
|
625
|
+
when Rubyang::Xpath::Predicate::PrimaryExpr
|
626
|
+
if Rubyang::Xpath::Parser::DEBUG
|
627
|
+
puts
|
628
|
+
puts "in PrimaryExpr"
|
629
|
+
puts "op1: #{expr.op1}"
|
630
|
+
puts
|
631
|
+
end
|
632
|
+
op1 = expr.op1
|
633
|
+
case op1
|
634
|
+
when Rubyang::Xpath::Predicate::Expr
|
635
|
+
raise "Primary Expr: '( Expr )' not implemented"
|
636
|
+
when Rubyang::Xpath::Predicate::FunctionCall
|
637
|
+
op1_result = self.evaluate_xpath_predicate_expr( op1, current )
|
638
|
+
when /^\$.*$/
|
639
|
+
raise "Primary Expr: 'Variable Reference' not implemented"
|
640
|
+
else
|
641
|
+
raise "Primary Expr: 'Literal' and 'Number' not implemented"
|
642
|
+
end
|
643
|
+
when Rubyang::Xpath::Predicate::FunctionCall
|
644
|
+
if Rubyang::Xpath::Parser::DEBUG
|
645
|
+
puts
|
646
|
+
puts "in FunctionCall"
|
647
|
+
puts "name: #{expr.name}"
|
648
|
+
puts "args: #{expr.args}"
|
649
|
+
puts
|
650
|
+
end
|
651
|
+
name = expr.name
|
652
|
+
case name
|
653
|
+
when Rubyang::Xpath::Predicate::FunctionCall::CURRENT
|
654
|
+
Rubyang::Xpath::LocationSteps.new
|
655
|
+
else
|
656
|
+
raise "FunctionCall: #{name} not implemented"
|
657
|
+
end
|
658
|
+
else
|
659
|
+
raise "Unrecognized predicate: #{predicate}"
|
660
|
+
end
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
class InteriorSchemaNode < SchemaNode
|
665
|
+
attr_accessor :yangs, :arg, :yang, :parent, :children
|
666
|
+
|
667
|
+
def initialize yangs, arg, yang, parent, _module
|
668
|
+
super yangs, arg, yang, parent, _module
|
669
|
+
@children = []
|
670
|
+
end
|
671
|
+
|
672
|
+
def resolve_type type_stmt, yangs, current_module, typedef_list
|
673
|
+
case type_stmt.arg
|
674
|
+
when 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64'
|
675
|
+
type = IntegerType.new type_stmt.arg
|
676
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
677
|
+
case s
|
678
|
+
when Rubyang::Model::Range
|
679
|
+
type.update_range s.arg
|
680
|
+
else
|
681
|
+
raise ArgumentError, "#{s} is not valid"
|
682
|
+
end
|
683
|
+
}
|
684
|
+
when 'string'
|
685
|
+
type = StringType.new
|
686
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
687
|
+
case s
|
688
|
+
when Rubyang::Model::Length
|
689
|
+
type.update_length s.arg
|
690
|
+
when Rubyang::Model::Pattern
|
691
|
+
type.update_pattern s.arg
|
692
|
+
else
|
693
|
+
raise ArgumentError, "#{s} is not valid"
|
694
|
+
end
|
695
|
+
}
|
696
|
+
when 'boolean'
|
697
|
+
type = BooleanType.new
|
698
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
699
|
+
raise ArgumentError, "#{s} is not valid"
|
700
|
+
}
|
701
|
+
when 'enumeration'
|
702
|
+
type = EnumerationType.new
|
703
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
704
|
+
case s
|
705
|
+
when Rubyang::Model::Enum
|
706
|
+
type.update_enum s.arg
|
707
|
+
else
|
708
|
+
raise ArgumentError, "#{s} is not valid"
|
709
|
+
end
|
710
|
+
}
|
711
|
+
when 'bits'
|
712
|
+
type = BitsType.new
|
713
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
714
|
+
case s
|
715
|
+
when Rubyang::Model::Bit
|
716
|
+
type.update_bit s.arg
|
717
|
+
else
|
718
|
+
raise ArgumentError, "#{s} is not valid"
|
719
|
+
end
|
720
|
+
}
|
721
|
+
when 'binary'
|
722
|
+
type = BinaryType.new
|
723
|
+
type_stmt.substmts( Rubyang::Model::TypeBodyStmtList ).each{ |s|
|
724
|
+
case s
|
725
|
+
when Rubyang::Model::Length
|
726
|
+
type.update_length s.arg
|
727
|
+
else
|
728
|
+
raise ArgumentError, "#{s} is not valid"
|
729
|
+
end
|
730
|
+
}
|
731
|
+
when 'leafref'
|
732
|
+
type = LeafrefType.new self, type_stmt.substmt( 'path' )[0].arg
|
733
|
+
else
|
734
|
+
case type_stmt.arg
|
735
|
+
when /^[^:]+$/
|
736
|
+
arg = type_stmt.arg
|
737
|
+
if typedef_list.find{ |s| s.arg == arg }
|
738
|
+
typedef_stmt = typedef_list.find{ |s| s.arg == arg }
|
739
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, current_module, typedef_list
|
740
|
+
else
|
741
|
+
include_submodule = current_module.substmt( 'include' ).map{ |s|
|
742
|
+
yangs.find{ |y| y.arg == s.arg }
|
743
|
+
}.find{ |s|
|
744
|
+
s.substmt( 'typedef' ).find{ |t| t.arg == arg }
|
745
|
+
}
|
746
|
+
typedef_stmt = include_submodule.substmt( 'typedef' ).find{ |s| s.arg == arg }
|
747
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, include_submodule, include_submodule.substmt( 'typedef' )
|
748
|
+
end
|
749
|
+
when /^[^:]+:[^:]+$/
|
750
|
+
prefix, arg = type_stmt.arg.split(':')
|
751
|
+
case current_module
|
752
|
+
when Rubyang::Model::Module
|
753
|
+
case prefix
|
754
|
+
when current_module.substmt( 'prefix' )[0].arg
|
755
|
+
typedef_stmt = typedef_list.find{ |s| s.arg == arg }
|
756
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, current_module, typedef_list
|
757
|
+
else
|
758
|
+
import_module = yangs.find{ |y|
|
759
|
+
y.arg == current_module.substmt( 'import' ).find{ |s| s.substmt( 'prefix' )[0].arg == prefix }.arg
|
760
|
+
}
|
761
|
+
typedef_stmt = import_module.substmt( 'typedef' ).find{ |s| s.arg == arg }
|
762
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, import_module, import_module.substmt( 'typedef' )
|
763
|
+
end
|
764
|
+
when Rubyang::Model::Submodule
|
765
|
+
case prefix
|
766
|
+
when current_module.substmt( 'belongs-to' )[0].substmt( 'prefix' )[0].arg
|
767
|
+
typedef_stmt = typedef_list.find{ |s| s.arg == arg }
|
768
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, current_module, typedef_list
|
769
|
+
else
|
770
|
+
import_module = yangs.find{ |y|
|
771
|
+
y.arg == current_module.substmt( 'import' ).find{ |s| s.substmt( 'prefix' )[0].arg == prefix }.arg
|
772
|
+
}
|
773
|
+
typedef_stmt = import_module.substmt( 'typedef' ).find{ |s| s.arg == arg }
|
774
|
+
type = resolve_type typedef_stmt.substmt( 'type' )[0], yangs, import_module, import_module.substmt( 'typedef' )
|
775
|
+
end
|
776
|
+
else
|
777
|
+
raise
|
778
|
+
end
|
779
|
+
end
|
780
|
+
end
|
781
|
+
type
|
782
|
+
end
|
783
|
+
|
784
|
+
def load_yang yang, yangs=@yangs, parent_module=yang, current_module=yang, grouping_list=[], typedef_list=[]
|
785
|
+
case yang
|
786
|
+
when Rubyang::Model::Module
|
787
|
+
yangs.push yang
|
788
|
+
module_arg = yang.arg
|
789
|
+
namespace_arg = yang.substmt( 'namespace' )[0].arg
|
790
|
+
prefix_arg = yang.substmt( 'prefix' )[0].arg
|
791
|
+
grouping_list += yang.substmt( 'grouping' )
|
792
|
+
typedef_list += yang.substmt( 'typedef' )
|
793
|
+
yang.substmt( 'include' ).each{ |i|
|
794
|
+
i.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
795
|
+
self.load_yang s, yangs, parent_module, i, i.substmt( 'grouping' ), i.substmt( 'typedef' )
|
796
|
+
}
|
797
|
+
}
|
798
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
799
|
+
self.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
800
|
+
}
|
801
|
+
when Rubyang::Model::Submodule
|
802
|
+
yangs.push yang
|
803
|
+
when Rubyang::Model::Container
|
804
|
+
container_arg = yang.arg
|
805
|
+
grouping_list += yang.substmt( 'grouping' )
|
806
|
+
typedef_list += yang.substmt( 'typedef' )
|
807
|
+
self.children.push Container.new( yangs, container_arg, yang, self, parent_module )
|
808
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
809
|
+
self.children.last.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
810
|
+
}
|
811
|
+
when Rubyang::Model::Leaf
|
812
|
+
leaf_arg = yang.arg
|
813
|
+
type = self.resolve_type yang.substmt( 'type' )[0], yangs, current_module, typedef_list
|
814
|
+
self.children.push Leaf.new( yangs, leaf_arg, yang, self, parent_module, type )
|
815
|
+
when Rubyang::Model::LeafList
|
816
|
+
leaf_arg = yang.arg
|
817
|
+
type = self.resolve_type yang.substmt( 'type' )[0], yangs, current_module, typedef_list
|
818
|
+
self.children.push LeafList.new( yangs, leaf_arg, yang, self, parent_module, type )
|
819
|
+
when Rubyang::Model::List
|
820
|
+
list_arg = yang.arg
|
821
|
+
grouping_list += yang.substmt( 'grouping' )
|
822
|
+
typedef_list += yang.substmt( 'typedef' )
|
823
|
+
self.children.push List.new( yangs, list_arg, yang, self, parent_module )
|
824
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
825
|
+
self.children.last.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
826
|
+
}
|
827
|
+
when Rubyang::Model::Choice
|
828
|
+
choice_arg = yang.arg
|
829
|
+
grouping_list += yang.substmt( 'grouping' )
|
830
|
+
typedef_list += yang.substmt( 'typedef' )
|
831
|
+
self.children.push Choice.new( yangs, choice_arg, yang, self, parent_module )
|
832
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
833
|
+
self.children.last.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
834
|
+
}
|
835
|
+
when Rubyang::Model::Case
|
836
|
+
case_arg = yang.arg
|
837
|
+
grouping_list += yang.substmt( 'grouping' )
|
838
|
+
typedef_list += yang.substmt( 'typedef' )
|
839
|
+
self.children.push Case.new( yangs, case_arg, yang, self, parent_module )
|
840
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
841
|
+
self.children.last.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
842
|
+
}
|
843
|
+
when Rubyang::Model::Augment
|
844
|
+
target_node = self.resolve_node( yang.arg )
|
845
|
+
yang.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
846
|
+
target_node.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
847
|
+
}
|
848
|
+
when Rubyang::Model::Uses
|
849
|
+
self.resolve_uses( yang, yangs, parent_module, current_module, grouping_list, typedef_list )
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
def resolve_uses uses_stmt, yangs, parent_module, current_module, grouping_list, typedef_list
|
854
|
+
case uses_stmt.arg
|
855
|
+
when /^[^:]+$/
|
856
|
+
arg = uses_stmt.arg
|
857
|
+
if grouping_list.find{ |s| s.arg == arg }
|
858
|
+
grouping_stmt = grouping_list.find{ |s| s.arg == arg }
|
859
|
+
grouping_list += grouping_stmt.substmt( 'grouping' )
|
860
|
+
typedef_list += grouping_stmt.substmt( 'typedef' )
|
861
|
+
grouping_stmt.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
862
|
+
self.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
863
|
+
}
|
864
|
+
else
|
865
|
+
include_submodule = current_module.substmt( 'include' ).map{ |s|
|
866
|
+
yangs.find{ |y| y.arg == s.arg }
|
867
|
+
}.find{ |s|
|
868
|
+
s.substmt( 'grouping' ).find{ |t| t.arg == arg }
|
869
|
+
}
|
870
|
+
grouping_stmt = include_submodule.substmt( 'grouping' ).find{ |s| s.arg == arg }
|
871
|
+
grouping_list = include_submodule.substmt( 'grouping' ) + grouping_stmt.substmt( 'grouping' )
|
872
|
+
typedef_list = include_submodule.substmt( 'typedef' ) + grouping_stmt.substmt( 'typedef' )
|
873
|
+
grouping_stmt.substmt( Rubyang::Model::DataDefStmtList ).each{ |s|
|
874
|
+
self.load_yang s, yangs, parent_module, include_submodule, grouping_list, typedef_list
|
875
|
+
}
|
876
|
+
end
|
877
|
+
when /^[^:]+:[^:]+$/
|
878
|
+
prefix, arg = uses_stmt.arg.split(':')
|
879
|
+
case current_module
|
880
|
+
when Rubyang::Model::Module
|
881
|
+
case prefix
|
882
|
+
when current_module.substmt( 'prefix' )[0].arg
|
883
|
+
grouping_stmt = grouping_list.find{ |s| s.arg == arg }
|
884
|
+
grouping_list += grouping_stmt.substmt( 'grouping' )
|
885
|
+
typedef_list += grouping_stmt.substmt( 'typedef' )
|
886
|
+
grouping_stmt.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
887
|
+
self.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
888
|
+
}
|
889
|
+
else
|
890
|
+
import_module = yangs.find{ |y|
|
891
|
+
y.arg == current_module.substmt( 'import' ).find{ |s| s.substmt( 'prefix' )[0].arg == prefix }.arg
|
892
|
+
}
|
893
|
+
grouping_stmt = import_module.substmt( 'grouping' ).find{ |s| s.arg == arg }
|
894
|
+
grouping_list = import_module.substmt( 'grouping' ) + grouping_stmt.substmt( 'grouping' )
|
895
|
+
typedef_list = import_module.substmt( 'typedef' ) + grouping_stmt.substmt( 'typedef' )
|
896
|
+
grouping_stmt.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
897
|
+
self.load_yang s, yangs, parent_module, import_module, grouping_list, typedef_list
|
898
|
+
}
|
899
|
+
end
|
900
|
+
when Rubyang::Model::Submodule
|
901
|
+
case prefix
|
902
|
+
when current_module.substmt( 'belongs-to' )[0].substmt( 'prefix' )[0].arg
|
903
|
+
grouping_stmt = grouping_list.find{ |s| s.arg == arg }
|
904
|
+
grouping_list += grouping_stmt.substmt( 'grouping' )
|
905
|
+
typedef_list += grouping_stmt.substmt( 'typedef' )
|
906
|
+
grouping_stmt.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
907
|
+
self.load_yang s, yangs, parent_module, current_module, grouping_list, typedef_list
|
908
|
+
}
|
909
|
+
else
|
910
|
+
import_module = yangs.find{ |y|
|
911
|
+
y.arg == current_module.substmt( 'import' ).find{ |s| s.substmt( 'prefix' )[0].arg == prefix }.arg
|
912
|
+
}
|
913
|
+
grouping_stmt = import_module.substmt( 'grouping' ).find{ |s| s.arg == arg }
|
914
|
+
grouping_list = import_module.substmt( 'grouping' ) + grouping_stmt.substmt( 'grouping' )
|
915
|
+
typedef_list = import_module.substmt( 'typedef' ) + grouping_stmt.substmt( 'typedef' )
|
916
|
+
grouping_stmt.substmts( Rubyang::Model::DataDefStmtList ).each{ |s|
|
917
|
+
self.load_yang s, yangs, parent_module, import_module, grouping_list, typedef_list
|
918
|
+
}
|
919
|
+
end
|
920
|
+
else
|
921
|
+
raise
|
922
|
+
end
|
923
|
+
end
|
924
|
+
end
|
925
|
+
def resolve_node path
|
926
|
+
path_splitted = path.split( '/' )
|
927
|
+
next_node = case path_splitted.first
|
928
|
+
when '', '.'
|
929
|
+
self
|
930
|
+
when '..'
|
931
|
+
self
|
932
|
+
else
|
933
|
+
@children.find{ |c| c.model.arg == path_splitted.first }
|
934
|
+
end
|
935
|
+
if path_splitted.size == 1
|
936
|
+
next_node
|
937
|
+
else
|
938
|
+
next_node.resolve_node( path_splitted[1..-1].join( '/' ) )
|
939
|
+
end
|
940
|
+
end
|
941
|
+
end
|
942
|
+
|
943
|
+
class LeafSchemaNode < SchemaNode
|
944
|
+
attr_reader :yangs, :arg, :yang, :parent, :module, :type
|
945
|
+
def initialize yangs, arg, yang, parent, _module, type
|
946
|
+
super yangs, arg, yang, parent, _module
|
947
|
+
@type = type
|
948
|
+
end
|
949
|
+
def type
|
950
|
+
@type
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
954
|
+
class Root < InteriorSchemaNode
|
955
|
+
def initialize yangs, arg=nil, yang=nil, parent=nil, _module=nil
|
956
|
+
super
|
957
|
+
end
|
958
|
+
def namespace
|
959
|
+
'http://rubyang/config/0.1'
|
960
|
+
end
|
961
|
+
def prefix
|
962
|
+
''
|
963
|
+
end
|
964
|
+
def to_json_recursive h
|
965
|
+
@children.each{ |c|
|
966
|
+
c.to_json_recursive h
|
967
|
+
}
|
968
|
+
h
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
972
|
+
class Container < InteriorSchemaNode
|
973
|
+
def to_json_recursive h
|
974
|
+
h['type'] = 'container'
|
975
|
+
h['arg'] = @arg
|
976
|
+
h['children'] = Hash.new
|
977
|
+
@children.each{ |c|
|
978
|
+
c.to_json_recursive h['children']
|
979
|
+
}
|
980
|
+
h
|
981
|
+
end
|
982
|
+
end
|
983
|
+
|
984
|
+
class Leaf < LeafSchemaNode
|
985
|
+
def to_json_recursive h
|
986
|
+
h['type'] = 'leaf'
|
987
|
+
h['arg'] = @arg
|
988
|
+
case @type
|
989
|
+
when Rubyang::Database::SchemaTree::StringType
|
990
|
+
h['datatype'] = 'string'
|
991
|
+
h['parameters'] = Hash.new
|
992
|
+
h['parameters']['length'] = @type.length.to_s
|
993
|
+
h['parameters']['pattern'] = @type.pattern.to_s
|
994
|
+
else
|
995
|
+
raise
|
996
|
+
end
|
997
|
+
h
|
998
|
+
end
|
999
|
+
end
|
1000
|
+
|
1001
|
+
class List < InteriorSchemaNode
|
1002
|
+
def keys
|
1003
|
+
@yang.substmt( 'key' )[0].arg.split( /[ \t]+/ )
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
class LeafList < LeafSchemaNode
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
class Choice < InteriorSchemaNode
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
class Case < InteriorSchemaNode
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
class Rpc < SchemaNode
|
1017
|
+
end
|
1018
|
+
class Input < SchemaNode
|
1019
|
+
end
|
1020
|
+
class Output < SchemaNode
|
1021
|
+
end
|
1022
|
+
class Notification < SchemaNode
|
1023
|
+
end
|
1024
|
+
class Anyxml < SchemaNode
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
def initialize yangs
|
1028
|
+
@yangs = yangs
|
1029
|
+
@root = Root.new @yangs
|
1030
|
+
end
|
1031
|
+
def root
|
1032
|
+
@root
|
1033
|
+
end
|
1034
|
+
def load model
|
1035
|
+
@root.load_yang( model )
|
1036
|
+
end
|
1037
|
+
end
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
if __FILE__ == $0
|
1042
|
+
require_relative '../../rubyang'
|
1043
|
+
yang_str =<<-EOB
|
1044
|
+
module module1 {
|
1045
|
+
namespace "http://module1.rspec/";
|
1046
|
+
prefix module1;
|
1047
|
+
container container1 {
|
1048
|
+
leaf leaf1 {
|
1049
|
+
type string {
|
1050
|
+
length 0..10;
|
1051
|
+
pattern '[0-9]+';
|
1052
|
+
}
|
1053
|
+
}
|
1054
|
+
}
|
1055
|
+
}
|
1056
|
+
EOB
|
1057
|
+
db = Rubyang::Database.new
|
1058
|
+
db.load_model Rubyang::Model::Parser.parse( yang_str )
|
1059
|
+
puts db.configure.schema.to_json
|
1060
|
+
end
|