Module: RSMP::Convert::Export::JSONSchema

Defined in:
lib/rsmp/convert/export/json_schema.rb

Constant Summary collapse

JSON_OPTIONS =
{
  array_nl: "\n",
  object_nl: "\n",
  indent: '  ',
  space_before: ' ',
  space: ' '
}.freeze

Class Method Summary collapse

Class Method Details

.build_item(item, property_key: 'v') ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/rsmp/convert/export/json_schema.rb', line 70

def self.build_item(item, property_key: 'v')
  json = { 'allOf' => [{ 'description' => item['description'] }] }
  if item['arguments']
    json['allOf'].first['properties'] = { 'n' => { 'enum' => item['arguments'].keys.sort } }
    item['arguments'].each_pair do |key, argument|
      json['allOf'] << {
        'if' => { 'required' => ['n'], 'properties' => { 'n' => { 'const' => key } } },
        'then' => { 'properties' => { property_key => build_value(argument) } }
      }
    end
  end
  json
end

.build_list_value(out, item) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rsmp/convert/export/json_schema.rb', line 36

def self.build_list_value(out, item)
  case item['type']
  when 'boolean'
    out['$ref'] = '../../../core/3.1.1/definitions.json#/boolean_list'
  when 'integer', 'ordinal', 'unit', 'scale', 'long'
    out['$ref'] = '../../../core/3.1.1/definitions.json#/integer_list'
  else
    raise "Error: List of #{item['type']} is not supported: #{item.inspect}"
  end

  if item['values']
    value_list = item['values'].keys.join('|')
    out['pattern'] = /(?-mix:^(#{value_list})(?:,(#{value_list}))*$)/
  end

  puts "Warning: Pattern not support for lists: #{item.inspect}" if item['pattern']
end

.build_root_refsObject



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rsmp/convert/export/json_schema.rb', line 159

def self.build_root_refs
  [
    {
      'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandRequest' } } },
      'then' => { '$ref' => 'commands/command_requests.json' }
    },
    {
      'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandResponse' } } },
      'then' => { '$ref' => 'commands/command_responses.json' }
    },
    {
      'if' => { 'required' => ['type'],
                'properties' => {
                  'type' => {
                    'enum' => %w[StatusRequest StatusResponse StatusSubscribe
                                 StatusUnsubscribe StatusUpdate]
                  }
                } },
      'then' => { '$ref' => 'statuses/statuses.json' }
    },
    {
      'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'Alarm' } } },
      'then' => { '$ref' => 'alarms/alarms.json' }
    }
  ]
end

.build_root_schema(meta) ⇒ Object



150
151
152
153
154
155
156
157
# File 'lib/rsmp/convert/export/json_schema.rb', line 150

def self.build_root_schema(meta)
  {
    'name' => meta['name'],
    'description' => meta['description'],
    'version' => meta['version'],
    'allOf' => build_root_refs
  }
end

.build_single_value(out, item) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rsmp/convert/export/json_schema.rb', line 54

def self.build_single_value(out, item)
  case item['type']
  when 'boolean'
    out['$ref'] = '../../../core/3.1.1/definitions.json#/boolean'
  when 'timestamp'
    out['$ref'] = '../../../core/3.1.1/definitions.json#/timestamp'
  when 'integer', 'ordinal', 'unit', 'scale', 'long'
    out['$ref'] = '../../../core/3.1.1/definitions.json#/integer'
  else # includes 'string', 'base64' and any other types
    out['type'] = 'string'
  end

  out['enum'] = item['values'].keys.sort if item['values']
  out['pattern'] = item['pattern'] if item['pattern']
end

.build_value(item) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rsmp/convert/export/json_schema.rb', line 23

def self.build_value(item)
  out = {}
  out['description'] = item['description'] if item['description']

  if item['list']
    build_list_value(out, item)
  else
    build_single_value(out, item)
  end

  out
end

.generate(sxl) ⇒ Object



191
192
193
194
195
196
197
198
# File 'lib/rsmp/convert/export/json_schema.rb', line 191

