atomsphere 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.md +96 -0
- data/atomsphere.gemspec +16 -0
- data/lib/atomsphere.rb +6 -0
- data/lib/atomsphere/action.rb +129 -0
- data/lib/atomsphere/action/change_listener_status.rb +11 -0
- data/lib/atomsphere/action/execute_process.rb +26 -0
- data/lib/atomsphere/action/get_assignable_roles.rb +7 -0
- data/lib/atomsphere/api.rb +6 -0
- data/lib/atomsphere/api/client.rb +90 -0
- data/lib/atomsphere/api/response.rb +23 -0
- data/lib/atomsphere/configuration.rb +32 -0
- data/lib/atomsphere/query.rb +84 -0
- data/lib/atomsphere/query/grouping_expression.rb +66 -0
- data/lib/atomsphere/query/simple_expression.rb +71 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25eae7b31f1b5dd9f640ec1a7942192a1fbec4c2aeffda74f9af08ce31879224
|
4
|
+
data.tar.gz: d4e1d956c1abbf2e74125b24c725b0664b8be0fc57078804e2eb120f43ab822b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 675f2fca40b7842b44b4abdb04993cd8af67f37095d3fcc1f039ba75f151b3166a4bfaa5fc63b94ee0b3f58d91eac332ce1bbcc3454cdc7c1a819e5a8b6459f4
|
7
|
+
data.tar.gz: edfc117e3812d520b4de08efbb1eee30052f6b58bd4bb42d15ab15200516f58b06bed5c9694de61728e0a17141afe85bfd619ef6bcb24adae12bf09b62117bf6
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Warren Guy
|
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,96 @@
|
|
1
|
+
# Boomi Atomsphere API client for Ruby
|
2
|
+
|
3
|
+
Unofficial Ruby client for the Dell Boomi Atomsphere API. Implements the JSON flavour of Boomi's "RESTish" API.
|
4
|
+
|
5
|
+
## Status
|
6
|
+
|
7
|
+
Implements authentication (including OTP), querying, and some actions. See *Usage* below.
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'atomsphere'
|
13
|
+
```
|
14
|
+
|
15
|
+
### Configuration
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
Atomsphere.configure do |config|
|
19
|
+
config.account_id = '' # Boomi account ID
|
20
|
+
config.username = '' # user name
|
21
|
+
config.password = '' # user password
|
22
|
+
config.otp_secret = '' # base32 OTP secret for two-factor auth
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
Alternatively, environment variables may be used:
|
27
|
+
* `BOOMI_ACCOUNT_ID`
|
28
|
+
* `BOOMI_USERNAME`
|
29
|
+
* `BOOMI_PASSWORD`
|
30
|
+
* `BOOMI_OTP_SECRET`
|
31
|
+
|
32
|
+
### Querying
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# create a new query
|
36
|
+
query = Atomsphere::Query.new
|
37
|
+
|
38
|
+
# specify the object type to query
|
39
|
+
query.object_type = 'Process'
|
40
|
+
|
41
|
+
# filter for query names starting with 'Netsuite'
|
42
|
+
query.filter = Atomsphere::Query::GroupingExpression.new(
|
43
|
+
operator: :and,
|
44
|
+
nested_expression: [
|
45
|
+
Atomsphere::Query::SimpleExpression.new(
|
46
|
+
operator: :equals,
|
47
|
+
property: :name,
|
48
|
+
argument: ['Netsuite%']
|
49
|
+
)
|
50
|
+
]
|
51
|
+
)
|
52
|
+
|
53
|
+
# run the query (fetches first page)
|
54
|
+
query.run
|
55
|
+
|
56
|
+
# see results from all pages that have been fetched
|
57
|
+
query.results
|
58
|
+
|
59
|
+
# fetch the next page (returns `false` if `last_page?` is `true`)
|
60
|
+
query.next_page
|
61
|
+
|
62
|
+
# fetch and show all pages of results (warning: loops over `next_page`)
|
63
|
+
query.all_results
|
64
|
+
```
|
65
|
+
|
66
|
+
### Actions
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
Atomsphere.get_assignable_roles
|
70
|
+
Atomsphere.execute_process atom_id: '12345-uuid-12345', process_id: '12345-uuid-12345'
|
71
|
+
Atomsphere.change_listener_status listener_id: '12345-uuid-12345', container_id: '12345-uuid-12345', action: :pause
|
72
|
+
```
|
73
|
+
|
74
|
+
## License
|
75
|
+
|
76
|
+
MIT License
|
77
|
+
|
78
|
+
Copyright (c) 2019 Warren Guy
|
79
|
+
|
80
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
81
|
+
of this software and associated documentation files (the "Software"), to deal
|
82
|
+
in the Software without restriction, including without limitation the rights
|
83
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
84
|
+
copies of the Software, and to permit persons to whom the Software is
|
85
|
+
furnished to do so, subject to the following conditions:
|
86
|
+
|
87
|
+
The above copyright notice and this permission notice shall be included in all
|
88
|
+
copies or substantial portions of the Software.
|
89
|
+
|
90
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
91
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
92
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
93
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
94
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
95
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
96
|
+
SOFTWARE.
|
data/atomsphere.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'atomsphere'
|
3
|
+
s.version = '0.1.6'
|
4
|
+
s.licenses = ['MIT']
|
5
|
+
s.summary = "Unofficial Ruby client for the Dell Boomi Atomsphere API"
|
6
|
+
s.authors = ["Warren Guy"]
|
7
|
+
s.email = 'warren@guy.net.au'
|
8
|
+
s.files = `git ls-files`.split("\n")
|
9
|
+
s.require_paths = ['lib']
|
10
|
+
s.homepage = 'https://github.com/warrenguy/atomsphere-ruby'
|
11
|
+
s.metadata = { "source_code_uri" => "https://github.com/warrenguy/atomsphere-ruby" }
|
12
|
+
|
13
|
+
s.required_ruby_version = '>= 2.2'
|
14
|
+
s.add_runtime_dependency 'rotp', '~>4'
|
15
|
+
s.add_runtime_dependency 'facets', '~>3'
|
16
|
+
end
|
data/lib/atomsphere.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'facets/string/camelcase'
|
2
|
+
require 'facets/string/snakecase'
|
3
|
+
|
4
|
+
module Atomsphere
|
5
|
+
module Action
|
6
|
+
module ClassMethods
|
7
|
+
def self.included base
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize params={}
|
11
|
+
set_params params
|
12
|
+
validate!
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields
|
16
|
+
%w(required one_of optional).map do |m|
|
17
|
+
self.class.class_variable_get :"@@#{m}"
|
18
|
+
end.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
@api_response ||= api_client.send(*[
|
23
|
+
api_method,
|
24
|
+
action,
|
25
|
+
api_method.eql?(:get) ? nil : request
|
26
|
+
].compact)
|
27
|
+
|
28
|
+
@response ||= @api_response.to_hash
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
%w(required one_of optional).each do |m|
|
34
|
+
define_method(:"#{m}") { self.class.class_variable_get(:"@@#{m}") }
|
35
|
+
end
|
36
|
+
|
37
|
+
def action
|
38
|
+
if self.class.class_variable_defined? :@@action
|
39
|
+
self.class.class_variable_get :@@action
|
40
|
+
else
|
41
|
+
self.class.name.split('::').last.lower_camelcase
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def api_method
|
46
|
+
if self.class.class_variable_defined? :@@api_method
|
47
|
+
self.class.class_variable_get :@@api_method
|
48
|
+
else
|
49
|
+
:post
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_params params
|
54
|
+
fields.each{ |f| send(:"#{f}=", params[f]) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def api_client
|
58
|
+
Api::Client.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate!
|
62
|
+
required.each do |f|
|
63
|
+
raise ArgumentError, "#{f} is required" unless send(:"#{f}")
|
64
|
+
end
|
65
|
+
|
66
|
+
one_of.each do |fs|
|
67
|
+
unless fs.map{ |f| send(:"#{f}") }.compact.size == 1
|
68
|
+
raise ArgumentError, "requires one of: #{fs.join(', ')}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module InstanceMethods
|
75
|
+
def self.extended base
|
76
|
+
%w(required one_of optional).each do |m|
|
77
|
+
base.class_variable_set :"@@#{m}", []
|
78
|
+
end
|
79
|
+
|
80
|
+
method_name = base.name.split('::').last.snakecase
|
81
|
+
Atomsphere.define_singleton_method(method_name) do |*params|
|
82
|
+
base.new(*params).run
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def action a
|
87
|
+
class_variable_set :@@action, a
|
88
|
+
end
|
89
|
+
|
90
|
+
def api_method m
|
91
|
+
class_variable_set :@@api_method, m
|
92
|
+
end
|
93
|
+
|
94
|
+
def required *params
|
95
|
+
params.each do |param|
|
96
|
+
class_variable_get(:@@required) << param
|
97
|
+
attr_accessor param
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def optional *params
|
102
|
+
params.each do |param|
|
103
|
+
class_variable_get(:@@optional) << param
|
104
|
+
attr_accessor param
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def one_of *params
|
109
|
+
if params.size < 2
|
110
|
+
raise ArgumentError, "one_of requires two or more parameters"
|
111
|
+
end
|
112
|
+
|
113
|
+
class_variable_get(:@@one_of) << [*params]
|
114
|
+
params.each{ |param| attr_accessor param }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Action
|
119
|
+
def self.inherited(other)
|
120
|
+
other.extend InstanceMethods
|
121
|
+
other.include ClassMethods
|
122
|
+
end
|
123
|
+
|
124
|
+
attr_reader :api_response, :response
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
Dir["#{Atomsphere::ROOT}/action/*.rb"].each{ |f| require f }
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Atomsphere
|
2
|
+
module Action
|
3
|
+
class ExecuteProcess < Action
|
4
|
+
required :atom_id
|
5
|
+
one_of :process_id, :process_name
|
6
|
+
|
7
|
+
def request
|
8
|
+
{
|
9
|
+
ProcessProperties: {
|
10
|
+
'@type': 'ProcessProperties',
|
11
|
+
ProcessProperty: [
|
12
|
+
{
|
13
|
+
'@type': '',
|
14
|
+
Name: 'priority',
|
15
|
+
Value: 'medium'
|
16
|
+
}
|
17
|
+
]
|
18
|
+
},
|
19
|
+
atomId: atom_id
|
20
|
+
}.merge(!process_id.nil? ?
|
21
|
+
{ processId: process_id } :
|
22
|
+
{ processName: process_name })
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'rotp'
|
5
|
+
|
6
|
+
module Atomsphere
|
7
|
+
module Api
|
8
|
+
class Client
|
9
|
+
def initialize
|
10
|
+
validate!
|
11
|
+
end
|
12
|
+
|
13
|
+
def post path, data
|
14
|
+
header = {
|
15
|
+
'Content-Type' => 'application/json',
|
16
|
+
'Accept' => ' application/json'
|
17
|
+
}
|
18
|
+
|
19
|
+
request = Net::HTTP::Post.new api_uri(path), header
|
20
|
+
request.body = (String === data ? data : data.to_json)
|
21
|
+
request.basic_auth config.username, config.password
|
22
|
+
|
23
|
+
http_request request
|
24
|
+
end
|
25
|
+
|
26
|
+
def get path
|
27
|
+
header = {'Accept' => 'application/json'}
|
28
|
+
|
29
|
+
request = Net::HTTP::Get.new api_uri(path), header
|
30
|
+
request.basic_auth config.username, config.password
|
31
|
+
|
32
|
+
http_request request
|
33
|
+
end
|
34
|
+
|
35
|
+
def bulk_get path, ids
|
36
|
+
request = { type: 'GET', request: ids.map{ |id| {id: id} } }
|
37
|
+
path = [*path] << :bulk
|
38
|
+
post path, request
|
39
|
+
end
|
40
|
+
|
41
|
+
%w(query create update execute).each do |v|
|
42
|
+
define_method :"#{v}" do |path, data|
|
43
|
+
[*path] << v
|
44
|
+
post path, data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def validate!
|
50
|
+
raise ArgumentError, "Atomsphere not configured" if config.nil?
|
51
|
+
|
52
|
+
required_vars = Atomsphere::Configuration::REQUIRED
|
53
|
+
if (missing_vars = required_vars.select{ |v| config.send(v).nil? }).size > 0
|
54
|
+
raise ArgumentError, "Atomsphere configuration incomplete," +
|
55
|
+
" required vars missing: #{missing_vars.join('; ')}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def config
|
60
|
+
@config ||= Atomsphere.configuration
|
61
|
+
end
|
62
|
+
|
63
|
+
def totp
|
64
|
+
ROTP::TOTP.new(config.otp_secret) if config.otp_secret
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_otp
|
68
|
+
totp.now
|
69
|
+
end
|
70
|
+
|
71
|
+
def api_uri path=nil
|
72
|
+
URI.parse config.base_uri +
|
73
|
+
config.account_id +
|
74
|
+
'/' + (Array === path ? path.join('/') : path.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
def http
|
78
|
+
h = Net::HTTP.new api_uri.host, api_uri.port
|
79
|
+
h.use_ssl = true
|
80
|
+
|
81
|
+
h
|
82
|
+
end
|
83
|
+
|
84
|
+
def http_request request
|
85
|
+
request['X-Boomi-OTP'] = generate_otp if config.otp_secret
|
86
|
+
response = Response.new(request, http.request(request))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Atomsphere
|
4
|
+
module Api
|
5
|
+
class Response
|
6
|
+
attr_reader :request, :code, :response
|
7
|
+
|
8
|
+
def initialize(request, response)
|
9
|
+
@request = request
|
10
|
+
@response = response
|
11
|
+
@code = response.code if response
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
begin
|
16
|
+
JSON.parse @response.body
|
17
|
+
rescue JSON::ParserError
|
18
|
+
@response.body
|
19
|
+
end if @response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Atomsphere
|
2
|
+
class Configuration
|
3
|
+
REQUIRED = :username, :password, :account_id
|
4
|
+
OPTIONAL = :base_uri, :otp_secret
|
5
|
+
VARS = REQUIRED + OPTIONAL
|
6
|
+
|
7
|
+
VARS.each { |v| attr_accessor v }
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@base_uri = 'https://api.boomi.com/api/rest/v1/'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configure
|
19
|
+
self.configuration ||= Configuration.new
|
20
|
+
yield configuration
|
21
|
+
|
22
|
+
configuration
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Hash[Atomsphere::Configuration::VARS.map do |v|
|
27
|
+
[v, "BOOMI_#{v.upcase}"]
|
28
|
+
end].each do |v, e|
|
29
|
+
Atomsphere.configure do |config|
|
30
|
+
config.send :"#{v}=", ENV[e]
|
31
|
+
end if ENV.keys.include? e
|
32
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Atomsphere
|
2
|
+
class Query
|
3
|
+
attr_accessor :object_type, :filter
|
4
|
+
attr_reader :query_token, :result_pages, :page
|
5
|
+
|
6
|
+
def initialize object_type=nil
|
7
|
+
@object_type ||= object_type
|
8
|
+
@page = nil
|
9
|
+
@result_pages = []
|
10
|
+
@filter = GroupingExpression.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate!
|
14
|
+
methods.select{ |m| m =~ /^validate_[a-z0-9_]\!$/ }.each{ |v| send(v) }
|
15
|
+
filter.validate!
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
@result_pages[0] ||= api_client.post [object_type, :query], to_hash
|
21
|
+
@page = 0
|
22
|
+
|
23
|
+
result_pages[0]
|
24
|
+
end
|
25
|
+
|
26
|
+
def results
|
27
|
+
result_pages.map(&:to_hash).map{ |h| h['result'] }.flatten(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
def all_results
|
31
|
+
next_page until last_page?
|
32
|
+
results
|
33
|
+
end
|
34
|
+
|
35
|
+
def last_page?
|
36
|
+
!page.nil? && query_token.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_page
|
40
|
+
return false if last_page?
|
41
|
+
return run if page.nil?
|
42
|
+
|
43
|
+
begin
|
44
|
+
@result_pages[@page += 1] = api_client.post [object_type, :queryMore], query_token
|
45
|
+
rescue => e
|
46
|
+
@page -= 1
|
47
|
+
raise e
|
48
|
+
end
|
49
|
+
|
50
|
+
result_pages[page]
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash
|
54
|
+
validate!
|
55
|
+
|
56
|
+
{ QueryFilter: filter.to_hash }
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_json
|
60
|
+
JSON.pretty_generate to_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def validate_object_type!
|
65
|
+
raise ArgumentError, "object_type is required" if @object_type.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_filter!
|
69
|
+
unless filter.is_a? GroupingExpression
|
70
|
+
raise ArgumentError, 'filter must be a GroupingExpression'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def api_client
|
75
|
+
Api::Client.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def query_token
|
79
|
+
page.nil? ? nil : result_pages.last.to_hash['queryToken']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
%w(grouping_expression simple_expression).each{ |m| require "#{ROOT}/query/#{m}" }
|
84
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Atomsphere
|
4
|
+
class Query
|
5
|
+
class GroupingExpression
|
6
|
+
attr_accessor :operator, :nested_expression
|
7
|
+
|
8
|
+
OPERATORS = :and, :or
|
9
|
+
|
10
|
+
def initialize(params={})
|
11
|
+
params = {
|
12
|
+
operator: :and,
|
13
|
+
nested_expression: []
|
14
|
+
}.merge(params)
|
15
|
+
|
16
|
+
@operator = params[:operator]
|
17
|
+
@nested_expression = params[:nested_expression]
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate!
|
21
|
+
methods.select{ |m| m =~ /^validate_[a-z0-9_]\!$/ }.each{ |v| send(v) }
|
22
|
+
@nested_expression.each(&:validate!)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_hash
|
27
|
+
{
|
28
|
+
expression: {
|
29
|
+
operator: operator.to_s,
|
30
|
+
nestedExpression: nested_expression.
|
31
|
+
map(&:to_hash).
|
32
|
+
map{ |h| h[:expression] }
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_json
|
38
|
+
JSON.pretty_generate to_hash
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def validate_operators!
|
43
|
+
unless OPERATORS.include? @operator
|
44
|
+
raise ArgumentError, "operator must be one of #{OPERATORS.join(', ')}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_expressions!
|
49
|
+
raise ArgumentError, "nested_expression must be an array" unless @nested_expression.is_a?(Array)
|
50
|
+
|
51
|
+
not_expressions = @nested_expression.map(&:class).reject do |k|
|
52
|
+
[GroupingExpression, SimpleExpression].include? k
|
53
|
+
end
|
54
|
+
|
55
|
+
if not_expressions.size > 0
|
56
|
+
raise ArgumentError,
|
57
|
+
"invalid expression class(es): #{not_expressions.map(&:class).join(', ')}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_expressions_size!
|
62
|
+
raise ArgumentError, "at least one expression required" if (@nested_expression.size < 1)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Atomsphere
|
4
|
+
class Query
|
5
|
+
class SimpleExpression
|
6
|
+
attr_accessor :operator, :property, :argument
|
7
|
+
|
8
|
+
OPERATORS = {
|
9
|
+
equals: 1,
|
10
|
+
like: 1,
|
11
|
+
not_equals: 1,
|
12
|
+
is_null: 0,
|
13
|
+
is_not_null: 0,
|
14
|
+
starts_with: 1,
|
15
|
+
between: 2,
|
16
|
+
greater_than: 1,
|
17
|
+
less_than: 1,
|
18
|
+
greater_than_or_equal: 1,
|
19
|
+
less_than_or_equal: 1
|
20
|
+
}
|
21
|
+
|
22
|
+
def initialize(params={})
|
23
|
+
params = {
|
24
|
+
operator: :equals,
|
25
|
+
property: nil,
|
26
|
+
argument: []
|
27
|
+
}.merge(params)
|
28
|
+
|
29
|
+
%w(operator property argument).each do |v|
|
30
|
+
send :"#{v}=", params[v.to_sym]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate!
|
35
|
+
methods.select{ |m| m =~ /^validate_[a-z0-9_]\!$/ }.each{ |v| send(v) }
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_hash
|
40
|
+
{
|
41
|
+
expression: {
|
42
|
+
operator: operator.upcase,
|
43
|
+
property: property,
|
44
|
+
argument: [*argument]
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_json
|
50
|
+
to_hash.to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def validate_operator!
|
55
|
+
unless OPERATORS.include? operator
|
56
|
+
raise ArgumentError, "operator must be one of #{OPERATORS.join(', ')}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_property!
|
61
|
+
raise ArgumentError, "property must be specified" unless @property
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_argument!
|
65
|
+
unless argument.is_a?(Array) && argument.size.eql?(OPERATORS[operator])
|
66
|
+
raise ArgumentError, "'#{operator}' expects #{OPERATORS[operator]} argument(s)"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atomsphere
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Warren Guy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rotp
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: facets
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
description:
|
42
|
+
email: warren@guy.net.au
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- ".gitignore"
|
48
|
+
- Gemfile
|
49
|
+
- LICENSE
|
50
|
+
- README.md
|
51
|
+
- atomsphere.gemspec
|
52
|
+
- lib/atomsphere.rb
|
53
|
+
- lib/atomsphere/action.rb
|
54
|
+
- lib/atomsphere/action/change_listener_status.rb
|
55
|
+
- lib/atomsphere/action/execute_process.rb
|
56
|
+
- lib/atomsphere/action/get_assignable_roles.rb
|
57
|
+
- lib/atomsphere/api.rb
|
58
|
+
- lib/atomsphere/api/client.rb
|
59
|
+
- lib/atomsphere/api/response.rb
|
60
|
+
- lib/atomsphere/configuration.rb
|
61
|
+
- lib/atomsphere/query.rb
|
62
|
+
- lib/atomsphere/query/grouping_expression.rb
|
63
|
+
- lib/atomsphere/query/simple_expression.rb
|
64
|
+
homepage: https://github.com/warrenguy/atomsphere-ruby
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata:
|
68
|
+
source_code_uri: https://github.com/warrenguy/atomsphere-ruby
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.2'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubygems_version: 3.0.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Unofficial Ruby client for the Dell Boomi Atomsphere API
|
88
|
+
test_files: []
|