Module: JSI::Schema
- Included in:
- MetaschemaNode::BootstrapSchema
- Defined in:
- lib/jsi/schema.rb,
lib/jsi/schema.rb,
lib/jsi/schema/issue.rb,
lib/jsi/schema/draft04.rb,
lib/jsi/schema/draft06.rb,
lib/jsi/schema/draft07.rb
Overview
JSI::Schema is a module which extends Base instances which represent JSON schemas.
This module is included on the JSI Schema module of any schema which describes other schemas, i.e. is a metaschema or other DescribesSchema. Therefore, any JSI instance described by a schema which is a DescribesSchema is a schema and is extended by this module.
The content of an instance which is a JSI::Schema (referred to in this context as schema_content) is typically a Hash (JSON object) or a boolean.
Defined Under Namespace
Modules: Application, BigMoneyId, DescribesSchema, Draft04, Draft06, Draft07, IdWithAnchor, OldId, SchemaAncestorNode, Validation Classes: Error, Issue, NotASchemaError, Ref, ReferenceError
Class Method Summary collapse
-
.ensure_describes_schema(describes_schema, name: nil, schema_registry: JSI.schema_registry) ⇒ Base + Schema + Schema::DescribesSchema
private
Ensures the given param identifies a JSI Schema which describes schemas, and returns that schema.
-
.ensure_schema(schema, msg: "indicated object is not a schema:", reinstantiate_as: nil) ⇒ Schema
ensure the given object is a JSI Schema.
Instance Method Summary collapse
-
#child_applicator_schemas(token, instance) ⇒ JSI::SchemaSet
a set of child applicator subschemas of this schema which apply to the child of the given instance on the given token.
-
#described_object_property_names ⇒ Set
any object property names this schema indicates may be present on its instances.
-
#describes_schema!(schema_implementation_modules)
indicates that this schema describes a schema.
-
#describes_schema? ⇒ Boolean
does this schema itself describe a schema?.
-
#each_child_applicator_schema(token, instance) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each child applicator subschema (from properties, items, etc.) which applies to the child of the given instance on the given token.
-
#each_inplace_applicator_schema(instance, visited_refs: []) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each inplace applicator schema which applies to the given instance.
-
#each_schema_uri {|Addressable::URI| ... } ⇒ Enumerator?
see #schema_uris.
- #initialize ⇒ Object
-
#inplace_applicator_schemas(instance) ⇒ JSI::SchemaSet
a set of inplace applicator schemas of this schema (from $ref, allOf, etc.) which apply to the given instance.
-
#instance_valid?(instance) ⇒ Boolean
whether the given instance is valid against this schema.
-
#instance_validate(instance) ⇒ JSI::Validation::Result
validates the given instance against this schema.
-
#jsi_schema_module ⇒ Module + SchemaModule
a module which extends all instances of this schema.
-
#jsi_schema_module_exec(*a, **kw, &block) ⇒ Object
Evaluates the given block in the context of this schema's JSI schema module.
-
#jsi_subschema_resource_ancestors ⇒ Array<JSI::Schema>
private
schema resources which are ancestors of any subschemas below this schema.
-
#keyword?(keyword) ⇒ Boolean
does this schema contain the given keyword?.
-
#new_jsi(instance, **kw) ⇒ JSI::Base subclass
Instantiates a new JSI whose content comes from the given
instance
param. -
#resource_root_subschema(ptr) ⇒ JSI::Schema
a schema in the same schema resource as this one (see #schema_resource_root) at the given pointer relative to the root of the schema resource.
-
#schema_absolute_uri ⇒ Addressable::URI?
the URI of this schema, calculated from our
#id
, resolved against our#jsi_schema_base_uri
. -
#schema_content ⇒ Object
the underlying JSON data used to instantiate this JSI::Schema.
- #schema_ref(keyword: "$ref") ⇒ Schema::Ref
-
#schema_resource_root ⇒ JSI::Base
a resource containing this schema.
-
#schema_resource_root? ⇒ Boolean
is this schema the root of a schema resource?.
-
#schema_uri ⇒ Addressable::URI?
a nonrelative URI which refers to this schema.
-
#schema_uris ⇒ Array<Addressable::URI>
nonrelative URIs (that is, absolute, but possibly with a fragment) which refer to this schema.
-
#subschema(subptr) ⇒ JSI::Schema
a subschema of this Schema.
Class Method Details
.ensure_describes_schema(describes_schema, name: nil, schema_registry: JSI.schema_registry) ⇒ Base + Schema + Schema::DescribesSchema
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Ensures the given param identifies a JSI Schema which describes schemas, and returns that schema.
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/jsi/schema.rb', line 399 def ensure_describes_schema(describes_schema, name: nil, schema_registry: JSI.schema_registry) if describes_schema.respond_to?(:to_str) schema = Schema::Ref.new(describes_schema, schema_registry: schema_registry).deref_schema if !schema.describes_schema? raise(TypeError, [name, "URI indicates a schema which does not describe schemas: #{describes_schema.pretty_inspect.chomp}"].compact.join(" ")) end schema elsif describes_schema.is_a?(SchemaModule::DescribesSchemaModule) describes_schema.schema elsif describes_schema.is_a?(DescribesSchema) describes_schema else raise(TypeError, "#{name || "param"} does not indicate a schema which describes schemas: #{describes_schema.pretty_inspect.chomp}") end end |
.ensure_schema(schema, msg: "indicated object is not a schema:", reinstantiate_as: nil) ⇒ Schema
ensure the given object is a JSI Schema
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/jsi/schema.rb', line 363 def ensure_schema(schema, msg: "indicated object is not a schema:", reinstantiate_as: nil) if schema.is_a?(Schema) schema else if reinstantiate_as && schema.is_a?(JSI::Base) # TODO warn; behavior is undefined and I hate this implementation result_schema_schemas = schema.jsi_schemas + reinstantiate_as result_schema_class = JSI::SchemaClasses.class_for_schemas(result_schema_schemas, includes: SchemaClasses.includes_for(schema.jsi_node_content) ) result_schema_class.new(schema.jsi_document, jsi_ptr: schema.jsi_ptr, jsi_indicated_schemas: schema.jsi_indicated_schemas, jsi_schema_base_uri: schema.jsi_schema_base_uri, jsi_schema_resource_ancestors: schema.jsi_schema_resource_ancestors, jsi_schema_registry: schema.jsi_schema_registry, jsi_root_node: schema.jsi_ptr.root? ? nil : schema.jsi_root_node, # bad ) else raise(NotASchemaError, [ *msg, schema.pretty_inspect.chomp, ].join("\n")) end end end |
Instance Method Details
#child_applicator_schemas(token, instance) ⇒ JSI::SchemaSet
a set of child applicator subschemas of this schema which apply to the child of the given instance on the given token.
672 673 674 |
# File 'lib/jsi/schema.rb', line 672 def child_applicator_schemas(token, instance) SchemaSet.new(each_child_applicator_schema(token, instance)) end |
#described_object_property_names ⇒ Set
any object property names this schema indicates may be present on its instances. this includes any keys of this schema's "properties" object and any entries of this schema's array of "required" property keys.
694 695 696 |
# File 'lib/jsi/schema.rb', line 694 def described_object_property_names @described_object_property_names_map[] end |
#describes_schema!(schema_implementation_modules)
This method returns an undefined value.
indicates that this schema describes a schema. this schema is extended with DescribesSchema and its #jsi_schema_module is extended with JSI::SchemaModule::DescribesSchemaModule, and the JSI Schema Module will include JSI::Schema and the given modules.
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/jsi/schema.rb', line 563 def describes_schema!(schema_implementation_modules) schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules) if describes_schema? # this schema, or one equal to it, has already had describes_schema! called on it. # this is to be avoided, but is not particularly a problem. # it is a bug if it was called different times with different schema_implementation_modules, though. unless jsi_schema_module.schema_implementation_modules == schema_implementation_modules raise(ArgumentError, "this schema already describes a schema with different schema_implementation_modules") end else jsi_schema_module.include(Schema) schema_implementation_modules.each do |mod| jsi_schema_module.include(mod) end jsi_schema_module.extend(SchemaModule::DescribesSchemaModule) jsi_schema_module.instance_variable_set(:@schema_implementation_modules, schema_implementation_modules) end extend(DescribesSchema) nil end |
#describes_schema? ⇒ Boolean
does this schema itself describe a schema?
551 552 553 |
# File 'lib/jsi/schema.rb', line 551 def describes_schema? jsi_schema_module <= JSI::Schema || false end |
#each_child_applicator_schema(token, instance) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each child applicator subschema (from properties, items, etc.) which applies to the child of the given instance on the given token.
682 683 684 685 686 687 688 |
# File 'lib/jsi/schema.rb', line 682 def each_child_applicator_schema(token, instance, &block) return to_enum(__method__, token, instance) unless block internal_child_applicate_keywords(token, instance, &block) nil end |
#each_inplace_applicator_schema(instance, visited_refs: []) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each inplace applicator schema which applies to the given instance.
655 656 657 658 659 660 661 662 663 |
# File 'lib/jsi/schema.rb', line 655 def each_inplace_applicator_schema(instance, visited_refs: [], &block) return to_enum(__method__, instance, visited_refs: visited_refs) unless block catch(:jsi_application_done) do internal_inplace_applicate_keywords(instance, visited_refs, &block) end nil end |
#each_schema_uri {|Addressable::URI| ... } ⇒ Enumerator?
see #schema_uris
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/jsi/schema.rb', line 478 def each_schema_uri return to_enum(__method__) unless block_given? yield schema_absolute_uri if schema_absolute_uri parent_schemas = jsi_subschema_resource_ancestors.reverse_each.select do |resource| resource.schema_absolute_uri end anchored = respond_to?(:anchor) ? anchor : nil parent_schemas.each do |parent_schema| if anchored if parent_schema.jsi_anchor_subschema(anchor) == self yield parent_schema.schema_absolute_uri.merge(fragment: anchor).freeze else anchored = false end end relative_ptr = jsi_ptr.relative_to(parent_schema.jsi_ptr) yield parent_schema.schema_absolute_uri.merge(fragment: relative_ptr.fragment).freeze end nil end |
#initialize ⇒ Object
417 418 419 420 |
# File 'lib/jsi/schema.rb', line 417 def initialize(*) super jsi_schema_initialize end |
#inplace_applicator_schemas(instance) ⇒ JSI::SchemaSet
a set of inplace applicator schemas of this schema (from $ref, allOf, etc.) which apply to the given instance.
the returned set will contain this schema itself, unless this schema contains a $ref keyword.
645 646 647 |
# File 'lib/jsi/schema.rb', line 645 def inplace_applicator_schemas(instance) SchemaSet.new(each_inplace_applicator_schema(instance)) end |
#instance_valid?(instance) ⇒ Boolean
whether the given instance is valid against this schema
727 728 729 730 731 732 |
# File 'lib/jsi/schema.rb', line 727 def instance_valid?(instance) if instance.is_a?(SchemaAncestorNode) instance = instance.jsi_node_content end internal_validate_instance(Ptr[], instance, validate_only: true).valid? end |
#instance_validate(instance) ⇒ JSI::Validation::Result
validates the given instance against this schema
713 714 715 716 717 718 719 720 721 722 |
# File 'lib/jsi/schema.rb', line 713 def instance_validate(instance) if instance.is_a?(SchemaAncestorNode) instance_ptr = instance.jsi_ptr instance_document = instance.jsi_document else instance_ptr = Ptr[] instance_document = instance end internal_validate_instance(instance_ptr, instance_document) end |
#jsi_schema_module ⇒ Module + SchemaModule
a module which extends all instances of this schema. this may be opened by the application to add methods to schema instances.
some functionality is also defined on the module itself (its singleton class, not for its instances):
- the module is extended with JSI::SchemaModule, which defines .new_jsi to instantiate instances of this schema (see #new_jsi).
- properties described by this schema's metaschema are defined as methods to get subschemas' schema
modules, so for example
schema.jsi_schema_module.items
returns the same module asschema.items.jsi_schema_module
. - method .schema which returns this schema.
517 518 519 |
# File 'lib/jsi/schema.rb', line 517 def jsi_schema_module JSI::SchemaClasses.module_for_schema(self) end |
#jsi_schema_module_exec(*a, **kw, &block) ⇒ Object
Evaluates the given block in the context of this schema's JSI schema module. Any arguments passed to this method will be passed to the block. shortcut to invoke Module#module_exec on our #jsi_schema_module.
527 528 529 |
# File 'lib/jsi/schema.rb', line 527 def jsi_schema_module_exec(*a, **kw, &block) jsi_schema_module.module_exec(*a, **kw, &block) end |
#jsi_subschema_resource_ancestors ⇒ Array<JSI::Schema>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
schema resources which are ancestors of any subschemas below this schema. this may include this schema if this is a schema resource root.
772 773 774 775 776 777 778 |
# File 'lib/jsi/schema.rb', line 772 def jsi_subschema_resource_ancestors if schema_resource_root? jsi_schema_resource_ancestors.dup.push(self).freeze else jsi_schema_resource_ancestors end end |
#keyword?(keyword) ⇒ Boolean
does this schema contain the given keyword?
437 438 439 440 |
# File 'lib/jsi/schema.rb', line 437 def keyword?(keyword) schema_content = jsi_node_content schema_content.respond_to?(:to_hash) && schema_content.key?(keyword) end |
#new_jsi(instance, **kw) ⇒ JSI::Base subclass
Instantiates a new JSI whose content comes from the given instance
param.
This schema indicates the schemas of the JSI - its schemas are inplace
applicators of this schema which apply to the given instance.
538 539 540 |
# File 'lib/jsi/schema.rb', line 538 def new_jsi(instance, **kw) SchemaSet[self].new_jsi(instance, **kw) end |
#resource_root_subschema(ptr) ⇒ JSI::Schema
a schema in the same schema resource as this one (see #schema_resource_root) at the given pointer relative to the root of the schema resource.
625 626 627 |
# File 'lib/jsi/schema.rb', line 625 def resource_root_subschema(ptr) @resource_root_subschema_map[ptr: Ptr.ary_ptr(ptr)] end |
#schema_absolute_uri ⇒ Addressable::URI?
the URI of this schema, calculated from our #id
, resolved against our #jsi_schema_base_uri
444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/jsi/schema.rb', line 444 def schema_absolute_uri if respond_to?(:id_without_fragment) && id_without_fragment if jsi_schema_base_uri jsi_schema_base_uri.join(id_without_fragment).freeze elsif id_without_fragment.absolute? id_without_fragment else # TODO warn / schema_error nil end end end |
#schema_content ⇒ Object
the underlying JSON data used to instantiate this JSI::Schema. this is an alias for Base#jsi_node_content, named for clarity in the context of working with a schema.
431 432 433 |
# File 'lib/jsi/schema.rb', line 431 def schema_content jsi_node_content end |
#schema_ref(keyword: "$ref") ⇒ Schema::Ref
544 545 546 547 |
# File 'lib/jsi/schema.rb', line 544 def schema_ref(keyword: "$ref") raise(ArgumentError, "keyword not present: #{keyword}") unless keyword?(keyword) @schema_ref_map[keyword: keyword, value: schema_content[keyword]] end |
#schema_resource_root ⇒ JSI::Base
a resource containing this schema.
if any parent, or this schema itself, is a schema with an absolute uri (see #schema_absolute_uri), the resource root is the closest schema with an absolute uri.
If no parent schema has an absolute uri, the schema_resource_root is the document's root node. In this case, the resource root may or may not be a schema itself.
596 597 598 |
# File 'lib/jsi/schema.rb', line 596 def schema_resource_root jsi_subschema_resource_ancestors.last || jsi_root_node end |
#schema_resource_root? ⇒ Boolean
is this schema the root of a schema resource?
602 603 604 |
# File 'lib/jsi/schema.rb', line 602 def schema_resource_root? jsi_ptr.root? || !!schema_absolute_uri end |
#schema_uri ⇒ Addressable::URI?
a nonrelative URI which refers to this schema. nil if no parent of this schema defines an id. see #schema_uris for all URIs known to refer to this schema.
461 462 463 |
# File 'lib/jsi/schema.rb', line 461 def schema_uri schema_uris.first end |
#schema_uris ⇒ Array<Addressable::URI>
nonrelative URIs (that is, absolute, but possibly with a fragment) which refer to this schema
467 468 469 |
# File 'lib/jsi/schema.rb', line 467 def schema_uris @schema_uris_map[] end |
#subschema(subptr) ⇒ JSI::Schema
a subschema of this Schema
610 611 612 |
# File 'lib/jsi/schema.rb', line 610 def subschema(subptr) @subschema_map[subptr: Ptr.ary_ptr(subptr)] end |