def self.generate(sxl)
  out = {}
  output_root out, sxl[:meta]
  output_alarms out, sxl[:alarms]
  output_statuses out, sxl[:statuses]
  output_commands out, sxl[:commands]
  out
end

.output_alarm(out, key, item) ⇒ Object



101
102
103
104
# File 'lib/rsmp/convert/export/json_schema.rb', line 101

def self.output_alarm(out, key, item)
  json = build_item item
  out["alarms/#{key}.json"] = output_json json
end

.output_alarms(out, items) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rsmp/convert/export/json_schema.rb', line 84

def self.output_alarms(out, items)
  list = items.keys.sort.map do |key|
    {
      'if' => { 'required' => ['aCId'], 'properties' => { 'aCId' => { 'const' => key } } },
      'then' => { '$ref' => "#{key}.json" }
    }
  end
  json = {
    'properties' => {
      'aCId' => { 'enum' => items.keys.sort },
      'rvs' => { 'items' => { 'allOf' => list } }
    }
  }
  out['alarms/alarms.json'] = output_json json
  items.each_pair { |key, item| output_alarm out, key, item }
end

.output_command(out, key, item) ⇒ Object



144
145
146
147
148
# File 'lib/rsmp/convert/export/json_schema.rb', line 144

def self.output_command(out, key, item)
  json = build_item item
  json['allOf'].first['properties']['cO'] = { 'const' => item['command'] }
  out["commands/#{key}.json"] = output_json json
end

.output_commands(out, items) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/rsmp/convert/export/json_schema.rb', line 124

def self.output_commands(out, items)
  list = [{ 'properties' => { 'cCI' => { 'enum' => items.keys.sort } } }]
  items.keys.sort.each do |key|
    list << {
      'if' => { 'required' => ['cCI'], 'properties' => { 'cCI' => { 'const' => key } } },
      'then' => { '$ref' => "#{key}.json" }
    }
  end
  json = { 'items' => { 'allOf' => list } }
  out['commands/commands.json'] = output_json json

  json = { 'properties' => { 'arg' => { '$ref' => 'commands.json' } } }
  out['commands/command_requests.json'] = output_json json

  json = { 'properties' => { 'rvs' => { '$ref' => 'commands.json' } } }
  out['commands/command_responses.json'] = output_json json

  items.each_pair { |key, item| output_command out, key, item }
end

.output_json(item) ⇒ Object



19
20
21
# File 'lib/rsmp/convert/export/json_schema.rb', line 19

def self.output_json(item)
  JSON.generate(item, JSON_OPTIONS)
end

.output_root(out, meta) ⇒ Object



186
187
188
189
# File 'lib/rsmp/convert/export/json_schema.rb', line 186

def self.output_root(out, meta)
  json = build_root_schema(meta)
  out['sxl.json'] = output_json json
end

.output_status(out, key, item) ⇒ Object



119
120
121
122
# File 'lib/rsmp/convert/export/json_schema.rb', line 119

def self.output_status(out, key, item)
  json = build_item item, property_key: 's'
  out["statuses/#{key}.json"] = output_json json
end

.output_statuses(out, items) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/rsmp/convert/export/json_schema.rb', line 106

def self.output_statuses(out, items)
  list = [{ 'properties' => { 'sCI' => { 'enum' => items.keys.sort } } }]
  items.keys.sort.each do |key|
    list << {
      'if' => { 'required' => ['sCI'], 'properties' => { 'sCI' => { 'const' => key } } },
      'then' => { '$ref' => "#{key}.json" }
    }
  end
  json = { 'properties' => { 'sS' => { 'items' => { 'allOf' => list } } } }
  out['statuses/statuses.json'] = output_json json
  items.each_pair { |key, item| output_status out, key, item }
end

.write(sxl, folder) ⇒ Object



200
201
202
203
204
205
206
207
208
# File 'lib/rsmp/convert/export/json_schema.rb', line 200

def self.write(sxl, folder)
  out = generate sxl
  out.each_pair do |relative_path, str|
    path = File.join(folder, relative_path)
    FileUtils.mkdir_p File.dirname(path) # create folders if needed
    file = File.open(path, 'w+') # w+ means truncate or create new file
    file.puts str
  end
end