module Nidyx::Parser
Public Instance Methods
@param schema [Hash] JSON Schema @param options [Hash] global application options @return [Hash] a Hash of ModelData objects
# File lib/nidyx/parser.rb, line 19 def parse(schema, options) # setup parser @class_prefix = options[:class_prefix] @options = options @schema = schema @models = {} # run model generation generate([], class_name(@class_prefix, nil)) @models end
Private Instance Methods
@param ref [String] reference in json pointer format @return [String] the class name of the object at the location of the ref
# File lib/nidyx/parser.rb, line 175 def class_name_from_ref(ref) class_name_from_path(@class_prefix, Nidyx::Pointer.new(ref).path, @schema) if ref end
Generates a Model
and adds it to the models array. @param path [Array] the path to an object in the schema @param name [String] raw model name
# File lib/nidyx/parser.rb, line 36 def generate(path, name) object = get_object(path) type = object[TYPE_KEY] if type == OBJECT_TYPE generate_object(path, name) elsif type == ARRAY_TYPE generate_top_level_array(path) elsif type.is_a?(Array) if type.include?(OBJECT_TYPE) raise UnsupportedSchemaError if type.include?(ARRAY_TYPE) generate_object(path, name) elsif type.include?(ARRAY_TYPE) generate_top_leve_array(path) else raise UnsupportedSchemaError; end else raise UnsupportedSchemaError; end end
# File lib/nidyx/parser.rb, line 58 def generate_object(path, name) @models[name] = model = Nidyx::Model.new(name) required_properties = get_object(path)[REQUIRED_KEY] properties_path = path + [PROPERTIES_KEY] get_object(properties_path).keys.each do |key| optional = is_optional?(key, required_properties) property_path = properties_path + [key] model.properties << generate_property(key, property_path, model, optional) end end
@param key [String] the key of the property in the JSON Schema @param path [Array] the path to the aforementioned object in the schema @param model [Property] the model that owns the property to be generated @param optional [Boolean] true if the property can be empty or null
# File lib/nidyx/parser.rb, line 78 def generate_property(key, path, model, optional) obj = resolve_reference(path) class_name = obj[DERIVED_NAME] if include_type?(obj, OBJECT_TYPE) && obj[PROPERTIES_KEY] model.dependencies << class_name elsif include_type?(obj, ARRAY_TYPE) obj[COLLECTION_TYPES_KEY] = resolve_array_refs(obj) model.dependencies += obj[COLLECTION_TYPES_KEY] end name = obj[NAME_OVERRIDE_KEY] || key property = Nidyx::Property.new(name, class_name, optional, obj) property.overriden_name = key if obj[NAME_OVERRIDE_KEY] property end
# File lib/nidyx/parser.rb, line 70 def generate_top_level_array(path) resolve_array_refs(get_object(path)) end
@param path [Array] the path to an object in the global schema @return [Hash] a object containing JSON schema
# File lib/nidyx/parser.rb, line 189 def get_object(path) object_at_path(path, @schema) end
@param type_obj [Array, String] the JSON Schema type @param type [String] a string type to test @param true if the string type is a valid type according type object
# File lib/nidyx/parser.rb, line 203 def include_type?(obj, type) type_obj = obj[TYPE_KEY] type_obj.is_a?(Array) ? type_obj.include?(type) : type_obj == type end
@param key [String] the id of a specific property @param required_keys [Array] an array of the required property keys @return true if the property is optional
# File lib/nidyx/parser.rb, line 196 def is_optional?(key, required_keys) !(required_keys && required_keys.include?(key)) end
Resolves any references buied in the ‘items` property of an array definition. Returns a list of collection types in the array. @param obj [Hash] the array property schema @return [Array] types contained in the array
# File lib/nidyx/parser.rb, line 136 def resolve_array_refs(obj) items = obj[ITEMS_KEY] case items when Array return resolve_items_array(items) when Hash # handle a nested any of key any_of = items[ANY_OF_KEY] return resolve_items_array(any_of) if any_of.is_a?(Array) resolve_reference_string(items[REF_KEY]) return [class_name_from_ref(items[REF_KEY])].compact else return [] end end
@param items [Array] an array of items @return [Array] types contained in the array
# File lib/nidyx/parser.rb, line 156 def resolve_items_array(items) types = [] items.each { |i| types << resolve_single_item(i) } types.compact end
Given a path, which could be at any part of a reference chain, resolve the immediate schema object. This means:
-
if there is an imediate ref, follow it
-
inherit any schema information from the parent reference chain
(unimplemented)
If we are at the end of a chain, do the following:
-
generate a model for this object if necessary
-
add ‘class_name` to the immediate object when appropriate
-
return the immediate object
@param path [Array] the path to an object in the schema @param parent [Hash, nil] the merged attributes of the parent reference chain @return [Hash] a modified schema object with inherited attributes from it’s parents.
# File lib/nidyx/parser.rb, line 112 def resolve_reference(path, parent = nil) obj = get_object(path) ref = obj[REF_KEY] # TODO: merge parent and obj into obj (destructive) # If we find an immediate reference, chase it and pass the immediate # object as a parent. return resolve_reference_string(ref) if ref # If we are dealing with an object, encode it's class name into the # schema and generate it's model if necessary. if include_type?(obj, OBJECT_TYPE) && obj[PROPERTIES_KEY] obj[DERIVED_NAME] = class_name_from_path(@class_prefix, path, @schema) generate(path, obj[DERIVED_NAME]) unless @models.has_key?(obj[DERIVED_NAME]) end obj end
Resolves a reference as a plain JSON Pointer
string. @param ref [String] reference in json pointer format @return [Hash] a modified schema object with inherited attributes from it’s parents.
# File lib/nidyx/parser.rb, line 183 def resolve_reference_string(ref) resolve_reference(Nidyx::Pointer.new(ref).path) if ref end
@param item [Hash] a single item return [Array] types for the single item
# File lib/nidyx/parser.rb, line 164 def resolve_single_item(item) if item[REF_KEY] resolve_reference_string(item[REF_KEY]) class_name_from_ref(item[REF_KEY]) elsif item[TYPE_KEY] item[TYPE_KEY] end end