rubyang 0.1.1 → 0.1.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.
- checksums.yaml +5 -5
- data/.travis.yml +13 -2
- data/README.md +2 -3
- data/lib/rubyang/database/data_tree.rb +494 -130
- data/lib/rubyang/database/schema_tree.rb +541 -293
- data/lib/rubyang/database.rb +10 -0
- data/lib/rubyang/logger.rb +19 -0
- data/lib/rubyang/model/parser/parser.tab.rb +919 -901
- data/lib/rubyang/model/parser/parser.y +9 -1
- data/lib/rubyang/model/parser.rb +48 -18
- data/lib/rubyang/model.rb +16 -1
- data/lib/rubyang/version.rb +1 -1
- data/lib/rubyang/xpath/parser/parser.tab.rb +561 -548
- data/lib/rubyang/xpath/parser/parser.y +74 -78
- data/lib/rubyang/xpath/parser.rb +12 -2
- data/lib/rubyang/xpath.rb +342 -105
- data/lib/rubyang.rb +1 -0
- data/rubyang.gemspec +2 -2
- metadata +8 -7
@@ -5,6 +5,7 @@ require 'rexml/document'
|
|
5
5
|
require 'rexml/formatters/pretty'
|
6
6
|
require 'json'
|
7
7
|
|
8
|
+
require_relative '../xpath'
|
8
9
|
require_relative 'helper'
|
9
10
|
require_relative 'component_manager'
|
10
11
|
|
@@ -20,13 +21,71 @@ module Rubyang
|
|
20
21
|
@schema_tree = schema_tree
|
21
22
|
@schema = schema
|
22
23
|
@children = []
|
24
|
+
@logger = Rubyang::Logger.instance
|
25
|
+
end
|
26
|
+
def to_s parent=true
|
27
|
+
head, vars, tail = "#<#{self.class.to_s}:0x#{(self.object_id << 1).to_s(16).rjust(14,'0')} ", Array.new, ">"
|
28
|
+
if parent
|
29
|
+
vars.push "@parent=#{@parent.to_s(false)}"
|
30
|
+
vars.push "@schema_tree=#{@schema_tree.to_s(false)}"
|
31
|
+
vars.push "@schema=#{@schema.to_s(true)}"
|
32
|
+
vars.push "@children=#{@children.to_s}"
|
33
|
+
end
|
34
|
+
head + vars.join(', ') + tail
|
35
|
+
end
|
36
|
+
def to_xml pretty: false
|
37
|
+
doc = REXML::Document.new
|
38
|
+
self.to_xml_recursive doc, ''
|
39
|
+
if pretty
|
40
|
+
pretty_formatter = REXML::Formatters::Pretty.new( 2 )
|
41
|
+
pretty_formatter.compact = true
|
42
|
+
output = ''
|
43
|
+
pretty_formatter.write( doc, output )
|
44
|
+
output
|
45
|
+
else
|
46
|
+
doc.to_s
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def to_json pretty: false
|
50
|
+
hash = Hash.new
|
51
|
+
self.to_json_recursive hash
|
52
|
+
if pretty
|
53
|
+
JSON.pretty_generate( hash )
|
54
|
+
else
|
55
|
+
JSON.generate( hash )
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def valid? current=true
|
59
|
+
result = if current
|
60
|
+
self.root.valid?
|
61
|
+
else
|
62
|
+
case self
|
63
|
+
when Rubyang::Database::DataTree::Container
|
64
|
+
@children.inject(self.evaluate_musts){ |r, c|
|
65
|
+
r.and c.valid?( false )
|
66
|
+
}
|
67
|
+
when Rubyang::Database::DataTree::LeafList, Rubyang::Database::DataTree::List
|
68
|
+
tmp = Rubyang::Xpath::BasicType::Boolean.new( self.evaluate_min_elements )
|
69
|
+
tmp.and Rubyang::Xpath::BasicType::Boolean.new( self.evaluate_max_elements )
|
70
|
+
else
|
71
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@logger.debug "#{self.class}#valid?: return: #{result} #{result.value}"
|
75
|
+
result
|
23
76
|
end
|
24
77
|
def load_merge_xml_recursive doc_xml
|
25
78
|
doc_xml.each_element{ |e|
|
26
79
|
child = edit( e.name )
|
27
80
|
unless e.has_elements?
|
28
81
|
if e.has_text?
|
29
|
-
|
82
|
+
classes_have_set = [
|
83
|
+
Rubyang::Database::DataTree::Leaf,
|
84
|
+
Rubyang::Database::DataTree::LeafList,
|
85
|
+
]
|
86
|
+
if classes_have_set.include?(child.class)
|
87
|
+
child.set e.text
|
88
|
+
end
|
30
89
|
end
|
31
90
|
end
|
32
91
|
child.load_merge_xml_recursive e
|
@@ -40,25 +99,180 @@ module Rubyang
|
|
40
99
|
@parent.root
|
41
100
|
end
|
42
101
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
102
|
+
|
103
|
+
# when start
|
104
|
+
def evaluate_whens
|
105
|
+
@schema.whens.inject( Rubyang::Xpath::BasicType::Boolean.new true ){ |r, w|
|
106
|
+
puts
|
107
|
+
puts 'evaluate whens:'
|
108
|
+
puts 'r:'
|
109
|
+
puts r.value
|
110
|
+
puts 'w:'
|
111
|
+
puts w.arg
|
112
|
+
_when = r.and self.evaluate_xpath( w.xpath, self )
|
113
|
+
puts '_when:'
|
114
|
+
require 'yaml'
|
115
|
+
puts _when.to_yaml
|
116
|
+
puts 'evaluate whens done'
|
117
|
+
puts
|
118
|
+
r.and self.evaluate_xpath( w.xpath, self )
|
119
|
+
}
|
120
|
+
end
|
121
|
+
# end
|
122
|
+
|
123
|
+
# must start
|
124
|
+
def evaluate_musts
|
125
|
+
@schema.musts.inject( Rubyang::Xpath::BasicType::Boolean.new true ){ |r, w|
|
126
|
+
puts
|
127
|
+
puts 'evaluate musts:'
|
128
|
+
puts 'r:'
|
129
|
+
puts r.value
|
130
|
+
puts 'w:'
|
131
|
+
puts w.arg
|
132
|
+
must = r.and self.evaluate_xpath( w.xpath, self )
|
133
|
+
puts 'must:'
|
134
|
+
require 'yaml'
|
135
|
+
puts must.to_yaml
|
136
|
+
puts 'evaluate musts done'
|
137
|
+
puts
|
138
|
+
r.and self.evaluate_xpath( w.xpath, self )
|
139
|
+
}
|
140
|
+
end
|
141
|
+
# end
|
142
|
+
|
143
|
+
# min-elements start
|
144
|
+
def evaluate_min_elements
|
145
|
+
if @schema.min_elements.size > 0
|
146
|
+
@logger.debug "#{self.class}#evaluate_min_elements: @schema.min_elements.first.arg: #{@schema.min_elements.first.arg}"
|
147
|
+
if @children.size >= @schema.min_elements.first.arg.to_i then true else false end
|
148
|
+
else
|
149
|
+
true
|
150
|
+
end
|
151
|
+
end
|
152
|
+
# end
|
153
|
+
|
154
|
+
# min-elements start
|
155
|
+
def evaluate_max_elements
|
156
|
+
if @schema.max_elements.size > 0
|
157
|
+
@logger.debug "#{self.class}#evaluate_max_elements: @schema.max_elements.first.arg: #{@schema.max_elements.first.arg}"
|
158
|
+
if @children.size <= @schema.max_elements.first.arg.to_i then true else false end
|
159
|
+
else
|
160
|
+
true
|
161
|
+
end
|
162
|
+
end
|
163
|
+
# end
|
164
|
+
|
165
|
+
def evaluate_xpath xpath, current=self
|
166
|
+
if Rubyang::Xpath::Parser::DEBUG
|
167
|
+
require 'yaml'
|
168
|
+
puts
|
169
|
+
puts 'in evaluate_xpath:'
|
170
|
+
puts
|
171
|
+
puts 'xpath:'
|
172
|
+
puts xpath.to_yaml
|
173
|
+
puts
|
174
|
+
puts 'self:'
|
175
|
+
puts self.class
|
176
|
+
puts self.schema.arg
|
177
|
+
puts self.schema.value rescue ''
|
178
|
+
puts 'current:'
|
179
|
+
puts current.class
|
180
|
+
puts current.schema.arg
|
181
|
+
puts current.schema.value rescue ''
|
182
|
+
puts
|
183
|
+
end
|
184
|
+
evaluate_xpath_expr xpath, current
|
185
|
+
end
|
186
|
+
|
187
|
+
def evaluate_xpath_path location_path, current
|
188
|
+
if Rubyang::Xpath::Parser::DEBUG
|
189
|
+
require 'yaml'
|
190
|
+
puts
|
191
|
+
puts 'in evaluate_xpath_path:'
|
192
|
+
puts
|
193
|
+
puts 'location_path:'
|
194
|
+
puts location_path.to_yaml
|
195
|
+
puts
|
196
|
+
puts 'self:'
|
197
|
+
puts self.class
|
198
|
+
puts self.schema.arg
|
199
|
+
puts self.schema.value rescue ''
|
200
|
+
puts 'current:'
|
201
|
+
puts current.class
|
202
|
+
puts current.schema.arg
|
203
|
+
puts current.schema.value rescue ''
|
204
|
+
puts
|
205
|
+
end
|
206
|
+
first_location_step = location_path.location_step_sequence.first
|
207
|
+
if Rubyang::Xpath::Parser::DEBUG
|
208
|
+
require 'yaml'
|
209
|
+
puts
|
210
|
+
puts 'first_location_step:'
|
211
|
+
puts first_location_step.to_yaml
|
212
|
+
end
|
213
|
+
candidates_by_axis = self.evaluate_xpath_axis( first_location_step, current )
|
214
|
+
if Rubyang::Xpath::Parser::DEBUG
|
215
|
+
require 'yaml'
|
216
|
+
puts
|
217
|
+
puts 'candidates_by_axis:'
|
218
|
+
puts candidates_by_axis.to_yaml
|
219
|
+
end
|
220
|
+
candidates_by_node_test = Rubyang::Xpath::BasicType::NodeSet.new candidates_by_axis.value.inject([]){ |cs, c| cs + c.evaluate_xpath_node_test( first_location_step, current ) }
|
221
|
+
if Rubyang::Xpath::Parser::DEBUG
|
222
|
+
require 'yaml'
|
223
|
+
puts
|
224
|
+
puts 'candidates_by_node_test:'
|
225
|
+
puts candidates_by_node_test.to_yaml
|
226
|
+
end
|
227
|
+
candidates_by_predicates = Rubyang::Xpath::BasicType::NodeSet.new candidates_by_node_test.value.inject([]){ |cs, c| cs + c.evaluate_xpath_predicates( first_location_step, current ) }
|
228
|
+
if Rubyang::Xpath::Parser::DEBUG
|
229
|
+
require 'yaml'
|
230
|
+
puts
|
231
|
+
puts 'candidates_by_predicates:'
|
232
|
+
puts candidates_by_predicates.to_yaml
|
233
|
+
end
|
234
|
+
if location_path.location_step_sequence[1..-1].size == 0
|
49
235
|
candidates_by_predicates
|
50
236
|
else
|
51
|
-
candidates_by_predicates.inject([]){ |cs, c|
|
237
|
+
Rubyang::Xpath::BasicType::NodeSet.new candidates_by_predicates.value.inject([]){ |cs, c|
|
238
|
+
following_location_path = Rubyang::Xpath::LocationPath.new *(location_path.location_step_sequence[1..-1])
|
239
|
+
if Rubyang::Xpath::Parser::DEBUG
|
240
|
+
puts
|
241
|
+
puts 'following_location_path:'
|
242
|
+
puts following_location_path.to_yaml
|
243
|
+
puts
|
244
|
+
end
|
245
|
+
cs + c.evaluate_xpath_path( following_location_path, current ).value
|
246
|
+
}
|
52
247
|
end
|
53
248
|
end
|
249
|
+
|
54
250
|
def evaluate_xpath_axis location_step, current
|
251
|
+
if Rubyang::Xpath::Parser::DEBUG
|
252
|
+
require 'yaml'
|
253
|
+
puts
|
254
|
+
puts 'in evaluate_xpath_axis:'
|
255
|
+
puts
|
256
|
+
puts 'location_step:'
|
257
|
+
puts location_step.to_yaml
|
258
|
+
puts
|
259
|
+
puts 'self:'
|
260
|
+
puts self.class
|
261
|
+
puts self.schema.arg
|
262
|
+
puts self.schema.value rescue ''
|
263
|
+
puts 'current:'
|
264
|
+
puts current.class
|
265
|
+
puts current.schema.arg
|
266
|
+
puts current.schema.value rescue ''
|
267
|
+
puts
|
268
|
+
end
|
55
269
|
case location_step.axis.name
|
56
270
|
when Rubyang::Xpath::Axis::SELF
|
57
|
-
[self]
|
271
|
+
Rubyang::Xpath::BasicType::NodeSet.new [self]
|
58
272
|
when Rubyang::Xpath::Axis::PARENT
|
59
|
-
[@parent]
|
273
|
+
Rubyang::Xpath::BasicType::NodeSet.new [@parent]
|
60
274
|
when Rubyang::Xpath::Axis::CHILD
|
61
|
-
@children.inject([]){ |cs, c|
|
275
|
+
Rubyang::Xpath::BasicType::NodeSet.new @children.inject([]){ |cs, c|
|
62
276
|
cs + case c
|
63
277
|
when Rubyang::Database::DataTree::ListElement
|
64
278
|
c.children
|
@@ -70,13 +284,25 @@ module Rubyang
|
|
70
284
|
raise "location_step.axis.name: #{location_step.axis.name} NOT implemented"
|
71
285
|
end
|
72
286
|
end
|
287
|
+
|
73
288
|
def evaluate_xpath_node_test location_step, current
|
289
|
+
puts
|
290
|
+
p 'in node_test'
|
291
|
+
p self.class
|
292
|
+
p self.schema.arg
|
293
|
+
p self.value rescue ''
|
294
|
+
puts
|
74
295
|
case location_step.node_test.node_test_type
|
75
296
|
when Rubyang::Xpath::NodeTest::NodeTestType::NAME_TEST
|
76
297
|
if "/" == location_step.node_test.node_test
|
77
298
|
[self.root]
|
78
299
|
elsif self.schema.model.arg == location_step.node_test.node_test
|
79
|
-
|
300
|
+
case self
|
301
|
+
when Rubyang::Database::DataTree::List
|
302
|
+
self.children
|
303
|
+
else
|
304
|
+
[self]
|
305
|
+
end
|
80
306
|
else
|
81
307
|
[]
|
82
308
|
end
|
@@ -97,19 +323,46 @@ module Rubyang
|
|
97
323
|
raise ""
|
98
324
|
end
|
99
325
|
end
|
326
|
+
|
100
327
|
def evaluate_xpath_predicates location_step, current
|
101
328
|
case location_step.predicates.size
|
102
329
|
when 0
|
103
330
|
[self]
|
104
331
|
else
|
105
|
-
location_step.predicates.inject([]){ |cs, predicate|
|
106
|
-
|
332
|
+
location_step.predicates.inject([self]){ |cs, predicate|
|
333
|
+
p 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
334
|
+
p self.class
|
335
|
+
if cs.size > 0
|
336
|
+
result = cs[0].evaluate_xpath_expr predicate.expr, current
|
337
|
+
case result
|
338
|
+
when Rubyang::Xpath::BasicType::NodeSet
|
339
|
+
raise
|
340
|
+
when Rubyang::Xpath::BasicType::Boolean
|
341
|
+
if result.value == true then cs else [] end
|
342
|
+
when Rubyang::Xpath::BasicType::Number
|
343
|
+
raise
|
344
|
+
when Rubyang::Xpath::BasicType::String
|
345
|
+
raise
|
346
|
+
end
|
347
|
+
else
|
348
|
+
[]
|
349
|
+
end
|
107
350
|
}
|
108
351
|
end
|
109
352
|
end
|
110
|
-
|
353
|
+
|
354
|
+
def evaluate_xpath_expr expr, current=self
|
111
355
|
case expr
|
112
|
-
when Rubyang::Xpath::
|
356
|
+
when Rubyang::Xpath::Expr
|
357
|
+
if Rubyang::Xpath::Parser::DEBUG
|
358
|
+
puts
|
359
|
+
puts "in Expr"
|
360
|
+
puts "op: #{expr.op}"
|
361
|
+
puts
|
362
|
+
end
|
363
|
+
op = expr.op
|
364
|
+
op_result = self.evaluate_xpath_expr( op, current )
|
365
|
+
when Rubyang::Xpath::OrExpr
|
113
366
|
if Rubyang::Xpath::Parser::DEBUG
|
114
367
|
puts
|
115
368
|
puts "in OrExpr"
|
@@ -119,14 +372,22 @@ module Rubyang
|
|
119
372
|
end
|
120
373
|
op1 = expr.op1
|
121
374
|
op2 = expr.op2
|
122
|
-
op1_result = self.
|
375
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
123
376
|
if op2 == nil
|
124
377
|
op1_result
|
125
378
|
else
|
126
|
-
op2_result = self.
|
127
|
-
op1_result
|
379
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
380
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
381
|
+
if op1_result.empty? && op2_result.empty?
|
382
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
383
|
+
else
|
384
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
385
|
+
end
|
386
|
+
else
|
387
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
388
|
+
end
|
128
389
|
end
|
129
|
-
when Rubyang::Xpath::
|
390
|
+
when Rubyang::Xpath::AndExpr
|
130
391
|
if Rubyang::Xpath::Parser::DEBUG
|
131
392
|
puts
|
132
393
|
puts "in AndExpr"
|
@@ -136,14 +397,20 @@ module Rubyang
|
|
136
397
|
end
|
137
398
|
op1 = expr.op1
|
138
399
|
op2 = expr.op2
|
139
|
-
op1_result = self.
|
400
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
140
401
|
if op2 == nil
|
141
402
|
op1_result
|
142
403
|
else
|
143
|
-
op2_result = self.
|
144
|
-
op1_result
|
404
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
405
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet
|
406
|
+
Rubyang::Xpath::BasicType::Boolean.new false if op1_result.empty?
|
407
|
+
elsif op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
408
|
+
Rubyang::Xpath::BasicType::Boolean.new false if op2_result.empty?
|
409
|
+
else
|
410
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
411
|
+
end
|
145
412
|
end
|
146
|
-
when Rubyang::Xpath::
|
413
|
+
when Rubyang::Xpath::EqualityExpr
|
147
414
|
if Rubyang::Xpath::Parser::DEBUG
|
148
415
|
puts
|
149
416
|
puts "in EqualityExpr"
|
@@ -155,21 +422,70 @@ module Rubyang
|
|
155
422
|
op1 = expr.op1
|
156
423
|
op2 = expr.op2
|
157
424
|
operator = expr.operator
|
158
|
-
op1_result = self.
|
425
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
159
426
|
if op2 == nil
|
160
427
|
op1_result
|
161
428
|
else
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
429
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
430
|
+
if Rubyang::Xpath::Parser::DEBUG
|
431
|
+
require 'yaml'
|
432
|
+
puts
|
433
|
+
puts "in EqualityExpr else:"
|
434
|
+
puts "op1_result: #{op1_result.to_yaml}"
|
435
|
+
puts "op2_result: #{op2_result.to_yaml}"
|
436
|
+
puts
|
437
|
+
end
|
438
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::String
|
439
|
+
case operator
|
440
|
+
when /^\=$/
|
441
|
+
#op1_result.select{ |a| op2_result.map{ |b| b.value }.include? a.value }.map{ |c| c.parent }
|
442
|
+
op1_result == op2_result
|
443
|
+
when /^\!\=$/
|
444
|
+
raise "Equality Expr: '!=' not implemented"
|
445
|
+
else
|
446
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
447
|
+
end
|
448
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::String && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
449
|
+
case operator
|
450
|
+
when /^\=$/
|
451
|
+
op2_result.select{ |a| op1_result.map{ |b| b.value }.include? a.value }.map{ |c| c.parent }
|
452
|
+
when /^\!\=$/
|
453
|
+
raise "Equality Expr: '!=' not implemented"
|
454
|
+
else
|
455
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
456
|
+
end
|
457
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
458
|
+
case operator
|
459
|
+
when /^\=$/
|
460
|
+
op1_result == op2_result
|
461
|
+
when /^\!\=$/
|
462
|
+
op1_result != op2_result
|
463
|
+
else
|
464
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
465
|
+
end
|
466
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::String && op2_result.class == Rubyang::Xpath::BasicType::String
|
467
|
+
case operator
|
468
|
+
when /^\=$/
|
469
|
+
op1_result == op2_result
|
470
|
+
when /^\!\=$/
|
471
|
+
op1_result != op2_result
|
472
|
+
else
|
473
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
474
|
+
end
|
475
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
476
|
+
case operator
|
477
|
+
when /^\=$/
|
478
|
+
op1_result == op2_result
|
479
|
+
when /^\!\=$/
|
480
|
+
op1_result != op2_result
|
481
|
+
else
|
482
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
483
|
+
end
|
168
484
|
else
|
169
|
-
|
485
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
170
486
|
end
|
171
487
|
end
|
172
|
-
when Rubyang::Xpath::
|
488
|
+
when Rubyang::Xpath::RelationalExpr
|
173
489
|
if Rubyang::Xpath::Parser::DEBUG
|
174
490
|
puts
|
175
491
|
puts "in RelationalExpr"
|
@@ -181,24 +497,29 @@ module Rubyang
|
|
181
497
|
op1 = expr.op1
|
182
498
|
op2 = expr.op2
|
183
499
|
operator = expr.operator
|
184
|
-
op1_result = self.
|
500
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
185
501
|
if op2 == nil
|
186
502
|
op1_result
|
187
503
|
else
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
504
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
505
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
506
|
+
case operator
|
507
|
+
when /^\>$/
|
508
|
+
op1_result > op2_result
|
509
|
+
when /^\<$/
|
510
|
+
op1_result < op2_result
|
511
|
+
when /^\>\=$/
|
512
|
+
op1_result >= op2_result
|
513
|
+
when /^\<\=$/
|
514
|
+
op1_result <= op2_result
|
515
|
+
else
|
516
|
+
raise "Relational Expr: other than '>', '<', '>=' and '<=' not valid"
|
517
|
+
end
|
197
518
|
else
|
198
|
-
|
519
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
199
520
|
end
|
200
521
|
end
|
201
|
-
when Rubyang::Xpath::
|
522
|
+
when Rubyang::Xpath::AdditiveExpr
|
202
523
|
if Rubyang::Xpath::Parser::DEBUG
|
203
524
|
puts
|
204
525
|
puts "in AdditiveExpr"
|
@@ -210,20 +531,25 @@ module Rubyang
|
|
210
531
|
op1 = expr.op1
|
211
532
|
op2 = expr.op2
|
212
533
|
operator = expr.operator
|
213
|
-
op1_result = self.
|
534
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
214
535
|
if op2 == nil
|
215
536
|
op1_result
|
216
537
|
else
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
538
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
539
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
540
|
+
case operator
|
541
|
+
when /^\+$/
|
542
|
+
op1_result + op2_result
|
543
|
+
when /^\-$/
|
544
|
+
op1_result - op2_result
|
545
|
+
else
|
546
|
+
raise "Additive Expr: other than '+' and '-' not valid"
|
547
|
+
end
|
222
548
|
else
|
223
|
-
|
549
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
224
550
|
end
|
225
551
|
end
|
226
|
-
when Rubyang::Xpath::
|
552
|
+
when Rubyang::Xpath::MultiplicativeExpr
|
227
553
|
if Rubyang::Xpath::Parser::DEBUG
|
228
554
|
puts
|
229
555
|
puts "in MultiplicativeExpr"
|
@@ -235,20 +561,25 @@ module Rubyang
|
|
235
561
|
op1 = expr.op1
|
236
562
|
op2 = expr.op2
|
237
563
|
operator = expr.operator
|
238
|
-
op1_result = self.
|
564
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
239
565
|
if op2 == nil
|
240
566
|
op1_result
|
241
567
|
else
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
568
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
569
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
570
|
+
case operator
|
571
|
+
when /^\*$/
|
572
|
+
op1_result * op2_result
|
573
|
+
when /^\/$/
|
574
|
+
op1_result / op2_result
|
575
|
+
else
|
576
|
+
raise "Multiplicative Expr: other than '*' and '/' not valid"
|
577
|
+
end
|
247
578
|
else
|
248
|
-
|
579
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
249
580
|
end
|
250
581
|
end
|
251
|
-
when Rubyang::Xpath::
|
582
|
+
when Rubyang::Xpath::UnaryExpr
|
252
583
|
if Rubyang::Xpath::Parser::DEBUG
|
253
584
|
puts
|
254
585
|
puts "in UnaryExpr"
|
@@ -258,16 +589,21 @@ module Rubyang
|
|
258
589
|
end
|
259
590
|
op1 = expr.op1
|
260
591
|
operator = expr.operator
|
261
|
-
op1_result = self.
|
592
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
262
593
|
case operator
|
263
594
|
when nil
|
264
595
|
op1_result
|
265
596
|
when /^\-$/
|
266
|
-
|
597
|
+
case op1_result
|
598
|
+
when Rubyang::Xpath::BasicType::Number
|
599
|
+
- op1_result
|
600
|
+
else
|
601
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
602
|
+
end
|
267
603
|
else
|
268
|
-
raise "Unary Expr: other than '-' not
|
604
|
+
raise "Unary Expr: other than '-' not valid"
|
269
605
|
end
|
270
|
-
when Rubyang::Xpath::
|
606
|
+
when Rubyang::Xpath::UnionExpr
|
271
607
|
if Rubyang::Xpath::Parser::DEBUG
|
272
608
|
puts
|
273
609
|
puts "in UnionExpr"
|
@@ -279,10 +615,11 @@ module Rubyang
|
|
279
615
|
op1 = expr.op1
|
280
616
|
op2 = expr.op2
|
281
617
|
operator = expr.operator
|
282
|
-
op1_result = self.
|
618
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
283
619
|
if op2 == nil
|
284
620
|
op1_result
|
285
621
|
else
|
622
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
286
623
|
case operator
|
287
624
|
when /^\|$/
|
288
625
|
raise "Union Expr: '|' not implemented"
|
@@ -290,7 +627,7 @@ module Rubyang
|
|
290
627
|
raise "Union Expr: other than '|' not implemented"
|
291
628
|
end
|
292
629
|
end
|
293
|
-
when Rubyang::Xpath::
|
630
|
+
when Rubyang::Xpath::PathExpr
|
294
631
|
if Rubyang::Xpath::Parser::DEBUG
|
295
632
|
puts
|
296
633
|
puts "in PathExpr"
|
@@ -302,32 +639,34 @@ module Rubyang
|
|
302
639
|
op1 = expr.op1
|
303
640
|
op2 = expr.op2
|
304
641
|
operator = expr.operator
|
305
|
-
case op1
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
when
|
322
|
-
|
642
|
+
op1_result = case op1
|
643
|
+
when Rubyang::Xpath::LocationPath
|
644
|
+
self.evaluate_xpath_path( op1, current )
|
645
|
+
when Rubyang::Xpath::FilterExpr
|
646
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
647
|
+
else
|
648
|
+
raise "PathExpr: #{op1} not supported"
|
649
|
+
end
|
650
|
+
if op2 == nil
|
651
|
+
op1_result
|
652
|
+
else
|
653
|
+
case operator
|
654
|
+
when /^\/$/
|
655
|
+
case op1_result
|
656
|
+
when Rubyang::Database::DataTree::Node
|
657
|
+
op1_result.evaluate_xpath_path op2, current
|
658
|
+
when Rubyang::Xpath::LocationPath
|
659
|
+
self.evaluate_xpath_path Rubyang::Xpath::LocationPath.new( *(op1_result.location_step_sequence + op2.location_step_sequence) ), current
|
323
660
|
else
|
324
|
-
raise
|
661
|
+
raise
|
325
662
|
end
|
663
|
+
when /^\/\/$/
|
664
|
+
raise "Path Expr: '//' not implemented"
|
665
|
+
else
|
666
|
+
raise "Path Expr: other than '/' and '//' not valid"
|
326
667
|
end
|
327
|
-
else
|
328
|
-
raise ""
|
329
668
|
end
|
330
|
-
when Rubyang::Xpath::
|
669
|
+
when Rubyang::Xpath::FilterExpr
|
331
670
|
if Rubyang::Xpath::Parser::DEBUG
|
332
671
|
puts
|
333
672
|
puts "in FilterExpr"
|
@@ -337,14 +676,14 @@ module Rubyang
|
|
337
676
|
end
|
338
677
|
op1 = expr.op1
|
339
678
|
op2 = expr.op2
|
340
|
-
op1_result = self.
|
679
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
341
680
|
if op2 == nil
|
342
681
|
op1_result
|
343
682
|
else
|
344
|
-
op2_result = self.
|
345
|
-
|
683
|
+
op2_result = self.evaluate_xpath_expr( op2.expr, current )
|
684
|
+
Rubyang::Xpath::BasicType::NodeSet.new
|
346
685
|
end
|
347
|
-
when Rubyang::Xpath::
|
686
|
+
when Rubyang::Xpath::PrimaryExpr
|
348
687
|
if Rubyang::Xpath::Parser::DEBUG
|
349
688
|
puts
|
350
689
|
puts "in PrimaryExpr"
|
@@ -353,16 +692,20 @@ module Rubyang
|
|
353
692
|
end
|
354
693
|
op1 = expr.op1
|
355
694
|
case op1
|
356
|
-
when Rubyang::Xpath::
|
357
|
-
raise "Primary Expr: '
|
358
|
-
when Rubyang::Xpath::
|
359
|
-
op1_result = self.
|
360
|
-
when
|
361
|
-
|
695
|
+
when Rubyang::Xpath::VariableReference
|
696
|
+
raise "Primary Expr: '#{op1}' not implemented"
|
697
|
+
when Rubyang::Xpath::Expr
|
698
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
699
|
+
when Rubyang::Xpath::Literal
|
700
|
+
Rubyang::Xpath::BasicType::String.new op1.value
|
701
|
+
when Rubyang::Xpath::Number
|
702
|
+
Rubyang::Xpath::BasicType::Number.new op1.value
|
703
|
+
when Rubyang::Xpath::FunctionCall
|
704
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
362
705
|
else
|
363
|
-
raise "Primary Expr: '
|
706
|
+
raise "Primary Expr: '#{op1}' not valid"
|
364
707
|
end
|
365
|
-
when Rubyang::Xpath::
|
708
|
+
when Rubyang::Xpath::FunctionCall
|
366
709
|
if Rubyang::Xpath::Parser::DEBUG
|
367
710
|
puts
|
368
711
|
puts "in FunctionCall"
|
@@ -372,41 +715,19 @@ module Rubyang
|
|
372
715
|
end
|
373
716
|
name = expr.name
|
374
717
|
case name
|
375
|
-
when Rubyang::Xpath::
|
376
|
-
|
718
|
+
when Rubyang::Xpath::FunctionCall::CURRENT
|
719
|
+
current
|
377
720
|
else
|
378
721
|
raise "FunctionCall: #{name} not implemented"
|
379
722
|
end
|
380
723
|
else
|
381
|
-
raise "Unrecognized
|
724
|
+
raise "Unrecognized Expr: #{expr}"
|
382
725
|
end
|
383
726
|
end
|
384
727
|
end
|
385
728
|
|
386
729
|
class InteriorNode < Node
|
387
|
-
def
|
388
|
-
doc = REXML::Document.new
|
389
|
-
self.to_xml_recursive doc
|
390
|
-
if pretty
|
391
|
-
pretty_formatter = REXML::Formatters::Pretty.new( 2 )
|
392
|
-
pretty_formatter.compact = true
|
393
|
-
output = ''
|
394
|
-
pretty_formatter.write( doc, output )
|
395
|
-
output
|
396
|
-
else
|
397
|
-
doc.to_s
|
398
|
-
end
|
399
|
-
end
|
400
|
-
def to_json pretty: false
|
401
|
-
hash = Hash.new
|
402
|
-
self.to_json_recursive hash
|
403
|
-
if pretty
|
404
|
-
JSON.pretty_generate( hash )
|
405
|
-
else
|
406
|
-
JSON.generate( hash )
|
407
|
-
end
|
408
|
-
end
|
409
|
-
def to_xml_recursive _doc, current_namespace=''
|
730
|
+
def to_xml_recursive _doc, current_namespace
|
410
731
|
doc = _doc.add_element( @schema.model.arg )
|
411
732
|
unless @schema.namespace == current_namespace
|
412
733
|
current_namespace = @schema.namespace
|
@@ -479,8 +800,15 @@ module Rubyang
|
|
479
800
|
child_node = @children.find{ |c| c.schema == child_schema }
|
480
801
|
unless child_node
|
481
802
|
case child_schema.model
|
803
|
+
when Rubyang::Model::Anyxml
|
804
|
+
child_node = Anyxml.new( self, @schema_tree, child_schema )
|
482
805
|
when Rubyang::Model::Container
|
483
806
|
child_node = Container.new( self, @schema_tree, child_schema )
|
807
|
+
# when start
|
808
|
+
unless child_node.evaluate_whens.value
|
809
|
+
raise "#{arg} is not valid because of 'when' conditions"
|
810
|
+
end
|
811
|
+
# end
|
484
812
|
when Rubyang::Model::Leaf
|
485
813
|
child_node = Leaf.new( self, @schema_tree, child_schema )
|
486
814
|
when Rubyang::Model::List
|
@@ -496,12 +824,12 @@ module Rubyang
|
|
496
824
|
end
|
497
825
|
def edit_xpath arg
|
498
826
|
xpath = Rubyang::Xpath::Parser.parse arg
|
499
|
-
|
500
|
-
case
|
827
|
+
candidates = self.evaluate_xpath( xpath )
|
828
|
+
case candidates.value.size
|
501
829
|
when 0
|
502
830
|
raise "no such xpath: #{arg}"
|
503
831
|
when 1
|
504
|
-
|
832
|
+
candidates.value.first
|
505
833
|
else
|
506
834
|
raise "too many match to xpath: #{arg}"
|
507
835
|
end
|
@@ -515,6 +843,12 @@ module Rubyang
|
|
515
843
|
end
|
516
844
|
|
517
845
|
class Root < InteriorNode
|
846
|
+
def valid? current=true
|
847
|
+
result = @children.inject(Rubyang::Xpath::BasicType::Boolean.new true){ |r, c|
|
848
|
+
r.and c.valid?( false )
|
849
|
+
}
|
850
|
+
result.value
|
851
|
+
end
|
518
852
|
def commit
|
519
853
|
begin
|
520
854
|
components = self.edit( "rubyang" ).edit( "component" ).children.map{ |c|
|
@@ -577,6 +911,27 @@ module Rubyang
|
|
577
911
|
end
|
578
912
|
end
|
579
913
|
|
914
|
+
class Anyxml < Node
|
915
|
+
def set arg
|
916
|
+
@value = REXML::Document.new( arg )
|
917
|
+
end
|
918
|
+
def value
|
919
|
+
@value.to_s
|
920
|
+
end
|
921
|
+
def to_xml_recursive _doc, current_namespace
|
922
|
+
doc = _doc.add_element @value
|
923
|
+
unless @schema.namespace == current_namespace
|
924
|
+
current_namespace = @schema.namespace
|
925
|
+
doc.add_namespace current_namespace
|
926
|
+
end
|
927
|
+
end
|
928
|
+
def to_json_recursive _hash
|
929
|
+
raise "anyxml to json is not implemented"
|
930
|
+
hash = _hash
|
931
|
+
hash[@schema.model.arg] = @value.to_s
|
932
|
+
end
|
933
|
+
end
|
934
|
+
|
580
935
|
class Container < InteriorNode
|
581
936
|
end
|
582
937
|
|
@@ -733,6 +1088,15 @@ module Rubyang
|
|
733
1088
|
@history = Array.new
|
734
1089
|
@component_manager = Rubyang::Database::ComponentManager.new
|
735
1090
|
end
|
1091
|
+
def to_s parent=true
|
1092
|
+
head, vars, tail = "#<#{self.class.to_s}:0x#{(self.object_id << 1).to_s(16).rjust(14,'0')} ", Array.new, ">"
|
1093
|
+
if parent
|
1094
|
+
vars.push "@yang=#{@root.to_s}"
|
1095
|
+
vars.push "@history=#{@history.to_s}"
|
1096
|
+
vars.push "@component_manager=#{@component_manager.to_s}"
|
1097
|
+
end
|
1098
|
+
head + vars.join(', ') + tail
|
1099
|
+
end
|
736
1100
|
def history
|
737
1101
|
@history
|
738
1102
|
end
|