burlap 1.0.0

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +38 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +16 -0
  9. data/Rakefile +31 -0
  10. data/burlap.gemspec +32 -0
  11. data/lib/active_support/ordered_hash.rb +179 -0
  12. data/lib/burlap/array.rb +18 -0
  13. data/lib/burlap/base_tag.rb +105 -0
  14. data/lib/burlap/call.rb +38 -0
  15. data/lib/burlap/core_ext/array.rb +7 -0
  16. data/lib/burlap/core_ext/boolean.rb +11 -0
  17. data/lib/burlap/core_ext/float.rb +5 -0
  18. data/lib/burlap/core_ext/hash.rb +5 -0
  19. data/lib/burlap/core_ext/integer.rb +10 -0
  20. data/lib/burlap/core_ext/nil.rb +5 -0
  21. data/lib/burlap/core_ext/object.rb +13 -0
  22. data/lib/burlap/core_ext/string.rb +5 -0
  23. data/lib/burlap/core_ext/symbol.rb +6 -0
  24. data/lib/burlap/core_ext/time.rb +5 -0
  25. data/lib/burlap/core_ext.rb +10 -0
  26. data/lib/burlap/default_resolver.rb +100 -0
  27. data/lib/burlap/error.rb +3 -0
  28. data/lib/burlap/fault.rb +6 -0
  29. data/lib/burlap/hash.rb +72 -0
  30. data/lib/burlap/listener.rb +34 -0
  31. data/lib/burlap/node.rb +48 -0
  32. data/lib/burlap/version.rb +3 -0
  33. data/lib/burlap.rb +47 -0
  34. data/lib/core_ext/time_burlap_iso8601.rb +32 -0
  35. data/spec/burlap/array_spec.rb +28 -0
  36. data/spec/burlap/call_spec.rb +126 -0
  37. data/spec/burlap/core_ext/array_spec.rb +123 -0
  38. data/spec/burlap/core_ext/class_spec.rb +24 -0
  39. data/spec/burlap/core_ext/false_class_spec.rb +17 -0
  40. data/spec/burlap/core_ext/float_spec.rb +15 -0
  41. data/spec/burlap/core_ext/hash_spec.rb +15 -0
  42. data/spec/burlap/core_ext/integer_spec.rb +28 -0
  43. data/spec/burlap/core_ext/nil_class_spec.rb +15 -0
  44. data/spec/burlap/core_ext/object_spec.rb +62 -0
  45. data/spec/burlap/core_ext/string_spec.rb +27 -0
  46. data/spec/burlap/core_ext/symbol_spec.rb +15 -0
  47. data/spec/burlap/core_ext/time_spec.rb +23 -0
  48. data/spec/burlap/core_ext/true_class_spec.rb +17 -0
  49. data/spec/burlap/default_resolver_spec.rb +140 -0
  50. data/spec/burlap/error_spec.rb +7 -0
  51. data/spec/burlap/hash_spec.rb +234 -0
  52. data/spec/burlap/listener_spec.rb +31 -0
  53. data/spec/burlap/node_spec.rb +39 -0
  54. data/spec/burlap_spec.rb +55 -0
  55. data/spec/data/no_such_method.burlap +1 -0
  56. data/spec/data/record_not_found.burlap +1 -0
  57. data/spec/spec_helper.rb +13 -0
  58. metadata +224 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a943c13d8d1a707bb5cd7aa90b1044294f3ac83e92bbc9dc47013bc665646015
