Class: Genio::Parser::Format::JsonSchema

Inherits:
Base
  • Object
show all
Includes:
Logging
Defined in:
lib/genio/parser/format/json_schema.rb

Instance Attribute Summary

Attributes inherited from Base

#data_types, #endpoint, #enum_types, #files, #options, #services

Instance Method Summary collapse

Methods included from Logging

#logger

Methods inherited from Base

#expand_path, #initialize, #load_files, #open, #read_file, #to_iodocs

Constructor Details

This class inherits a constructor from Genio::Parser::Format::Base

Instance Method Details

#class_name(name) ⇒ Object

Format class name

Example

class_name("credit-card") # return "CreditCard"
class_name("/path/to/payment.json") # return "Payment"


177
178
179
# File 'lib/genio/parser/format/json_schema.rb', line 177

def class_name(name)
  File.basename(name.to_s.gsub(/\#$/, "").gsub(/-/, "_"), ".json").camelcase
end

#file_name(name) ⇒ Object

Fix file name format



182
183
184
# File 'lib/genio/parser/format/json_schema.rb', line 182

def file_name(name)
  name.to_s.gsub(/-/, "_").underscore
end

#fix_unknown_serviceObject

Map operations based on the Request or Response types.



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/genio/parser/format/json_schema.rb', line 187

def fix_unknown_service
  new_services = Types::Base.new
  services.each do |service_name, service|
    unless data_types[service_name]
      service.operations.each do |operation_name, operation|
        if data_types[operation.request]
          new_services[operation.request] ||= Types::Base.new( :operations => {} )
          new_services[operation.request].operations[operation_name] = operation
        elsif data_types[operation.response]
          new_services[operation.response] ||= Types::Base.new( :operations => {} )
          new_services[operation.response].operations[operation_name] = operation
        end
      end
    end
  end
  services.merge!(new_services)
end

#load(filename, force = false) ⇒ Object

Load schema

Example

schema.load("path/to/json_schema.json")
schema.load("http://example.com/json_schema.json")


13
14
15
16
17
18
19
20
21
22
# File 'lib/genio/parser/format/json_schema.rb', line 13

def load(filename, force = false)
  if data_types[filename] || (!force and data_types[class_name(filename)])
    class_name(filename)
  elsif files[filename]
    files[filename]
  else
    files[filename] = class_name(filename)
    parse_file(filename)
  end
end

#parse_file(filename) ⇒ Object

Parse Given schema file and return class name



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/genio/parser/format/json_schema.rb', line 25

def parse_file(filename)
  klass = class_name(filename)
  read_file(filename) do |data|
    data = JSON.parse(data, :object_class => Types::Base, :max_nesting => 100)
    if data.type == "object" or data.properties or data.type.is_a? Array   # Check the type is object or not.
      data_types[klass] = {}
      data_types[klass] = parse_object(data)
    elsif data.resources                          # Checkout the schema file contains the services or not
      parse_resource(data)
    end
  end
  klass
end

#parse_object(data) ⇒ Object

Parse object schema



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
# File 'lib/genio/parser/format/json_schema.rb', line 40

def parse_object(data)
  if data["$ref"]
    return self.data_types[self.load(data["$ref"], true)]
  end

  properties = Types::Base.new

  # Parse each properties
  if data.properties
    data.properties.each do |name, options|
      properties[name] = parse_property(name, options)
    end
  elsif data.type.is_a?(Array)
    data.type.each do |object|
      properties.merge!(parse_object(object).properties)
    end
  end

  # Load extends class.
  if data.extends.is_a? String
    data.extends = self.load(data.extends)
  else
    data.extends = nil
  end

  # Parse array type
  if data.items
    array_type = parse_object(data.items)
    properties.merge!(array_type.properties)
    data.extends ||= array_type.extends
    data.array = true
  end

  data.properties = properties
  Types::DataType.new(data)
end

#parse_property(name, data) ⇒ Object

Parse property.



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
# File 'lib/genio/parser/format/json_schema.rb', line 78

def parse_property(name, data)
  data.array = true if data.type == "array"
  data.type  =
    if data["$ref"]               # Check the type is refer to another schema or not
      self.load(data["$ref"])
    elsif data.additionalProperties and data.additionalProperties["$ref"]
      self.load(data.additionalProperties["$ref"])
    elsif data.properties # Check the type has object definition or not
      klass_name = class_name(name)
      data_types[klass_name] = parse_object(data)
      klass_name
    elsif data.type.is_a? Array
      data.union_types = data.type.map do |type|
        parse_object(type)
      end
      "object"
    elsif data.items              # Parse array value type
      array_property = parse_property(name, data.items)
      array_property.type
    else
      data.type                   # Simple type
    end
  Types::Property.new(data)
rescue => error
  logger.error error.message
  Types::Property.new
end

#parse_resource(data) ⇒ Object

Parse resource schema



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/genio/parser/format/json_schema.rb', line 107

def parse_resource(data)

  self.endpoint ||= data.rootUrl

  if data.schemas
    data.schemas.each do |name, options|
      data_types[class_name(name)] = true
    end
    data.schemas.each do |name, options|
      data_types[class_name(name)] = parse_object(options)
    end
  end

  parse_services(data.resources, data)
end

#parse_service(data, service) ⇒ Object

Parse each operation in service



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/genio/parser/format/json_schema.rb', line 136

def parse_service(data, service)
  data["methods"] ||= {}

  data["methods"].each do |name, options|
    options.relative_path = options.path
    options.path = File.join(service.servicePath, options.path)
    options.type = options.httpMethod
    if options.request
      options.request_property = parse_property("#{name}_request", options.request)
      options.request = options.request_property.type
    end
    if options.response
      options.response_property = parse_property("#{name}_response", options.response)
      options.response = options.response_property.type
    end
    # Load service parameters
    if options.parameters.nil? and options.type == "GET"
      options.parameters = service.parameters
    end
  end

  data.operations = data["methods"]

  parse_services(data.resources, service) if data.resources

  Types::Service.new(data)
end

#parse_services(resources, data) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/genio/parser/format/json_schema.rb', line 123

def parse_services(resources, data)
  # Parse Resources
  resources.each do |name, options|
    service = parse_service(options, data)
    service.path = File.join(data.servicePath, name)
    if services[class_name(name)]
      service.operations.merge!(services[class_name(name)].operations)
    end
    services[class_name(name)] = service
  end
end

#update_ref_paths(data, paths = {}) ⇒ Object

Update configured ref links



165
166
167
168
169
170
171
# File 'lib/genio/parser/format/json_schema.rb', line 165

def update_ref_paths(data, paths = {})
  paths.each do |path, replace_path|
    replace_path = replace_path.sub(/\/?$/, "/")
    data = data.gsub(/("\$ref"\s*:\s*")#{Regexp.escape(path)}\/?/, "\\1#{replace_path}")
  end
  data
end