Class: ElasticGraph::SchemaDefinition::Indexing::FieldType::Object Private

Inherits:
Object
  • Object
show all
Defined in:
elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Responsible for the JSON schema and mapping of a SchemaElements::ObjectType.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#json_schema_optionsHash<String, ::Object> (readonly)

Returns options to be included in the JSON schema.

Returns:

  • (Hash<String, ::Object>)

    options to be included in the JSON schema



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 29

class Object < Support::MemoizableData.define(:type_name, :subfields, :mapping_options, :json_schema_options)
  # @return [Hash<String, ::Object>] the datastore mapping for this object type.
  def to_mapping
    @to_mapping ||= begin
      base_mapping = Field.normalized_mapping_hash_for(subfields)
      # When a custom mapping type is used, we need to omit `properties`, because custom mapping
      # types generally don't use `properties` (and if you need to use `properties` with a custom
      # type, you're responsible for defining the properties).
      base_mapping = base_mapping.except("properties") if (mapping_options[:type] || "object") != "object"
      base_mapping.merge(Support::HashUtil.stringify_keys(mapping_options))
    end
  end

  # @return [Hash<String, ::Object>] the JSON schema for this object type.
  def to_json_schema
    @to_json_schema ||=
      if json_schema_options.empty?
        # Fields that are `sourced_from` an alternate type must not be included in this types JSON schema,
        # since events of this type won't include them.
        other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
        validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
        json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)

        {
          "type" => "object",
          "properties" => json_schema_subfields.to_h { |f| [f.name, f.json_schema] }.merge(json_schema_typename_field),
          # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
          # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
          # to require it in the context of a union type. The union's json schema requires the field.
          "required" => json_schema_subfields.map(&:name).freeze
        }.freeze
      else
        Support::HashUtil.stringify_keys(json_schema_options)
      end
  end

  # @return [Hash<String, ::Object>] additional ElasticGraph metadata to put in the JSON schema for this object type.
  def 
    subfields.to_h { |f| [f.name, f.] }
  end

  # @param customizations [Hash<String, ::Object>] JSON schema customizations
  # @return [Hash<String, ::Object>] formatted customizations.
  def format_field_json_schema_customizations(customizations)
    customizations
  end

  private

  def after_initialize
    subfields.freeze
  end

  # Returns a __typename property which we use for union types.
  #
  # This must always be set to the name of the type (thus the const value).
  #
  # We also add a "default" value. This does not impact validation, but rather
  # aids tools like our kotlin codegen to save publishers from having to set the
  # property explicitly when creating events.
  def json_schema_typename_field
    {
      "__typename" => {
        "type" => "string",
        "const" => type_name,
        "default" => type_name
      }
    }
  end

  def validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
    problem_fields = other_source_subfields.reject { |f| f.json_schema_customizations.empty? }
    return if problem_fields.empty?

    field_descriptions = problem_fields.map(&:name).sort.map { |f| "`#{f}`" }.join(", ")
    raise Errors::SchemaError,
      "`#{type_name}` has #{problem_fields.size} field(s) (#{field_descriptions}) that are `sourced_from` " \
      "another type and also have JSON schema customizations. Instead, put the JSON schema " \
      "customizations on the source type's field definitions."
  end
end

#mapping_optionsHash<String, ::Object> (readonly)

Returns options to be included in the mapping.

Returns:

  • (Hash<String, ::Object>)

    options to be included in the mapping



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 29

class Object < Support::MemoizableData.define(:type_name, :subfields, :mapping_options, :json_schema_options)
  # @return [Hash<String, ::Object>] the datastore mapping for this object type.
  def to_mapping
    @to_mapping ||= begin
      base_mapping = Field.normalized_mapping_hash_for(subfields)
      # When a custom mapping type is used, we need to omit `properties`, because custom mapping
      # types generally don't use `properties` (and if you need to use `properties` with a custom
      # type, you're responsible for defining the properties).
      base_mapping = base_mapping.except("properties") if (mapping_options[:type] || "object") != "object"
      base_mapping.merge(Support::HashUtil.stringify_keys(mapping_options))
    end
  end

  # @return [Hash<String, ::Object>] the JSON schema for this object type.
  def to_json_schema
    @to_json_schema ||=
      if json_schema_options.empty?
        # Fields that are `sourced_from` an alternate type must not be included in this types JSON schema,
        # since events of this type won't include them.
        other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
        validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
        json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)

        {
          "type" => "object",
          "properties" => json_schema_subfields.to_h { |f| [f.name, f.json_schema] }.merge(json_schema_typename_field),
          # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
          # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
          # to require it in the context of a union type. The union's json schema requires the field.
          "required" => json_schema_subfields.map(&:name).freeze
        }.freeze
      else
        Support::HashUtil.stringify_keys(json_schema_options)
      end
  end

  # @return [Hash<String, ::Object>] additional ElasticGraph metadata to put in the JSON schema for this object type.
  def 
    subfields.to_h { |f| [f.name, f.] }
  end

  # @param customizations [Hash<String, ::Object>] JSON schema customizations
  # @return [Hash<String, ::Object>] formatted customizations.
  def format_field_json_schema_customizations(customizations)
    customizations
  end

  private

  def after_initialize
    subfields.freeze
  end

  # Returns a __typename property which we use for union types.
  #
  # This must always be set to the name of the type (thus the const value).
  #
  # We also add a "default" value. This does not impact validation, but rather
  # aids tools like our kotlin codegen to save publishers from having to set the
  # property explicitly when creating events.
  def json_schema_typename_field
    {
      "__typename" => {
        "type" => "string",
        "const" => type_name,
        "default" => type_name
      }
    }
  end

  def validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
    problem_fields = other_source_subfields.reject { |f| f.json_schema_customizations.empty? }
    return if problem_fields.empty?

    field_descriptions = problem_fields.map(&:name).sort.map { |f| "`#{f}`" }.join(", ")
    raise Errors::SchemaError,
      "`#{type_name}` has #{problem_fields.size} field(s) (#{field_descriptions}) that are `sourced_from` " \
      "another type and also have JSON schema customizations. Instead, put the JSON schema " \
      "customizations on the source type's field definitions."
  end
