rsmp_schema 0.9.1 → 0.10.1
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 +4 -4
- data/.rubocop.yml +55 -0
- data/.tool-versions +1 -1
- data/Gemfile +13 -1
- data/Gemfile.lock +92 -15
- data/Rakefile +4 -4
- data/examples/validate.rb +14 -14
- data/lib/rsmp_schema/cli.rb +31 -23
- data/lib/rsmp_schema/convert/export/json_schema.rb +193 -182
- data/lib/rsmp_schema/convert/import/yaml.rb +17 -19
- data/lib/rsmp_schema/error.rb +14 -8
- data/lib/rsmp_schema/schema.rb +177 -153
- data/lib/rsmp_schema/version.rb +3 -2
- data/lib/rsmp_schema.rb +2 -2
- data/rsmp_schema.gemspec +19 -21
- metadata +9 -49
|
@@ -6,26 +6,27 @@ require 'fileutils'
|
|
|
6
6
|
|
|
7
7
|
module RSMP
|
|
8
8
|
module Convert
|
|
9
|
+
# Handles exporting SXL definitions.
|
|
9
10
|
module Export
|
|
11
|
+
# Converts SXL definitions to JSON Schema files.
|
|
10
12
|
module JSONSchema
|
|
11
|
-
|
|
12
|
-
@@json_options = {
|
|
13
|
+
JSON_OPTIONS = {
|
|
13
14
|
array_nl: "\n",
|
|
14
15
|
object_nl: "\n",
|
|
15
16
|
indent: ' ',
|
|
16
17
|
space_before: ' ',
|
|
17
18
|
space: ' '
|
|
18
|
-
}
|
|
19
|
+
}.freeze
|
|
19
20
|
|
|
20
|
-
def self.output_json
|
|
21
|
-
JSON.generate(item
|
|
21
|
+
def self.output_json(item)
|
|
22
|
+
JSON.generate(item, JSON_OPTIONS)
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
# convert a yaml item to json schema
|
|
25
|
-
def self.build_value
|
|
26
|
+
def self.build_value(item)
|
|
26
27
|
out = {}
|
|
27
28
|
out['description'] = item['description'] if item['description']
|
|
28
|
-
if item['type']
|
|
29
|
+
if item['type'] =~ /_list$/
|
|
29
30
|
handle_string_list item, out
|
|
30
31
|
else
|
|
31
32
|
handle_types item, out
|
|
@@ -36,283 +37,294 @@ module RSMP
|
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# convert an item which is not a string-list, to json schema
|
|
39
|
-
def self.handle_types
|
|
40
|
+
def self.handle_types(item, out)
|
|
40
41
|
case item['type']
|
|
41
|
-
when
|
|
42
|
-
out[
|
|
43
|
-
when
|
|
44
|
-
out[
|
|
45
|
-
when
|
|
46
|
-
out[
|
|
47
|
-
when
|
|
48
|
-
out["$ref"] = "../../../core/3.1.2/definitions.json#/integer"
|
|
49
|
-
when 'array' # a json array
|
|
42
|
+
when 'boolean'
|
|
43
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/boolean'
|
|
44
|
+
when 'timestamp'
|
|
45
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/timestamp'
|
|
46
|
+
when 'integer', 'ordinal', 'unit', 'scale', 'long'
|
|
47
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/integer'
|
|
48
|
+
when 'array' # a json array
|
|
50
49
|
build_json_array item['items'], out
|
|
51
|
-
else
|
|
52
|
-
out[
|
|
50
|
+
else # string, base64, and any unknown types
|
|
51
|
+
out['type'] = 'string'
|
|
53
52
|
end
|
|
54
53
|
end
|
|
55
54
|
|
|
56
55
|
# convert an yaml item with type: array to json schema
|
|
57
|
-
def self.build_json_array
|
|
58
|
-
required = item.
|
|
56
|
+
def self.build_json_array(item, out)
|
|
57
|
+
required = item.reject { |_k, v| v['optional'] == true }.keys.sort
|
|
59
58
|
out.merge!({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
out[
|
|
68
|
-
item.each_pair do |key,v|
|
|
69
|
-
out[
|
|
59
|
+
'type' => 'array',
|
|
60
|
+
'items' => {
|
|
61
|
+
'type' => 'object',
|
|
62
|
+
'required' => required,
|
|
63
|
+
'unevaluatedProperties' => false # Modern alternative to additionalProperties
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
out['items']['properties'] = {}
|
|
67
|
+
item.each_pair do |key, v|
|
|
68
|
+
out['items']['properties'][key] = build_value(v)
|
|
70
69
|
end
|
|
71
70
|
out
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
# JSON Schema 2020-12 allows combining $ref with other properties directly
|
|
75
|
-
def self.wrap_refs
|
|
74
|
+
def self.wrap_refs(out)
|
|
76
75
|
# No wrapping needed with modern JSON Schema
|
|
77
76
|
out
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
# convert a yaml item with list: true to json schema
|
|
81
|
-
def self.handle_string_list
|
|
80
|
+
def self.handle_string_list(item, out)
|
|
82
81
|
case item['type']
|
|
83
|
-
when
|
|
84
|
-
out[
|
|
85
|
-
when
|
|
86
|
-
out[
|
|
87
|
-
when
|
|
88
|
-
out[
|
|
82
|
+
when 'boolean_list'
|
|
83
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/boolean_list'
|
|
84
|
+
when 'integer_list'
|
|
85
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/integer_list'
|
|
86
|
+
when 'string_list'
|
|
87
|
+
out['$ref'] = '../../../core/3.1.2/definitions.json#/string_list'
|
|
89
88
|
else
|
|
90
89
|
raise "Error: List of #{item['type']} is not supported: #{item.inspect}"
|
|
91
90
|
end
|
|
92
91
|
|
|
93
|
-
if item[
|
|
94
|
-
value_list = item[
|
|
92
|
+
if item['values']
|
|
93
|
+
value_list = item['values'].keys.join('|')
|
|
95
94
|
out['pattern'] = /(?-mix:^(#{value_list})(?:,(#{value_list}))*$)/
|
|
96
95
|
end
|
|
97
96
|
|
|
98
|
-
puts "Warning: Pattern not support for lists: #{item.inspect}" if item[
|
|
97
|
+
puts "Warning: Pattern not support for lists: #{item.inspect}" if item['pattern']
|
|
99
98
|
end
|
|
100
99
|
|
|
101
100
|
# convert yaml values to jsons schema enum
|
|
102
|
-
def self.handle_enum
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
v.to_s
|
|
119
|
-
else
|
|
120
|
-
v
|
|
121
|
-
end
|
|
122
|
-
end
|
|
101
|
+
def self.handle_enum(item, out)
|
|
102
|
+
return unless item['values']
|
|
103
|
+
|
|
104
|
+
out['enum'] = stringify_values(enum_keys(item))
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.enum_keys(item)
|
|
108
|
+
case item['values']
|
|
109
|
+
when Hash
|
|
110
|
+
validate_hash_values! item
|
|
111
|
+
item['values'].keys.sort
|
|
112
|
+
when Array
|
|
113
|
+
item['values'].sort
|
|
114
|
+
else
|
|
115
|
+
raise 'Error: Values must be specified as either a Hash or an Array, ' \
|
|
116
|
+
"got #{item['values'].class}"
|
|
123
117
|
end
|
|
124
118
|
end
|
|
125
119
|
|
|
120
|
+
def self.validate_hash_values!(item)
|
|
121
|
+
item['values'].each_pair do |k, v|
|
|
122
|
+
next unless ['', nil].include?(v)
|
|
123
|
+
|
|
124
|
+
raise "Error: '#{k}' has empty value in #{item}. " \
|
|
125
|
+
'(When using a hash to specify \'values\', the hash values cannot be empty.)'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.stringify_values(values)
|
|
130
|
+
values.map { |v| v.is_a?(Integer) || v.is_a?(Float) ? v.to_s : v }
|
|
131
|
+
end
|
|
132
|
+
|
|
126
133
|
# convert yaml pattern to jsons schema
|
|
127
|
-
def self.handle_pattern
|
|
128
|
-
out[
|
|
134
|
+
def self.handle_pattern(item, out)
|
|
135
|
+
out['pattern'] = item['pattern'] if item['pattern']
|
|
129
136
|
end
|
|
130
137
|
|
|
131
138
|
# convert yaml alarm/status/command item to corresponding jsons schema
|
|
132
|
-
def self.build_item
|
|
133
|
-
unless item['arguments']
|
|
134
|
-
json = {
|
|
135
|
-
"$schema" => "https://json-schema.org/draft/2020-12/schema",
|
|
136
|
-
"description" => item['description'],
|
|
137
|
-
}
|
|
138
|
-
return json
|
|
139
|
-
end
|
|
140
|
-
|
|
139
|
+
def self.build_item(item, property_key: 'v')
|
|
141
140
|
arguments = item['arguments']
|
|
141
|
+
return simple_item(item) unless arguments
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
},
|
|
159
|
-
# reference shared guard (relative from statuses folder to tlc/defs)
|
|
160
|
-
"if" => { "$ref" => "../../defs/guards.json#/$defs/q_unknown_or_undefined" },
|
|
161
|
-
"then" => {},
|
|
162
|
-
"else" => { "allOf" => branches }
|
|
143
|
+
property_key == 's' ? build_status_item(item, arguments) : build_default_item(item, arguments, property_key)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.simple_item(item)
|
|
147
|
+
{
|
|
148
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
149
|
+
'description' => item['description']
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.build_status_item(item, arguments)
|
|
154
|
+
branches = arguments.map do |key, argument|
|
|
155
|
+
{
|
|
156
|
+
'if' => { 'properties' => { 'n' => { 'const' => key } } },
|
|
157
|
+
'then' => { 'properties' => { 's' => build_value(argument) } }
|
|
163
158
|
}
|
|
164
159
|
end
|
|
160
|
+
{
|
|
161
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
162
|
+
'description' => item['description'],
|
|
163
|
+
'properties' => { 'n' => { 'enum' => arguments.keys.sort } },
|
|
164
|
+
'if' => { '$ref' => '../../defs/guards.json#/$defs/q_unknown_or_undefined' },
|
|
165
|
+
'then' => {},
|
|
166
|
+
'else' => { 'allOf' => branches }
|
|
167
|
+
}
|
|
168
|
+
end
|
|
165
169
|
|
|
166
|
-
|
|
170
|
+
def self.build_default_item(item, arguments, property_key)
|
|
167
171
|
rules = arguments.map do |key, argument|
|
|
168
172
|
{
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
'if' => { 'properties' => { 'n' => { 'const' => key } } },
|
|
174
|
+
'then' => { 'properties' => { property_key => build_value(argument) } }
|
|
171
175
|
}
|
|
172
176
|
end
|
|
173
|
-
|
|
174
177
|
{
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
},
|
|
180
|
-
"allOf" => rules
|
|
178
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
179
|
+
'description' => item['description'],
|
|
180
|
+
'properties' => { 'n' => { 'enum' => arguments.keys.sort } },
|
|
181
|
+
'allOf' => rules
|
|
181
182
|
}
|
|
182
183
|
end
|
|
183
184
|
|
|
184
185
|
# convert alarms to json schema
|
|
185
|
-
def self.output_alarms
|
|
186
|
+
def self.output_alarms(out, items)
|
|
186
187
|
list = items.keys.sort.map do |key|
|
|
187
188
|
{
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
'if' => { 'required' => ['aCId'], 'properties' => { 'aCId' => { 'const' => key } } },
|
|
190
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
190
191
|
}
|
|
191
192
|
end
|
|
192
193
|
json = {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
195
|
+
'properties' => {
|
|
196
|
+
'aCId' => { 'enum' => items.keys.sort },
|
|
197
|
+
'rvs' => { 'items' => { 'allOf' => list } }
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
200
|
out['alarms/alarms.json'] = output_json json
|
|
200
|
-
items.each_pair { |key,item| output_alarm out, key, item }
|
|
201
|
+
items.each_pair { |key, item| output_alarm out, key, item }
|
|
201
202
|
end
|
|
202
203
|
|
|
203
204
|
# convert an alarm to json schema
|
|
204
|
-
def self.output_alarm
|
|
205
|
+
def self.output_alarm(out, key, item)
|
|
205
206
|
json = build_item item
|
|
206
207
|
out["alarms/#{key}.json"] = output_json json
|
|
207
208
|
end
|
|
208
209
|
|
|
209
210
|
# convert statuses to json schema
|
|
210
|
-
def self.output_statuses
|
|
211
|
+
def self.output_statuses(out, items)
|
|
211
212
|
# ensure shared guard is written (relative to version folder)
|
|
212
213
|
out['../defs/guards.json'] ||= output_json({
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
214
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
215
|
+
'$defs' => {
|
|
216
|
+
'q_unknown_or_undefined' => {
|
|
217
|
+
'allOf' => [
|
|
218
|
+
{ 'required' => ['q'] },
|
|
219
|
+
{ 'properties' => { 'q' => { 'enum' => %w[undefined
|
|
220
|
+
unknown] } } }
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
list = [{ 'properties' => { 'sCI' => { 'enum' => items.keys.sort } } }]
|
|
225
227
|
items.keys.sort.each do |key|
|
|
226
228
|
list << {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
'if' => { 'required' => ['sCI'], 'properties' => { 'sCI' => { 'const' => key } } },
|
|
230
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
229
231
|
}
|
|
230
232
|
end
|
|
231
|
-
json = {
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
json = {
|
|
234
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
235
|
+
'properties' => { 'sS' => { 'items' => { 'allOf' => list } } }
|
|
234
236
|
}
|
|
235
237
|
out['statuses/statuses.json'] = output_json json
|
|
236
|
-
items.each_pair { |key,item| output_status out, key, item }
|
|
238
|
+
items.each_pair { |key, item| output_status out, key, item }
|
|
237
239
|
end
|
|
238
240
|
|
|
239
241
|
# convert a status to json schema
|
|
240
|
-
def self.output_status
|
|
242
|
+
def self.output_status(out, key, item)
|
|
241
243
|
json = build_item item, property_key: 's'
|
|
242
244
|
out["statuses/#{key}.json"] = output_json json
|
|
243
245
|
end
|
|
244
246
|
|
|
245
247
|
# convert commands to json schema
|
|
246
|
-
def self.output_commands
|
|
247
|
-
list = [
|
|
248
|
+
def self.output_commands(out, items)
|
|
249
|
+
list = [{ 'properties' => { 'cCI' => { 'enum' => items.keys.sort } } }]
|
|
248
250
|
items.keys.sort.each do |key|
|
|
249
251
|
list << {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
'if' => { 'required' => ['cCI'], 'properties' => { 'cCI' => { 'const' => key } } },
|
|
253
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
252
254
|
}
|
|
253
255
|
end
|
|
254
|
-
json = {
|
|
255
|
-
|
|
256
|
-
|
|
256
|
+
json = {
|
|
257
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
258
|
+
'items' => { 'allOf' => list }
|
|
257
259
|
}
|
|
258
260
|
out['commands/commands.json'] = output_json json
|
|
259
261
|
|
|
260
|
-
json = {
|
|
261
|
-
|
|
262
|
-
|
|
262
|
+
json = {
|
|
263
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
264
|
+
'properties' => { 'arg' => { '$ref' => 'commands.json' } }
|
|
263
265
|
}
|
|
264
266
|
out['commands/command_requests.json'] = output_json json
|
|
265
267
|
|
|
266
|
-
json = {
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
json = {
|
|
269
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
270
|
+
'properties' => { 'rvs' => { '$ref' => 'commands.json' } }
|
|
269
271
|
}
|
|
270
272
|
out['commands/command_responses.json'] = output_json json
|
|
271
273
|
|
|
272
|
-
items.each_pair { |key,item| output_command out, key, item }
|
|
274
|
+
items.each_pair { |key, item| output_command out, key, item }
|
|
273
275
|
end
|
|
274
276
|
|
|
275
277
|
# convert a command to json schema
|
|
276
|
-
def self.output_command
|
|
278
|
+
def self.output_command(out, key, item)
|
|
277
279
|
json = build_item item
|
|
278
280
|
# Always add the command operation (cO) constraint at the top-level properties
|
|
279
|
-
json[
|
|
280
|
-
json[
|
|
281
|
-
|
|
281
|
+
json['properties'] ||= {}
|
|
282
|
+
json['properties']['cO'] = { 'const' => item['command'] }
|
|
283
|
+
|
|
282
284
|
out["commands/#{key}.json"] = output_json json
|
|
283
285
|
end
|
|
284
286
|
|
|
285
287
|
# output the json schema root
|
|
286
|
-
def self.output_root
|
|
288
|
+
def self.output_root(out, meta)
|
|
287
289
|
json = {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
{
|
|
294
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "CommandRequest" }}},
|
|
295
|
-
"then" => { "$ref" => "commands/command_requests.json" }
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "CommandResponse" }}},
|
|
299
|
-
"then" => { "$ref" => "commands/command_responses.json" }
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "enum" => ["StatusRequest","StatusResponse","StatusSubscribe","StatusUnsubscribe","StatusUpdate"] }}},
|
|
303
|
-
"then" => { "$ref" => "statuses/statuses.json" }
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "Alarm" }}},
|
|
307
|
-
"then" => { "$ref" => "alarms/alarms.json" }
|
|
308
|
-
}
|
|
309
|
-
]
|
|
290
|
+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
|
291
|
+
'name' => meta['name'],
|
|
292
|
+
'description' => meta['description'],
|
|
293
|
+
'version' => meta['version'],
|
|
294
|
+
'allOf' => root_type_rules
|
|
310
295
|
}
|
|
311
|
-
out[
|
|
296
|
+
out['rsmp.json'] = output_json json
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def self.root_type_rules
|
|
300
|
+
[
|
|
301
|
+
{
|
|
302
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandRequest' } } },
|
|
303
|
+
'then' => { '$ref' => 'commands/command_requests.json' }
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandResponse' } } },
|
|
307
|
+
'then' => { '$ref' => 'commands/command_responses.json' }
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
'if' => {
|
|
311
|
+
'required' => ['type'],
|
|
312
|
+
'properties' => {
|
|
313
|
+
'type' => { 'enum' => %w[StatusRequest StatusResponse StatusSubscribe StatusUnsubscribe
|
|
314
|
+
StatusUpdate] }
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
'then' => { '$ref' => 'statuses/statuses.json' }
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'Alarm' } } },
|
|
321
|
+
'then' => { '$ref' => 'alarms/alarms.json' }
|
|
322
|
+
}
|
|
323
|
+
]
|
|
312
324
|
end
|
|
313
325
|
|
|
314
326
|
# generate the json schema from a string containing yaml
|
|
315
|
-
def self.generate
|
|
327
|
+
def self.generate(sxl)
|
|
316
328
|
out = {}
|
|
317
329
|
output_root out, sxl[:meta]
|
|
318
330
|
output_alarms out, sxl[:alarms]
|
|
@@ -322,16 +334,15 @@ module RSMP
|
|
|
322
334
|
end
|
|
323
335
|
|
|
324
336
|
# convert yaml to json schema and write files to a folder
|
|
325
|
-
def self.write
|
|
337
|
+
def self.write(sxl, folder)
|
|
326
338
|
out = generate sxl
|
|
327
|
-
out.each_pair do |relative_path,str|
|
|
339
|
+
out.each_pair do |relative_path, str|
|
|
328
340
|
path = File.join(folder, relative_path)
|
|
329
|
-
FileUtils.mkdir_p File.dirname(path)
|
|
330
|
-
|
|
331
|
-
file.puts str
|
|
341
|
+
FileUtils.mkdir_p File.dirname(path)
|
|
342
|
+
File.open(path, 'w+') { |file| file.puts str }
|
|
332
343
|
end
|
|
333
344
|
end
|
|
334
345
|
end
|
|
335
346
|
end
|
|
336
347
|
end
|
|
337
|
-
end
|
|
348
|
+
end
|
|
@@ -5,37 +5,35 @@ require 'json'
|
|
|
5
5
|
require 'fileutils'
|
|
6
6
|
|
|
7
7
|
module RSMP
|
|
8
|
+
# Namespace for SXL format conversion tools.
|
|
8
9
|
module Convert
|
|
10
|
+
# Handles importing SXL definitions.
|
|
9
11
|
module Import
|
|
12
|
+
# Reads SXL definitions from YAML files.
|
|
10
13
|
module YAML
|
|
11
|
-
|
|
12
|
-
def self.read path
|
|
14
|
+
def self.read(path)
|
|
13
15
|
convert ::YAML.load_file(path)
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
def self.parse
|
|
17
|
-
convert ::YAML.
|
|
18
|
+
def self.parse(str)
|
|
19
|
+
convert ::YAML.safe_load(str)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
def self.convert
|
|
21
|
-
sxl = {
|
|
22
|
-
meta: {},
|
|
23
|
-
alarms: {},
|
|
24
|
-
statuses: {},
|
|
25
|
-
commands: {}
|
|
26
|
-
}
|
|
27
|
-
|
|
22
|
+
def self.convert(yaml)
|
|
23
|
+
sxl = { meta: {}, alarms: {}, statuses: {}, commands: {} }
|
|
28
24
|
sxl[:meta] = yaml['meta']
|
|
25
|
+
collect_objects yaml['objects'], sxl
|
|
26
|
+
sxl
|
|
27
|
+
end
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
object[
|
|
33
|
-
object[
|
|
29
|
+
def self.collect_objects(objects, sxl)
|
|
30
|
+
objects.each_pair do |_type, object|
|
|
31
|
+
object['alarms']&.each { |id, item| sxl[:alarms][id] = item }
|
|
32
|
+
object['statuses']&.each { |id, item| sxl[:statuses][id] = item }
|
|
33
|
+
object['commands']&.each { |id, item| sxl[:commands][id] = item }
|
|
34
34
|
end
|
|
35
|
-
sxl
|
|
36
35
|
end
|
|
37
36
|
end
|
|
38
|
-
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
|
-
end
|
|
39
|
+
end
|
data/lib/rsmp_schema/error.rb
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
module RSMP
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
module RSMP
|
|
2
|
+
module Schema
|
|
3
|
+
# Base error class for rsmp_schema.
|
|
4
|
+
class Error < StandardError
|
|
5
|
+
end
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
# Raised when an unknown schema type or version is requested.
|
|
8
|
+
class UnknownSchemaError < Error
|
|
9
|
+
end
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
# Raised when the requested schema type does not exist.
|
|
12
|
+
class UnknownSchemaTypeError < UnknownSchemaError
|
|
13
|
+
end
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
# Raised when the requested schema version does not exist.
|
|
16
|
+
class UnknownSchemaVersionError < UnknownSchemaError
|
|
17
|
+
end
|
|
12
18
|
end
|
|
13
19
|
end
|