cts-mpx 1.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.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/.rspec +2 -0
- data/.rubocop.yml +88 -0
- data/CONTRIBUTING +8 -0
- data/COPYRIGHT +10 -0
- data/EXAMPLES.md +81 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +172 -0
- data/Guardfile +41 -0
- data/LICENSE +201 -0
- data/NOTICE +9 -0
- data/README.md +60 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/data_services.json +423 -0
- data/config/ingest_services.json +14 -0
- data/config/root_registry_sea1.json +118 -0
- data/config/web_services.json +544 -0
- data/cts-mpx.gemspec +43 -0
- data/examples/basic_query.rb +23 -0
- data/examples/login.rb +7 -0
- data/examples/update_media.rb +16 -0
- data/examples/update_procedurally.rb +20 -0
- data/lib/cts/mpx.rb +42 -0
- data/lib/cts/mpx/driver.rb +47 -0
- data/lib/cts/mpx/driver/assemblers.rb +96 -0
- data/lib/cts/mpx/driver/connections.rb +41 -0
- data/lib/cts/mpx/driver/exceptions.rb +50 -0
- data/lib/cts/mpx/driver/helpers.rb +67 -0
- data/lib/cts/mpx/driver/page.rb +38 -0
- data/lib/cts/mpx/driver/request.rb +60 -0
- data/lib/cts/mpx/driver/response.rb +72 -0
- data/lib/cts/mpx/entries.rb +80 -0
- data/lib/cts/mpx/entry.rb +100 -0
- data/lib/cts/mpx/field.rb +38 -0
- data/lib/cts/mpx/fields.rb +120 -0
- data/lib/cts/mpx/query.rb +115 -0
- data/lib/cts/mpx/registry.rb +60 -0
- data/lib/cts/mpx/service.rb +70 -0
- data/lib/cts/mpx/services.rb +113 -0
- data/lib/cts/mpx/services/data.rb +124 -0
- data/lib/cts/mpx/services/ingest.rb +60 -0
- data/lib/cts/mpx/services/web.rb +90 -0
- data/lib/cts/mpx/user.rb +74 -0
- data/lib/cts/mpx/validators.rb +51 -0
- data/lib/cts/mpx/version.rb +6 -0
- data/sdk-ring-diagram.png +0 -0
- data/sdk-uml.png +0 -0
- data/uml.nomnoml +242 -0
- metadata +401 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Driver
|
4
|
+
# <Description>
|
5
|
+
# @attribute entries
|
6
|
+
# @return [Array] array of deserialized entries
|
7
|
+
# @attribute xmlns
|
8
|
+
# @return [Hash] active namespace received for this page
|
9
|
+
class Page
|
10
|
+
extend Creatable
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
attribute name: 'entries', kind_of: Array
|
14
|
+
attribute name: 'xmlns', kind_of: Hash
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@entries = []
|
18
|
+
@xmlns = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# return a json copy of the object, useful for later interpreation
|
22
|
+
# @param [Object] indent_depth sets indent depth to 2 if not nil
|
23
|
+
# @return [String] json serialized copy of the page
|
24
|
+
def to_s(indent_depth = nil)
|
25
|
+
indent_depth = 2 if indent_depth
|
26
|
+
|
27
|
+
Oj.dump(
|
28
|
+
{
|
29
|
+
"xmlns" => xmlns,
|
30
|
+
"entries" => entries
|
31
|
+
},
|
32
|
+
indent: indent_depth
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Driver
|
4
|
+
#
|
5
|
+
# A single request of any type to the services.
|
6
|
+
#
|
7
|
+
# @attribute method
|
8
|
+
# @return [Symbol] type of rest method, GET, PUT, POST, DELETE
|
9
|
+
# @attribute url
|
10
|
+
# @return [String] url to make the request against
|
11
|
+
# @attribute query
|
12
|
+
# @return [Hash] query to send with the request
|
13
|
+
# @attribute payload
|
14
|
+
# @return [String] payload to be sent to the services
|
15
|
+
# @attribute response
|
16
|
+
# @return [Cts::Mpx::Driver::Response] response from the service
|
17
|
+
# @attribute headers
|
18
|
+
# @return [Hash] headers to transmit to the services along with the request
|
19
|
+
class Request
|
20
|
+
extend Creatable
|
21
|
+
|
22
|
+
attribute name: 'method', kind_of: Symbol
|
23
|
+
attribute name: 'url', kind_of: String
|
24
|
+
attribute name: 'query', kind_of: Hash
|
25
|
+
attribute name: 'payload', kind_of: String
|
26
|
+
attribute name: 'response', kind_of: ::Cts::Mpx::Driver::Response
|
27
|
+
attribute name: 'headers', kind_of: Hash
|
28
|
+
|
29
|
+
# Call the built request.
|
30
|
+
# @raise [RuntimeException] if the method is not a get, put, post or delete
|
31
|
+
# @raise [RuntimeException] if the url is not a valid reference
|
32
|
+
# @return [Cts::Mpx::Driver::Response] response from the service
|
33
|
+
def call
|
34
|
+
@headers ||= {}
|
35
|
+
@query ||= {}
|
36
|
+
|
37
|
+
call_exceptions method, url
|
38
|
+
socket = Connections[url]
|
39
|
+
params = {
|
40
|
+
headers: @headers,
|
41
|
+
path: URI.parse(url).path,
|
42
|
+
query: @query
|
43
|
+
}
|
44
|
+
params[:body] = payload if payload
|
45
|
+
|
46
|
+
r = socket.send method, params
|
47
|
+
@response = Response.create original: r
|
48
|
+
@response
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def call_exceptions(method, url)
|
54
|
+
raise "#{method} is not a valid method" unless %i[get put post delete].include? method.downcase
|
55
|
+
raise "#{url} is not a valid reference" unless Cts::Mpx::Validators.reference? url
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
module Driver
|
4
|
+
#
|
5
|
+
# Class to contain a response from the services, has a few helper methods to make reading the data easier.
|
6
|
+
#
|
7
|
+
class Response
|
8
|
+
extend Creatable
|
9
|
+
|
10
|
+
# @!attribute original
|
11
|
+
# @return [Excon::Response] copy of the original excon response.
|
12
|
+
attribute name: 'original', kind_of: Excon::Response
|
13
|
+
|
14
|
+
#
|
15
|
+
# Hash output of the data returned from the services.
|
16
|
+
#
|
17
|
+
# @return [Hash] Hash including keys specific to the service and type of service.
|
18
|
+
#
|
19
|
+
def data
|
20
|
+
return @data if @data
|
21
|
+
|
22
|
+
raise 'response does not appear to be healthy' unless healthy?
|
23
|
+
|
24
|
+
begin
|
25
|
+
@data = Oj.load(original.body)
|
26
|
+
rescue Oj::ParseError => e
|
27
|
+
raise "could not parse data: #{e}"
|
28
|
+
end
|
29
|
+
@data
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Is the response healthy? did it have a status code outside 2xx or 3xx.
|
34
|
+
#
|
35
|
+
# @return [TrueFalse] false if status <= 199 or => 400, otherwise true.
|
36
|
+
#
|
37
|
+
def healthy?
|
38
|
+
return false if status <= 199 || status >= 400
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Does this response contain a service exception
|
44
|
+
#
|
45
|
+
# @return [TrueFalse] true if it does, false if it does not.
|
46
|
+
#
|
47
|
+
def service_exception?
|
48
|
+
data['isException'] == true
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# a page of data, processes the response.data for any entries.
|
53
|
+
#
|
54
|
+
# @return [Cts::Mpx::Driver::Page] a page of data.
|
55
|
+
#
|
56
|
+
def page
|
57
|
+
raise 'response does not appear to be healthy' unless healthy?
|
58
|
+
Cts::Mpx::Driver::Page.create entries: data['entries'], xmlns: data['$xmlns']
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Status code of the response
|
63
|
+
#
|
64
|
+
# @return [Fixnum] http status code
|
65
|
+
#
|
66
|
+
def status
|
67
|
+
original.status || nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
# Enumerable collection that can store an entry in it
|
4
|
+
# @attribute collection storage for the individual entry
|
5
|
+
# @return [Entry[]]
|
6
|
+
class Entries
|
7
|
+
include Enumerable
|
8
|
+
include Driver
|
9
|
+
extend Creatable
|
10
|
+
|
11
|
+
attribute name: 'collection', kind_of: Array
|
12
|
+
|
13
|
+
# Create a new entries collection from a page
|
14
|
+
# @param [Page] page the page object to process
|
15
|
+
# @raise [ArgumentError] if :page is not available
|
16
|
+
# @return [Entries] a new entries collection
|
17
|
+
def self.create_from_page(page)
|
18
|
+
Exceptions.raise_unless_argument_error? page, Page
|
19
|
+
entries = new
|
20
|
+
page.entries.each do |e|
|
21
|
+
entry = Entry.new
|
22
|
+
entry.fields = Fields.create_from_data(data: e, xmlns: page.xmlns)
|
23
|
+
entry.id = entry.fields['id'] if entry.fields['id']
|
24
|
+
entries.add entry
|
25
|
+
end
|
26
|
+
entries
|
27
|
+
end
|
28
|
+
|
29
|
+
# Addressable method, indexed by entry object
|
30
|
+
# @param [Entry] key the entry to return
|
31
|
+
# @return [Self.collection,Entry,nil] Can return the collection, a single entry, or nil if nothing found
|
32
|
+
def [](key = nil)
|
33
|
+
return @collection unless key
|
34
|
+
@collection.find { |e| e.id == key }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Add an entry object to the collection
|
38
|
+
# @param [Entry] entry instantiated Entry to include
|
39
|
+
# @raise [ArgumentError] if entry is not an Entry
|
40
|
+
# @return [Self]
|
41
|
+
def add(entry)
|
42
|
+
return self if @collection.include? entry
|
43
|
+
Exceptions.raise_unless_argument_error? entry, Entry
|
44
|
+
@collection.push entry
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# Iterator method for self
|
49
|
+
# @return [Entry] next object in the list
|
50
|
+
def each
|
51
|
+
@collection.each { |c| yield c }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Reset the entry array to a blank state
|
55
|
+
# @return [Void]
|
56
|
+
def initialize
|
57
|
+
reset
|
58
|
+
end
|
59
|
+
|
60
|
+
# Remove a entry object from the collection
|
61
|
+
# @param [Entry] argument instantiated Entry to remove
|
62
|
+
# @return [Self]
|
63
|
+
def remove(argument)
|
64
|
+
@collection.delete_if { |f| f == argument }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Reset the entry array to a blank state
|
68
|
+
# @return [Void]
|
69
|
+
def reset
|
70
|
+
@collection = []
|
71
|
+
end
|
72
|
+
|
73
|
+
# A hash of all available entries
|
74
|
+
# @return [Hash]
|
75
|
+
def to_h
|
76
|
+
map(&:to_h)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
# ORM style class to contain any entry from the data services.
|
4
|
+
class Entry
|
5
|
+
extend Creatable
|
6
|
+
|
7
|
+
attribute name: 'endpoint', kind_of: String
|
8
|
+
attribute name: 'fields', kind_of: Fields
|
9
|
+
attribute name: 'id', kind_of: String
|
10
|
+
attribute name: 'service', kind_of: String
|
11
|
+
|
12
|
+
# Load a Entry based on a long form ID
|
13
|
+
# @param [User] user user to make calls with
|
14
|
+
# @param [String] id long form id to look up
|
15
|
+
# @param [String] fields comma delimited list of fields to collect
|
16
|
+
# @return [Entry] the resulting entry
|
17
|
+
def self.load_by_id(user: nil, id: nil, fields: nil)
|
18
|
+
Driver::Helpers.required_arguments %i[user id], binding
|
19
|
+
|
20
|
+
Driver::Exceptions.raise_unless_argument_error? user, User
|
21
|
+
Driver::Exceptions.raise_unless_reference? id
|
22
|
+
|
23
|
+
e = new
|
24
|
+
e.id = id
|
25
|
+
e.load user: user, fields: nil
|
26
|
+
e
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return the id of the entry.
|
30
|
+
# @return [Entry] the resulting entry
|
31
|
+
def id
|
32
|
+
fields['id']
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set the id of the entry, will check if it's a valid reference.
|
36
|
+
# @param [String] account_id account_id to set the entry to
|
37
|
+
# @return [Entry] the resulting entry
|
38
|
+
def id=(account_id)
|
39
|
+
Driver::Exceptions.raise_unless_reference? account_id
|
40
|
+
result = Services.from_url account_id
|
41
|
+
fields['id'] = account_id
|
42
|
+
|
43
|
+
@service = result[:service]
|
44
|
+
@endpoint = result[:endpoint]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Initialize an entry.
|
48
|
+
# Currently only instantiates fields.
|
49
|
+
def initialize
|
50
|
+
@fields = Fields.new
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return a [Hash] of the entry.
|
54
|
+
# @return [Hash] includes keys xmlns: [Hash] and entries: [Fields]
|
55
|
+
def to_h
|
56
|
+
{
|
57
|
+
xmlns: fields.xmlns,
|
58
|
+
entry: fields.to_h
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# Load data from the remote services based on the id.
|
63
|
+
# @param [User] user user to make calls with
|
64
|
+
# @param [String] fields comma delimited list of fields to collect
|
65
|
+
# @return [Driver::Response] Response of the call.
|
66
|
+
def load(user: nil, fields: nil)
|
67
|
+
Driver::Helpers.required_arguments %i[user], binding
|
68
|
+
|
69
|
+
Driver::Exceptions.raise_unless_argument_error? user, User
|
70
|
+
Driver::Exceptions.raise_unless_argument_error? fields, String if fields
|
71
|
+
Driver::Exceptions.raise_unless_reference? id
|
72
|
+
|
73
|
+
response = Services::Data.get user: user, service: service, endpoint: endpoint, fields: fields, ids: id.split("/").last
|
74
|
+
self.fields.parse data: response.data['entries'].first, xmlns: response.data['xmlns']
|
75
|
+
response
|
76
|
+
end
|
77
|
+
|
78
|
+
# Save the entry to the remote services.
|
79
|
+
# @param [User] user user to make calls with
|
80
|
+
# @return [Driver::Response] Response of the call.
|
81
|
+
def save(user: nil)
|
82
|
+
Driver::Helpers.required_arguments %i[user], binding
|
83
|
+
Driver::Exceptions.raise_unless_argument_error? user, User
|
84
|
+
|
85
|
+
p = Driver::Page.create entries: [fields.to_h], xmlns: fields.xmlns
|
86
|
+
|
87
|
+
if id
|
88
|
+
response = Services::Data.put user: user, service: service, endpoint: endpoint, page: p
|
89
|
+
else
|
90
|
+
raise ArgumentError, "service is a required keyword" unless service
|
91
|
+
raise ArgumentError, "endpoint is a required keyword" unless endpoint
|
92
|
+
|
93
|
+
response = Services::Data.post user: user, service: service, endpoint: endpoint, page: p
|
94
|
+
end
|
95
|
+
|
96
|
+
response
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
# Indivudal field, contains the name, value, and an optional namespace
|
4
|
+
# @attribute name name of the field
|
5
|
+
# @return [String]
|
6
|
+
# @attribute value value of the field
|
7
|
+
# @return [Object]
|
8
|
+
# @attribute xmlns namespace of the field
|
9
|
+
# @return [Hash]
|
10
|
+
class Field
|
11
|
+
extend Creatable
|
12
|
+
|
13
|
+
attribute name: 'name', kind_of: String
|
14
|
+
attribute name: 'value'
|
15
|
+
attribute name: 'xmlns', kind_of: Hash
|
16
|
+
|
17
|
+
# Return just the name value as key/value
|
18
|
+
# @return [Hash]
|
19
|
+
def to_h
|
20
|
+
{ name => value }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Determines if this field is a custom field or not
|
24
|
+
# @return [Symbol] :internal or :custom if it is a custom field
|
25
|
+
def type
|
26
|
+
return :custom if name.include? "$"
|
27
|
+
:internal
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the namespace of the field
|
31
|
+
# @param [Hash] xmlns namespace of the fields
|
32
|
+
# @return [Void]
|
33
|
+
def xmlns=(xmlns)
|
34
|
+
@xmlns = xmlns if name.include? '$'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Cts
|
2
|
+
module Mpx
|
3
|
+
# Enumerable collection that can store an entry field in it
|
4
|
+
# @attribute collection storage for the individual field
|
5
|
+
# @return [Field[]]
|
6
|
+
class Fields
|
7
|
+
include Enumerable
|
8
|
+
extend Creatable
|
9
|
+
|
10
|
+
attribute name: 'collection', kind_of: Array
|
11
|
+
|
12
|
+
# Create a new fields collection from a data hash
|
13
|
+
# @param [Hash] data raw fields to add
|
14
|
+
# @param [Hash] xmlns namespace of the fields
|
15
|
+
# @raise [ArgumentError] if :data or :xmlns are not provided
|
16
|
+
# @return [Fields] a new fields collection
|
17
|
+
def self.create_from_data(data: nil, xmlns: nil)
|
18
|
+
Driver::Helpers.required_arguments([:data], binding)
|
19
|
+
obj = new
|
20
|
+
obj.parse(data: data, xmlns: xmlns)
|
21
|
+
obj
|
22
|
+
end
|
23
|
+
|
24
|
+
# Addressable method, indexed by field name
|
25
|
+
# @param [String] key name of the field
|
26
|
+
# @return [Self.collection,Field,nil] Can return the collection, a single field, or nil if nothing found
|
27
|
+
def [](key = nil)
|
28
|
+
return @collection unless key
|
29
|
+
result = @collection.find { |f| f.name == key }
|
30
|
+
return result.value if result
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Addresable set method, indexed by field name
|
35
|
+
# @note will create a new copy if it is not found in the collection
|
36
|
+
# @param [String] key name of the field
|
37
|
+
# @param [Object] value value of the field
|
38
|
+
# @param [Hash] xmlns namespace of the field
|
39
|
+
# @example to include xmlns, you need to use the long format of this method
|
40
|
+
# fields.[]= 'id', 'value', xmlns: {}
|
41
|
+
# @return [Void]
|
42
|
+
def []=(key, value, xmlns: nil)
|
43
|
+
existing_field = find { |f| f.name == key }
|
44
|
+
if existing_field
|
45
|
+
existing_field.value = value
|
46
|
+
else
|
47
|
+
add Field.create name: key, value: value, xmlns: xmlns
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Add a field object to the collection
|
52
|
+
# @param [Field] field instantiated Field to include
|
53
|
+
# @raise [ArgumentError] if field is not a Field
|
54
|
+
# @return [Self]
|
55
|
+
def add(field)
|
56
|
+
return self if @collection.include? field
|
57
|
+
Driver::Exceptions.raise_unless_argument_error? field, Field
|
58
|
+
@collection.push field
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Iterator method for self
|
63
|
+
# @return [Field] next object in the list
|
64
|
+
def each
|
65
|
+
@collection.each { |c| yield c }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Reset the field array to a blank state
|
69
|
+
# @return [Void]
|
70
|
+
def initialize
|
71
|
+
reset
|
72
|
+
end
|
73
|
+
|
74
|
+
# Parse two hashes into a field array
|
75
|
+
# @note this will also set the collection
|
76
|
+
# @param [Hash] xmlns namespace
|
77
|
+
# @param [Hash] data fields in hash form
|
78
|
+
# @raise [ArgumentError] if xmlns is not a Hash
|
79
|
+
# @return [Field[]] returns a collection of fields
|
80
|
+
def parse(xmlns: nil, data: nil)
|
81
|
+
Driver::Exceptions.raise_unless_argument_error? data, Hash
|
82
|
+
data.delete :service
|
83
|
+
data.delete :endpoint
|
84
|
+
reset
|
85
|
+
@collection = data.map { |k, v| Field.create name: k.to_s, value: v, xmlns: xmlns }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Remove a field object from the collection
|
89
|
+
# @param [String] name instantiated Field to remove
|
90
|
+
# @return [Self]
|
91
|
+
def remove(name)
|
92
|
+
@collection.delete_if { |f| f.name == name }
|
93
|
+
end
|
94
|
+
|
95
|
+
# Reset the field array to a blank state
|
96
|
+
# @return [Void]
|
97
|
+
def reset
|
98
|
+
@collection = []
|
99
|
+
end
|
100
|
+
|
101
|
+
# return the fields as a hash
|
102
|
+
# @return [Hash] key is name, value is value
|
103
|
+
def to_h
|
104
|
+
h = {}
|
105
|
+
each { |f| h.store f.name, f.value }
|
106
|
+
h
|
107
|
+
end
|
108
|
+
|
109
|
+
# Return the cumulative namespace of all Field's in the collection
|
110
|
+
# @return [Hash] key is the namespace key, value is the value
|
111
|
+
def xmlns
|
112
|
+
a = collection.map(&:xmlns).uniq
|
113
|
+
a.delete nil
|
114
|
+
h = {}
|
115
|
+
a.each { |e| h.merge! e }
|
116
|
+
h
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|