junoser 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +37 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/example/vsrx-12.1.x47.rb +38421 -0
- data/exe/junoser +51 -0
- data/junoser.gemspec +27 -0
- data/lib/junoser/cli.rb +55 -0
- data/lib/junoser/development.rb +2 -0
- data/lib/junoser/display/base.rb +40 -0
- data/lib/junoser/display/config_store.rb +52 -0
- data/lib/junoser/display/set.rb +82 -0
- data/lib/junoser/display/structure.rb +29 -0
- data/lib/junoser/display.rb +16 -0
- data/lib/junoser/parser.rb +38453 -0
- data/lib/junoser/ruler.rb +173 -0
- data/lib/junoser/transformer.rb +41 -0
- data/lib/junoser/version.rb +3 -0
- data/lib/junoser/xsd/base.rb +54 -0
- data/lib/junoser/xsd/choice.rb +33 -0
- data/lib/junoser/xsd/complex_type.rb +74 -0
- data/lib/junoser/xsd/element.rb +100 -0
- data/lib/junoser/xsd/enumeration.rb +30 -0
- data/lib/junoser/xsd/parsable.rb +33 -0
- data/lib/junoser/xsd/restriction.rb +34 -0
- data/lib/junoser/xsd/sequence.rb +39 -0
- data/lib/junoser/xsd/simple_content.rb +31 -0
- data/lib/junoser.rb +3 -0
- metadata +146 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
module Junoser
|
2
|
+
class Ruler
|
3
|
+
OFFSET = ' '
|
4
|
+
|
5
|
+
def initialize(input)
|
6
|
+
@rule = input
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_rule
|
10
|
+
rule_header << rule << rule_footer
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule
|
14
|
+
str = @rule.read
|
15
|
+
str = process_reserved_element(str)
|
16
|
+
str = str.split(/\n/).map {|l| format(process_line(l)) }.join("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def process_line(str)
|
23
|
+
return str if str =~ /^(.* do|end)$/
|
24
|
+
|
25
|
+
str.gsub!(/("[^"]+")/) { "str(#$1)" } # "foo" -> str("foo")
|
26
|
+
|
27
|
+
str.gsub!(/^(\s*)arg(\.as\(:\S+\))? \($/) { "#{$1}b(arg#$2," } # arg ( -> b(arg,
|
28
|
+
str.gsub!(/^(\s*)(str\(\S+\)) ([^ \t\n\r\f\(|,]+)(\.as\(:\S+\))?(,?)$/) { "#{$1}a(#$2, #$3)#$4#$5" } # str("foo") bar -> a(str("foo"), bar)
|
29
|
+
str.gsub!(/^(\s*)(str\(\S+\)) \((.*)\)(,?)$/) { "#{$1}a(#$2, #$3)#$4" } # str("foo") (a | b) -> a(str("foo"), a | b)
|
30
|
+
|
31
|
+
str.gsub!(/^(\s*)(str\(\S+\)) \($/) { "#{$1}b(#$2," } # str("foo") ( -> b(str("foo"),
|
32
|
+
str.gsub!(/^(\s*)(\(.*\))(\.as\(:\S\))? \($/) { "#{$1}b(#$2#$3," } # (a | b) ( -> b((a | b),
|
33
|
+
str.gsub!(/^(\s*)(str\(\S+\)) ([^ \t\n\r\f\(|,]+) \($/) { "#{$1}b(a(#$2, #$3)," } # str("foo") bar ( -> b(a(str("foo"), bar),
|
34
|
+
str.gsub!(/^(\s*)(str\(\S+\)) \((.*)\) \($/) { "#{$1}a(#$2, #$3," } # str("foo") (a | b) ( -> a(str("foo"), a | b,
|
35
|
+
|
36
|
+
str
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_reserved_element(str)
|
40
|
+
str.gsub! /"\$\S+"/, 'arg'
|
41
|
+
str.gsub! '"as-number" arg', 'arg'
|
42
|
+
str.gsub! '"equal-literal"', '"="'
|
43
|
+
str.gsub! '"plus-literal"', '"+"'
|
44
|
+
str.gsub! '"minus-literal"', '"-"'
|
45
|
+
|
46
|
+
str.gsub!(/\((.*) \| "name"\)/) { "(#$1 | arg)" }
|
47
|
+
str.gsub! '"vlan" ("id-name" | "all")', '"vlan" ("all" | arg)'
|
48
|
+
str.gsub!(/("ssh-\S+") arg/) { "#$1 (quote | arg)" }
|
49
|
+
str.gsub! '"metric-value" arg', 'arg'
|
50
|
+
str.gsub! '"limit-threshold" arg', 'arg'
|
51
|
+
str.gsub! '"filename" arg', 'arg'
|
52
|
+
str.gsub! '"description" arg', '"description" (quote | arg)'
|
53
|
+
str.gsub! '"as-path-prepend" arg', '"as-path-prepend" (quote | arg)'
|
54
|
+
|
55
|
+
|
56
|
+
str.gsub!(/^(\s*)"inline-services"/) do
|
57
|
+
format(['"inline-services" (',
|
58
|
+
' "bandwidth" ("1g" | "10g")',
|
59
|
+
')'], $1)
|
60
|
+
end
|
61
|
+
str.gsub!(/^(\s*)"ieee-802.3ad" \(\s*sc\(\s*"lacp" \(\s*sc\(/) do
|
62
|
+
format(['"802.3ad" (',
|
63
|
+
' sc(',
|
64
|
+
' arg,',
|
65
|
+
' "lacp" (',
|
66
|
+
' sc(',
|
67
|
+
' "force-up",'], $1)
|
68
|
+
end
|
69
|
+
str.gsub!(/^(\s*)"as-path" \(\s*sc\(\s*"path" arg/) do
|
70
|
+
format(['"as-path" (',
|
71
|
+
' sc(',
|
72
|
+
' arg'], $1)
|
73
|
+
end
|
74
|
+
str.gsub!(/^(\s*)"as-path" arg \(\s*sc\(\s*"path" arg\s*\)/) do
|
75
|
+
format(['"as-path" arg (',
|
76
|
+
' sc(',
|
77
|
+
' quote,',
|
78
|
+
' arg',
|
79
|
+
' )'], $1)
|
80
|
+
end
|
81
|
+
|
82
|
+
%w[metric metric2 metric3 metric4 tag tag2 preference preference2 color color2 local-preference].each do |key|
|
83
|
+
str.gsub!(/^(\s*"#{key}" \(\s*sc\(\s*c\(\s*)"#{key}" arg/) { "#{$1}arg" }
|
84
|
+
end
|
85
|
+
|
86
|
+
str.gsub!(/(s\(\s*)"address" \(\s*arg\s*\)/) { "#{$1}arg" }
|
87
|
+
str.gsub!(/^(\s*"idle-timeout" \(\s*sc\(\s*c\(\s*"forever",\s*)"timeout" arg/) { "#{$1}arg" }
|
88
|
+
|
89
|
+
str = omit_label(str, 'contents', 'syslog_object')
|
90
|
+
str = omit_label(str, 'interface', 'cos_interfaces_type')
|
91
|
+
str = omit_label(str, 'interface', 'ir_interfaces_type')
|
92
|
+
str = omit_label(str, 'interface', 'interfaces_type')
|
93
|
+
str = omit_label(str, 'client-address-list', 'client_address_object')
|
94
|
+
str = omit_label(str, 'prefix-list-item', 'prefix_list_items')
|
95
|
+
str = omit_label(str, 'instance', 'juniper_routing_instance')
|
96
|
+
str = omit_label(str, 'vlan', 'vlan_type')
|
97
|
+
|
98
|
+
str.gsub!(/"icmp"(.*)"icmp6"/) { %["icmpv6"#$1"icmp"] }
|
99
|
+
str.gsub!(/"http"(.*)"https"/) { %["https"#$1"http"] }
|
100
|
+
str.gsub!(/"snmp"(.*)"snmptrap"/) { %["snmptrap"#$1"snmp"] }
|
101
|
+
|
102
|
+
str
|
103
|
+
end
|
104
|
+
|
105
|
+
def omit_label(str, label, content)
|
106
|
+
str.gsub(/(\s*)"#{label}" \(\s*#{content}\s*\)/) { "#{$1}#{content}" }
|
107
|
+
end
|
108
|
+
|
109
|
+
def format(str, offset=OFFSET)
|
110
|
+
case str
|
111
|
+
when String
|
112
|
+
str.empty? ? '' : offset + str
|
113
|
+
when Array
|
114
|
+
str.map {|s| s.empty? ? '' : offset + s.to_s }.join("\n")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def rule_header
|
119
|
+
<<-EOS
|
120
|
+
require 'parslet'
|
121
|
+
|
122
|
+
module Junoser
|
123
|
+
class Parser < Parslet::Parser
|
124
|
+
# block with children maybe
|
125
|
+
def b(object, *children)
|
126
|
+
children.inject(object) {|rule, child| rule.as(:label) >> (space >> child.as(:child) | eos) }
|
127
|
+
end
|
128
|
+
|
129
|
+
# with an argument, and children maybe
|
130
|
+
def a(object, arg, *children)
|
131
|
+
b(object.as(:statement) >> space >> arg.as(:argument), *children)
|
132
|
+
end
|
133
|
+
|
134
|
+
# choice
|
135
|
+
def c(*objects)
|
136
|
+
objects.inject {|rule, object| rule | object }
|
137
|
+
end
|
138
|
+
|
139
|
+
# sequence
|
140
|
+
def s(*objects)
|
141
|
+
# TODO: eval "minOccurs" attribute of choice element
|
142
|
+
objects.inject {|rule, object| rule >> (space >> object).maybe }
|
143
|
+
end
|
144
|
+
|
145
|
+
# sequential choice
|
146
|
+
def sc(*objects)
|
147
|
+
(c(*objects) >> space.maybe).repeat(0)
|
148
|
+
end
|
149
|
+
|
150
|
+
rule(:arg) { match('\\S').repeat(1) }
|
151
|
+
rule(:space) { match('\\s').repeat(1) }
|
152
|
+
rule(:any) { match('.').repeat(1) }
|
153
|
+
rule(:eos) { match('$') }
|
154
|
+
rule(:dotted) { match('[^. \\t\\n\\r\\f]').repeat(1) >> match('\.') >> match('[^. \\t\\n\\r\\f]').repeat(1) }
|
155
|
+
rule(:quote) { match('"') >> match('[^"]').repeat(1) >> match('"') }
|
156
|
+
rule(:address) { match('[0-9a-fA-F:\.]').repeat(1) }
|
157
|
+
rule(:prefix ) { address >> (match('/') >> match('[0-9]').repeat(1)).maybe }
|
158
|
+
|
159
|
+
root(:set)
|
160
|
+
rule(:set) { (str('set') | str('deactivate')) >> space >> configuration.as(:config) }
|
161
|
+
|
162
|
+
EOS
|
163
|
+
end
|
164
|
+
|
165
|
+
def rule_footer
|
166
|
+
<<-EOS
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
EOS
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Junoser
|
4
|
+
class Transformer < Parslet::Transform
|
5
|
+
rule(config: simple(:config)) do
|
6
|
+
config.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
rule(config: sequence(:configs)) do
|
10
|
+
configs.join("\n")
|
11
|
+
end
|
12
|
+
|
13
|
+
rule(arg: simple(:arg)) do
|
14
|
+
"arg(#{arg})"
|
15
|
+
end
|
16
|
+
|
17
|
+
rule(label: simple(:label)) do
|
18
|
+
label.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
rule(label: simple(:label), child: simple(:child)) do
|
22
|
+
"#{label}\n#{child}"
|
23
|
+
end
|
24
|
+
|
25
|
+
rule(label: simple(:label), child: sequence(:children)) do
|
26
|
+
%[#{label}\n#{children.join("\n")}]
|
27
|
+
end
|
28
|
+
|
29
|
+
rule(statement: simple(:statement), argument: simple(:argument)) do
|
30
|
+
"#{statement} #{argument}"
|
31
|
+
end
|
32
|
+
|
33
|
+
rule(statement: simple(:statement), argument: sequence(:arguments)) do
|
34
|
+
%[#{statement}\n#{arguments.join("\n")}]
|
35
|
+
end
|
36
|
+
|
37
|
+
rule(oneline: simple(:str)) do
|
38
|
+
str.gsub "\n", ' '
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Junoser
|
2
|
+
module Xsd
|
3
|
+
module Base
|
4
|
+
attr_reader :xml
|
5
|
+
|
6
|
+
OFFSET = ' '
|
7
|
+
|
8
|
+
def initialize(xml, options={})
|
9
|
+
@xml = xml
|
10
|
+
@depth = options[:depth] || 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def config
|
14
|
+
raise "ERROR: no implementation"
|
15
|
+
end
|
16
|
+
|
17
|
+
def children
|
18
|
+
@children||= xml.xpath('./*[not(self::xsd:annotation)]')
|
19
|
+
end
|
20
|
+
|
21
|
+
def root?
|
22
|
+
@depth == 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
["#<#{self.class}:0x#{object_id}",
|
27
|
+
"xml=#{xml.namespace.prefix}:#{xml.name}" <<
|
28
|
+
" attributes=" << Hash[xml.attributes.map {|k, v| [k, v.value] }].to_s <<
|
29
|
+
(respond_to?(:label) ? " label=#{label}" : ''),
|
30
|
+
"config=[",
|
31
|
+
*config.map {|c| c.inspect },
|
32
|
+
']>'].join("\n#{OFFSET*(@depth+1)}")
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def oneliner?
|
39
|
+
@oneliner ||= !xml.xpath('./xsd:annotation/xsd:appinfo/flag[contains(text(), "oneliner")]').empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_single_child_of?(klass)
|
43
|
+
config.size == 1 && config.first.is_a?(klass)
|
44
|
+
end
|
45
|
+
|
46
|
+
def format(header, content=nil, footer=nil)
|
47
|
+
str = OFFSET*@depth << header.to_s
|
48
|
+
str << "\n" << content if content
|
49
|
+
str << "\n" << OFFSET*@depth << footer if footer
|
50
|
+
str
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
require 'junoser/xsd/element'
|
3
|
+
|
4
|
+
module Junoser
|
5
|
+
module Xsd
|
6
|
+
class Choice
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def config
|
10
|
+
@config ||= children.map {|child|
|
11
|
+
case child.name
|
12
|
+
when 'element'
|
13
|
+
Junoser::Xsd::Element.new(child, depth: @depth+1)
|
14
|
+
when 'choice'
|
15
|
+
Junoser::Xsd::Choice.new(child, depth: @depth+1)
|
16
|
+
else
|
17
|
+
raise "ERROR: unknown element: #{child.name}"
|
18
|
+
end
|
19
|
+
}.compact
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
case
|
24
|
+
when config.empty?
|
25
|
+
when has_single_child_of?(Junoser::Xsd::Choice)
|
26
|
+
format('c(', config.first.config.map(&:to_s).compact.join(",\n"), ')')
|
27
|
+
else
|
28
|
+
format('c(', config.map(&:to_s).compact.join(",\n"), ')')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
require 'junoser/xsd/element'
|
3
|
+
require 'junoser/xsd/sequence'
|
4
|
+
require 'junoser/xsd/simple_content'
|
5
|
+
|
6
|
+
module Junoser
|
7
|
+
module Xsd
|
8
|
+
class ComplexType
|
9
|
+
include Base
|
10
|
+
|
11
|
+
def initialize(xml, options={})
|
12
|
+
super
|
13
|
+
raise "ERROR: #{xml.name} shouldn't have name '#{xml['name']}'" if xml['name'] && !root?
|
14
|
+
@argument = find_name_element
|
15
|
+
end
|
16
|
+
|
17
|
+
def config
|
18
|
+
@config ||= children.map {|child|
|
19
|
+
case child.name
|
20
|
+
when 'sequence'
|
21
|
+
Junoser::Xsd::Sequence.new(child, depth: @depth+1)
|
22
|
+
when 'simpleContent'
|
23
|
+
Junoser::Xsd::SimpleContent.new(child, depth: @depth+1)
|
24
|
+
when 'attribute'
|
25
|
+
'arg'
|
26
|
+
else
|
27
|
+
raise "ERROR: unknown element: #{child.name}"
|
28
|
+
end
|
29
|
+
}.compact
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.compact.join("\n")
|
34
|
+
|
35
|
+
str = case [!argument.nil?, !str.empty?]
|
36
|
+
when [true, true]
|
37
|
+
format("#{argument} (", str, ')')
|
38
|
+
when [true, false]
|
39
|
+
format(argument)
|
40
|
+
when [false, true]
|
41
|
+
simple_argument?(str) ? "#{str}.as(:arg)" : str
|
42
|
+
else
|
43
|
+
''
|
44
|
+
end
|
45
|
+
|
46
|
+
oneliner? ? "#{str}.as(:oneline)" : str
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def argument
|
53
|
+
return unless @argument
|
54
|
+
|
55
|
+
arg = Junoser::Xsd::Element.new(@argument, depth: @depth+1).config
|
56
|
+
raise "ERROR: argument shouldn't consist of multiple elements" if arg.size > 1
|
57
|
+
|
58
|
+
if root?
|
59
|
+
arg.first.to_s.strip + ".as(:arg)"
|
60
|
+
else
|
61
|
+
arg.first.to_s.strip
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_name_element
|
66
|
+
xml.xpath('./xsd:sequence/xsd:element[@name="name"]').remove.first
|
67
|
+
end
|
68
|
+
|
69
|
+
def simple_argument?(str)
|
70
|
+
root? && str =~ /\A\s*arg\z/
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'junoser/xsd/base'
|
3
|
+
require 'junoser/xsd/complex_type'
|
4
|
+
|
5
|
+
module Junoser
|
6
|
+
module Xsd
|
7
|
+
class Element
|
8
|
+
include Base
|
9
|
+
|
10
|
+
def initialize(xml, options={})
|
11
|
+
super
|
12
|
+
@argument = find_name_element || find_single_simple_type || find_simple_type_attribute
|
13
|
+
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
@config ||= children.map {|child|
|
17
|
+
case child.name
|
18
|
+
when 'complexType'
|
19
|
+
Junoser::Xsd::ComplexType.new(child, depth: @depth+1)
|
20
|
+
when 'simpleType'
|
21
|
+
'arg'
|
22
|
+
else
|
23
|
+
raise "ERROR: unknown element: #{child.name}"
|
24
|
+
end
|
25
|
+
}.compact
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.compact.join("\n")
|
30
|
+
|
31
|
+
str = case
|
32
|
+
when str.empty? && xml['type']
|
33
|
+
l = label ? "#{label} (" : '('
|
34
|
+
format(l, format(OFFSET + xml['type'].underscore), ')')
|
35
|
+
when str.empty?
|
36
|
+
format(label)
|
37
|
+
else
|
38
|
+
l = label ? "#{label} (" : '('
|
39
|
+
format(l, str, ')')
|
40
|
+
end
|
41
|
+
|
42
|
+
oneliner? ? "#{str}.as(:oneline)" : str
|
43
|
+
end
|
44
|
+
|
45
|
+
def content
|
46
|
+
str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.compact.join("\n")
|
47
|
+
|
48
|
+
case
|
49
|
+
when str.empty? && xml['type']
|
50
|
+
format(OFFSET + xml['type'].underscore)
|
51
|
+
when str.empty?
|
52
|
+
''
|
53
|
+
else
|
54
|
+
str
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def label
|
62
|
+
return unless xml['name']
|
63
|
+
|
64
|
+
%["#{xml['name']}" #{argument}].strip
|
65
|
+
end
|
66
|
+
|
67
|
+
def argument
|
68
|
+
return unless @argument
|
69
|
+
|
70
|
+
case
|
71
|
+
when @argument.is_a?(String)
|
72
|
+
@argument
|
73
|
+
when @argument.name == 'simpleType'
|
74
|
+
'arg'
|
75
|
+
else
|
76
|
+
arg = Junoser::Xsd::Element.new(@argument, depth: @depth+1).config
|
77
|
+
raise "ERROR: argument shouldn't consist of multiple elements" if arg.size > 1
|
78
|
+
arg.first.to_s.strip
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_name_element
|
83
|
+
xml.xpath('./xsd:complexType/xsd:sequence/xsd:element[@name="name"]').remove.first
|
84
|
+
end
|
85
|
+
|
86
|
+
def find_single_simple_type
|
87
|
+
simples = xml.xpath('./xsd:simpleType').remove
|
88
|
+
raise "ERROR: Element shouldn't have simpleType child and another" if simples.size > 1
|
89
|
+
simples.first
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_simple_type_attribute
|
93
|
+
if xml['type'] =~ /^xsd:.*/
|
94
|
+
xml.remove_attribute 'type'
|
95
|
+
'arg'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
|
3
|
+
module Junoser
|
4
|
+
module Xsd
|
5
|
+
class Enumeration
|
6
|
+
include Base
|
7
|
+
|
8
|
+
def initialize(xml, options={})
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def config
|
13
|
+
raise "ERROR: unknown Enumeration format" if children.size > 1
|
14
|
+
|
15
|
+
has_match? ? 'arg' : %["#{xml['value']}"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
format(OFFSET + config)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def has_match?
|
26
|
+
return true unless xml.xpath('.//match').empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'junoser/xsd/complex_type'
|
3
|
+
require 'junoser/xsd/element'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module Junoser
|
7
|
+
module Xsd
|
8
|
+
module Parsable
|
9
|
+
def to_config
|
10
|
+
rule = "rule(:#{self['name'].underscore}) do\n"
|
11
|
+
|
12
|
+
case name
|
13
|
+
when 'complexType'
|
14
|
+
rule << Junoser::Xsd::ComplexType.new(self, depth: 1).to_s
|
15
|
+
when 'element'
|
16
|
+
rule << Junoser::Xsd::Element.new(self, depth: 1).content
|
17
|
+
else
|
18
|
+
raise "ERROR: unknown element: #{name}"
|
19
|
+
end
|
20
|
+
|
21
|
+
rule << "\nend\n\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_unused
|
25
|
+
xpath('/xsd:schema/*[self::xsd:import]').remove
|
26
|
+
xpath('//xsd:element[@ref="undocumented" or @ref="junos:comment"]').remove
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Nokogiri::XML::Element.include Junoser::Xsd::Parsable
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
require 'junoser/xsd/enumeration'
|
3
|
+
|
4
|
+
module Junoser
|
5
|
+
module Xsd
|
6
|
+
class Restriction
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def children
|
10
|
+
@children||= xml.xpath('./*[not(self::xsd:annotation or ' +
|
11
|
+
'self::xsd:minInclusive or self::xsd:maxInclusive or ' +
|
12
|
+
'self::xsd:minLength or self::xsd:maxLength)]')
|
13
|
+
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
@config ||= children.map {|child|
|
17
|
+
case child.name
|
18
|
+
when 'enumeration'
|
19
|
+
Junoser::Xsd::Enumeration.new(child, depth: @depth+1)
|
20
|
+
else
|
21
|
+
raise "ERROR: unknown element: #{child.name}"
|
22
|
+
end
|
23
|
+
}.compact
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
return format('arg') if config.empty?
|
28
|
+
|
29
|
+
str = '(' + config.map {|c| c.to_s.strip }.compact.join(' | ') + ')'
|
30
|
+
format(str)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
require 'junoser/xsd/choice'
|
3
|
+
require 'junoser/xsd/element'
|
4
|
+
|
5
|
+
module Junoser
|
6
|
+
module Xsd
|
7
|
+
class Sequence
|
8
|
+
include Base
|
9
|
+
|
10
|
+
def config
|
11
|
+
@config ||= children.map {|child|
|
12
|
+
case child.name
|
13
|
+
when 'choice'
|
14
|
+
Junoser::Xsd::Choice.new(child, depth: @depth+1)
|
15
|
+
when 'element'
|
16
|
+
Junoser::Xsd::Element.new(child, depth: @depth+1)
|
17
|
+
when 'any'
|
18
|
+
'any'
|
19
|
+
else
|
20
|
+
raise "ERROR: unknown element: #{child.name}"
|
21
|
+
end
|
22
|
+
}.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
case
|
27
|
+
when config.empty?
|
28
|
+
when has_single_child_of?(Junoser::Xsd::Choice)
|
29
|
+
child = config.first
|
30
|
+
str = child.config.map(&:to_s).compact.join(",\n")
|
31
|
+
format('sc(', str, ')') unless str.empty?
|
32
|
+
else
|
33
|
+
str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.compact.join(",\n")
|
34
|
+
format('s(', str, ')')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'junoser/xsd/base'
|
2
|
+
require 'junoser/xsd/restriction'
|
3
|
+
|
4
|
+
module Junoser
|
5
|
+
module Xsd
|
6
|
+
class SimpleContent
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def config
|
10
|
+
@config ||= children.map {|child|
|
11
|
+
case child.name
|
12
|
+
when 'restriction'
|
13
|
+
Junoser::Xsd::Restriction.new(child, depth: @depth+1)
|
14
|
+
when 'extension'
|
15
|
+
'arg'
|
16
|
+
else
|
17
|
+
raise "ERROR: unknown element: #{child.name}"
|
18
|
+
end
|
19
|
+
}.compact
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
return if config.empty?
|
24
|
+
raise "ERROR: simpleContent shouldn't have multiple children" if config.size > 1
|
25
|
+
|
26
|
+
child = config.first
|
27
|
+
child.is_a?(String) ? format(OFFSET + child) : child.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/junoser.rb
ADDED