Class: OpenAPIArrangement::Schema::Orderer

Inherits:
Object
  • Object
show all
Defined in:
lib/openapi/arrangement/schema.rb

Overview

Orders schemas according to given orderer. There is only one actual ordering method now.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, schema_specs) ⇒ Orderer

Returns a new instance of Orderer.



124
125
126
127
128
129
130
# File 'lib/openapi/arrangement/schema.rb', line 124

def initialize(path, schema_specs)
  @schemas = {}
  schema_specs.each do |name, schema|
    r = "#{path}#{name}"
    @schemas[r] = Info.new(r, name, schema)
  end
end

Instance Attribute Details

#orderObject

Returns the value of attribute order.



122
123
124
# File 'lib/openapi/arrangement/schema.rb', line 122

def order
  @order
end

#ordererObject

Returns the value of attribute orderer.



122
123
124
# File 'lib/openapi/arrangement/schema.rb', line 122

def orderer
  @orderer
end

#schemasObject

Returns the value of attribute schemas.



122
123
124
# File 'lib/openapi/arrangement/schema.rb', line 122

def schemas
  @schemas
end

Class Method Details

.var_or_method_value(x, name) ⇒ Object

Raises:

  • (ArgumentError)


206
207
208
209
210
211
# File 'lib/openapi/arrangement/schema.rb', line 206

def self.var_or_method_value(x, name)
  n = name.start_with?('@') ? name : "@#{name}"
  return x.instance_variable_get(n) if x.instance_variable_defined?(n)
  return x.public_send(name) if x.respond_to?(name)
  raise ArgumentError, "#{name} is not #{x.class} instance variable nor public method"
end

Instance Method Details

#count_comparison(optfwd, manfwd, optrem, manrem, si, best) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/openapi/arrangement/schema.rb', line 152

def count_comparison(optfwd, manfwd, optrem, manrem, si, best)
  # Fewer mandatory forwards is good because it leaves more room for implementation.
  return true if manfwd < best[1]
  if manfwd == best[1]
    return true if manrem < best[3]
    if manrem == best[3]
      return true if optfwd < best[0]
      if optfwd == best[0]
        return true if optrem < best[2]
        if optrem == best[2]
          best_req_si = best.last.direct_refs.fetch(si.ref, false)
          si_req_best = si.direct_refs.fetch(best.last.ref, false)
          return nil if best_req_si == si_req_best
          return !si_req_best
        end
      end
    end
  end
  false
end

#greedy_required_firstObject



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/openapi/arrangement/schema.rb', line 173

def greedy_required_first
  chosen = []
  until chosen.size == @schemas.size
    used = Set.new(chosen.map(&:ref))
    available = @schemas.values.reject { |si| used.member?(si.ref) }
    best = nil
    available.each do |si|
      # Optional forwards from chosen.
      optfwd = chosen.count { |x| !x.direct_refs.fetch(si.ref, false) && x.direct_refs.key?(si.ref) }
      # Mandatory forwards from chosen.
      manfwd = chosen.count { |x| x.direct_refs.fetch(si.ref, false) && x.direct_refs.key?(si.ref) }
      # Optional and mandatory references from si.
      opts = Set.new(si.direct_refs.keys.reject { |n| si.direct_refs[n] })
      mans = Set.new(si.direct_refs.keys.select { |n| si.direct_refs[n] })
      # Optional forwards to be added for si.
      optrem = (opts - used).size
      # Mandatory forwards to be added for si.
      manrem = (mans - used).size
      better = false
      if best.nil?
        better = true
      else
        better = count_comparison(optfwd, manfwd, optrem, manrem, si, best)
        # Order by name if equally good otherwise.
        better = si.name < best.last.name if better.nil?
      end
      best = [ optfwd, manfwd, optrem, manrem, si ] if better
    end
    chosen.push(best.last)
  end
  chosen
end

#sort!(orderer = 'greedy_required_first') ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/openapi/arrangement/schema.rb', line 132

def sort!(orderer = 'greedy_required_first')
  @orderer = orderer
  case orderer
  when 'greedy_required_first' then @order = greedy_required_first
  when '<=>' then @order = @schemas.values.sort { |a, b| a <=> b }
  else
    @order = @schemas.values.sort do |a, b|
      va = self.class.var_or_method_value(a, orderer)
      vb = self.class.var_or_method_value(b, orderer)
      va <=> vb
    end
  end
  seen = Set.new
  @order.each do |si|
    si.mark_as_seen(seen)
    seen.add(si.name)
  end
  @order
end