oracle_ows 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ce372d91dfb83a8c32a81b57731df0c80460ac439b21bbf3591505b6de8424bf
4
+ data.tar.gz: 54cd96415f562f88ddc692db212742d5e30676ae37736dce9e52ec67e96fbc0e
5
+ SHA512:
6
+ metadata.gz: 1f45f472cefefba5ea8e8e54db5eb0dce589d9242b5cee32755ada0972c77168da42cd5094b2a7b25da0e7951cb6327cbd57d6d133e9daa13aaf8518aa552a74
7
+ data.tar.gz: 44322bda7acec1c7239669190e482a60c6be79d36625a34e081b4bf26f9e14bc0ab9c886e5bf664f475632473ff4062e24701e09c978f57ac4facd7253803ae2
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # If any of the configuration keys above are not set, your application will
4
+ # raise an error during initialization. This method is preferred because it
5
+ # prevents runtime errors in a production application due to improper
6
+ # configuration.
7
+ Dotenv.require_keys('URL', 'USERNAME', 'PASSWORD')
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # environment
4
+ require 'dotenv/load'
5
+ # load config for gem
6
+ require 'config/dotenv'
7
+
8
+ # gem components
9
+ #
10
+ # base components
11
+ require 'oracle_ows/base'
12
+ require 'oracle_ows/error'
13
+
14
+ # feature components
15
+ #
16
+ require 'oracle_ows/guest_services'
17
+ require 'oracle_ows/house_keeping'
18
+ require 'oracle_ows/information'
19
+ require 'oracle_ows/reservation'
20
+ require 'oracle_ows/resv_advanced'
21
+ require 'oracle_ows/version'
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/common'
4
+
5
+ #
6
+ # Oracle Hospitality OPERA Web Self-Service
7
+ # (Specifications)[https://docs.oracle.com/cd/E90572_01/index.html]
8
+ #
9
+ module OracleOWS
10
+ #
11
+ # OracleOws::Base stores basic parameters to connect to the service
12
+ #
13
+ class Base
14
+ include OracleOWS::Common
15
+
16
+ #
17
+ # Instantiates the OracleOWS::Base object
18
+ #
19
+ # @param [Hash] options contains a hash of parameters to beused for every API call
20
+ # @option options [String] :url base URL of the SOAP API endpoint
21
+ # @option options [String] :username login username
22
+ # @option options [String] :password password to use
23
+ # @option options [Hash] :namespaces a hash of XML namespaces to use as headers
24
+ #
25
+ def initialize(options = {})
26
+ # { url: 'http://some.domain/path/' }
27
+ @url = options[:url]
28
+ # { username: 'abc' }
29
+ @username = options[:username]
30
+ # { password: 'abc' }
31
+ @password = options[:password]
32
+ # basic namespaces required at least, to begin with
33
+ @namespaces = {
34
+ 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
35
+ 'xmlns:cor' => 'http://webservices.micros.com/og/4.3/Core/'
36
+ }
37
+ # merge any additional given namespaces
38
+ @namespaces.merge!(options[:namespaces] || {})
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'savon'
4
+
5
+ #
6
+ # OracleOws::Common
7
+ #
8
+ module OracleOWS
9
+ # common methods to include in all classes
10
+ module Common
11
+ # @return [String] url => base URL for the API endpoint
12
+ # @return [String] username => login to use like ENV['ORACLE_OWS_LOGIN']
13
+ # @return [String] password => password to use like ENV['ORACLE_OWS_PASSWORD']
14
+ # @return [Hash] namespaces => a hash of XML namespaces for SOAP header
15
+ #
16
+ # Example:
17
+ # !{
18
+ # 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
19
+ # 'xmlns:cor' => 'http://webservices.micros.com/og/4.3/Core/'
20
+ # }
21
+ attr_accessor :url, :username, :password
22
+ # # @return [OracleOws::Base] base class object holds connection parameters
23
+ # attr_accessor :base
24
+ # @return [Hash] XML namesspaces as hash
25
+ # {#namespaces=} writer method adds more namespaces to the hash
26
+ attr_reader :namespaces
27
+
28
+ #
29
+ # Merges existing namespaces hash with additional values
30
+ #
31
+ # @param [Hash] hash of XML namespaces to be used additionally
32
+ #
33
+ # @return [Hash] hash of all namespaces merged together
34
+ #
35
+ def namespaces=(hash = {})
36
+ hash = {} unless hash.is_a? Hash
37
+
38
+ @namespaces ||= {}
39
+ @namespaces.merge!(hash)
40
+ end
41
+
42
+ private
43
+
44
+ #
45
+ # soap client object to make API calls
46
+ #
47
+ # @return [Savon::Client] client object ready to make calls
48
+ #
49
+ def soap_client
50
+ # authentication
51
+ credentials = { 'cor:UserName' => username, 'cor:UserPassword' => password }
52
+ # required SOAP header
53
+ soap_header = { 'cor:OGHeader' => { 'cor:Authentication' => { 'cor:UserCredentials' => credentials } } }
54
+ # logging options
55
+ log_options = { log_level: :debug, log: true, pretty_print_xml: true }
56
+ # class name of caller object
57
+ klass_name = self.class.name.split('::').last
58
+ # WSDL endpoint is derived from ClassName
59
+ options = { wsdl: "#{url}/#{klass_name}.asmx?WSDL", namespaces: namespaces, soap_header: soap_header }
60
+ # SOAP client
61
+ Savon.client(options.merge(log_options))
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # OracleOws::Error handler for the gem
5
+ #
6
+ module OracleOWS
7
+ #
8
+ # Custom error handling
9
+ #
10
+ class Error < StandardError; end
11
+ # Error handling code goes here...
12
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/base'
4
+
5
+ #
6
+ # OracleOws::GuestServices
7
+ #
8
+ module OracleOWS
9
+ #
10
+ # [Guest Services Web Service]
11
+ # {https://docs.oracle.com/cd/E90572_01/docs/Guest%20Services%20Web%20Service%20Specification.htm}
12
+ #
13
+ class GuestServices < Base
14
+ #
15
+ # Initialize
16
+ #
17
+ # @param [Hash] object with connection parameters
18
+ #
19
+ def initialize(options = {})
20
+ # call the parent method, all arguments passed
21
+ super
22
+
23
+ # we need these for API calls
24
+ more_namespaces = {
25
+ 'xmlns:gue' => 'http://webservices.micros.com/og/4.3/GuestServices/',
26
+ 'xmlns:hot' => 'http://webservices.micros.com/og/4.3/HotelCommon/'
27
+ }
28
+ # merge base + additional namespaces
29
+ @namespaces.merge!(more_namespaces)
30
+ end
31
+
32
+ #
33
+ # Update Room Status
34
+ #
35
+ # @param [Hash] options to update the room status
36
+ # @option options [String] :hotel_code code of the hotel
37
+ # @option options [Numeric, String] :room number to update
38
+ #
39
+ # @return [Hash] result hash extracted from the deply nested XML
40
+ #
41
+ def update_room_status(options = {})
42
+ # save resources if we have nothing to do
43
+ return {} if options.blank?
44
+
45
+ # make the SOAP API call
46
+ response = soap_client.call(
47
+ # endpoint action
48
+ :update_room_status,
49
+ # payload
50
+ message: {
51
+ 'HotelReference' => {
52
+ '@hotelCode' => options[:hotel_code]
53
+ },
54
+ 'RoomNumber' => options[:room],
55
+ 'RoomStatus' => 'Clean',
56
+ 'TurnDownStatus' => 'Completed',
57
+ 'GuestServiceStatus' => 'DoNotDisturb'
58
+ }
59
+ )
60
+
61
+ # fetch the response safely (without exception or too many conditional blocks)
62
+ response.body.dig(:update_room_status_response, :result)
63
+
64
+ # handle exceptions gracefully
65
+ rescue OracleOWS::Error => e
66
+ # handle exception gracefully
67
+ ensure
68
+ {} # at least return a blank hash
69
+ end
70
+
71
+ #
72
+ # Wake Up Call
73
+ #
74
+ # @param [Hash] options parameters
75
+ # @option options [String] :hotel_code is the code of the hotel
76
+ # @option options [Numeric, String] :room number
77
+ #
78
+ # @return [Hash] result hash from the deeply nested XML response
79
+ #
80
+ def wake_up_call(options = {})
81
+ return {} if options.blank?
82
+
83
+ response = soap_client.call(
84
+ :wake_up_call,
85
+ message: {
86
+ 'HotelReference' => { '@hotelCode' => options[:hotel_code] },
87
+ 'RoomNumber' => options[:room]
88
+ }
89
+ )
90
+
91
+ # fetch the response safely (without exception or too many conditional blocks)
92
+ response.body.dig(:wake_up_call_response, :result)
93
+
94
+ # handle exceptions gracefully
95
+ rescue OracleOWS::Error => e
96
+ # handle exception gracefully
97
+ ensure
98
+ {} # at least return a blank hash
99
+ end
100
+ end
101
+ # class Hosuekeeping
102
+ end
103
+ # module OracleOws
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/base'
4
+
5
+ #
6
+ # OracleOws::Housekeeping
7
+ #
8
+ module OracleOWS
9
+ #
10
+ # [Housekeeping Web Service]
11
+ # {https://docs.oracle.com/cd/E90572_01/docs/Housekeeping%20Web%20Service%20Specifications.htm}
12
+ #
13
+ class HouseKeeping < Base
14
+ #
15
+ # Initialize
16
+ #
17
+ # @param [Hash] object with connection parameters
18
+ #
19
+ def initialize(options = {})
20
+ # call the parent method, all arguments passed
21
+ super
22
+
23
+ # we need these for API calls
24
+ more_namespaces = {
25
+ 'xmlns:hkeep' => 'http://webservices.micros.com/ows/5.1/HouseKeeping.wsdl',
26
+ 'xmlns:room' => 'http://webservices.micros.com/og/4.3/HouseKeeping/'
27
+ }
28
+ # merge base + additional namespaces
29
+ @namespaces.merge!(more_namespaces)
30
+ end
31
+
32
+ #
33
+ # FetchHouseKeepingRoomStatus
34
+ #
35
+ # @param [Hash] options with parameters
36
+ # @option options [String] :hotel_code is the identifier for the hotel
37
+ # @option options [Hash] :room a hash of :from and :to parameters
38
+ # @option options [Symbol] :from parameter in :room => { :from => 1 }
39
+ # @option options [Symbol] :to parameter in :room => { :to => 1 }
40
+ #
41
+ # @return [Hash] of the result from deeply nested XML response
42
+ #
43
+ def room_status(options = {})
44
+ return {} if options.blank?
45
+
46
+ response = soap_client.call(
47
+ :fetch_house_keeping_room_status,
48
+ message: {
49
+ 'HotelReference' => { '@hotelCode' => options[:hotel_code] },
50
+ 'Criteria' => {
51
+ 'FromRoom' => options[:room][:from],
52
+ 'ToRoom' => options[:room][:to],
53
+ 'RoomStatusList' => { 'Code' => 'CLEAN' },
54
+ 'HKStatusList' => { 'Code' => 'VACANT' },
55
+ 'FOStatusList' => { 'Code' => 'VACANT' },
56
+ 'ReservationStatusList' => { 'Code' => 'STAYOVER' }
57
+ }
58
+ }
59
+ )
60
+
61
+ # fetch the response safely (without exception or too many conditional blocks)
62
+ response.body.dig(:fetch_house_keeping_room_status_response, :result)
63
+
64
+ # handle exceptions gracefully
65
+ rescue OracleOWS::Error => e
66
+ # handle exception gracefully
67
+ ensure
68
+ {} # at least return a blank hash
69
+ end
70
+ end
71
+ # class Hosuekeeping
72
+ end
73
+ # module OracleOws
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/base'
4
+
5
+ #
6
+ # OracleOws::Information
7
+ #
8
+ module OracleOWS
9
+ # [Information Web Service]
10
+ # {https://docs.oracle.com/cd/E90572_01/docs/Information%20Web%20Service%20Specifications.htm}
11
+ class Information < Base
12
+ #
13
+ # initialize the API endpoint object
14
+ #
15
+ # @param [OracleOws::Base] base object with initial parameters
16
+ #
17
+ def initialize(options = {})
18
+ # call the parent method, all arguments passed
19
+ super
20
+
21
+ # we need these for API calls
22
+ more_namespaces = {
23
+ 'xmlns:inf' => 'http://webservices.micros.com/ows/5.1/Information.wsdl'
24
+ }
25
+ # merge base + additional namespaces
26
+ @namespaces.merge!(more_namespaces)
27
+ end
28
+
29
+ # action: hotel information
30
+ # Usage:
31
+ # hotel_information({ hotel_code: 'ABC' })
32
+ def hotel_information(options = {})
33
+ return {} if options.blank?
34
+
35
+ response = soap_client.call(
36
+ :query_hotel_information,
37
+ message: {
38
+ 'HotelInformationQuery' => { '@hotelCode' => options[:hotel_code] }
39
+ }
40
+ )
41
+
42
+ # fetch the response safely (without exception or too many conditional blocks)
43
+ response.body.dig(:hotel_information_response, :result)
44
+
45
+ # handle exceptions gracefully
46
+ rescue OracleOWS::Error => e
47
+ # handle exception gracefully
48
+ ensure
49
+ {} # at least return a blank hash
50
+ end
51
+ end
52
+ # class
53
+ end
54
+ # module OracleOws
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/base'
4
+
5
+ #
6
+ # OracleOws::Reservation
7
+ #
8
+ module OracleOWS
9
+ # [Reservation Web Service]
10
+ # {https://docs.oracle.com/cd/E90572_01/docs/Reservation%20Web%20Service%20Specifications.htm}
11
+ class Reservation < Base
12
+ #
13
+ # initialize
14
+ #
15
+ # @param [Hash] options for connection
16
+ #
17
+ def initialize(options = {})
18
+ # call the parent method, all arguments passed
19
+ super
20
+
21
+ # we need these for API calls
22
+ more_namespaces = {
23
+ 'xmlns:res' => 'http://webservices.micros.com/ows/5.1/Reservation.wsdl',
24
+ 'xmlns:res1' => 'http://webservices.micros.com/og/4.3/Reservation/'
25
+ }
26
+ # merge base + this API namespaces
27
+ @namespaces.merge!(more_namespaces)
28
+ end
29
+
30
+ #
31
+ # PreCheckin
32
+ #
33
+ # @param [Hash] options of parameters for the API call
34
+ # @option options [String] :hotel_code to identify the hotel
35
+ # @option options [String] :chain_code to identify the chain of hotels it belongs to
36
+ # @option options [String] :confirmation number of the check in
37
+ #
38
+ # @return [Hash] result hash from the deeply nested XML response
39
+ #
40
+ def pre_checkin(options = {})
41
+ return {} if options.blank?
42
+
43
+ response = soap_client.call(
44
+ :pre_checkin,
45
+ message: {
46
+ 'HotelReference' => {
47
+ '@hotelCode' => options[:hotel_code],
48
+ '@chainCode' => options[:chain_code]
49
+ },
50
+ 'ConfirmationNumber' => options[:confirmation]
51
+ }
52
+ )
53
+
54
+ # fetch the response safely (without exception or too many conditional blocks)
55
+ response.body.dig(:pre_checkin_response, :result)
56
+
57
+ # handle exceptions gracefully
58
+ rescue OracleOWS::Error => e
59
+ # handle exception gracefully
60
+ ensure
61
+ {} # at least return a blank hash
62
+ end
63
+
64
+ # Usage:
65
+ # method({ hotel_code: 'ABC', type: 'ABC', source: 'ABC' })
66
+ def fetch_booked_inventory_items(options = {})
67
+ return {} if options.blank?
68
+
69
+ response = soap_client.call(
70
+ :fetch_booked_inventory_items,
71
+ message: {
72
+ 'HotelReference' => { '@hotelCode' => options[:hotel_code] } #,
73
+ # 'ConfirmationNumber' => { '@type' => options[:type], '@source' => options[:source] }
74
+ }
75
+ )
76
+
77
+ # fetch the response safely (without exception or too many conditional blocks)
78
+ response.body.dig(:fetch_booked_inventory_items_response, :result)
79
+
80
+ # handle exceptions gracefully
81
+ rescue OracleOWS::Error => e
82
+ # handle exception gracefully
83
+ ensure
84
+ {} # at least return a blank hash
85
+ end
86
+ end
87
+ # class
88
+ end
89
+ # module OracleOws
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oracle_ows/base'
4
+
5
+ #
6
+ # OracleOws::ReservationAdvanced
7
+ #
8
+ module OracleOWS
9
+ # [Reservation Advanced Web Service]
10
+ # {https://docs.oracle.com/cd/E90572_01/docs/Reservation%20Advanced%20Web%20Service%20Specifications.htm}
11
+ class ResvAdvanced < Base
12
+ #
13
+ # initialize the object
14
+ #
15
+ # @param [OracleOws::Base] base parameters
16
+ #
17
+ def initialize(options = {})
18
+ # call the parent method, all arguments passed
19
+ super
20
+
21
+ # we need these for API calls
22
+ more_namespaces = {
23
+ 'xmlns:rsa' => 'http://webservices.micros.com/og/4.3/ResvAdvanced/',
24
+ 'xmlns:com' => 'http://webservices.micros.com/og/4.3/Common/',
25
+ 'xmlns:hot' => 'http://webservices.micros.com/og/4.3/HotelCommon/',
26
+ 'xmlns:res' => 'http://webservices.micros.com/og/4.3/Reservation/'
27
+ }
28
+ # merge base + additional namespaces
29
+ @namespaces.merge!(more_namespaces)
30
+ end
31
+
32
+ #
33
+ # CheckIn
34
+ #
35
+ # @param [Hash] options for API call
36
+ # @option options [String] :hotel_code to identify the hotel
37
+ # @option options [String] :key_1 Key #1
38
+ # @option options [String] :key_2 Key #2
39
+ # @option options [String] :key_3 Key #3
40
+ # @option options [String] :key_4 Key #4
41
+ #
42
+ # @return [Hash] result hash from deeply nested XML Response
43
+ #
44
+ def checkin(options = {})
45
+ return {} if options.blank?
46
+
47
+ response = soap_client.call(
48
+ :check_in,
49
+ message: {
50
+ 'ReservationRequest' => {
51
+ 'HotelReference' => { '@hotelCode' => options[:hotel_code] },
52
+ 'KeyTrack' => {
53
+ '@Key1Track' => options[:key_1],
54
+ '@Key2Track' => options[:key_2],
55
+ '@Key3Track' => options[:key_3],
56
+ '@Key4Track' => options[:key_4]
57
+ }
58
+ }
59
+ }
60
+ )
61
+
62
+ # fetch the response safely (without exception or too many conditional blocks)
63
+ response.body.dig(:check_in_response, :result)
64
+
65
+ # handle exceptions gracefully
66
+ rescue OracleOWS::Error => e
67
+ # handle exception gracefully
68
+ ensure
69
+ {} # at least return a blank hash
70
+ end
71
+
72
+ #
73
+ # CheckOut
74
+ #
75
+ # @param [Hash] options for API call
76
+ # @option options [String] :hotel_code to identify the hotel
77
+ # @option options [String] :key_1 Key #1
78
+ # @option options [String] :key_2 Key #2
79
+ # @option options [String] :key_3 Key #3
80
+ # @option options [String] :key_4 Key #4
81
+ #
82
+ # @return [Hash] result hash from deeply nested XML Response
83
+ #
84
+ def checkout(options = {})
85
+ return {} if options.blank?
86
+
87
+ response = soap_client.call(
88
+ :check_out,
89
+ message: {
90
+ 'ReservationRequest' => {
91
+ 'HotelReference' => { '@hotelCode' => options[:hotel_code] },
92
+ 'KeyTrack' => {
93
+ '@Key1Track' => options[:key_1],
94
+ '@Key2Track' => options[:key_2],
95
+ '@Key3Track' => options[:key_3],
96
+ '@Key4Track' => options[:key_4]
97
+ }
98
+ }
99
+ }
100
+ )
101
+
102
+ # fetch the response safely (without exception or too many conditional blocks)
103
+ response.body.dig(:check_out_response, :result)
104
+
105
+ # handle exceptions gracefully
106
+ rescue OracleOWS::Error => e
107
+ # handle exception gracefully
108
+ ensure
109
+ {} # at least return a blank hash
110
+ end
111
+ end
112
+ # class
113
+ end
114
+ # module OracleOws
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Version of this gem
5
+ #
6
+ module OracleOWS
7
+ VERSION = '0.2.1'
8
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oracle_ows
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Ram
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: savon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.12'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.12'
27
+ description: Oracle Hospitality OPERA Web Self-Service
28
+ email:
29
+ - RamOnRails@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/config/dotenv.rb
35
+ - lib/oracle_ows.rb
36
+ - lib/oracle_ows/base.rb
37
+ - lib/oracle_ows/common.rb
38
+ - lib/oracle_ows/error.rb
39
+ - lib/oracle_ows/guest_services.rb
40
+ - lib/oracle_ows/house_keeping.rb
41
+ - lib/oracle_ows/information.rb
42
+ - lib/oracle_ows/reservation.rb
43
+ - lib/oracle_ows/resv_advanced.rb
44
+ - lib/oracle_ows/version.rb
45
+ homepage: https://github.com/ramonrails/oracle_ows
46
+ licenses:
47
+ - MIT
48
+ metadata:
49
+ homepage_uri: https://github.com/ramonrails/oracle_ows
50
+ source_code_uri: https://github.com/ramonrails/oracle_ows
51
+ changelog_uri: https://github.com/ramonrails/oracle_ows/CHANGELOG.md
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.3.0
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 3.1.2
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Oracle OWS
71
+ test_files: []