rubyang 0.1.2.1 → 0.1.3
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/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -3
- data/lib/rubyang.rb +5 -6
- data/lib/rubyang/cli.rb +114 -114
- data/lib/rubyang/cli/parser.rb +56 -56
- data/lib/rubyang/compat.rb +14 -0
- data/lib/rubyang/component/base.rb +21 -21
- data/lib/rubyang/component/example.rb +8 -7
- data/lib/rubyang/database.rb +45 -34
- data/lib/rubyang/database/component_manager.rb +64 -64
- data/lib/rubyang/database/data_tree.rb +1110 -1077
- data/lib/rubyang/database/helper.rb +31 -30
- data/lib/rubyang/database/logger.rb +58 -0
- data/lib/rubyang/database/schema_tree.rb +1198 -1298
- data/lib/rubyang/model.rb +1139 -923
- data/lib/rubyang/model/logger.rb +58 -0
- data/lib/rubyang/model/parser.rb +197 -195
- data/lib/rubyang/model/parser/parser.tab.rb +1373 -1263
- data/lib/rubyang/model/parser/parser.y +393 -215
- data/lib/rubyang/restapi.rb +4 -3
- data/lib/rubyang/restapi/app.rb +52 -53
- data/lib/rubyang/server.rb +4 -3
- data/lib/rubyang/server/base.rb +20 -20
- data/lib/rubyang/server/example.rb +2 -1
- data/lib/rubyang/version.rb +4 -1
- data/lib/rubyang/webui.rb +4 -3
- data/lib/rubyang/webui/app.rb +62 -63
- data/lib/rubyang/webui/make_json_schema.rb +49 -48
- data/lib/rubyang/xpath.rb +458 -456
- data/lib/rubyang/xpath/logger.rb +58 -0
- data/lib/rubyang/xpath/parser.rb +134 -144
- data/lib/rubyang/xpath/parser/parser.tab.rb +373 -616
- data/lib/rubyang/xpath/parser/parser.y +249 -492
- data/rubyang.gemspec +11 -15
- metadata +49 -32
- data/lib/rubyang/logger.rb +0 -19
@@ -1,35 +1,35 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
2
3
|
|
3
4
|
require 'bundler/setup'
|
4
|
-
|
5
5
|
require 'fileutils'
|
6
6
|
require 'drb/drb'
|
7
7
|
|
8
8
|
module Rubyang
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
module Component
|
10
|
+
class Base
|
11
|
+
include DRb::DRbUndumped
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def initialize
|
14
|
+
@rubyang_sock_file = "/tmp/rubyang/server/Example.sock"
|
15
|
+
@db = DRbObject.new_with_uri( "drbunix:#{@rubyang_sock_file}" )
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
#@pid = Process.pid
|
18
|
+
@sock_dir = "/tmp/rubyang/component"
|
19
|
+
#@sock_file = "#{@sock_dir}/#{self.class}.#{pid}.sock"
|
20
|
+
@sock_file = "#{@sock_dir}/#{self.class}.sock"
|
21
21
|
|
22
|
-
|
22
|
+
FileUtils.mkdir_p @sock_dir
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
DRb.start_service( "drbunix:#{@sock_file}", self )
|
25
|
+
DRb.thread.join
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
def run
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
def finish
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
35
|
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
2
3
|
|
3
|
-
|
4
|
+
require 'rubyang/component/base'
|
4
5
|
|
5
6
|
class Example < Rubyang::Component::Base
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
def run
|
8
|
+
config = @db.configure
|
9
|
+
File.open( '/tmp/rubyang_component_example.txt', 'w' ){ |fo|
|
10
|
+
fo.puts config.to_xml( pretty: true )
|
11
|
+
}
|
12
|
+
end
|
12
13
|
end
|
13
14
|
|
14
15
|
example = Example.new
|
data/lib/rubyang/database.rb
CHANGED
@@ -1,39 +1,50 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
require 'rubyang/model'
|
5
|
+
require 'rubyang/xpath'
|
6
|
+
require 'rubyang/database/logger'
|
7
|
+
require 'rubyang/database/schema_tree'
|
8
|
+
require 'rubyang/database/data_tree'
|
8
9
|
|
9
10
|
module Rubyang
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
11
|
+
class Database
|
12
|
+
def initialize
|
13
|
+
@yangs = Array.new
|
14
|
+
@schema_tree = SchemaTree.new @yangs
|
15
|
+
@config_tree = DataTree.new @schema_tree, Rubyang::Database::DataTree::Mode::CONFIG
|
16
|
+
@oper_tree = DataTree.new @schema_tree, Rubyang::Database::DataTree::Mode::OPER
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s parent=true
|
20
|
+
head, vars, tail = "#<#{self.class.to_s}:0x#{(self.object_id << 1).to_s(16).rjust(14,'0')} ", Array.new, ">"
|
21
|
+
if parent
|
22
|
+
vars.push "@yangs=#{@yangs.to_s}"
|
23
|
+
vars.push "@schema_tree=#{@schema_tree.to_s( false )}"
|
24
|
+
vars.push "@config_tree=#{@config_tree.to_s( false )}"
|
25
|
+
vars.push "@oper_tree=#{@oper_tree.to_s( false )}"
|
26
|
+
end
|
27
|
+
head + vars.join(', ') + tail
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_model model
|
31
|
+
@schema_tree.load model
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure
|
35
|
+
@config_tree.root
|
36
|
+
end
|
37
|
+
|
38
|
+
def configuration
|
39
|
+
@config_tree.root
|
40
|
+
end
|
41
|
+
|
42
|
+
def oper
|
43
|
+
@oper_tree.root
|
44
|
+
end
|
45
|
+
|
46
|
+
def operational
|
47
|
+
@oper_tree.root
|
48
|
+
end
|
49
|
+
end
|
39
50
|
end
|
@@ -1,77 +1,77 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
2
3
|
|
3
4
|
require 'open3'
|
4
5
|
require 'drb/drb'
|
5
|
-
|
6
|
-
require_relative '../../rubyang'
|
6
|
+
require 'rubyang'
|
7
7
|
|
8
8
|
module Rubyang
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
class Database
|
10
|
+
class ComponentManager
|
11
|
+
class Component
|
12
|
+
attr_reader :name, :hook, :path, :sock, :thread, :instance
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
def initialize name, hook, path
|
15
|
+
@name = name
|
16
|
+
@hook = hook
|
17
|
+
@path = path
|
18
|
+
@sock = "/tmp/rubyang/component/#{@name}.sock"
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
21
|
+
def start
|
22
|
+
begin
|
23
|
+
@thread = Thread.new( @path ) do |path|
|
24
|
+
stdout, stderr, status = Open3.capture3( "#{RUBY_ENGINE} #{path}" )
|
25
|
+
end
|
26
|
+
10.times{ |i|
|
27
|
+
break if File.socket? @sock
|
28
|
+
sleep 1
|
29
|
+
raise "Load failed: #{@name} : #{@path}" if i == 9
|
30
|
+
}
|
31
|
+
@instance = DRbObject.new_with_uri( "drbunix:#{@sock}" )
|
32
|
+
rescue => e
|
33
|
+
puts "Error: #{e}"
|
34
|
+
end
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
def run
|
38
|
+
begin
|
39
|
+
@instance.run
|
40
|
+
rescue => e
|
41
|
+
puts "Error: #{e}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def initialize
|
47
|
+
@components = Array.new
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
50
|
+
def update components
|
51
|
+
current_component_names = @components.map{ |c| c.name }
|
52
|
+
new_component_names = components.map{ |c| c[0] }
|
53
|
+
unloading_component_names = current_component_names - new_component_names
|
54
|
+
loading_component_names = new_component_names - current_component_names
|
55
|
+
puts "Load: #{loading_component_names}"
|
56
|
+
puts "Unload: #{unloading_component_names}"
|
57
|
+
unloading_component_names.each{ |n|
|
58
|
+
component = @components.find{ |c| c.name == n }
|
59
|
+
component.thread.kill
|
60
|
+
@components.delete_if{ |c| c.name == n }
|
61
|
+
}
|
62
|
+
loading_component_names.each{ |n|
|
63
|
+
name, hook, path = components.find{ |c| c[0] == n }
|
64
|
+
component = Component.new name, hook, path
|
65
|
+
component.start
|
66
|
+
@components.push component
|
67
|
+
}
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
def run hook
|
71
|
+
@components.select{ |c| c.hook == hook }.each{ |c|
|
72
|
+
c.run
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
77
|
end
|
@@ -1,1109 +1,1142 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
2
3
|
|
3
4
|
require 'drb/drb'
|
4
5
|
require 'rexml/document'
|
5
6
|
require 'rexml/formatters/pretty'
|
6
7
|
require 'json'
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
require 'yaml'
|
9
|
+
require 'rubyang/xpath'
|
10
|
+
require 'rubyang/database/helper'
|
11
|
+
require 'rubyang/database/component_manager'
|
11
12
|
|
12
13
|
module Rubyang
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
class Database
|
15
|
+
class DataTree
|
16
|
+
include DRb::DRbUndumped
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@schema_tree = schema_tree
|
22
|
-
@schema = schema
|
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
|
76
|
-
end
|
77
|
-
def load_merge_xml_recursive doc_xml
|
78
|
-
doc_xml.each_element{ |e|
|
79
|
-
child = edit( e.name )
|
80
|
-
unless e.has_elements?
|
81
|
-
if e.has_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
|
89
|
-
end
|
90
|
-
end
|
91
|
-
child.load_merge_xml_recursive e
|
92
|
-
}
|
93
|
-
end
|
94
|
-
def root
|
95
|
-
case @parent
|
96
|
-
when Rubyang::Database::DataTree::Root
|
97
|
-
@parent
|
98
|
-
else
|
99
|
-
@parent.root
|
100
|
-
end
|
101
|
-
end
|
18
|
+
module Mode
|
19
|
+
CONFIG = :config
|
20
|
+
OPER = :oper
|
21
|
+
end
|
102
22
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
23
|
+
class Node
|
24
|
+
attr_reader :parent, :schema_tree, :schema, :children
|
25
|
+
def initialize parent, schema_tree, schema, db_mode, ctx_mode
|
26
|
+
@logger = Logger.new(self.class.name)
|
27
|
+
@parent = parent
|
28
|
+
@schema_tree = schema_tree
|
29
|
+
@schema = schema
|
30
|
+
@db_mode = db_mode
|
31
|
+
@ctx_mode = ctx_mode
|
32
|
+
@children = []
|
33
|
+
end
|
34
|
+
def to_s parent=true
|
35
|
+
head, vars, tail = "#<#{self.class.to_s}:0x#{(self.object_id << 1).to_s(16).rjust(14,'0')} ", Array.new, ">"
|
36
|
+
if parent
|
37
|
+
vars.push "@parent=#{@parent.to_s(false)}"
|
38
|
+
vars.push "@schema_tree=#{@schema_tree.to_s(false)}"
|
39
|
+
vars.push "@schema=#{@schema.to_s(true)}"
|
40
|
+
vars.push "@children=#{@children.to_s}"
|
41
|
+
end
|
42
|
+
head + vars.join(', ') + tail
|
43
|
+
end
|
44
|
+
def to_xml pretty: false
|
45
|
+
doc = REXML::Document.new
|
46
|
+
self.to_xml_recursive doc, ''
|
47
|
+
if pretty
|
48
|
+
pretty_formatter = REXML::Formatters::Pretty.new( 2 )
|
49
|
+
pretty_formatter.compact = true
|
50
|
+
output = ''
|
51
|
+
pretty_formatter.write( doc, output )
|
52
|
+
output
|
53
|
+
else
|
54
|
+
doc.to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
def to_json pretty: false
|
58
|
+
hash = Hash.new
|
59
|
+
self.to_json_recursive hash
|
60
|
+
if pretty
|
61
|
+
JSON.pretty_generate( hash )
|
62
|
+
else
|
63
|
+
JSON.generate( hash )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def valid? current=true
|
67
|
+
result = if current
|
68
|
+
self.root.valid?
|
69
|
+
else
|
70
|
+
case self
|
71
|
+
when Rubyang::Database::DataTree::Container
|
72
|
+
@children.inject(self.evaluate_musts){ |r, c|
|
73
|
+
r.and c.valid?( false )
|
74
|
+
}
|
75
|
+
when Rubyang::Database::DataTree::LeafList, Rubyang::Database::DataTree::List
|
76
|
+
tmp = Rubyang::Xpath::BasicType::Boolean.new( self.evaluate_min_elements )
|
77
|
+
tmp.and Rubyang::Xpath::BasicType::Boolean.new( self.evaluate_max_elements )
|
78
|
+
else
|
79
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
@logger.debug { "#{self.class}#valid?: return: #{result} #{result.value}" }
|
83
|
+
result
|
84
|
+
end
|
85
|
+
def load_merge_xml_recursive doc_xml
|
86
|
+
doc_xml.each_element{ |e|
|
87
|
+
child = edit( e.name )
|
88
|
+
unless e.has_elements?
|
89
|
+
if e.has_text?
|
90
|
+
classes_have_set = [
|
91
|
+
Rubyang::Database::DataTree::Leaf,
|
92
|
+
Rubyang::Database::DataTree::LeafList,
|
93
|
+
]
|
94
|
+
if classes_have_set.include?(child.class)
|
95
|
+
child.set e.text
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
child.load_merge_xml_recursive e
|
100
|
+
}
|
101
|
+
end
|
102
|
+
def root
|
103
|
+
case @parent
|
104
|
+
when Rubyang::Database::DataTree::Root
|
105
|
+
@parent
|
106
|
+
else
|
107
|
+
@parent.root
|
108
|
+
end
|
109
|
+
end
|
122
110
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
}
|
140
|
-
end
|
141
|
-
# end
|
111
|
+
# when start
|
112
|
+
def evaluate_whens
|
113
|
+
@schema.whens.inject( Rubyang::Xpath::BasicType::Boolean.new true ){ |r, w|
|
114
|
+
@logger.debug { 'evaluate whens:' }
|
115
|
+
@logger.debug { 'r:' }
|
116
|
+
@logger.debug { r.value }
|
117
|
+
@logger.debug { 'w:' }
|
118
|
+
@logger.debug { w.arg }
|
119
|
+
_when = r.and self.evaluate_xpath( w.xpath, self )
|
120
|
+
@logger.debug { '_when:' }
|
121
|
+
@logger.debug { _when.to_yaml }
|
122
|
+
@logger.debug { 'evaluate whens done' }
|
123
|
+
r.and self.evaluate_xpath( w.xpath, self )
|
124
|
+
}
|
125
|
+
end
|
126
|
+
# end
|
142
127
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
128
|
+
# must start
|
129
|
+
def evaluate_musts
|
130
|
+
@schema.musts.inject( Rubyang::Xpath::BasicType::Boolean.new true ){ |r, w|
|
131
|
+
@logger.debug { 'evaluate musts:' }
|
132
|
+
@logger.debug { 'r:' }
|
133
|
+
@logger.debug { r.value }
|
134
|
+
@logger.debug { 'w:' }
|
135
|
+
@logger.debug { w.arg }
|
136
|
+
must = r.and self.evaluate_xpath( w.xpath, self )
|
137
|
+
@logger.debug { 'must:' }
|
138
|
+
require 'yaml'
|
139
|
+
@logger.debug { must.to_yaml }
|
140
|
+
@logger.debug { 'evaluate musts done' }
|
141
|
+
r.and self.evaluate_xpath( w.xpath, self )
|
142
|
+
}
|
143
|
+
end
|
144
|
+
# end
|
153
145
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
146
|
+
# min-elements start
|
147
|
+
def evaluate_min_elements
|
148
|
+
if @schema.min_elements.size > 0
|
149
|
+
@logger.debug { "#{self.class}#evaluate_min_elements: @schema.min_elements.first.arg: #{@schema.min_elements.first.arg}" }
|
150
|
+
if @children.size >= @schema.min_elements.first.arg.to_i then true else false end
|
151
|
+
else
|
152
|
+
true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
# end
|
164
156
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
157
|
+
# min-elements start
|
158
|
+
def evaluate_max_elements
|
159
|
+
if @schema.max_elements.size > 0
|
160
|
+
@logger.debug { "#{self.class}#evaluate_max_elements: @schema.max_elements.first.arg: #{@schema.max_elements.first.arg}" }
|
161
|
+
if @children.size <= @schema.max_elements.first.arg.to_i then true else false end
|
162
|
+
else
|
163
|
+
true
|
164
|
+
end
|
165
|
+
end
|
166
|
+
# end
|
186
167
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
235
|
-
candidates_by_predicates
|
236
|
-
else
|
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
|
-
}
|
247
|
-
end
|
248
|
-
end
|
168
|
+
def evaluate_xpath xpath, current=self
|
169
|
+
@logger.debug { 'in evaluate_xpath:' }
|
170
|
+
@logger.debug { 'xpath:' }
|
171
|
+
@logger.debug { xpath.to_yaml }
|
172
|
+
@logger.debug { 'self:' }
|
173
|
+
@logger.debug { self.class }
|
174
|
+
@logger.debug { self.schema.arg }
|
175
|
+
@logger.debug { self.schema.value rescue '' }
|
176
|
+
@logger.debug { 'current:' }
|
177
|
+
@logger.debug { current.class }
|
178
|
+
@logger.debug { current.schema.arg }
|
179
|
+
@logger.debug { current.schema.value rescue '' }
|
180
|
+
evaluate_xpath_expr xpath, current
|
181
|
+
end
|
249
182
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
end
|
286
|
-
end
|
183
|
+
def evaluate_xpath_path location_path, current
|
184
|
+
@logger.debug { 'in evaluate_xpath_path:' }
|
185
|
+
@logger.debug { 'location_path:' }
|
186
|
+
@logger.debug { location_path.to_yaml }
|
187
|
+
@logger.debug { 'self:' }
|
188
|
+
@logger.debug { self.class }
|
189
|
+
@logger.debug { self.schema.arg }
|
190
|
+
@logger.debug { self.schema.value rescue '' }
|
191
|
+
@logger.debug { 'current:' }
|
192
|
+
@logger.debug { current.class }
|
193
|
+
@logger.debug { current.schema.arg }
|
194
|
+
@logger.debug { current.schema.value rescue '' }
|
195
|
+
first_location_step = location_path.location_step_sequence.first
|
196
|
+
@logger.debug { 'first_location_step:' }
|
197
|
+
@logger.debug { first_location_step.to_yaml }
|
198
|
+
candidates_by_axis = self.evaluate_xpath_axis( first_location_step, current )
|
199
|
+
@logger.debug { 'candidates_by_axis:' }
|
200
|
+
@logger.debug { candidates_by_axis.to_yaml }
|
201
|
+
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 ) }
|
202
|
+
@logger.debug { 'candidates_by_node_test:' }
|
203
|
+
@logger.debug { candidates_by_node_test.to_yaml }
|
204
|
+
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 ) }
|
205
|
+
@logger.debug { 'candidates_by_predicates:' }
|
206
|
+
@logger.debug { candidates_by_predicates.to_yaml }
|
207
|
+
if location_path.location_step_sequence[1..-1].size == 0
|
208
|
+
candidates_by_predicates
|
209
|
+
else
|
210
|
+
Rubyang::Xpath::BasicType::NodeSet.new candidates_by_predicates.value.inject([]){ |cs, c|
|
211
|
+
following_location_path = Rubyang::Xpath::LocationPath.new *(location_path.location_step_sequence[1..-1])
|
212
|
+
@logger.debug { 'following_location_path:' }
|
213
|
+
@logger.debug { following_location_path.to_yaml }
|
214
|
+
cs + c.evaluate_xpath_path( following_location_path, current ).value
|
215
|
+
}
|
216
|
+
end
|
217
|
+
end
|
287
218
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
raise "node-type not match to comment or text or node"
|
319
|
-
end
|
320
|
-
when Rubyang::Xpath::NodeTest::NodeTestType::PROCESSING_INSTRUCTION
|
321
|
-
raise "processing-instruction is not implemented"
|
322
|
-
else
|
323
|
-
raise ""
|
324
|
-
end
|
325
|
-
end
|
219
|
+
def evaluate_xpath_axis location_step, current
|
220
|
+
@logger.debug { 'in evaluate_xpath_axis:' }
|
221
|
+
@logger.debug { 'location_step:' }
|
222
|
+
@logger.debug { location_step.to_yaml }
|
223
|
+
@logger.debug { 'self:' }
|
224
|
+
@logger.debug { self.class }
|
225
|
+
@logger.debug { self.schema.arg }
|
226
|
+
@logger.debug { self.schema.value rescue '' }
|
227
|
+
@logger.debug { 'current:' }
|
228
|
+
@logger.debug { current.class }
|
229
|
+
@logger.debug { current.schema.arg }
|
230
|
+
@logger.debug { current.schema.value rescue '' }
|
231
|
+
case location_step.axis.name
|
232
|
+
when Rubyang::Xpath::Axis::SELF
|
233
|
+
Rubyang::Xpath::BasicType::NodeSet.new [self]
|
234
|
+
when Rubyang::Xpath::Axis::PARENT
|
235
|
+
Rubyang::Xpath::BasicType::NodeSet.new [@parent]
|
236
|
+
when Rubyang::Xpath::Axis::CHILD
|
237
|
+
Rubyang::Xpath::BasicType::NodeSet.new @children.inject([]){ |cs, c|
|
238
|
+
cs + case c
|
239
|
+
when Rubyang::Database::DataTree::ListElement
|
240
|
+
c.children
|
241
|
+
else
|
242
|
+
[c]
|
243
|
+
end
|
244
|
+
}
|
245
|
+
else
|
246
|
+
raise "location_step.axis.name: #{location_step.axis.name} NOT implemented"
|
247
|
+
end
|
248
|
+
end
|
326
249
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
250
|
+
def evaluate_xpath_node_test location_step, current
|
251
|
+
@logger.debug { 'in node_test' }
|
252
|
+
@logger.debug { self.class }
|
253
|
+
@logger.debug { self.schema.arg }
|
254
|
+
@logger.debug { self.value rescue '' }
|
255
|
+
case location_step.node_test.node_test_type
|
256
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::NAME_TEST
|
257
|
+
if "/" == location_step.node_test.node_test
|
258
|
+
[self.root]
|
259
|
+
elsif self.schema.model.arg == location_step.node_test.node_test
|
260
|
+
case self
|
261
|
+
when Rubyang::Database::DataTree::List
|
262
|
+
self.children
|
263
|
+
else
|
264
|
+
[self]
|
265
|
+
end
|
266
|
+
else
|
267
|
+
[]
|
268
|
+
end
|
269
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::NODE_TYPE
|
270
|
+
case location_step.node_test.node_test
|
271
|
+
when Rubyang::Xpath::NodeTest::NodeType::COMMENT
|
272
|
+
raise "node-type: comment is not implemented"
|
273
|
+
when Rubyang::Xpath::NodeTest::NodeType::TEXT
|
274
|
+
raise "node-type: text is not implemented"
|
275
|
+
when Rubyang::Xpath::NodeTest::NodeType::NODE
|
276
|
+
[self]
|
277
|
+
else
|
278
|
+
raise "node-type not match to comment or text or node"
|
279
|
+
end
|
280
|
+
when Rubyang::Xpath::NodeTest::NodeTestType::PROCESSING_INSTRUCTION
|
281
|
+
raise "processing-instruction is not implemented"
|
282
|
+
else
|
283
|
+
raise ""
|
284
|
+
end
|
285
|
+
end
|
353
286
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
else
|
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
|
389
|
-
end
|
390
|
-
when Rubyang::Xpath::AndExpr
|
391
|
-
if Rubyang::Xpath::Parser::DEBUG
|
392
|
-
puts
|
393
|
-
puts "in AndExpr"
|
394
|
-
puts "op1: #{expr.op1}"
|
395
|
-
puts "op2: #{expr.op2}"
|
396
|
-
puts
|
397
|
-
end
|
398
|
-
op1 = expr.op1
|
399
|
-
op2 = expr.op2
|
400
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
401
|
-
if op2 == nil
|
402
|
-
op1_result
|
403
|
-
else
|
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
|
412
|
-
end
|
413
|
-
when Rubyang::Xpath::EqualityExpr
|
414
|
-
if Rubyang::Xpath::Parser::DEBUG
|
415
|
-
puts
|
416
|
-
puts "in EqualityExpr"
|
417
|
-
puts "op1: #{expr.op1}"
|
418
|
-
puts "op2: #{expr.op2}"
|
419
|
-
puts "operator: #{expr.operator}"
|
420
|
-
puts
|
421
|
-
end
|
422
|
-
op1 = expr.op1
|
423
|
-
op2 = expr.op2
|
424
|
-
operator = expr.operator
|
425
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
426
|
-
if op2 == nil
|
427
|
-
op1_result
|
428
|
-
else
|
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
|
484
|
-
else
|
485
|
-
Rubyang::Xpath::BasicType::Boolean.new false
|
486
|
-
end
|
487
|
-
end
|
488
|
-
when Rubyang::Xpath::RelationalExpr
|
489
|
-
if Rubyang::Xpath::Parser::DEBUG
|
490
|
-
puts
|
491
|
-
puts "in RelationalExpr"
|
492
|
-
puts "op1: #{expr.op1}"
|
493
|
-
puts "op2: #{expr.op2}"
|
494
|
-
puts "operator: #{expr.operator}"
|
495
|
-
puts
|
496
|
-
end
|
497
|
-
op1 = expr.op1
|
498
|
-
op2 = expr.op2
|
499
|
-
operator = expr.operator
|
500
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
501
|
-
if op2 == nil
|
502
|
-
op1_result
|
503
|
-
else
|
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
|
518
|
-
else
|
519
|
-
Rubyang::Xpath::BasicType::Boolean.new false
|
520
|
-
end
|
521
|
-
end
|
522
|
-
when Rubyang::Xpath::AdditiveExpr
|
523
|
-
if Rubyang::Xpath::Parser::DEBUG
|
524
|
-
puts
|
525
|
-
puts "in AdditiveExpr"
|
526
|
-
puts "op1: #{expr.op1}"
|
527
|
-
puts "op2: #{expr.op2}"
|
528
|
-
puts "operator: #{expr.operator}"
|
529
|
-
puts
|
530
|
-
end
|
531
|
-
op1 = expr.op1
|
532
|
-
op2 = expr.op2
|
533
|
-
operator = expr.operator
|
534
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
535
|
-
if op2 == nil
|
536
|
-
op1_result
|
537
|
-
else
|
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
|
548
|
-
else
|
549
|
-
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
550
|
-
end
|
551
|
-
end
|
552
|
-
when Rubyang::Xpath::MultiplicativeExpr
|
553
|
-
if Rubyang::Xpath::Parser::DEBUG
|
554
|
-
puts
|
555
|
-
puts "in MultiplicativeExpr"
|
556
|
-
puts "op1: #{expr.op1}"
|
557
|
-
puts "op2: #{expr.op2}"
|
558
|
-
puts "operator: #{expr.operator}"
|
559
|
-
puts
|
560
|
-
end
|
561
|
-
op1 = expr.op1
|
562
|
-
op2 = expr.op2
|
563
|
-
operator = expr.operator
|
564
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
565
|
-
if op2 == nil
|
566
|
-
op1_result
|
567
|
-
else
|
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
|
578
|
-
else
|
579
|
-
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
580
|
-
end
|
581
|
-
end
|
582
|
-
when Rubyang::Xpath::UnaryExpr
|
583
|
-
if Rubyang::Xpath::Parser::DEBUG
|
584
|
-
puts
|
585
|
-
puts "in UnaryExpr"
|
586
|
-
puts "op1: #{expr.op1}"
|
587
|
-
puts "operator: #{expr.operator}"
|
588
|
-
puts
|
589
|
-
end
|
590
|
-
op1 = expr.op1
|
591
|
-
operator = expr.operator
|
592
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
593
|
-
case operator
|
594
|
-
when nil
|
595
|
-
op1_result
|
596
|
-
when /^\-$/
|
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
|
603
|
-
else
|
604
|
-
raise "Unary Expr: other than '-' not valid"
|
605
|
-
end
|
606
|
-
when Rubyang::Xpath::UnionExpr
|
607
|
-
if Rubyang::Xpath::Parser::DEBUG
|
608
|
-
puts
|
609
|
-
puts "in UnionExpr"
|
610
|
-
puts "op1: #{expr.op1}"
|
611
|
-
puts "op2: #{expr.op2}"
|
612
|
-
puts "operator: #{expr.operator}"
|
613
|
-
puts
|
614
|
-
end
|
615
|
-
op1 = expr.op1
|
616
|
-
op2 = expr.op2
|
617
|
-
operator = expr.operator
|
618
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
619
|
-
if op2 == nil
|
620
|
-
op1_result
|
621
|
-
else
|
622
|
-
op2_result = self.evaluate_xpath_expr( op2, current )
|
623
|
-
case operator
|
624
|
-
when /^\|$/
|
625
|
-
raise "Union Expr: '|' not implemented"
|
626
|
-
else
|
627
|
-
raise "Union Expr: other than '|' not implemented"
|
628
|
-
end
|
629
|
-
end
|
630
|
-
when Rubyang::Xpath::PathExpr
|
631
|
-
if Rubyang::Xpath::Parser::DEBUG
|
632
|
-
puts
|
633
|
-
puts "in PathExpr"
|
634
|
-
puts "op1: #{expr.op1}"
|
635
|
-
puts "op2: #{expr.op2}"
|
636
|
-
puts "operator: #{expr.operator}"
|
637
|
-
puts
|
638
|
-
end
|
639
|
-
op1 = expr.op1
|
640
|
-
op2 = expr.op2
|
641
|
-
operator = expr.operator
|
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
|
660
|
-
else
|
661
|
-
raise
|
662
|
-
end
|
663
|
-
when /^\/\/$/
|
664
|
-
raise "Path Expr: '//' not implemented"
|
665
|
-
else
|
666
|
-
raise "Path Expr: other than '/' and '//' not valid"
|
667
|
-
end
|
668
|
-
end
|
669
|
-
when Rubyang::Xpath::FilterExpr
|
670
|
-
if Rubyang::Xpath::Parser::DEBUG
|
671
|
-
puts
|
672
|
-
puts "in FilterExpr"
|
673
|
-
puts "op1: #{expr.op1}"
|
674
|
-
puts "op2: #{expr.op2}"
|
675
|
-
puts
|
676
|
-
end
|
677
|
-
op1 = expr.op1
|
678
|
-
op2 = expr.op2
|
679
|
-
op1_result = self.evaluate_xpath_expr( op1, current )
|
680
|
-
if op2 == nil
|
681
|
-
op1_result
|
682
|
-
else
|
683
|
-
op2_result = self.evaluate_xpath_expr( op2.expr, current )
|
684
|
-
Rubyang::Xpath::BasicType::NodeSet.new
|
685
|
-
end
|
686
|
-
when Rubyang::Xpath::PrimaryExpr
|
687
|
-
if Rubyang::Xpath::Parser::DEBUG
|
688
|
-
puts
|
689
|
-
puts "in PrimaryExpr"
|
690
|
-
puts "op1: #{expr.op1}"
|
691
|
-
puts
|
692
|
-
end
|
693
|
-
op1 = expr.op1
|
694
|
-
case op1
|
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 )
|
705
|
-
else
|
706
|
-
raise "Primary Expr: '#{op1}' not valid"
|
707
|
-
end
|
708
|
-
when Rubyang::Xpath::FunctionCall
|
709
|
-
if Rubyang::Xpath::Parser::DEBUG
|
710
|
-
puts
|
711
|
-
puts "in FunctionCall"
|
712
|
-
puts "name: #{expr.name}"
|
713
|
-
puts "args: #{expr.args}"
|
714
|
-
puts
|
715
|
-
end
|
716
|
-
name = expr.name
|
717
|
-
case name
|
718
|
-
when Rubyang::Xpath::FunctionCall::CURRENT
|
719
|
-
current
|
720
|
-
else
|
721
|
-
raise "FunctionCall: #{name} not implemented"
|
722
|
-
end
|
723
|
-
else
|
724
|
-
raise "Unrecognized Expr: #{expr}"
|
725
|
-
end
|
726
|
-
end
|
727
|
-
end
|
287
|
+
def evaluate_xpath_predicates location_step, current
|
288
|
+
case location_step.predicates.size
|
289
|
+
when 0
|
290
|
+
[self]
|
291
|
+
else
|
292
|
+
location_step.predicates.inject([self]){ |cs, predicate|
|
293
|
+
if cs.size > 0
|
294
|
+
result = cs[0].evaluate_xpath_expr predicate.expr, current
|
295
|
+
case result
|
296
|
+
when Rubyang::Xpath::BasicType::NodeSet
|
297
|
+
raise
|
298
|
+
when Rubyang::Xpath::BasicType::Boolean
|
299
|
+
if result.value == true then cs else [] end
|
300
|
+
when Rubyang::Xpath::BasicType::Number
|
301
|
+
raise
|
302
|
+
when Rubyang::Xpath::BasicType::String
|
303
|
+
raise
|
304
|
+
end
|
305
|
+
else
|
306
|
+
[]
|
307
|
+
end
|
308
|
+
}
|
309
|
+
end
|
310
|
+
end
|
728
311
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
312
|
+
def evaluate_xpath_expr expr, current=self
|
313
|
+
case expr
|
314
|
+
when Rubyang::Xpath::Expr
|
315
|
+
@logger.debug { "in Expr" }
|
316
|
+
@logger.debug { "op: #{expr.op}" }
|
317
|
+
op = expr.op
|
318
|
+
op_result = self.evaluate_xpath_expr( op, current )
|
319
|
+
when Rubyang::Xpath::OrExpr
|
320
|
+
@logger.debug { "in OrExpr" }
|
321
|
+
@logger.debug { "op1: #{expr.op1}" }
|
322
|
+
@logger.debug { "op2: #{expr.op2}" }
|
323
|
+
op1 = expr.op1
|
324
|
+
op2 = expr.op2
|
325
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
326
|
+
if op2 == nil
|
327
|
+
op1_result
|
328
|
+
else
|
329
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
330
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
331
|
+
if op1_result.empty? && op2_result.empty?
|
332
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
333
|
+
else
|
334
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
335
|
+
end
|
336
|
+
else
|
337
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
338
|
+
end
|
339
|
+
end
|
340
|
+
when Rubyang::Xpath::AndExpr
|
341
|
+
@logger.debug { "in AndExpr" }
|
342
|
+
@logger.debug { "op1: #{expr.op1}" }
|
343
|
+
@logger.debug { "op2: #{expr.op2}" }
|
344
|
+
op1 = expr.op1
|
345
|
+
op2 = expr.op2
|
346
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
347
|
+
if op2 == nil
|
348
|
+
op1_result
|
349
|
+
else
|
350
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
351
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet
|
352
|
+
Rubyang::Xpath::BasicType::Boolean.new false if op1_result.empty?
|
353
|
+
elsif op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
354
|
+
Rubyang::Xpath::BasicType::Boolean.new false if op2_result.empty?
|
355
|
+
else
|
356
|
+
Rubyang::Xpath::BasicType::Boolean.new true
|
357
|
+
end
|
358
|
+
end
|
359
|
+
when Rubyang::Xpath::EqualityExpr
|
360
|
+
@logger.debug { "in EqualityExpr" }
|
361
|
+
@logger.debug { "op1: #{expr.op1}" }
|
362
|
+
@logger.debug { "op2: #{expr.op2}" }
|
363
|
+
@logger.debug { "operator: #{expr.operator}" }
|
364
|
+
op1 = expr.op1
|
365
|
+
op2 = expr.op2
|
366
|
+
operator = expr.operator
|
367
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
368
|
+
if op2 == nil
|
369
|
+
op1_result
|
370
|
+
else
|
371
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
372
|
+
@logger.debug { "in EqualityExpr else:" }
|
373
|
+
@logger.debug { "op1_result: #{op1_result.to_yaml}" }
|
374
|
+
@logger.debug { "op2_result: #{op2_result.to_yaml}" }
|
375
|
+
if op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::String
|
376
|
+
case operator
|
377
|
+
when /^\=$/
|
378
|
+
#op1_result.select{ |a| op2_result.map{ |b| b.value }.include? a.value }.map{ |c| c.parent }
|
379
|
+
op1_result == op2_result
|
380
|
+
when /^\!\=$/
|
381
|
+
raise "Equality Expr: '!=' not implemented"
|
382
|
+
else
|
383
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
384
|
+
end
|
385
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::String && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
386
|
+
case operator
|
387
|
+
when /^\=$/
|
388
|
+
op2_result.select{ |a| op1_result.map{ |b| b.value }.include? a.value }.map{ |c| c.parent }
|
389
|
+
when /^\!\=$/
|
390
|
+
raise "Equality Expr: '!=' not implemented"
|
391
|
+
else
|
392
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
393
|
+
end
|
394
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
395
|
+
case operator
|
396
|
+
when /^\=$/
|
397
|
+
op1_result == op2_result
|
398
|
+
when /^\!\=$/
|
399
|
+
op1_result != op2_result
|
400
|
+
else
|
401
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
402
|
+
end
|
403
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::String && op2_result.class == Rubyang::Xpath::BasicType::String
|
404
|
+
case operator
|
405
|
+
when /^\=$/
|
406
|
+
op1_result == op2_result
|
407
|
+
when /^\!\=$/
|
408
|
+
op1_result != op2_result
|
409
|
+
else
|
410
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
411
|
+
end
|
412
|
+
elsif op1_result.class == Rubyang::Xpath::BasicType::NodeSet && op2_result.class == Rubyang::Xpath::BasicType::NodeSet
|
413
|
+
case operator
|
414
|
+
when /^\=$/
|
415
|
+
op1_result == op2_result
|
416
|
+
when /^\!\=$/
|
417
|
+
op1_result != op2_result
|
418
|
+
else
|
419
|
+
raise "Equality Expr: other than '=' and '!=' not implemented"
|
420
|
+
end
|
421
|
+
else
|
422
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
423
|
+
end
|
424
|
+
end
|
425
|
+
when Rubyang::Xpath::RelationalExpr
|
426
|
+
@logger.debug { "in RelationalExpr" }
|
427
|
+
@logger.debug { "op1: #{expr.op1}" }
|
428
|
+
@logger.debug { "op2: #{expr.op2}" }
|
429
|
+
@logger.debug { "operator: #{expr.operator}" }
|
430
|
+
op1 = expr.op1
|
431
|
+
op2 = expr.op2
|
432
|
+
operator = expr.operator
|
433
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
434
|
+
if op2 == nil
|
435
|
+
op1_result
|
436
|
+
else
|
437
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
438
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
439
|
+
case operator
|
440
|
+
when /^\>$/
|
441
|
+
op1_result > op2_result
|
442
|
+
when /^\<$/
|
443
|
+
op1_result < op2_result
|
444
|
+
when /^\>\=$/
|
445
|
+
op1_result >= op2_result
|
446
|
+
when /^\<\=$/
|
447
|
+
op1_result <= op2_result
|
448
|
+
else
|
449
|
+
raise "Relational Expr: other than '>', '<', '>=' and '<=' not valid"
|
450
|
+
end
|
451
|
+
else
|
452
|
+
Rubyang::Xpath::BasicType::Boolean.new false
|
453
|
+
end
|
454
|
+
end
|
455
|
+
when Rubyang::Xpath::AdditiveExpr
|
456
|
+
@logger.debug { "in AdditiveExpr" }
|
457
|
+
@logger.debug { "op1: #{expr.op1}" }
|
458
|
+
@logger.debug { "op2: #{expr.op2}" }
|
459
|
+
@logger.debug { "operator: #{expr.operator}" }
|
460
|
+
op1 = expr.op1
|
461
|
+
op2 = expr.op2
|
462
|
+
operator = expr.operator
|
463
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
464
|
+
if op2 == nil
|
465
|
+
op1_result
|
466
|
+
else
|
467
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
468
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
469
|
+
case operator
|
470
|
+
when /^\+$/
|
471
|
+
op1_result + op2_result
|
472
|
+
when /^\-$/
|
473
|
+
op1_result - op2_result
|
474
|
+
else
|
475
|
+
raise "Additive Expr: other than '+' and '-' not valid"
|
476
|
+
end
|
477
|
+
else
|
478
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
479
|
+
end
|
480
|
+
end
|
481
|
+
when Rubyang::Xpath::MultiplicativeExpr
|
482
|
+
@logger.debug { "in MultiplicativeExpr" }
|
483
|
+
@logger.debug { "op1: #{expr.op1}" }
|
484
|
+
@logger.debug { "op2: #{expr.op2}" }
|
485
|
+
@logger.debug { "operator: #{expr.operator}" }
|
486
|
+
op1 = expr.op1
|
487
|
+
op2 = expr.op2
|
488
|
+
operator = expr.operator
|
489
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
490
|
+
if op2 == nil
|
491
|
+
op1_result
|
492
|
+
else
|
493
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
494
|
+
if op1_result.class == Rubyang::Xpath::BasicType::Number && op2_result.class == Rubyang::Xpath::BasicType::Number
|
495
|
+
case operator
|
496
|
+
when /^\*$/
|
497
|
+
op1_result * op2_result
|
498
|
+
when /^\/$/
|
499
|
+
op1_result / op2_result
|
500
|
+
else
|
501
|
+
raise "Multiplicative Expr: other than '*' and '/' not valid"
|
502
|
+
end
|
503
|
+
else
|
504
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
505
|
+
end
|
506
|
+
end
|
507
|
+
when Rubyang::Xpath::UnaryExpr
|
508
|
+
@logger.debug { "in UnaryExpr" }
|
509
|
+
@logger.debug { "op1: #{expr.op1}" }
|
510
|
+
@logger.debug { "operator: #{expr.operator}" }
|
511
|
+
op1 = expr.op1
|
512
|
+
operator = expr.operator
|
513
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
514
|
+
case operator
|
515
|
+
when nil
|
516
|
+
op1_result
|
517
|
+
when /^\-$/
|
518
|
+
case op1_result
|
519
|
+
when Rubyang::Xpath::BasicType::Number
|
520
|
+
- op1_result
|
521
|
+
else
|
522
|
+
Rubyang::Xpath::BasicType::Number.new Float::NAN
|
523
|
+
end
|
524
|
+
else
|
525
|
+
raise "Unary Expr: other than '-' not valid"
|
526
|
+
end
|
527
|
+
when Rubyang::Xpath::UnionExpr
|
528
|
+
@logger.debug { "in UnionExpr" }
|
529
|
+
@logger.debug { "op1: #{expr.op1}" }
|
530
|
+
@logger.debug { "op2: #{expr.op2}" }
|
531
|
+
@logger.debug { "operator: #{expr.operator}" }
|
532
|
+
op1 = expr.op1
|
533
|
+
op2 = expr.op2
|
534
|
+
operator = expr.operator
|
535
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
536
|
+
if op2 == nil
|
537
|
+
op1_result
|
538
|
+
else
|
539
|
+
op2_result = self.evaluate_xpath_expr( op2, current )
|
540
|
+
case operator
|
541
|
+
when /^\|$/
|
542
|
+
raise "Union Expr: '|' not implemented"
|
543
|
+
else
|
544
|
+
raise "Union Expr: other than '|' not implemented"
|
545
|
+
end
|
546
|
+
end
|
547
|
+
when Rubyang::Xpath::PathExpr
|
548
|
+
@logger.debug { "in PathExpr" }
|
549
|
+
@logger.debug { "op1: #{expr.op1}" }
|
550
|
+
@logger.debug { "op2: #{expr.op2}" }
|
551
|
+
@logger.debug { "operator: #{expr.operator}" }
|
552
|
+
op1 = expr.op1
|
553
|
+
op2 = expr.op2
|
554
|
+
operator = expr.operator
|
555
|
+
op1_result = case op1
|
556
|
+
when Rubyang::Xpath::LocationPath
|
557
|
+
self.evaluate_xpath_path( op1, current )
|
558
|
+
when Rubyang::Xpath::FilterExpr
|
559
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
560
|
+
else
|
561
|
+
raise "PathExpr: #{op1} not supported"
|
562
|
+
end
|
563
|
+
if op2 == nil
|
564
|
+
op1_result
|
565
|
+
else
|
566
|
+
case operator
|
567
|
+
when /^\/$/
|
568
|
+
case op1_result
|
569
|
+
when Rubyang::Database::DataTree::Node
|
570
|
+
op1_result.evaluate_xpath_path op2, current
|
571
|
+
when Rubyang::Xpath::LocationPath
|
572
|
+
self.evaluate_xpath_path Rubyang::Xpath::LocationPath.new( *(op1_result.location_step_sequence + op2.location_step_sequence) ), current
|
573
|
+
else
|
574
|
+
raise
|
575
|
+
end
|
576
|
+
when /^\/\/$/
|
577
|
+
raise "Path Expr: '//' not implemented"
|
578
|
+
else
|
579
|
+
raise "Path Expr: other than '/' and '//' not valid"
|
580
|
+
end
|
581
|
+
end
|
582
|
+
when Rubyang::Xpath::FilterExpr
|
583
|
+
@logger.debug { "in FilterExpr" }
|
584
|
+
@logger.debug { "op1: #{expr.op1}" }
|
585
|
+
@logger.debug { "op2: #{expr.op2}" }
|
586
|
+
op1 = expr.op1
|
587
|
+
op2 = expr.op2
|
588
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
589
|
+
if op2 == nil
|
590
|
+
op1_result
|
591
|
+
else
|
592
|
+
op2_result = self.evaluate_xpath_expr( op2.expr, current )
|
593
|
+
Rubyang::Xpath::BasicType::NodeSet.new
|
594
|
+
end
|
595
|
+
when Rubyang::Xpath::PrimaryExpr
|
596
|
+
@logger.debug { "in PrimaryExpr" }
|
597
|
+
@logger.debug { "op1: #{expr.op1}" }
|
598
|
+
op1 = expr.op1
|
599
|
+
case op1
|
600
|
+
when Rubyang::Xpath::VariableReference
|
601
|
+
raise "Primary Expr: '#{op1}' not implemented"
|
602
|
+
when Rubyang::Xpath::Expr
|
603
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
604
|
+
when Rubyang::Xpath::Literal
|
605
|
+
Rubyang::Xpath::BasicType::String.new op1.value
|
606
|
+
when Rubyang::Xpath::Number
|
607
|
+
Rubyang::Xpath::BasicType::Number.new op1.value
|
608
|
+
when Rubyang::Xpath::FunctionCall
|
609
|
+
op1_result = self.evaluate_xpath_expr( op1, current )
|
610
|
+
else
|
611
|
+
raise "Primary Expr: '#{op1}' not valid"
|
612
|
+
end
|
613
|
+
when Rubyang::Xpath::FunctionCall
|
614
|
+
@logger.debug { "in FunctionCall" }
|
615
|
+
@logger.debug { "name: #{expr.name}" }
|
616
|
+
@logger.debug { "args: #{expr.args}" }
|
617
|
+
name = expr.name
|
618
|
+
case name
|
619
|
+
when Rubyang::Xpath::FunctionCall::CURRENT
|
620
|
+
current
|
621
|
+
else
|
622
|
+
raise "FunctionCall: #{name} not implemented"
|
623
|
+
end
|
624
|
+
else
|
625
|
+
raise "Unrecognized Expr: #{expr}"
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
838
629
|
|
839
|
-
|
840
|
-
|
630
|
+
class InteriorNode < Node
|
631
|
+
def to_xml_recursive _doc, current_namespace
|
632
|
+
doc = _doc.add_element( @schema.model.arg )
|
633
|
+
unless @schema.namespace == current_namespace
|
634
|
+
current_namespace = @schema.namespace
|
635
|
+
doc.add_namespace current_namespace
|
636
|
+
end
|
637
|
+
@children.each{ |c|
|
638
|
+
c.to_xml_recursive doc, current_namespace
|
639
|
+
}
|
640
|
+
end
|
641
|
+
def to_json_recursive( _hash )
|
642
|
+
hash = Hash.new
|
643
|
+
_hash[@schema.model.arg] = hash
|
644
|
+
@children.each{ |c|
|
645
|
+
c.to_json_recursive hash
|
646
|
+
}
|
647
|
+
end
|
648
|
+
def find_child_schema schema, arg
|
649
|
+
schema.children.map{ |c|
|
650
|
+
case c
|
651
|
+
when Database::SchemaTree::Choice
|
652
|
+
find_child_schema c, arg
|
653
|
+
when Database::SchemaTree::Case
|
654
|
+
find_child_schema c, arg
|
655
|
+
when Database::SchemaTree::Anyxml, Database::SchemaTree::Leaf, Database::SchemaTree::LeafList
|
656
|
+
if c.model.arg == arg
|
657
|
+
if @db_mode == Database::DataTree::Mode::CONFIG && @ctx_mode == Database::DataTree::Mode::CONFIG
|
658
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'false'
|
659
|
+
nil
|
660
|
+
else
|
661
|
+
c
|
662
|
+
end
|
663
|
+
elsif @db_mode == Database::DataTree::Mode::CONFIG && @ctx_mode == Database::DataTree::Mode::OPER
|
664
|
+
nil
|
665
|
+
elsif @db_mode == Database::DataTree::Mode::OPER && @ctx_mode == Database::DataTree::Mode::CONFIG
|
666
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'false'
|
667
|
+
c
|
668
|
+
else
|
669
|
+
nil
|
670
|
+
end
|
671
|
+
elsif @db_mode == Database::DataTree::Mode::OPER && @ctx_mode == Database::DataTree::Mode::OPER
|
672
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'true'
|
673
|
+
nil
|
674
|
+
else
|
675
|
+
c
|
676
|
+
end
|
677
|
+
end
|
678
|
+
else
|
679
|
+
nil
|
680
|
+
end
|
681
|
+
else
|
682
|
+
if c.model.arg == arg
|
683
|
+
if @db_mode == Database::DataTree::Mode::CONFIG && @ctx_mode == Database::DataTree::Mode::CONFIG
|
684
|
+
c
|
685
|
+
elsif @db_mode == Database::DataTree::Mode::CONFIG && @ctx_mode == Database::DataTree::Mode::OPER
|
686
|
+
c
|
687
|
+
elsif @db_mode == Database::DataTree::Mode::OPER && @ctx_mode == Database::DataTree::Mode::CONFIG
|
688
|
+
c
|
689
|
+
elsif @db_mode == Database::DataTree::Mode::OPER && @ctx_mode == Database::DataTree::Mode::OPER
|
690
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'true'
|
691
|
+
nil
|
692
|
+
else
|
693
|
+
c
|
694
|
+
end
|
695
|
+
end
|
696
|
+
else
|
697
|
+
nil
|
698
|
+
end
|
699
|
+
end
|
841
700
|
|
842
|
-
|
843
|
-
|
701
|
+
=begin
|
702
|
+
case @db_mode
|
703
|
+
when Rubyang::Database::DataTree::Mode::CONFIG
|
704
|
+
case c
|
705
|
+
when Rubyang::Database::SchemaTree::Choice
|
706
|
+
find_child_schema c, arg
|
707
|
+
when Rubyang::Database::SchemaTree::Case
|
708
|
+
find_child_schema c, arg
|
709
|
+
when Rubyang::Database::SchemaTree::Leaf, Rubyang::Database::SchemaTree::LeafList
|
710
|
+
if c.model.arg == arg
|
711
|
+
c
|
712
|
+
else
|
713
|
+
nil
|
714
|
+
end
|
715
|
+
else
|
716
|
+
if c.model.arg == arg
|
717
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'false'
|
718
|
+
nil
|
719
|
+
else
|
720
|
+
c
|
721
|
+
end
|
722
|
+
else
|
723
|
+
nil
|
724
|
+
end
|
725
|
+
end
|
726
|
+
when Rubyang::Database::DataTree::Mode::OPER
|
727
|
+
case c
|
728
|
+
when Rubyang::Database::SchemaTree::Choice
|
729
|
+
find_child_schema c, arg
|
730
|
+
when Rubyang::Database::SchemaTree::Case
|
731
|
+
find_child_schema c, arg
|
732
|
+
when Rubyang::Database::SchemaTree::Leaf, Rubyang::Database::SchemaTree::LeafList
|
733
|
+
if c.model.arg == arg
|
734
|
+
if c.yang.substmt('config').any? && c.yang.substmt('config')[0].arg == 'false'
|
735
|
+
c
|
736
|
+
else
|
737
|
+
nil
|
738
|
+
end
|
739
|
+
else
|
740
|
+
nil
|
741
|
+
end
|
742
|
+
else
|
743
|
+
if c.model.arg == arg
|
744
|
+
c
|
745
|
+
else
|
746
|
+
nil
|
747
|
+
end
|
748
|
+
end
|
749
|
+
end
|
750
|
+
=end
|
751
|
+
}.find{ |c| c }
|
752
|
+
end
|
753
|
+
def delete_same_choice_other_case schema, arg, children
|
754
|
+
child_schema = nil
|
755
|
+
schema.children.each{ |c|
|
756
|
+
case c
|
757
|
+
when Rubyang::Database::SchemaTree::Choice
|
758
|
+
child_schema = delete_same_choice_other_case c, arg, children
|
759
|
+
when Rubyang::Database::SchemaTree::Case
|
760
|
+
child_schema = delete_same_choice_other_case c, arg, children
|
761
|
+
if Rubyang::Database::SchemaTree::Choice === schema
|
762
|
+
other_schema_children = schema.children.select{ |c2| c2 != c }
|
763
|
+
children.delete_if{ |c2|
|
764
|
+
other_schema_children.find{ |sc|
|
765
|
+
find_child_schema sc, c2.schema.model.arg or sc.model.arg == c2.schema.model.arg
|
766
|
+
}
|
767
|
+
}
|
768
|
+
end
|
769
|
+
else
|
770
|
+
if c.model.arg == arg
|
771
|
+
child_schema = c
|
772
|
+
if Rubyang::Database::SchemaTree::Choice === schema
|
773
|
+
other_schema_children = schema.children.select{ |c2| c2 != c }
|
774
|
+
children.delete_if{ |c2|
|
775
|
+
other_schema_children.find{ |sc|
|
776
|
+
find_child_schema sc, c2.schema.model.arg or sc.model.arg == c2.schema.model.arg
|
777
|
+
}
|
778
|
+
}
|
779
|
+
end
|
780
|
+
else
|
781
|
+
nil
|
782
|
+
end
|
783
|
+
end
|
784
|
+
}
|
785
|
+
child_schema
|
786
|
+
end
|
787
|
+
def edit arg
|
788
|
+
child_schema = find_child_schema @schema, arg
|
789
|
+
delete_same_choice_other_case @schema, arg, @children
|
790
|
+
child_node = @children.find{ |c| c.schema == child_schema }
|
791
|
+
unless child_node
|
792
|
+
begin
|
793
|
+
ctx_mode = if child_schema.yang.substmt('config').any?
|
794
|
+
case child_schema.yang.substmt('config')[0].arg
|
795
|
+
when 'true'
|
796
|
+
Rubyang::Database::DataTree::Mode::CONFIG
|
797
|
+
when 'false'
|
798
|
+
Rubyang::Database::DataTree::Mode::OPER
|
799
|
+
end
|
800
|
+
else
|
801
|
+
@ctx_mode
|
802
|
+
end
|
803
|
+
case child_schema.model
|
804
|
+
when Rubyang::Model::Anyxml
|
805
|
+
child_node = Anyxml.new( self, @schema_tree, child_schema, @db_mode, ctx_mode )
|
806
|
+
when Rubyang::Model::Container
|
807
|
+
child_node = Container.new( self, @schema_tree, child_schema, @db_mode, ctx_mode )
|
808
|
+
# when start
|
809
|
+
unless child_node.evaluate_whens.value
|
810
|
+
raise "#{arg} is not valid because of 'when' conditions"
|
811
|
+
end
|
812
|
+
# end
|
813
|
+
when Rubyang::Model::Leaf
|
814
|
+
child_node = Leaf.new( self, @schema_tree, child_schema, @db_mode, ctx_mode )
|
815
|
+
when Rubyang::Model::List
|
816
|
+
child_node = List.new( self, @schema_tree, child_schema, @db_mode, ctx_mode )
|
817
|
+
when Rubyang::Model::LeafList
|
818
|
+
child_node = LeafList.new( self, @schema_tree, child_schema, @db_mode, ctx_mode )
|
819
|
+
else
|
820
|
+
raise
|
821
|
+
end
|
822
|
+
rescue
|
823
|
+
raise ArgumentError, "#{arg} NOT match"
|
824
|
+
end
|
825
|
+
@children.push child_node
|
826
|
+
end
|
827
|
+
child_node
|
828
|
+
end
|
829
|
+
def edit_xpath arg
|
830
|
+
xpath = Rubyang::Xpath::Parser.parse arg
|
831
|
+
candidates = self.evaluate_xpath( xpath )
|
832
|
+
case candidates.value.size
|
833
|
+
when 0
|
834
|
+
raise "no such xpath: #{arg}"
|
835
|
+
when 1
|
836
|
+
candidates.value.first
|
837
|
+
else
|
838
|
+
raise "too many match to xpath: #{arg}"
|
839
|
+
end
|
840
|
+
end
|
841
|
+
def delete arg
|
842
|
+
child_schema = find_child_schema @schema, arg
|
843
|
+
child_node = @children.find{ |c| c.schema == child_schema }
|
844
|
+
@children.delete child_node
|
845
|
+
end
|
846
|
+
end
|
844
847
|
|
845
|
-
|
846
|
-
|
847
|
-
result = @children.inject(Rubyang::Xpath::BasicType::Boolean.new true){ |r, c|
|
848
|
-
r.and c.valid?( false )
|
849
|
-
}
|
850
|
-
result.value
|
851
|
-
end
|
852
|
-
def commit
|
853
|
-
begin
|
854
|
-
components = self.edit( "rubyang" ).edit( "component" ).children.map{ |c|
|
855
|
-
component = c.key_values.first
|
856
|
-
hook = c.edit("hook").value
|
857
|
-
file_path = c.edit("file-path").value
|
858
|
-
[component, hook, file_path]
|
859
|
-
}
|
860
|
-
self.root.parent.component_manager.update components
|
861
|
-
self.root.parent.component_manager.run "commit"
|
862
|
-
rescue => e
|
863
|
-
puts 'rescue in commit'
|
864
|
-
puts e
|
865
|
-
ensure
|
866
|
-
backup = self.to_xml
|
867
|
-
@parent.history.push backup
|
868
|
-
end
|
869
|
-
end
|
870
|
-
def revert
|
871
|
-
backup = @parent.history.pop
|
872
|
-
if backup
|
873
|
-
self.load_override_xml backup
|
874
|
-
else
|
875
|
-
self.load_override_xml self.new.to_xml
|
876
|
-
end
|
877
|
-
end
|
878
|
-
def to_xml_recursive _doc, current_namespace=''
|
879
|
-
doc = _doc.add_element( 'config' )
|
880
|
-
current_namespace = @schema_tree.root.namespace
|
881
|
-
doc.add_namespace( current_namespace )
|
882
|
-
@children.each{ |c|
|
883
|
-
c.to_xml_recursive doc, current_namespace
|
884
|
-
}
|
885
|
-
end
|
886
|
-
def to_json_recursive _hash
|
887
|
-
hash = Hash.new
|
888
|
-
_hash['config'] = hash
|
889
|
-
@children.each{ |c|
|
890
|
-
c.to_json_recursive hash
|
891
|
-
}
|
892
|
-
end
|
893
|
-
def load_xml xml_str
|
894
|
-
doc_xml = REXML::Document.new( xml_str ).root
|
895
|
-
self.load_merge_xml_recursive doc_xml
|
896
|
-
end
|
897
|
-
def load_merge_xml xml_str
|
898
|
-
self.load_xml xml_str
|
899
|
-
end
|
900
|
-
def load_override_xml xml_str
|
901
|
-
@children.clear
|
902
|
-
self.load_xml xml_str
|
903
|
-
end
|
904
|
-
def load_merge_json json_str
|
905
|
-
xml_str = json_to_xml( json_str )
|
906
|
-
self.load_merge_xml xml_str
|
907
|
-
end
|
908
|
-
def load_override_json json_str
|
909
|
-
xml_str = json_to_xml( json_str )
|
910
|
-
self.load_override_xml xml_str
|
911
|
-
end
|
912
|
-
end
|
848
|
+
class LeafNode < Node
|
849
|
+
end
|
913
850
|
|
914
|
-
|
915
|
-
|
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
|
851
|
+
class ListNode < Node
|
852
|
+
end
|
934
853
|
|
935
|
-
|
936
|
-
|
854
|
+
class Root < InteriorNode
|
855
|
+
def valid? current=true
|
856
|
+
result = @children.inject(Rubyang::Xpath::BasicType::Boolean.new true){ |r, c|
|
857
|
+
r.and c.valid?( false )
|
858
|
+
}
|
859
|
+
result.value
|
860
|
+
end
|
861
|
+
def commit
|
862
|
+
begin
|
863
|
+
components = self.edit( "rubyang" ).edit( "component" ).children.map{ |c|
|
864
|
+
component = c.key_values.first
|
865
|
+
hook = c.edit("hook").value
|
866
|
+
file_path = c.edit("file-path").value
|
867
|
+
[component, hook, file_path]
|
868
|
+
}
|
869
|
+
self.root.parent.component_manager.update components
|
870
|
+
self.root.parent.component_manager.run "commit"
|
871
|
+
rescue => e
|
872
|
+
@logger.debug { 'rescue in commit' }
|
873
|
+
@logger.debug { e }
|
874
|
+
ensure
|
875
|
+
backup = self.to_xml
|
876
|
+
@parent.history.push backup
|
877
|
+
end
|
878
|
+
end
|
879
|
+
def revert
|
880
|
+
backup = @parent.history.pop
|
881
|
+
if backup
|
882
|
+
self.load_override_xml backup
|
883
|
+
else
|
884
|
+
self.load_override_xml self.new.to_xml
|
885
|
+
end
|
886
|
+
end
|
887
|
+
def to_xml_recursive _doc, current_namespace=''
|
888
|
+
root_tag = case @db_mode
|
889
|
+
when Rubyang::Database::DataTree::Mode::CONFIG
|
890
|
+
'config'
|
891
|
+
when Rubyang::Database::DataTree::Mode::OPER
|
892
|
+
'oper'
|
893
|
+
end
|
894
|
+
doc = _doc.add_element( root_tag )
|
895
|
+
current_namespace = @schema_tree.root.namespace
|
896
|
+
doc.add_namespace( current_namespace )
|
897
|
+
@children.each{ |c|
|
898
|
+
c.to_xml_recursive doc, current_namespace
|
899
|
+
}
|
900
|
+
end
|
901
|
+
def to_json_recursive _hash
|
902
|
+
root_tag = case @db_mode
|
903
|
+
when Rubyang::Database::DataTree::Mode::CONFIG
|
904
|
+
'config'
|
905
|
+
when Rubyang::Database::DataTree::Mode::OPER
|
906
|
+
'oper'
|
907
|
+
end
|
908
|
+
hash = Hash.new
|
909
|
+
_hash[root_tag] = hash
|
910
|
+
@children.each{ |c|
|
911
|
+
c.to_json_recursive hash
|
912
|
+
}
|
913
|
+
end
|
914
|
+
def load_xml xml_str
|
915
|
+
doc_xml = REXML::Document.new( xml_str ).root
|
916
|
+
self.load_merge_xml_recursive doc_xml
|
917
|
+
end
|
918
|
+
def load_merge_xml xml_str
|
919
|
+
self.load_xml xml_str
|
920
|
+
end
|
921
|
+
def load_override_xml xml_str
|
922
|
+
@children.clear
|
923
|
+
self.load_xml xml_str
|
924
|
+
end
|
925
|
+
def load_merge_json json_str
|
926
|
+
xml_str = json_to_xml( json_str )
|
927
|
+
self.load_merge_xml xml_str
|
928
|
+
end
|
929
|
+
def load_override_json json_str
|
930
|
+
xml_str = json_to_xml( json_str )
|
931
|
+
self.load_override_xml xml_str
|
932
|
+
end
|
933
|
+
end
|
937
934
|
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
else
|
959
|
-
false
|
960
|
-
end
|
961
|
-
end
|
962
|
-
def to_xml_recursive _doc, current_namespace
|
963
|
-
doc = _doc.add_element( @schema.model.arg )
|
964
|
-
unless @schema.namespace == current_namespace
|
965
|
-
current_namespace = @schema.namespace
|
966
|
-
doc.add_namespace current_namespace
|
967
|
-
end
|
968
|
-
doc.add_text( @value )
|
969
|
-
end
|
970
|
-
def to_json_recursive _hash
|
971
|
-
hash = _hash
|
972
|
-
hash[@schema.model.arg] = @value
|
973
|
-
end
|
974
|
-
end
|
935
|
+
class Anyxml < Node
|
936
|
+
def set arg
|
937
|
+
@value = REXML::Document.new( arg )
|
938
|
+
end
|
939
|
+
def value
|
940
|
+
@value.to_s
|
941
|
+
end
|
942
|
+
def to_xml_recursive _doc, current_namespace
|
943
|
+
doc = _doc.add_element @value
|
944
|
+
unless @schema.namespace == current_namespace
|
945
|
+
current_namespace = @schema.namespace
|
946
|
+
doc.add_namespace current_namespace
|
947
|
+
end
|
948
|
+
end
|
949
|
+
def to_json_recursive _hash
|
950
|
+
raise "anyxml to json is not implemented"
|
951
|
+
hash = _hash
|
952
|
+
hash[@schema.model.arg] = @value.to_s
|
953
|
+
end
|
954
|
+
end
|
975
955
|
|
976
|
-
|
977
|
-
|
978
|
-
child_node = @children.find{ |c| c.key_values == args }
|
979
|
-
unless child_node
|
980
|
-
begin
|
981
|
-
child_node = ListElement.new( self, @schema_tree, @schema, args )
|
982
|
-
rescue
|
983
|
-
raise ArgumentError, "#{args} NOT match"
|
984
|
-
end
|
985
|
-
@children.push child_node
|
986
|
-
end
|
987
|
-
child_node
|
988
|
-
end
|
989
|
-
def to_xml_recursive _doc, current_namespace
|
990
|
-
doc = _doc
|
991
|
-
@children.each{ |c|
|
992
|
-
c.to_xml_recursive doc, current_namespace
|
993
|
-
}
|
994
|
-
end
|
995
|
-
def to_json_recursive _hash
|
996
|
-
array = Array.new
|
997
|
-
_hash[@schema.model.arg] = array
|
998
|
-
@children.each{ |c|
|
999
|
-
c.to_json_recursive array
|
1000
|
-
}
|
1001
|
-
end
|
1002
|
-
def load_merge_xml_recursive doc_xml
|
1003
|
-
return if doc_xml.elements.size == 0
|
1004
|
-
key_args = @schema.keys.map{ |k| doc_xml.elements[k].text }
|
1005
|
-
child = edit( *key_args )
|
1006
|
-
elements = REXML::Document.new('<tmp />')
|
1007
|
-
doc_xml.each_element{ |e|
|
1008
|
-
next if @schema.keys.include? e.name
|
1009
|
-
elements.root.add_element e
|
1010
|
-
}
|
1011
|
-
child.load_merge_xml_recursive elements.root
|
1012
|
-
end
|
1013
|
-
end
|
956
|
+
class Container < InteriorNode
|
957
|
+
end
|
1014
958
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
959
|
+
class Leaf < LeafNode
|
960
|
+
attr_accessor :value
|
961
|
+
def set arg
|
962
|
+
case @schema.type
|
963
|
+
when SchemaTree::LeafrefType
|
964
|
+
elements = self.evaluate_xpath( @schema.type.path )
|
965
|
+
values = elements.inject([]){ |vs, v| vs + [v.value] }
|
966
|
+
unless values.include? arg
|
967
|
+
raise ArgumentError, "#{arg} is not valid for #{@schema.type.inspect}"
|
968
|
+
end
|
969
|
+
else
|
970
|
+
unless @schema.type.valid? arg
|
971
|
+
raise ArgumentError, "#{arg} is not valid for #{@schema.type.inspect}"
|
972
|
+
end
|
973
|
+
end
|
974
|
+
self.value = arg
|
975
|
+
end
|
976
|
+
def has_value?
|
977
|
+
if @value
|
978
|
+
true
|
979
|
+
else
|
980
|
+
false
|
981
|
+
end
|
982
|
+
end
|
983
|
+
def to_xml_recursive _doc, current_namespace
|
984
|
+
doc = _doc.add_element( @schema.model.arg )
|
985
|
+
unless @schema.namespace == current_namespace
|
986
|
+
current_namespace = @schema.namespace
|
987
|
+
doc.add_namespace current_namespace
|
988
|
+
end
|
989
|
+
doc.add_text( @value )
|
990
|
+
end
|
991
|
+
def to_json_recursive _hash
|
992
|
+
hash = _hash
|
993
|
+
hash[@schema.model.arg] = @value
|
994
|
+
end
|
995
|
+
end
|
1045
996
|
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
997
|
+
class List < ListNode
|
998
|
+
def edit *args
|
999
|
+
child_node = @children.find{ |c| c.key_values == args }
|
1000
|
+
unless child_node
|
1001
|
+
begin
|
1002
|
+
child_node = ListElement.new( self, @schema_tree, @schema, @db_mode, @ctx_mode, args )
|
1003
|
+
rescue
|
1004
|
+
raise ArgumentError, "#{args} NOT match"
|
1005
|
+
end
|
1006
|
+
@children.push child_node
|
1007
|
+
end
|
1008
|
+
child_node
|
1009
|
+
end
|
1010
|
+
def delete *args
|
1011
|
+
child_node = @children.find{ |c| c.key_values == args }
|
1012
|
+
@children.delete child_node
|
1013
|
+
end
|
1014
|
+
def to_xml_recursive _doc, current_namespace
|
1015
|
+
doc = _doc
|
1016
|
+
@children.each{ |c|
|
1017
|
+
c.to_xml_recursive doc, current_namespace
|
1018
|
+
}
|
1019
|
+
end
|
1020
|
+
def to_json_recursive _hash
|
1021
|
+
array = Array.new
|
1022
|
+
_hash[@schema.model.arg] = array
|
1023
|
+
@children.each{ |c|
|
1024
|
+
c.to_json_recursive array
|
1025
|
+
}
|
1026
|
+
end
|
1027
|
+
def load_merge_xml_recursive doc_xml
|
1028
|
+
return if doc_xml.elements.size == 0
|
1029
|
+
key_args = @schema.keys.map{ |k| doc_xml.elements[k].text }
|
1030
|
+
child = edit( *key_args )
|
1031
|
+
elements = REXML::Document.new('<tmp />')
|
1032
|
+
doc_xml.each_element{ |e|
|
1033
|
+
next if @schema.keys.include? e.name
|
1034
|
+
elements.root.add_element e
|
1035
|
+
}
|
1036
|
+
child.load_merge_xml_recursive elements.root
|
1037
|
+
end
|
1038
|
+
end
|
1066
1039
|
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1040
|
+
class ListElement < InteriorNode
|
1041
|
+
def initialize parent, schema_tree, schema, db_mode, ctx_mode, key_values
|
1042
|
+
@logger = Logger.new(self.class.name)
|
1043
|
+
@parent = parent
|
1044
|
+
@schema_tree = schema_tree
|
1045
|
+
@schema = schema
|
1046
|
+
@db_mode = db_mode
|
1047
|
+
@ctx_mode = ctx_mode
|
1048
|
+
@children = []
|
1049
|
+
@key_values = key_values
|
1050
|
+
@schema.keys.zip( key_values ).each{ |key, value|
|
1051
|
+
self.edit( key, true ).set( value )
|
1052
|
+
}
|
1053
|
+
end
|
1054
|
+
def key_values
|
1055
|
+
@key_values
|
1056
|
+
end
|
1057
|
+
def edit arg, in_initialize=false
|
1058
|
+
unless in_initialize
|
1059
|
+
if @schema.model.substmt( 'key' ).find{ |s| s.arg == arg }
|
1060
|
+
raise "#{arg} is key"
|
1061
|
+
end
|
1062
|
+
end
|
1063
|
+
super arg
|
1064
|
+
end
|
1065
|
+
def to_json_recursive _array
|
1066
|
+
hash = Hash.new
|
1067
|
+
_array.push hash
|
1068
|
+
@children.each{ |c|
|
1069
|
+
c.to_json_recursive hash
|
1070
|
+
}
|
1071
|
+
end
|
1072
|
+
end
|
1084
1073
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
end
|
1106
|
-
end
|
1107
|
-
end
|
1108
|
-
end
|
1074
|
+
class LeafList < InteriorNode
|
1075
|
+
def set arg
|
1076
|
+
child_node = @children.find{ |c| c.value == arg }
|
1077
|
+
unless child_node
|
1078
|
+
begin
|
1079
|
+
child_node = LeafListElement.new( self, @schema_tree, @schema, @db_mode, @ctx_mode, arg )
|
1080
|
+
rescue
|
1081
|
+
raise ArgumentError
|
1082
|
+
end
|
1083
|
+
@children.push child_node
|
1084
|
+
end
|
1085
|
+
child_node
|
1086
|
+
end
|
1087
|
+
def to_xml_recursive _doc, current_namespace
|
1088
|
+
doc = _doc
|
1089
|
+
@children.each{ |c|
|
1090
|
+
c.to_xml_recursive doc, current_namespace
|
1091
|
+
}
|
1092
|
+
end
|
1093
|
+
end
|
1109
1094
|
|
1095
|
+
class LeafListElement < LeafNode
|
1096
|
+
attr_accessor :value
|
1097
|
+
def initialize parent, schema_tree, schema, db_mode, ctx_mode, value
|
1098
|
+
@logger = Logger.new(self.class.name)
|
1099
|
+
@parent = parent
|
1100
|
+
@schema_tree = schema_tree
|
1101
|
+
@schema = schema
|
1102
|
+
@db_mode = db_mode
|
1103
|
+
@ctx_mode = ctx_mode
|
1104
|
+
@value = value
|
1105
|
+
end
|
1106
|
+
def to_xml_recursive _doc, current_namespace
|
1107
|
+
doc = _doc.add_element( @schema.model.arg )
|
1108
|
+
unless @schema.namespace == current_namespace
|
1109
|
+
current_namespace = @schema.namespace
|
1110
|
+
doc.add_namespace current_namespace
|
1111
|
+
end
|
1112
|
+
doc.add_text( @value )
|
1113
|
+
end
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
attr_accessor :component_manager
|
1117
|
+
def initialize schema_tree, mode=Rubyang::Database::DataTree::Mode::CONFIG
|
1118
|
+
@logger = Logger.new(self.class.name)
|
1119
|
+
@db_mode = mode
|
1120
|
+
@ctx_mode = Rubyang::Database::DataTree::Mode::CONFIG
|
1121
|
+
@root = Root.new( self, schema_tree, schema_tree.root, @db_mode, @ctx_mode )
|
1122
|
+
@history = Array.new
|
1123
|
+
@component_manager = Rubyang::Database::ComponentManager.new
|
1124
|
+
end
|
1125
|
+
def to_s parent=true
|
1126
|
+
head, vars, tail = "#<#{self.class.to_s}:0x#{(self.object_id << 1).to_s(16).rjust(14,'0')} ", Array.new, ">"
|
1127
|
+
if parent
|
1128
|
+
vars.push "@yang=#{@root.to_s}"
|
1129
|
+
vars.push "@history=#{@history.to_s}"
|
1130
|
+
vars.push "@component_manager=#{@component_manager.to_s}"
|
1131
|
+
end
|
1132
|
+
head + vars.join(', ') + tail
|
1133
|
+
end
|
1134
|
+
def history
|
1135
|
+
@history
|
1136
|
+
end
|
1137
|
+
def root
|
1138
|
+
@root
|
1139
|
+
end
|
1140
|
+
end
|
1141
|
+
end
|
1142
|
+
end
|