rubyang 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|