rubyang 0.1.1 → 0.1.2

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