brujula 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +9 -0
  3. data/Gemfile +5 -0
  4. data/README.md +64 -0
  5. data/Rakefile +21 -0
  6. data/SPEC_SUPPORT.md +183 -0
  7. data/TODO.md +1 -0
  8. data/lib/brujula.rb +71 -0
  9. data/lib/brujula/basic_type.rb +46 -0
  10. data/lib/brujula/data_transformers/body_declaration.rb +39 -0
  11. data/lib/brujula/data_transformers/property_declaration.rb +28 -0
  12. data/lib/brujula/data_transformers/security_scheme_settings_declaration.rb +23 -0
  13. data/lib/brujula/initializers/inflecto_ramelize.rb +9 -0
  14. data/lib/brujula/initializers/yaml_include.rb +42 -0
  15. data/lib/brujula/key.rb +45 -0
  16. data/lib/brujula/map_object.rb +99 -0
  17. data/lib/brujula/mergers/map_object_merger.rb +78 -0
  18. data/lib/brujula/mergers/merger.rb +27 -0
  19. data/lib/brujula/mergers/object_merger.rb +41 -0
  20. data/lib/brujula/object.rb +40 -0
  21. data/lib/brujula/object_builder.rb +114 -0
  22. data/lib/brujula/object_parser.rb +65 -0
  23. data/lib/brujula/raml.rb +5 -0
  24. data/lib/brujula/raml/definition.rb +45 -0
  25. data/lib/brujula/raml/exceptions.rb +6 -0
  26. data/lib/brujula/raml/v1_0/array.rb +8 -0
  27. data/lib/brujula/raml/v1_0/base_uri_parameters.rb +9 -0
  28. data/lib/brujula/raml/v1_0/body.rb +9 -0
  29. data/lib/brujula/raml/v1_0/body_type.rb +9 -0
  30. data/lib/brujula/raml/v1_0/header.rb +9 -0
  31. data/lib/brujula/raml/v1_0/markdown.rb +8 -0
  32. data/lib/brujula/raml/v1_0/media_type.rb +8 -0
  33. data/lib/brujula/raml/v1_0/method.rb +22 -0
  34. data/lib/brujula/raml/v1_0/null_security_scheme.rb +8 -0
  35. data/lib/brujula/raml/v1_0/property.rb +34 -0
  36. data/lib/brujula/raml/v1_0/query_parameter.rb +9 -0
  37. data/lib/brujula/raml/v1_0/raml_type.rb +37 -0
  38. data/lib/brujula/raml/v1_0/resource.rb +19 -0
  39. data/lib/brujula/raml/v1_0/resource_type.rb +15 -0
  40. data/lib/brujula/raml/v1_0/response.rb +16 -0
  41. data/lib/brujula/raml/v1_0/root.rb +30 -0
  42. data/lib/brujula/raml/v1_0/security_scheme.rb +15 -0
  43. data/lib/brujula/raml/v1_0/security_scheme_part.rb +18 -0
  44. data/lib/brujula/raml/v1_0/security_scheme_settings.rb +24 -0
  45. data/lib/brujula/raml/v1_0/string.rb +8 -0
  46. data/lib/brujula/raml/v1_0/trait.rb +17 -0
  47. data/lib/brujula/raml/v1_0/uri_parameter.rb +9 -0
  48. data/lib/brujula/raml/v1_0/uri_template.rb +8 -0
  49. data/lib/brujula/scheme.rb +77 -0
  50. data/lib/brujula/type_extender/method.rb +29 -0
  51. data/lib/brujula/type_extender/resource.rb +52 -0
  52. data/lib/brujula/type_extender/resource_type.rb +36 -0
  53. data/lib/brujula/version.rb +3 -0
  54. data/lib/brujula/yaml_parser.rb +67 -0
  55. metadata +224 -0
