wadling 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8488952190da41b994a7b5599c984e2c9ac27a2a
4
+ data.tar.gz: 9bbd3bc4792a0ac1bbe9f3ff4fb748e85532a0bf
5
+ SHA512:
6
+ metadata.gz: 556bf91c7e4d880a2eaaa9190fdb767fc7ba4e6b3e7488fa9058b3caa805b36d61cbedead37566876a7184fd9c7d60ab8af4b9ac54448ec9ed82b8c627aec7c5
7
+ data.tar.gz: 587803d1dc850756bdabb2c05fa913466f46604b97612c323d46bdb72887d3b8125511d76cc636f82ba9d5b2af5d27626d8562579896afec65173a2108095eff
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ coverage
2
+ Gemfile.lock
3
+ *swp
4
+ *gem
5
+ backup
6
+ doc
7
+ prototype
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ smaak
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p451
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in wadling.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Ernst van Graan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # Wadling
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ gem 'wadling'
8
+
9
+ And then execute:
10
+
11
+ $ bundle
12
+
13
+ Or install it yourself as:
14
+
15
+ $ gem install wadling
16
+
17
+ ## Contributing
18
+
19
+ Please send feedback and comments to the author at:
20
+
21
+ Ernst van Graan <ernst.van.graan@hetzner.co.za>
22
+
23
+ This gem is sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module Wadling
2
+ VERSION = "0.1.0"
3
+ end
data/lib/wadling.rb ADDED
@@ -0,0 +1,123 @@
1
+ require "wadling/version"
2
+ require 'byebug'
3
+
4
+ module Wadling
5
+ class LexiconTranslator
6
+ def translate_resources_into_wadl(resources)
7
+ return empty_wadl if no_resources?(resources)
8
+ raise ArgumentError.new("A resource dictionary is expected") if resources_invalid?(resources)
9
+ header + resources_base + translate_resources(resources) + resources_close + footer
10
+ end
11
+
12
+ def header
13
+ "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
14
+ " xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02 wadl.xsd\"" \
15
+ " xmlns=\"http://wadl.dev.java.net/2009/02\">"
16
+ end
17
+
18
+ def resources_base
19
+ "<resources base=\"/\">"
20
+ end
21
+
22
+ def resources_close
23
+ "</resources>"
24
+ end
25
+
26
+ def footer
27
+ "</application>"
28
+ end
29
+
30
+ private
31
+
32
+ def resources_invalid?(resources)
33
+ not resources.is_a? Hash
34
+ end
35
+
36
+ def translate_resources(resources)
37
+ entries = ""
38
+ resources.each do |r, v|
39
+ entries = translate_and_append_resource(entries, r, v)
40
+ end
41
+ entries
42
+ end
43
+
44
+ def translate_and_append_resource(entries, r, v)
45
+ entries, required = append_resource_header(entries, r, v)
46
+ v['params'].each do |p, vv|
47
+ entries = append_param(entries, required, p, vv)
48
+ end
49
+ entries = append_resource_footer(entries)
50
+ end
51
+
52
+ def append_resource_header(entries, r, v)
53
+ method, required = parse_resource(r, v)
54
+ entries = entries + "<resource path=\"#{r}\">"
55
+ entries = entries + " <method name=\"#{method}\" id=\"#{v['id']}\">"
56
+ entries = entries + " <request>"
57
+ entries = entries + " <doc>"
58
+ entries = entries + " #{v['doc']}"
59
+ entries = entries + " </doc>"
60
+ return entries, required
61
+ end
62
+
63
+ def append_resource_footer(entries)
64
+ entries = entries + " </request>"
65
+ entries = entries + " </method>"
66
+ entries = entries + "</resource>"
67
+ end
68
+
69
+ def append_param(entries, required, p, vv)
70
+ type = parse_param(required, p, vv)
71
+ entries = entries + " <param name=\"#{p}\" type=\"xsd:#{type}\" required=\"#{vv['required']}\" style=\"query\""
72
+ entries = entries + " default=\"#{vv['default']}\"" if vv['default']
73
+ entries = entries + "> </param>"
74
+ end
75
+
76
+ def parse_resource(r, v)
77
+ raise ArgumentError.new("Invalid resource path") if r.nil?
78
+ raise ArgumentError.new("Resource definition invalid") if (v.nil?) or (not v.is_a?(Hash))
79
+ method = translate_method(v['method'])
80
+ raise ArgumentError.new("Resource documentation invalid") if v['doc'].nil? or not v['doc'].is_a? String
81
+ raise ArgumentError.new("Resource id invalid") if v['id'].nil?
82
+ required = translate_required(v['required'])
83
+ return method, required
84
+ end
85
+
86
+ def parse_param(required, p, vv)
87
+ type = translate_type(vv['type'])
88
+ raise ArgumentError.new("parameter should not have a default value when required") if required and not vv['default'].nil?
89
+ type
90
+ end
91
+
92
+ def no_resources?(resources)
93
+ (resources.nil?) or (resources == {})
94
+ end
95
+
96
+ def empty_wadl
97
+ header + resources_base + resources_close + footer
98
+ end
99
+
100
+ def translate_method(method)
101
+ raise ArgumentError.new("Invalid method") if method.nil? or method.strip == ""
102
+ return "GET" if (method.strip().casecmp("GET") == 0)
103
+ return "POST" if (method.strip().casecmp("POST") == 0)
104
+ return "PUT" if (method.strip().casecmp("PUT") == 0)
105
+ return "DELETE" if (method.strip().casecmp("DELETE") == 0)
106
+ raise ArgumentError.new("Invalid method")
107
+ end
108
+
109
+ def translate_type(type)
110
+ raise ArgumentError.new("Parameter type invalid") if type.nil? or not type.is_a? String
111
+ return "string" if type.strip.downcase == "string"
112
+ raise ArgumentError.new("Parameter type invalid")
113
+ end
114
+
115
+ def translate_required(required)
116
+ return nil if required.nil?
117
+ return 'true' if required == true or required.downcase.strip == 'true'
118
+ return 'false' if required == false or required.downcase.strip == 'false'
119
+ raise ArgumentError.new("Parameter presence indicator invalid")
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,152 @@
1
+ require './spec/spec_helper.rb'
2
+
3
+ describe Wadling do
4
+ def copy_hash(hash)
5
+ Marshal.load(Marshal.dump(hash))
6
+ end
7
+
8
+ before :all do
9
+ @iut = Wadling::LexiconTranslator.new
10
+ @wadl_header = "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
11
+ " xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02 wadl.xsd\"" \
12
+ " xmlns=\"http://wadl.dev.java.net/2009/02\">" \
13
+ "<resources base=\"/\">"
14
+ @wadl_footer = "</resources>" \
15
+ "</application>"
16
+ @empty_wadl = @wadl_header + @wadl_footer
17
+ @resource1 = { '/resource1' => {
18
+ 'doc' => 'This returns resource1 for the identifier provided',
19
+ 'method' => 'GET',
20
+ 'id' => 'resource1',
21
+ 'params' => {
22
+ 'identifier' => {
23
+ 'required' => 'false',
24
+ 'type' => 'string',
25
+ 'default' => '123' }}}}
26
+ @resource2 = { '/resource2' => {
27
+ 'doc' => 'This sets resource2 for the identifier provided to the value provided',
28
+ 'method' => 'POST',
29
+ 'id' => 'resource2',
30
+ 'params' => {
31
+ 'identifier' => {
32
+ 'required' => 'false',
33
+ 'type' => 'string',
34
+ 'default' => '123' },
35
+ 'field2' => {
36
+ 'required' => 'true',
37
+ 'type' => 'string' }}}}
38
+ @resource1_wadl = "<resource path=\"/resource1\">" \
39
+ " <method name=\"GET\" id=\"resource1\">" \
40
+ " <request>" \
41
+ " <doc>" \
42
+ " This returns resource1 for the identifier provided" \
43
+ " </doc>" \
44
+ " <param name=\"identifier\" type=\"xsd:string\" required=\"false\" style=\"query\" default=\"123\">" \
45
+ " </param>" \
46
+ " </request>" \
47
+ " </method>" \
48
+ "</resource>"
49
+ @resource2_wadl = "<resource path=\"/resource2\">" \
50
+ " <method name=\"POST\" id=\"resource2\">" \
51
+ " <request>" \
52
+ " <doc>" \
53
+ " This sets resource2 for the identifier provided to the value provided" \
54
+ " </doc>" \
55
+ " <param name=\"identifier\" type=\"xsd:string\" required=\"false\" style=\"query\" default=\"123\">" \
56
+ " </param>" \
57
+ " <param name=\"field2\" type=\"xsd:string\" required=\"true\" style=\"query\">" \
58
+ " </param>" \
59
+ " </request>" \
60
+ " </method>" \
61
+ "</resource>"
62
+ @wadl1 = @wadl_header + @resource1_wadl + @wadl_footer
63
+ @wadl2 = @wadl_header + @resource1_wadl + @resource2_wadl + @wadl_footer
64
+ end
65
+
66
+ context "when given nil" do
67
+ it "should return an empty WADL descriptor" do
68
+ expect(@iut.translate_resources_into_wadl(nil)).to eq(@empty_wadl)
69
+ end
70
+ end
71
+
72
+ context "when given an empty dictionary" do
73
+ it "should return an empty WADL descriptor" do
74
+ expect(@iut.translate_resources_into_wadl(nil)).to eq(@empty_wadl)
75
+ end
76
+ end
77
+
78
+ context "when given a non-dictionary" do
79
+ it "should raise an ArgumentError indicating a dictionary is required" do
80
+ expect {
81
+ @iut.translate_resources_into_wadl([])
82
+ }.to raise_error ArgumentError, "A resource dictionary is expected"
83
+ end
84
+ end
85
+
86
+ context "when given a dictionary with resources" do
87
+ context "when given one resource" do
88
+ it "should return a WADL definition for that resource" do
89
+ expect(@iut.translate_resources_into_wadl(@resource1)).to eq(@wadl1)
90
+ end
91
+ end
92
+
93
+ context "when given multiple resources" do
94
+ it "should return a WADL definition for all resources" do
95
+ test = {}
96
+ test = test.merge(@resource1)
97
+ test = test.merge(@resource2)
98
+ expect(@iut.translate_resources_into_wadl(test)).to eq(@wadl2)
99
+ end
100
+ end
101
+
102
+ context "when a resource is ill-defined" do
103
+ it "should raise an ArgumentError with appropriate descrition of the error" do
104
+ expect {
105
+ test = { nil => {
106
+ 'doc' => 'This returns resource1 for the identifier provided' }}
107
+ @iut.translate_resources_into_wadl(test)
108
+ }.to raise_error(ArgumentError, "Invalid resource path")
109
+ expect {
110
+ test = { '/resource' => 2 }
111
+ @iut.translate_resources_into_wadl(test)
112
+ }.to raise_error(ArgumentError, "Resource definition invalid")
113
+ expect {
114
+ test = copy_hash(@resource1)
115
+ test['/resource1']['doc'] = nil
116
+ @iut.translate_resources_into_wadl(test)
117
+ }.to raise_error(ArgumentError, "Resource documentation invalid")
118
+ expect {
119
+ test = copy_hash(@resource1)
120
+ test['/resource1']['method'] = nil
121
+ @iut.translate_resources_into_wadl(test)
122
+ }.to raise_error(ArgumentError, "Invalid method")
123
+ expect {
124
+ test = copy_hash(@resource1)
125
+ test['/resource1']['method'] = 'invalid'
126
+ @iut.translate_resources_into_wadl(test)
127
+ }.to raise_error(ArgumentError, "Invalid method")
128
+ expect {
129
+ test = copy_hash(@resource1)
130
+ test['/resource1']['id'] = nil
131
+ @iut.translate_resources_into_wadl(test)
132
+ }.to raise_error(ArgumentError, "Resource id invalid")
133
+ expect {
134
+ test = copy_hash(@resource1)
135
+ test['/resource1']['required'] = 'invalid'
136
+ @iut.translate_resources_into_wadl(test)
137
+ }.to raise_error(ArgumentError, "Parameter presence indicator invalid")
138
+ expect {
139
+ test = copy_hash(@resource1)
140
+ test['/resource1']['params']['identifier']['type'] = 'invalid'
141
+ @iut.translate_resources_into_wadl(test)
142
+ }.to raise_error(ArgumentError, "Parameter type invalid")
143
+ expect {
144
+ test = copy_hash(@resource1)
145
+ test['/resource1']['required'] = 'true'
146
+ test['/resource1']['default'] = 'one'
147
+ @iut.translate_resources_into_wadl(test)
148
+ }.to raise_error(ArgumentError, "parameter should not have a default value when required")
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,29 @@
1
+ require 'rspec'
2
+ require 'rspec/mocks'
3
+ require 'tempfile'
4
+ require 'simplecov'
5
+ require 'simplecov-rcov'
6
+ require 'byebug'
7
+
8
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'wadling'))
9
+ $:.unshift(File.join(File.dirname(__FILE__), '..'))
10
+
11
+ require 'lib/wadling.rb'
12
+
13
+ RSpec.configure do |config|
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+ #config.expect_with(:rspec) { |c| c.syntax = :should }
17
+
18
+ # Run specs in random order to surface order dependencies. If you find an
19
+ # order dependency and want to debug it, you can fix the order by providing
20
+ # the seed, which is printed after each run.
21
+ # --seed 1234
22
+ config.order = 'random'
23
+ end
24
+
25
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
26
+ SimpleCov.start do
27
+ add_filter "/spec/"
28
+ end
29
+
data/wadling.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wadling/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wadling"
8
+ spec.version = Wadling::VERSION
9
+ spec.authors = ["Ernst van Graan"]
10
+ spec.email = ["ernst.van.graan@hetzner.co.za"]
11
+ spec.description = %q{Turns a list of services (REST resources) definitions into a WADL definition}
12
+ spec.summary = %q{Given a dictionary of resources with a description, input and output schemas, produces a WADL definition}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = '>= 2.0'
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "byebug"
25
+ spec.add_development_dependency 'simplecov'
26
+ spec.add_development_dependency 'simplecov-rcov'
27
+ spec.add_development_dependency 'rspec'
28
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wadling
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ernst van Graan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov-rcov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Turns a list of services (REST resources) definitions into a WADL definition
98
+ email:
99
+ - ernst.van.graan@hetzner.co.za
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .ruby-gemset
106
+ - .ruby-version
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - lib/wadling.rb
112
+ - lib/wadling/version.rb
113
+ - spec/lib/wadling/wadling_spec.rb
114
+ - spec/spec_helper.rb
115
+ - wadling.gemspec
116
+ homepage: ''
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '2.0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.0.14
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Given a dictionary of resources with a description, input and output schemas,
140
+ produces a WADL definition
141
+ test_files:
142
+ - spec/lib/wadling/wadling_spec.rb
143
+ - spec/spec_helper.rb