end

#subfieldsArray<Field> (readonly)

Returns the subfields of this object type.

Returns:

  • (Array<Field>)

    the subfields of this object type



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 29

class Object < Support::MemoizableData.define(:type_name, :subfields, :mapping_options, :json_schema_options)
  # @return [Hash<String, ::Object>] the datastore mapping for this object type.
  def to_mapping
    @to_mapping ||= begin
      base_mapping = Field.normalized_mapping_hash_for(subfields)
      # When a custom mapping type is used, we need to omit `properties`, because custom mapping
      # types generally don't use `properties` (and if you need to use `properties` with a custom
      # type, you're responsible for defining the properties).
      base_mapping = base_mapping.except("properties") if (mapping_options[:type] || "object") != "object"
      base_mapping.merge(Support::HashUtil.stringify_keys(mapping_options))
    end
  end

  # @return [Hash<String, ::Object>] the JSON schema for this object type.
  def to_json_schema
    @to_json_schema ||=
      if json_schema_options.empty?
        # Fields that are `sourced_from` an alternate type must not be included in this types JSON schema,
        # since events of this type won't include them.
        other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
        validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
        json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)

        {
          "type" => "object",
          "properties" => json_schema_subfields.to_h { |f| [f.name, f.json_schema] }.merge(json_schema_typename_field),
          # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
          # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
          # to require it in the context of a union type. The union's json schema requires the field.
          "required" => json_schema_subfields.map(&:name).freeze
        }.freeze
      else
        Support::HashUtil.stringify_keys(json_schema_options)
      end
  end

  # @return [Hash<String, ::Object>] additional ElasticGraph metadata to put in the JSON schema for this object type.
  def 
    subfields.to_h { |f| [f.name, f.] }
  end

  # @param customizations [Hash<String, ::Object>] JSON schema customizations
  # @return [Hash<String, ::Object>] formatted customizations.
  def format_field_json_schema_customizations(customizations)
    customizations
  end

  private

  def after_initialize
    subfields.freeze
  end

  # Returns a __typename property which we use for union types.
  #
  # This must always be set to the name of the type (thus the const value).
  #
  # We also add a "default" value. This does not impact validation, but rather
  # aids tools like our kotlin codegen to save publishers from having to set the
  # property explicitly when creating events.
  def json_schema_typename_field
    {
      "__typename" => {
        "type" => "string",
        "const" => type_name,
        "default" => type_name
      }
    }
  end

  def validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
    problem_fields = other_source_subfields.reject { |f| f.json_schema_customizations.empty? }
    return if problem_fields.empty?

    field_descriptions = problem_fields.map(&:name).sort.map { |f| "`#{f}`" }.join(", ")
    raise Errors::SchemaError,
      "`#{type_name}` has #{problem_fields.size} field(s) (#{field_descriptions}) that are `sourced_from` " \
      "another type and also have JSON schema customizations. Instead, put the JSON schema " \
      "customizations on the source type's field definitions."
  end
end

#type_nameString (readonly)

Returns name of the object type.

Returns:

  • (String)

    name of the object type



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 29

