brujula 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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