Module: RSMP::Schema
- Defined in:
- lib/rsmp/schema.rb,
lib/rsmp/schema_error.rb
Overview
Provides JSON Schema validation for RSMP messages across core and SXL versions.
Defined Under Namespace
Classes: Error, UnknownSchemaError, UnknownSchemaTypeError, UnknownSchemaVersionError
Class Method Summary collapse
-
.core_versions ⇒ Object
get array of core schema versions.
-
.earliest_core_version ⇒ Object
get earliest core schema version.
-
.earliest_version(type) ⇒ Object
get earliest schema version for a particular schema type.
-
.find_schema(type, version, options = {}) ⇒ Object
find schema for a particular schema and version return nil if not found.
-
.find_schema!(type, version, options = {}) ⇒ Object
find schema for a particular schema and version raise error if not found.
-
.find_schemas(type) ⇒ Object
find schemas versions for particular schema type return nil if type not found.
-
.find_schemas!(type) ⇒ Object
find schemas versions for particular schema type raise error if not found.
-
.latest_core_version ⇒ Object
get latesty core schema version.
-
.latest_version(type) ⇒ Object
get latest schema version for a particular schema type.
-
.load_schema_type(type, type_path, force: false) ⇒ Object
load an schema from a folder.
-
.remove_schema_type(type) ⇒ Object
remove a schema type.
-
.sanitize_version(version) ⇒ Object
get major.minor.patch part of a version string, where patch is optional ignore trailing characters, e.g.
-
.schema?(type, version, options = {}) ⇒ Boolean
true if a particular schema type and version found.
-
.schema_types ⇒ Object
get schemas types.
-
.schemas ⇒ Object
get all schemas, oganized by type and version.
- .setup ⇒ Object
-
.sort_versions(versions) ⇒ Object
sort version strings.
-
.status_catalogue(type, version) ⇒ Object
return a catalogue of statuses for a particular schema type and version returns a hash of { status_code_id_sym => [arg_name_sym, …] } raises an error if the schema type/version is not found, or has no sxl.yaml.
-
.validate(message, schemas, options = {}) ⇒ Object
validate using a particular schema and version raises error if schema is not found return nil if validation succeds, otherwise returns an array of errors.
-
.validate_using_schema(message, schema) ⇒ Object
validate an rsmp messages using a schema object.
-
.versions(type) ⇒ Object
get array of schema versions for a particular schema type.
Class Method Details
.core_versions ⇒ Object
get array of core schema versions
61 62 63 |
# File 'lib/rsmp/schema.rb', line 61 def self.core_versions versions :core end |
.earliest_core_version ⇒ Object
get earliest core schema version
66 67 68 |
# File 'lib/rsmp/schema.rb', line 66 def self.earliest_core_version earliest_version :core end |
.earliest_version(type) ⇒ Object
get earliest schema version for a particular schema type
82 83 84 85 |
# File 'lib/rsmp/schema.rb', line 82 def self.earliest_version(type) schemas = find_schemas!(type).keys sort_versions(schemas).first end |
.find_schema(type, version, options = {}) ⇒ Object
find schema for a particular schema and version return nil if not found
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rsmp/schema.rb', line 131 def self.find_schema(type, version, = {}) raise ArgumentError, 'version missing' unless version version = sanitize_version version if [:lenient] if version schemas = find_schemas type return schemas[version] if schemas end nil end |
.find_schema!(type, version, options = {}) ⇒ Object
find schema for a particular schema and version raise error if not found
159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/rsmp/schema.rb', line 159 def self.find_schema!(type, version, = {}) schema = find_schema type, version, raise ArgumentError, 'version missing' unless version version = sanitize_version version if [:lenient] if version schemas = find_schemas! type schema = schemas[version] return schema if schema end raise UnknownSchemaVersionError, "Unknown schema version #{type} #{version}" end |
.find_schemas(type) ⇒ Object
find schemas versions for particular schema type return nil if type not found
114 115 116 117 118 |
# File 'lib/rsmp/schema.rb', line 114 def self.find_schemas(type) raise ArgumentError, 'type missing' unless type @schemas[type.to_sym] end |
.find_schemas!(type) ⇒ Object
find schemas versions for particular schema type raise error if not found
122 123 124 125 126 127 |
# File 'lib/rsmp/schema.rb', line 122 def self.find_schemas!(type) schemas = find_schemas type raise UnknownSchemaTypeError, "Unknown schema type #{type}" unless schemas schemas end |
.latest_core_version ⇒ Object
get latesty core schema version
71 72 73 |
# File 'lib/rsmp/schema.rb', line 71 def self.latest_core_version latest_version :core end |
.latest_version(type) ⇒ Object
get latest schema version for a particular schema type
88 89 90 91 |
# File 'lib/rsmp/schema.rb', line 88 def self.latest_version(type) schemas = find_schemas!(type).keys sort_versions(schemas).last end |
.load_schema_type(type, type_path, force: false) ⇒ Object
load an schema from a folder. schemas are organized by version, and contain json schema files, with the entry point being rsmp.jspon, eg: tlc
1.0.7
rsmp.json
other jon schema files...
1.0.8
...
an error is raised if the schema type already exists, and force is not set to true
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rsmp/schema.rb', line 28 def self.load_schema_type(type, type_path, force: false) raise "Schema type #{type} already loaded" if @schemas[type] && force != true @schemas[type] = {} Dir.glob("#{type_path}/*").select { |f| File.directory? f }.each do |schema_path| version = File.basename(schema_path) file_path = File.join(schema_path, 'rsmp.json') next unless File.exist? file_path @schemas[type][version] = JSONSchemer.schema( Pathname.new(File.join(schema_path, 'rsmp.json')) ) end end |
.remove_schema_type(type) ⇒ Object
remove a schema type
44 45 46 |
# File 'lib/rsmp/schema.rb', line 44 def self.remove_schema_type(type) schemas.delete type end |
.sanitize_version(version) ⇒ Object
get major.minor.patch part of a version string, where patch is optional ignore trailing characters, e.g.
3.1.3.32A => 3.1.3
3.1A3r3 >= 3.1
return nil if string doesn’t match
147 148 149 150 151 152 153 154 155 |
# File 'lib/rsmp/schema.rb', line 147 def self.sanitize_version(version) # match normal semver z.y.z format if (matched = /^\d+\.\d+\.\d+/.match(version)) matched.to_s # match x.y format, and add patch version zero to get z.y.0 elsif (matched = /^\d+\.\d+/.match(version)) "#{matched}.0" end end |
.schema?(type, version, options = {}) ⇒ Boolean
true if a particular schema type and version found
173 174 175 |
# File 'lib/rsmp/schema.rb', line 173 def self.schema?(type, version, = {}) find_schema(type, version, ) != nil end |
.schema_types ⇒ Object
get schemas types
49 50 51 |
# File 'lib/rsmp/schema.rb', line 49 def self.schema_types schemas.keys end |
.schemas ⇒ Object
get all schemas, oganized by type and version
54 55 56 57 58 |
# File 'lib/rsmp/schema.rb', line 54 def self.schemas raise 'No schemas available, perhaps Schema.setup was never called?' unless @schemas @schemas end |
.setup ⇒ Object
9 10 11 12 13 14 15 16 |
# File 'lib/rsmp/schema.rb', line 9 def self.setup @schemas = {} schemas_path = File.(File.join(__dir__, '..', '..', 'schemas')) Dir.glob("#{schemas_path}/*").select { |f| File.directory? f }.each do |type_path| type = File.basename(type_path).to_sym load_schema_type type, type_path end end |
.sort_versions(versions) ⇒ Object
sort version strings
108 109 110 |
# File 'lib/rsmp/schema.rb', line 108 def self.sort_versions(versions) versions.sort_by { |k| Gem::Version.new(k) } end |
.status_catalogue(type, version) ⇒ Object
return a catalogue of statuses for a particular schema type and version returns a hash of { status_code_id_sym => [arg_name_sym, …] } raises an error if the schema type/version is not found, or has no sxl.yaml
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/rsmp/schema.rb', line 180 def self.status_catalogue(type, version) find_schema! type, version schemas_path = File.(File.join(__dir__, '..', '..', 'schemas')) yaml_path = File.join(schemas_path, type.to_s, version, 'sxl.yaml') raise "No sxl.yaml for #{type} #{version}" unless File.exist?(yaml_path) sxl = RSMP::Convert::Import::YAML.read(yaml_path) sxl[:statuses].transform_keys(&:to_sym).transform_values do |status| (status['arguments'] || {}).keys.map(&:to_sym) end end |
.validate(message, schemas, options = {}) ⇒ Object
validate using a particular schema and version raises error if schema is not found return nil if validation succeds, otherwise returns an array of errors
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/rsmp/schema.rb', line 195 def self.validate(, schemas, = {}) raise ArgumentError, 'message missing' unless raise ArgumentError, 'schemas missing' unless schemas raise ArgumentError, 'schemas must be a Hash' unless schemas.is_a?(Hash) raise ArgumentError, 'schemas cannot be empty' unless schemas.any? errors = schemas.flat_map do |type, version| schema = find_schema! type, version, validate_using_schema(, schema) end return nil if errors.empty? errors end |
.validate_using_schema(message, schema) ⇒ Object
validate an rsmp messages using a schema object
94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rsmp/schema.rb', line 94 def self.validate_using_schema(, schema) raise ArgumentError, 'message missing' unless raise ArgumentError, 'schema missing' unless schema if schema.valid? [] else schema.validate().map do |item| [item['data_pointer'], item['type'], item['details']] end end end |
.versions(type) ⇒ Object
get array of schema versions for a particular schema type
76 77 78 79 |
# File 'lib/rsmp/schema.rb', line 76 def self.versions(type) schemas = find_schemas!(type).keys sort_versions(schemas) end |