class Object < Support::MemoizableData.define(:type_name, :subfields, :mapping_options, :json_schema_options)
  # @return [Hash<String, ::Object>] the datastore mapping for this object type.
  def to_mapping
    @to_mapping ||= begin
      base_mapping = Field.normalized_mapping_hash_for(subfields)
      # When a custom mapping type is used, we need to omit `properties`, because custom mapping
      # types generally don't use `properties` (and if you need to use `properties` with a custom
      # type, you're responsible for defining the properties).
      base_mapping = base_mapping.except("properties") if (mapping_options[:type] || "object") != "object"
      base_mapping.merge(Support::HashUtil.stringify_keys(mapping_options))
    end
  end

  # @return [Hash<String, ::Object>] the JSON schema for this object type.
  def to_json_schema
    @to_json_schema ||=
      if json_schema_options.empty?
        # Fields that are `sourced_from` an alternate type must not be included in this types JSON schema,
        # since events of this type won't include them.
        other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
        validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
        json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)

        {
          "type" => "object",
          "properties" => json_schema_subfields.to_h { |f| [f.name, f.json_schema] }.merge(json_schema_typename_field),
          # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
          # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
          # to require it in the context of a union type. The union's json schema requires the field.
          "required" => json_schema_subfields.map(&:name).freeze
        }.freeze
      else
        Support::HashUtil.stringify_keys(json_schema_options)
      end
  end

  # @return [Hash<String, ::Object>] additional ElasticGraph metadata to put in the JSON schema for this object type.
  def 
    subfields.to_h { |f| [f.name, f.] }
  end

  # @param customizations [Hash<String, ::Object>] JSON schema customizations
  # @return [Hash<String, ::Object>] formatted customizations.
  def format_field_json_schema_customizations(customizations)
    customizations
  end

  private

  def after_initialize
    subfields.freeze
  end

  # Returns a __typename property which we use for union types.
  #
  # This must always be set to the name of the type (thus the const value).
  #
  # We also add a "default" value. This does not impact validation, but rather
  # aids tools like our kotlin codegen to save publishers from having to set the
  # property explicitly when creating events.
  def json_schema_typename_field
    {
      "__typename" => {
        "type" => "string",
        "const" => type_name,
        "default" => type_name
      }
    }
  end

  def validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
    problem_fields = other_source_subfields.reject { |f| f.json_schema_customizations.empty? }
    return if problem_fields.empty?

    field_descriptions = problem_fields.map(&:name).sort.map { |f| "`#{f}`" }.join(", ")
    raise Errors::SchemaError,
      "`#{type_name}` has #{problem_fields.size} field(s) (#{field_descriptions}) that are `sourced_from` " \
      "another type and also have JSON schema customizations. Instead, put the JSON schema " \
      "customizations on the source type's field definitions."
  end
end

Instance Method Details

#format_field_json_schema_customizations(customizations) ⇒ Hash<String, ::Object>

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.

Returns formatted customizations.

Parameters:

  • customizations (Hash<String, ::Object>)

    JSON schema customizations

Returns:

  • (Hash<String, ::Object>)

    formatted customizations.



72
73
74
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 72

def format_field_json_schema_customizations(customizations)
  customizations
end

#json_schema_field_metadata_by_field_nameHash<String, ::Object>

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.

Returns additional ElasticGraph metadata to put in the JSON schema for this object type.

Returns:

  • (Hash<String, ::Object>)

    additional ElasticGraph metadata to put in the JSON schema for this object type.



66
67
68
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 66

def 
  subfields.to_h { |f| [f.name, f.] }
end

#to_json_schemaHash<String, ::Object>

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.

Returns the JSON schema for this object type.

Returns:

  • (Hash<String, ::Object>)

    the JSON schema for this object type.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 43

def to_json_schema
  @to_json_schema ||=
    if json_schema_options.empty?
      # Fields that are `sourced_from` an alternate type must not be included in this types JSON schema,
      # since events of this type won't include them.
      other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
      validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
      json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)

      {
        "type" => "object",
        "properties" => json_schema_subfields.to_h { |f| [f.name, f.json_schema] }.merge(json_schema_typename_field),
        # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
        # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
        # to require it in the context of a union type. The union's json schema requires the field.
        "required" => json_schema_subfields.map(&:name).freeze
      }.freeze
    else
      Support::HashUtil.stringify_keys(json_schema_options)
    end
end

#to_mappingHash<String, ::Object>

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.

Returns the datastore mapping for this object type.

Returns:

  • (Hash<String, ::Object>)

    the datastore mapping for this object type.



31
32
33
34
35
36
37
38
39
40
# File 'elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/field_type/object.rb', line 31

def to_mapping
  @to_mapping ||= begin
    base_mapping = Field.normalized_mapping_hash_for(subfields)
    # When a custom mapping type is used, we need to omit `properties`, because custom mapping
    # types generally don't use `properties` (and if you need to use `properties` with a custom
    # type, you're responsible for defining the properties).
    base_mapping = base_mapping.except("properties") if (mapping_options[:type] || "object") != "object"
    base_mapping.merge(Support::HashUtil.stringify_keys(mapping_options))
  end
end