4
+ data.tar.gz: 148192348442c2b25471c582c35800f38f37bed6275e54db5d29f40dfade6659
5
+ SHA512:
6
+ metadata.gz: 887990e582c68cc1603786307e76cc02f75e9770d01404e21e84f42ed4584c578614e704874f33504a0b33ae5c97287aa57b109e4b2e913d311e299a8888cd13
7
+ data.tar.gz: d00650665f60de24108f908bb804a15d835bb61957a473ae15f6e63d6c842c23e675be8a3362dac1c9583e61f8865b851db27c8b61eeb04bb298cfce91ee2c50
@@ -0,0 +1,38 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1"]
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ # uses: ruby/setup-ruby@v1
33
+ uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
37
+ - name: Run tests
38
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ tmp/*
5
+ log/*
6
+ doc/*
7
+ .yardoc
8
+ Gemfile.lock
9
+ vendor
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=progress
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup=markdown
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in brappa.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2010 Brightbox Systems Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # Burlap
2
+
3
+ This gem handles parsing and generating [Burlap][] XML.
4
+
5
+
6
+ ## Installation
7
+
8
+ gem install burlap
9
+
10
+ or from the git repo
11
+
12
+ rake install
13
+
14
+ ## Development
15
+
16
+ Clone the git repo
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ begin
5
+ require "rspec/core/rake_task"
6
+ require "rspec/core/version"
7
+
8
+ desc "Run all examples"
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ t.rspec_opts = %w(--color)
11
+ end
12
+ rescue LoadError
13
+ # rspec not loaded, tasks not available
14
+ desc "[RSpec failed to load] Run all examples"
15
+ task :spec do
16
+ fail "RSpec failed to load, this task can't be run"
17
+ end
18
+ end
19
+
20
+ desc "Alias for spec"
21
+ task :test => :spec
22
+
23
+ begin
24
+ require "yard"
25
+
26
+ YARD::Rake::YardocTask.new :doc do |yard|
27
+ yard.files = Dir.glob("lib/**/*.rb")
28
+ end
29
+ rescue LoadError
30
+ puts "failed to load yard"
31
+ end
data/burlap.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "burlap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "burlap"
7
+ s.version = Burlap::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Caius Durling", "Paul Thornthwaite", "John Leach"]
10
+ s.email = ["hello@brightbox.com"]
11
+ s.homepage = "https://github.com/brightbox/burlap"
12
+ s.summary = %q{Wrapper for burlap APIs}
13
+ s.description = %q{Translates responses from Burlap APIs to ruby, and generates requests to send back.}
14
+ s.license = "MIT"
15
+ s.metadata['rubygems_mfa_required'] = "true"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.required_ruby_version = "> 2.3"
23
+
24
+ s.add_dependency "nokogiri", ">= 1.4.4"
25
+ s.add_dependency "builder", ">= 2.0"
26
+
27
+ s.add_development_dependency "rspec", "~> 3.0"
28
+ s.add_development_dependency "activesupport", ">= 2.3.4"
29
+ s.add_development_dependency "timecop", "= 0.3.5"
30
+ s.add_development_dependency "rake"
31
+ s.add_development_dependency "yard"
32
+ end
@@ -0,0 +1,179 @@
1
+ require 'yaml'
2
+
3
+ YAML.add_builtin_type("omap") do |type, val|
4
+ ActiveSupport::OrderedHash[val.map(&:to_a).map(&:first)]
5
+ end
6
+
7
+ # OrderedHash is namespaced to prevent conflicts with other implementations
8
+ module ActiveSupport #:nodoc:
9
+ class OrderedHash < ::Hash #:nodoc:
10
+ def to_yaml_type
11
+ "!tag:yaml.org,2002:omap"
12
+ end
13
+
14
+ def to_yaml(opts = {})
15
+ YAML.quick_emit(self, opts) do |out|
16
+ out.seq(taguri, to_yaml_style) do |seq|
17
+ each do |k, v|
18
+ seq.add(k => v)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # Hash is ordered in Ruby 1.9!
25
+ if RUBY_VERSION < '1.9'
26
+
27
+ # In MRI the Hash class is core and written in C. In particular, methods are
28
+ # programmed with explicit C function calls and polymorphism is not honored.
29
+ #
30
+ # For example, []= is crucial in this implementation to maintain the @keys
31
+ # array but hash.c invokes rb_hash_aset() originally. This prevents method
32
+ # reuse through inheritance and forces us to reimplement stuff.
33
+ #
34
+ # For instance, we cannot use the inherited #merge! because albeit the algorithm
35
+ # itself would work, our []= is not being called at all by the C code.
36
+
37
+ def initialize(*args, &block)
38
+ super
39
+ @keys = []
40
+ end
41
+
42
+ def self.[](*args)
43
+ ordered_hash = new
44
+
45
+ if (args.length == 1 && args.first.is_a?(Array))
46
+ args.first.each do |key_value_pair|
47
+ next unless (key_value_pair.is_a?(Array))
48
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
49
+ end
50
+
51
+ return ordered_hash
52
+ end
53
+
54
+ unless (args.size % 2 == 0)
55
+ raise ArgumentError.new("odd number of arguments for Hash")
56
+ end
57
+
58
+ args.each_with_index do |val, ind|
59
+ next if (ind % 2 != 0)
60
+ ordered_hash[val] = args[ind + 1]
61
+ end
62
+
63
+ ordered_hash
64
+ end
65
+
66
+ def initialize_copy(other)
67
+ super
68
+ # make a deep copy of keys
69
+ @keys = other.keys
70
+ end
71
+
72
+ def []=(key, value)
73
+ @keys << key if !has_key?(key)
74
+ super
75
+ end
76
+
77
+ def delete(key)
78
+ if has_key? key
79
+ index = @keys.index(key)
80
+ @keys.delete_at index
81
+ end
82
+ super
83
+ end
84
+
85
+ def delete_if
86
+ super
87
+ sync_keys!
88
+ self
89
+ end
90
+
91
+ def reject!
92
+ super
93
+ sync_keys!
94
+ self
95
+ end
96
+
97
+ def reject(&block)
98
+ dup.reject!(&block)
99
+ end
100
+
101
+ def keys
102
+ @keys.dup
103
+ end
104
+
105
+ def values
106
+ @keys.collect { |key| self[key] }
107
+ end
108
+
109
+ def to_hash
110
+ self
111
+ end
112
+
113
+ def to_a
114
+ @keys.map { |key| [ key, self[key] ] }
115
+ end
116
+
117
+ def each_key
118
+ @keys.each { |key| yield key }
119
+ end
120
+
121
+ def each_value
122
+ @keys.each { |key| yield self[key]}
123
+ end
124
+
125
+ def each
126
+ @keys.each {|key| yield [key, self[key]]}
127
+ end
128
+
129
+ alias_method :each_pair, :each
130
+
131
+ def clear
132
+ super
133
+ @keys.clear
134
+ self
135
+ end
136
+
137
+ def shift
138
+ k = @keys.first
139
+ v = delete(k)
140
+ [k, v]
141
+ end
142
+
143
+ def merge!(other_hash)
144
+ if block_given?
145
+ other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
146
+ else
147
+ other_hash.each { |k, v| self[k] = v }
148
+ end
149
+ self
150
+ end
151
+
152
+ alias_method :update, :merge!
153
+
154
+ def merge(other_hash, &block)
155
+ dup.merge!(other_hash, &block)
156
+ end
157
+
158
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
159
+ def replace(other)
160
+ super
161
+ @keys = other.keys
162
+ self
163
+ end
164
+
165
+ def invert
166
+ OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
167
+ end
168
+
169
+ def inspect
170
+ "#<OrderedHash #{super}>"
171
+ end
172
+
173
+ private
174
+ def sync_keys!
175
+ @keys.delete_if {|k| !has_key?(k)}
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,18 @@
1
+ module Burlap
2
+ class Array < ::Array
3
+
4
+ def to_burlap
5
+ # <list><type>[string</type><length>1</length><string>Some</string></list>
6
+ list_content = [
7
+ Burlap::Node.new(:name => "type", :value => "").to_burlap,
8
+ Burlap::Node.new(:name => "length", :value => self.length.to_s).to_burlap
9
+ ]
10
+ list_content += self.map do |element|
11
+ element.to_burlap
12
+ end
13
+ list_content = list_content.join("")
14
+ Burlap::Node.new(:name => "list", :value => list_content).to_burlap
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,105 @@
1
+ module Burlap
2
+
3
+ class BaseTag
4
+ attr_accessor :name, :value, :children
5
+
6
+ def initialize params={}
7
+ params.each do |k,v|
8
+ meffod = :"#{k}="
9
+ send(meffod, v) if respond_to?(meffod)
10
+ end
11
+ end
12
+
13
+ def children
14
+ @children ||= []
15
+ end
16
+
17
+ def value
18
+ @value ||= ""
19
+ end
20
+
21
+ def parse_matched_pairs
22
+ # The children are matched pairs.
23
+ # We use an array here because ruby 1.8.x is _FUN_ to
24
+ # use ordered hashes with and doing it in an array is
25
+ # easier for now. Viva la 1.9!
26
+ values = []
27
+
28
+ self.children.each_slice(2) do |arr|
29
+ key = arr.first.to_ruby
30
+ value = if arr.last.name == "ref"
31
+ i = arr.last.value.to_i - 1
32
+ v = values[i]
33
+ v.last if v
34
+ else
35
+ arr.last.to_ruby
36
+ end
37
+
38
+ values << [key, value]
39
+ end
40
+
41
+ values
42
+ end
43
+
44
+ def to_ruby
45
+ Burlap.resolver.convert_to_native self
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ __END__
53
+
54
+ # todo: introduce into resolver block for map
55
+ class Timestamp < Map
56
+ handle_mapping "java.sql.Timestamp"
57
+
58
+ def to_ruby
59
+ # This is already parsed as a Time object
60
+ contents["value"]
61
+ end
62
+ end
63
+
64
+ # todo: introduce into resolver block for map
65
+ require "bigdecimal"
66
+ class BigDecimal < Map
67
+ handle_mapping "java.math.BigDecimal"
68
+
69
+ def to_ruby
70
+ ::BigDecimal.new(contents["value"])
71
+ end
72
+ end
73
+ end
74
+
75
+ # todo: add a resolver block to parse this out
76
+ class Fault
77
+ attr_reader :code, :message, :detail_message, :stack_trace, :cause
78
+
79
+ def initialize opts={}
80
+ data = opts[:contents]
81
+
82
+ @message = data["message"]
83
+ @code = data["code"]
84
+ detail = data["detail"].contents
85
+ @detail_message = detail["detailMessage"]
86
+ @stack_trace = detail["stackTrace"]
87
+ @cause = detail["cause"]
88
+
89
+ @contents = nil
90
+ end
91
+ end
92
+
93
+ # todo: add a resolver block for this logic
94
+ class FaultTag < BaseTag
95
+ def to_ruby
96
+ dict = {}
97
+
98
+ children.each_slice(2) do |arr|
99
+ key, value = arr.map(&:to_ruby)
100
+ dict[key] = value
101
+ end
102
+
103
+ Fault.new(:contents => dict)
104
+ end
105
+ end
@@ -0,0 +1,38 @@
1
+ module Burlap
2
+ class Call
3
+ attr_accessor :headers, :method, :arguments
4
+
5
+ def initialize params={}
6
+ params.each do |key, value|
7
+ method = :"#{key}="
8
+ send(method, value) if respond_to?(method)
9
+ end
10
+
11
+ validate_attributes
12
+ end
13
+
14
+ def headers
15
+ @headers ||= {}
16
+ end
17
+
18
+ def arguments
19
+ @arguments ||= []
20
+ end
21
+
22
+ def to_burlap
23
+ # todo: handle headers
24
+ contents = [Burlap::Node.new(:name => "method", :value => method).to_burlap]
25
+ contents += arguments.map do |arg|
26
+ arg.to_burlap
27
+ end
28
+ Burlap::Node.new(:name => "burlap:call", :value => contents.join("")).to_burlap
29
+ end
30
+
31
+ protected
32
+
33
+ def validate_attributes
34
+ raise(ArgumentError, "method is required") unless self.method
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ class Array
2
+ def to_burlap
3
+ # We use the splat here so it creates an array with our elements,
4
+ # rather than an array containing an array of our elements
5
+ Burlap::Array[*to_a].to_burlap
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class TrueClass
2
+ def to_burlap
3
+ Burlap::Node.new(:name => "boolean", :value => "1").to_burlap
4
+ end
5
+ end
6
+
7
+ class FalseClass
8
+ def to_burlap
9
+ Burlap::Node.new(:name => "boolean", :value => "0").to_burlap
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class Float
2
+ def to_burlap
3
+ Burlap::Node.new(:name => "double", :value => self).to_burlap
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_burlap
3
+ Burlap::Hash[self].to_burlap
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class Integer
2
+ def to_burlap
3
+ if between?(-2**31, 2**31-1)
4
+ Burlap::Node.new(:name => "int", :value => self.to_i).to_burlap
5
+ else
6
+ # <map><type>java.math.BigDecimal</type><string>value</string><string>0</string></map>
7
+ Burlap::Hash[{:value => self.to_i.to_s}, "java.math.BigDecimal"].to_burlap
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class NilClass
2
+ def to_burlap
3
+ Burlap::Node.new(:name => "null", :value => "").to_burlap
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Object
2
+ def to_burlap
3
+ dict = {}
4
+
5
+ vars = instance_variables.map do |var|
6
+ key = var[/^@(.*)$/, 1]
7
+ value = instance_variable_get(var)
8
+ [key, value]
9
+ end.sort_by {|e| e.first }
10
+
11
+ Burlap::Hash[vars, self.class.to_s].to_burlap
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def to_burlap
3
+ Burlap::Node.new(:name => "string", :value => ERB::Util.html_escape(self)).to_burlap
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class Symbol
2
+ def to_burlap
3
+ # Return the same as if we were a string
4
+ self.to_s.to_burlap
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class Time
2
+ def to_burlap
3
+ Burlap::Node.new(:name => "date", :value => self.burlap_iso8601(3)).to_burlap
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require "burlap/core_ext/array"
2
+ require "burlap/core_ext/boolean"
3
+ require "burlap/core_ext/float"
4
+ require "burlap/core_ext/hash"
5
+ require "burlap/core_ext/integer"
6
+ require "burlap/core_ext/nil"
7
+ require "burlap/core_ext/object"
8
+ require "burlap/core_ext/string"
9
+ require "burlap/core_ext/symbol"
10
+ require "burlap/core_ext/time"