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.
@@ -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
- child.set e.text
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
- def evaluate_xpath location_steps, current=self
44
- location_step = location_steps.first
45
- candidates_by_axis = self.evaluate_xpath_axis( location_step, current )
46
- candidates_by_node_test = candidates_by_axis.inject([]){ |cs, c| cs + c.evaluate_xpath_node_test( location_step, current ) }
47
- candidates_by_predicates = candidates_by_node_test.inject([]){ |cs, c| cs + c.evaluate_xpath_predicates( location_step, current ) }
48
- if location_steps[1..-1].size == 0
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| c.evaluate_xpath( location_steps[1..-1], current ) }
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
- [self]
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
- self.evaluate_xpath_predicate_expr predicate.expr, current
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
- def evaluate_xpath_predicate_expr expr, current
353
+
354
+ def evaluate_xpath_expr expr, current=self
111
355
  case expr
112
- when Rubyang::Xpath::Predicate::OrExpr
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.evaluate_xpath_predicate_expr( op1, current )
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.evaluate_xpath_predicate_expr( op2, current )
127
- op1_result | op2_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::Predicate::AndExpr
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.evaluate_xpath_predicate_expr( op1, current )
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.evaluate_xpath_predicate_expr( op2, current )
144
- op1_result & op2_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::Predicate::EqualityExpr
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.evaluate_xpath_predicate_expr( op1, current )
425
+ op1_result = self.evaluate_xpath_expr( op1, current )
159
426
  if op2 == nil
160
427
  op1_result
161
428
  else
162
- case operator
163
- when /^\=$/
164
- op2_result = self.evaluate_xpath_predicate_expr( op2, current )
165
- op1_result.select{ |a| op2_result.map{ |b| b.value }.include? a.value }.map{ |c| c.parent }
166
- when /^\!\=$/
167
- raise "Equality Expr: '!=' not implemented"
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
- raise "Equality Expr: other than '=' and '!=' not implemented"
485
+ Rubyang::Xpath::BasicType::Boolean.new false
170
486
  end
171
487
  end
172
- when Rubyang::Xpath::Predicate::RelationalExpr
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.evaluate_xpath_predicate_expr( op1, current )
500
+ op1_result = self.evaluate_xpath_expr( op1, current )
185
501
  if op2 == nil
186
502
  op1_result
187
503
  else
188
- case operator
189
- when /^\>$/
190
- raise "Relational Expr: '>' not implemented"
191
- when /^\<$/
192
- raise "Relational Expr: '<' not implemented"
193
- when /^\>\=$/
194
- raise "Relational Expr: '>=' not implemented"
195
- when /^\<\=$/
196
- raise "Relational Expr: '<=' not implemented"
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
- raise "Relational Expr: other than '>', '<', '>=' and '<=' not implemented"
519
+ Rubyang::Xpath::BasicType::Boolean.new false
199
520
  end
200
521
  end
201
- when Rubyang::Xpath::Predicate::AdditiveExpr
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.evaluate_xpath_predicate_expr( op1, current )
534
+ op1_result = self.evaluate_xpath_expr( op1, current )
214
535
  if op2 == nil
215
536
  op1_result
216
537
  else
217
- case operator
218
- when /^\+$/
219
- raise "Additive Expr: '+' not implemented"
220
- when /^\-$/
221
- raise "Additive Expr: '-' not implemented"
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
- raise "Additive Expr: other than '+' and '-' not implemented"
549
+ Rubyang::Xpath::BasicType::Number.new Float::NAN
224
550
  end
225
551
  end
226
- when Rubyang::Xpath::Predicate::MultiplicativeExpr
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.evaluate_xpath_predicate_expr( op1, current )
564
+ op1_result = self.evaluate_xpath_expr( op1, current )
239
565
  if op2 == nil
240
566
  op1_result
241
567
  else
242
- case operator
243
- when /^\*$/
244
- raise "Multiplicative Expr: '*' not implemented"
245
- when /^\/$/
246
- raise "Multiplicative Expr: '/' not implemented"
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
- raise "Multiplicative Expr: other than '*' and '/' not implemented"
579
+ Rubyang::Xpath::BasicType::Number.new Float::NAN
249
580
  end
250
581
  end
251
- when Rubyang::Xpath::Predicate::UnaryExpr
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.evaluate_xpath_predicate_expr( op1, current )
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
- raise "Unary Expr: '-' not implemented"
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 implemented"
604
+ raise "Unary Expr: other than '-' not valid"
269
605
  end
270
- when Rubyang::Xpath::Predicate::UnionExpr
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.evaluate_xpath_predicate_expr( op1, current )
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::Predicate::PathExpr
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
- when Rubyang::Xpath::LocationSteps
307
- op1_result = self.evaluate_xpath( op1, current )
308
- when Rubyang::Xpath::Predicate::FilterExpr
309
- op1_result = self.evaluate_xpath_predicate_expr( op1, current )
310
- if op2 == nil
311
- op1_result
312
- else
313
- case operator
314
- when /^\/$/
315
- case op2
316
- when Rubyang::Xpath::LocationSteps
317
- current.evaluate_xpath (op1_result + op2), current
318
- else
319
- raise "Path Expr: op1 is not LocationSteps"
320
- end
321
- when /^\/\/$/
322
- raise "Path Expr: '//' not implemented"
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 "Path Expr: other than '/' and '//' not implemented"
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::Predicate::FilterExpr
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.evaluate_xpath_predicate_expr( op1, current )
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.evaluate_xpath_predicate_expr( op2.expr, current )
345
- raise "Filter Expr: Filter Predicate not implemented"
683
+ op2_result = self.evaluate_xpath_expr( op2.expr, current )
684
+ Rubyang::Xpath::BasicType::NodeSet.new
346
685
  end
347
- when Rubyang::Xpath::Predicate::PrimaryExpr
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::Predicate::Expr
357
- raise "Primary Expr: '( Expr )' not implemented"
358
- when Rubyang::Xpath::Predicate::FunctionCall
359
- op1_result = self.evaluate_xpath_predicate_expr( op1, current )
360
- when /^\$.*$/
361
- raise "Primary Expr: 'Variable Reference' not implemented"
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: 'Literal' and 'Number' not implemented"
706
+ raise "Primary Expr: '#{op1}' not valid"
364
707
  end
365
- when Rubyang::Xpath::Predicate::FunctionCall
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::Predicate::FunctionCall::CURRENT
376
- Rubyang::Xpath::LocationSteps.new
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 predicate: #{predicate}"
724
+ raise "Unrecognized Expr: #{expr}"
382
725
  end
383
726
  end
384
727
  end
385
728
 
386
729
  class InteriorNode < Node
387
- def to_xml pretty: false
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
- elements = self.evaluate_xpath( xpath )
500
- case elements.size
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
- elements.first
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