@@ -0,0 +1,28 @@
1
+ module Brujula
2
+ module DataTransformers
3
+ class PropertyDeclaration
4
+ class << self
5
+ def call(*args)
6
+ new(*args).call
7
+ end
8
+ end
9
+
10
+ attr_reader :data, :parent
11
+
12
+ def initialize(parent, data)
13
+ @parent = parent
14
+ @data = data
15
+ end
16
+
17
+ def call
18
+ data.each_with_object({}) do |(key, property), object|
19
+ if property.is_a?(String) # data as type
20
+ object.merge!(key => { "type" => property })
21
+ else
22
+ object.merge!(key => property)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module Brujula
2
+ module DataTransformers
3
+ class SecuritySchemeSettingsDeclaration
4
+ class << self
5
+ def call(*args)
6
+ new(*args).call
7
+ end
8
+ end
9
+
10
+ attr_reader :data, :parent
11
+
12
+ def initialize(parent, data)
13
+ @parent = parent
14
+ @data = data
15
+ end
16
+
17
+ # Add the type from the parent and carry on
18
+ def call
19
+ data.merge("type" => parent.type)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Inflecto
2
+ class << self
3
+ def ramelize(string)
4
+ camelize(string).tap do |string|
5
+ string[0] = string[0].downcase
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ require 'yaml'
2
+
3
+ # stolen from https://github.com/coub/raml_ruby/
4
+ module Brujula
5
+ class YamlInclude
6
+ attr_reader :path
7
+
8
+ def init_with(coder)
9
+ @path = coder.scalar
10
+ end
11
+
12
+ def load_external_data(base_dir)
13
+ YAML.load external_data_content(base_dir)
14
+ end
15
+
16
+ def parseable?
17
+ parseable_extensions.include?(path_extension)
18
+ end
19
+
20
+ private
21
+
22
+ def external_data_content(base_dir)
23
+ File.read(external_data_path(base_dir))
24
+ end
25
+
26
+ def external_data_path(base_dir)
27
+ return path if path.start_with?('/') # absolute path reference
28
+
29
+ File.join(base_dir, path)
30
+ end
31
+
32
+ def path_extension
33
+ File.extname(path)
34
+ end
35
+
36
+ def parseable_extensions
37
+ %w( .yaml .yml .raml )
38
+ end
39
+ end
40
+ end
41
+
42
+ YAML.add_tag '!include', Brujula::YamlInclude
@@ -0,0 +1,45 @@
1
+ module Brujula
2
+ class Key
3
+ attr_reader :expression, :required, :options, :for_types, :referrable,
4
+ :data_transformer, :name
5
+
6
+ alias_method :required?, :required
7
+ alias_method :referrable?, :referrable
8
+
9
+ def initialize(expression, options)
10
+ @expression = expression
11
+ @name = expression.to_s
12
+ @options = options
13
+ @required = !!options[:required]
14
+ @referrable = !!options[:referrable]
15
+ @for_types = options[:for_types] || []
16
+ @data_transformer = options[:data_transformer]
17
+ end
18
+
19
+ def accessor_name
20
+ options[:accessor] || expression
21
+ end
22
+
23
+ def fixed?
24
+ expression.is_a?(Symbol)
25
+ end
26
+
27
+ def matches?(key_name)
28
+ !(expression =~ key_name).nil?
29
+ end
30
+
31
+ def valid_for_type?(type)
32
+ return true if for_types.empty?
33
+
34
+ for_types.include?(type)
35
+ end
36
+
37
+ def basic_type?
38
+ basic_types.include?(options[:as])
39
+ end
40
+
41
+ def basic_types
42
+ %i( any array boolean markdown media_type number string uri_template )
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,99 @@
1
+ module Brujula
2
+ class MapObject
3
+ include Enumerable
4
+
5
+ attr_reader :parent, :name, :child_class
6
+
7
+ def initialize(data:, parent: nil, name:, child_class:)
8
+ @parent = parent
9
+ @name = name
10
+ @child_class = child_class
11
+ @collection = {}
12
+ each_flatted_child(data) do |child_name, child_data|
13
+ child_object = build_object(child_name, child_data)
14
+
15
+ @collection.merge!(child_name.to_s => child_object)
16
+ end
17
+ end
18
+
19
+ def key?(key)
20
+ @collection.key?(key.to_s)
21
+ end
22
+
23
+ def [](key)
24
+ @collection.fetch(key.to_s, nil)
25
+ end
26
+
27
+ def fetch(key)
28
+ @collection.fetch(key.to_s)
29
+ rescue KeyError => error
30
+ $stderr.puts "Couldn't find item #{ key } in collection #{ name }"
31
+ raise error
32
+ end
33
+
34
+ def merge(key, value)
35
+ @collection.merge!(key.to_s => value)
36
+ end
37
+
38
+ def each
39
+ @collection.values.each { |item| yield item }
40
+ end
41
+
42
+ def expand
43
+ self
44
+ end
45
+
46
+ private
47
+
48
+ def build_object(name, data)
49
+ child_data = normalize_child_data(data)
50
+ options = { data: child_data, name: name, parent: self }
51
+ object = child_klass.new(options)
52
+ apply_inheritance(object)
53
+ end
54
+
55
+ def child_klass
56
+ Brujula::Raml::V1_0.const_get(Inflecto.camelize(child_class))
57
+ end
58
+
59
+ def normalize_child_data(data)
60
+ return data unless data.is_a?(Brujula::YamlInclude)
61
+
62
+ data.load_external_data(parent.root.base_dir)
63
+ end
64
+
65
+ def apply_inheritance(child)
66
+ case child
67
+ when Brujula::Raml::V1_0::Resource
68
+ Brujula::TypeExtender::Resource.new(definition: child).call
69
+ when Brujula::Raml::V1_0::Method
70
+ Brujula::TypeExtender::Method.new(definition: child).call
71
+ when Brujula::Raml::V1_0::ResourceType
72
+ Brujula::TypeExtender::ResourceType.new(definition: child).call
73
+ else
74
+ child
75
+ end
76
+ end
77
+
78
+ def each_flatted_child(data)
79
+ flatten_children(data).each do |child_name, child_data|
80
+ yield child_name, child_data
81
+ end
82
+ end
83
+
84
+ def flatten_children(data)
85
+ case data
86
+ when Array
87
+ data.each_with_object({}) do |child, children|
88
+ child.each do |key, value|
89
+ children.merge!(key => value)
90
+ end
91
+ end
92
+ when Hash
93
+ data
94
+ else
95
+ raise 'Invalid data for map_object'
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,78 @@
1
+ module Brujula
2
+ module Mergers
3
+ class MapObjectMerger
4
+ attr_reader :superinstance, :instance
5
+
6
+ def initialize(instance:, superinstance:)
7
+ @superinstance = superinstance
8
+ @instance = instance
9
+ end
10
+
11
+ def call
12
+ return superinstance.dup if instance.nil?
13
+
14
+ instance.dup.tap do |extended_instance|
15
+ each_inheritable_items do |inherit_item|
16
+ extended_instance.merge(inherit_item.name, inherit_item)
17
+ end
18
+ end
19
+ end
20
+
21
+ def each_inheritable_items
22
+ superinstance.each do |inherit_item|
23
+
24
+ merge_item = case item_reference(inherit_item.name)
25
+ when :optional_to_optional
26
+ instance.fetch(inherit_item.name)
27
+ when :optional
28
+ instance.fetch(inherit_item.name.gsub(/\?$/, ''))
29
+ when :direct
30
+ instance.key?(inherit_item.name) ?
31
+ instance.fetch(inherit_item.name) : nil
32
+ else
33
+ next
34
+ end
35
+
36
+ yield merger(merge_item, inherit_item)
37
+ end
38
+ end
39
+
40
+ def merger(merge_item, inherit_item)
41
+ Merger.new(instance: merge_item, superinstance: inherit_item).call
42
+ end
43
+
44
+ def item_reference(key)
45
+ case
46
+ when optional_key?(key) && instance_has_optional_item?(key)
47
+ :optional_to_optional
48
+ when optional_key?(key) && instance_has_item?(key)
49
+ :optional
50
+ when !optional_key?(key)
51
+ :direct
52
+ end
53
+ end
54
+
55
+ def merge_item?(key)
56
+ return true unless optional_key?(key)
57
+
58
+ instance_has_item?(key) || instance_has_optional_item?(key)
59
+ end
60
+
61
+ def optional_key?(key)
62
+ key.to_s.end_with?('?')
63
+ end
64
+
65
+ def instance_has_item?(key)
66
+ item_names.include?(key.gsub(/\?$/, ''))
67
+ end
68
+
69
+ def instance_has_optional_item?(key)
70
+ item_names.include?(key)
71
+ end
72
+
73
+ def item_names
74
+ @item_names ||= instance.to_a.map(&:name)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,27 @@
1
+ module Brujula
2
+ module Mergers
3
+ class Merger
4
+ attr_reader :superinstance, :instance
5
+
6
+ def initialize(instance:, superinstance:)
7
+ @superinstance = superinstance
8
+ @instance = instance
9
+ end
10
+
11
+ def call
12
+ case
13
+ when superinstance.is_a?(Brujula::MapObject)
14
+ MapObjectMerger.new(
15
+ instance: instance, superinstance: superinstance
16
+ ).call
17
+ when superinstance.is_a?(Brujula::Object)
18
+ ObjectMerger.new(
19
+ instance: instance, superinstance: superinstance
20
+ ).call
21
+ else
22
+ superinstance.dup
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ module Brujula
2
+ module Mergers
3
+ class ObjectMerger
4
+ attr_reader :superinstance, :instance
5
+
6
+ def initialize(instance:, superinstance:)
7
+ @superinstance = superinstance
8
+ @instance = instance
9
+ end
10
+
11
+ def call
12
+ return superinstance.dup if instance.nil?
13
+ instance.dup.tap do |object|
14
+ each_inheritable_attributes do |name, attribute|
15
+ original_item = object.instance_variable_get("@#{ name }")
16
+ thing = Merger.new(
17
+ instance: original_item, superinstance: attribute
18
+ ).call
19
+ object.instance_variable_set("@#{ name }", thing)
20
+ end
21
+ end
22
+ end
23
+
24
+ def each_inheritable_attributes
25
+ applicable_attributes.each do |name|
26
+ next if superinstance.instance_variable_get(name).nil?
27
+ string_name = name.to_s.gsub(/^@/, '')
28
+ yield(string_name, superinstance.instance_variable_get(name))
29
+ end
30
+ end
31
+
32
+ def applicable_attributes
33
+ superinstance.instance_variables - excluded_attributes
34
+ end
35
+
36
+ def excluded_attributes
37
+ %i( @parent @name @type )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ module Brujula
2
+ class Object
3
+ attr_reader :name
4
+
5
+ class << self
6
+ attr_reader :scheme, :block
7
+
8
+ def scheme(options = {}, &block) # TODO
9
+ return @scheme unless @scheme.nil?
10
+
11
+ if block_given?
12
+ @block = block
13
+ @scheme = Brujula::Scheme.new(self, options, block)
14
+ else
15
+ @scheme = Brujula::Scheme.new(self, options)
16
+ end
17
+ end
18
+ end
19
+
20
+ def initialize(data:, parent: nil, name:)
21
+ @name = name
22
+ define_singleton_method(:raw_data) { data }
23
+ define_singleton_method(:parent) { parent }
24
+
25
+ Brujula::ObjectParser.call(definition: self, data: data, parent: parent)
26
+ end
27
+
28
+ def expand # TODO
29
+ @representation || self
30
+ end
31
+
32
+ def root
33
+ object = self
34
+ until object.is_a? Brujula::Raml::V1_0::Root
35
+ object = object.parent
36
+ end
37
+ object
38
+ end
39
+ end
40
+ end