11# frozen_string_literal: true
22
3- require 'json '
3+ require_relative 'documents '
44
55module Smithy
66 module Schema
77 # TODO: need to address the following and more
88 # * documentation
9- # * some json considerations like timestamp, jsonName trait etc
10- # * handle union stuffs
119 class Document
10+ include Documents
1211 def initialize ( data , schema = nil )
13- @data = format_data ( data , schema ) # ruby obj to make it easy to work with
14- @discriminator = schema ? extract_discriminator ( data , schema ) : nil
12+ @data = format_data ( data , schema )
13+ @discriminator = Extractor . discriminator ( data , schema )
14+ @schema = schema
1515 end
1616
17- attr_reader :data , :discriminator
18-
19- # if discriminator is set, add discriminator being generating
20- def as_json
21- JSON . generate ( @data , allow_nan : true ) # do we want to allow this?
22- end
17+ attr_reader :data , :discriminator , :schema
2318
2419 def []( key )
2520 return unless @data . is_a? ( Hash ) && @data . key? ( key )
2621
2722 @data [ key ]
2823 end
2924
30- # expected schema here is a shape that has a type representation
3125 def as_typed ( schema )
32- # ensures that given schema has a type representation and
3326 error_message = 'Invalid schema or document data'
3427 raise ArgumentError , error_message unless valid_schema? ( schema ) && @data . is_a? ( Hash )
3528
3629 type = schema . type . new
37- apply_data ( schema , @data , type )
30+ Applier . apply ( schema , @data , type )
3831 end
3932
4033 private
4134
42- def apply_data ( schema , data , type = nil )
43- case schema
44- when Shapes ::StructureShape then apply_structure ( schema , data , type )
45- # when Shapes::UnionShape then union(shape, value, type)
46- when Shapes ::ListShape then apply_list ( schema , data )
47- when Shapes ::MapShape then apply_map ( schema , data )
48- else data
49- end
50- end
51-
52- def apply_structure ( schema , data , type )
53- type = schema . type . new if type . nil?
54- data . each do |k , v |
55- next if ( name = resolve_member_name ( schema , k ) ) . nil?
56-
57- type [ name ] = apply_data ( schema . member ( name ) . shape , v )
58- end
59- type
60- end
61-
62- def resolve_member_name ( schema , key )
63- return unless schema . name_by_member_name? ( key ) || schema . member? ( key . to_sym )
64-
65- schema . name_by_member_name ( key ) || key . to_sym
66- end
67-
68- def apply_list ( schema , data )
69- data . map do |v |
70- next if v . nil?
71-
72- apply_data ( schema . member . shape , v )
73- end
74- end
75-
76- def apply_map ( schema , data )
77- data . each_with_object ( { } ) do |( k , v ) , h |
78- h [ k . to_s ] =
79- if v . nil?
80- nil
81- else
82- apply_data ( schema . value . shape , v )
83- end
84- end
85- end
86-
87- def valid_schema? ( schema )
88- schema . is_a? ( Shapes ::StructureShape ) && !schema . type . nil?
89- end
90-
9135 def discriminator? ( data )
9236 data . is_a? ( Hash ) && data . key? ( '__type' )
9337 end
@@ -96,63 +40,20 @@ def format_data(data, schema)
9640 return if data . nil?
9741
9842 case data
99- when Smithy ::Schema ::Structure # indicates that this is a runtime shape
43+ when Smithy ::Schema ::Structure
10044 if schema . nil? || !schema . is_a? ( Shapes ::StructureShape )
10145 raise ArgumentError , 'Unable to convert as document with given schema'
10246 end
10347
104- extract_data ( schema , data )
48+ Extractor . extract ( schema , data )
10549 else
106- data
107- end
108- end
109-
110- # handle timestamp, union, number?
111- def extract_data ( schema , data )
112- return nil if data . nil?
113-
114- case schema
115- when Shapes ::StructureShape then extract_structure ( schema , data )
116- when Shapes ::ListShape then extract_list ( schema , data )
117- when Shapes ::MapShape then extract_map ( schema , data )
118- when Shapes ::BlobShape then extract_blob ( data )
119- else data
120- end
121- end
122-
123- def extract_structure ( schema , data )
124- data . to_h . each_with_object ( { } ) do |( k , v ) , o |
125- next unless schema . member? ( k )
126-
127- member_shape = schema . member ( k )
128- o [ member_shape . name ] = extract_data ( member_shape . shape , v )
129- end
130- end
131-
132- def extract_list ( schema , data )
133- data . collect { |value | extract_data ( schema . member . shape , value ) }
134- end
135-
136- def extract_map ( schema , data )
137- data . each . with_object ( { } ) do |( k , v ) , h |
138- h [ k . to_s ] = extract_data ( schema . value . shape , v )
50+ data = data . except ( '__type' ) if discriminator? ( data )
51+ data # TODO: add some validation if schema exists
13952 end
14053 end
14154
142- def extract_blob ( data )
143- Base64 . strict_encode64 ( data . is_a? ( String ) ? data : data . read )
144- end
145-
146- def extract_discriminator ( data , schema )
147- return if data . nil?
148-
149- if discriminator? ( data )
150- data [ '__type' ]
151- elsif schema
152- raise "Expected a structure schema, given #{ schema } instead" unless schema . is_a? ( Shapes ::Shape )
153-
154- schema . id
155- end
55+ def valid_schema? ( schema )
56+ schema . is_a? ( Shapes ::StructureShape ) && !schema . type . nil?
15657 end
15758 end
15859 end
0 commit comments