restful_mapper 0.0.2 → 0.0.3
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 +4 -4
- data/features/get_request.feature +32 -31
- data/features/non_json_response.feature +3 -4
- data/features/step_definitions/get_request_steps.rb +1 -1
- data/lib/restful_mapper.rb +46 -17
- data/lib/restful_mapper/version.rb +1 -1
- data/restful_mapper.gemspec +1 -0
- metadata +66 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55142b9171e3076f21c36d5a67cb22d463ed51f0
|
4
|
+
data.tar.gz: da22cc24b476a86f5b59ffcbc8bf77f6597d9652
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d3b4537f5c191c92ef22597d7f8842e922366d1f5e7b5e5f4af5a77c91e4b858a32fdf9a15d1ece9f827085a2bd61f3684c5534daf1e55b154ce02af3499080
|
7
|
+
data.tar.gz: 96bfa897c9ecf33ed9b13c48abd14e803b44795433699565e2b1f800bea16b608f747aa2124768136ca2afa9cb9ea95e3158e2e786b87e9f4b2df6ed98a44adf
|
@@ -2,13 +2,13 @@ Feature: get request
|
|
2
2
|
|
3
3
|
Scenario: simple get request without any parameters that returns 200
|
4
4
|
Given following service definition
|
5
|
-
"""
|
5
|
+
"""
|
6
6
|
class SimpleService < RestfulMapper::Service
|
7
7
|
base_url "http://localhost:8765"
|
8
8
|
|
9
9
|
get :simple_endpoint do
|
10
10
|
path "/simple"
|
11
|
-
|
11
|
+
|
12
12
|
responses 200 => {String => String}
|
13
13
|
end
|
14
14
|
|
@@ -16,7 +16,7 @@ Feature: get request
|
|
16
16
|
"""
|
17
17
|
And the service endpoint at port 8765 responds with following http response:
|
18
18
|
"""
|
19
|
-
HTTP/1.1 200 OK
|
19
|
+
HTTP/1.1 200 OK
|
20
20
|
Connection: close
|
21
21
|
Content-Type: application/json
|
22
22
|
|
@@ -28,32 +28,33 @@ Feature: get request
|
|
28
28
|
{"a" => "b"}
|
29
29
|
"""
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
# @wip
|
32
|
+
# Scenario: simple get request without any parameters that returns 302
|
33
|
+
# Given following service definition
|
34
|
+
# """
|
35
|
+
# class SimpleService < RestfulMapper::Service
|
36
|
+
# base_url "http://localhost:8765"
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
responses 302 => true
|
41
|
-
end
|
38
|
+
# get :simple_endpoint do
|
39
|
+
# path "/simple"
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
And the service endpoint at port 8765 responds with following http response:
|
46
|
-
"""
|
47
|
-
HTTP/1.1 302 OK
|
48
|
-
Connection: close
|
49
|
-
Content-Type: application/json
|
41
|
+
# responses 302 => true
|
42
|
+
# end
|
50
43
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
44
|
+
# end
|
45
|
+
# """
|
46
|
+
# And the service endpoint at port 8765 responds with following http response:
|
47
|
+
# """
|
48
|
+
# HTTP/1.1 302 OK
|
49
|
+
# Connection: close
|
50
|
+
# Content-Type: application/json
|
51
|
+
|
52
|
+
# """
|
53
|
+
# When I call service "SimpleService.simple_endpoint"
|
54
|
+
# Then the result should be equal to:
|
55
|
+
# """
|
56
|
+
# true
|
57
|
+
# """
|
57
58
|
|
58
59
|
Scenario: simple get request with request parameters
|
59
60
|
Given following service definition
|
@@ -65,7 +66,7 @@ Feature: get request
|
|
65
66
|
path "/simple"
|
66
67
|
|
67
68
|
query_parameters [:name]
|
68
|
-
|
69
|
+
|
69
70
|
responses 302 => true
|
70
71
|
end
|
71
72
|
|
@@ -87,7 +88,7 @@ Scenario: simple get request with path parameters
|
|
87
88
|
|
88
89
|
get :simple_endpoint do
|
89
90
|
path "/simple/{{name}}"
|
90
|
-
|
91
|
+
|
91
92
|
responses 302 => true
|
92
93
|
end
|
93
94
|
|
@@ -98,7 +99,7 @@ Scenario: simple get request with path parameters
|
|
98
99
|
Then the endpoint should receive request
|
99
100
|
"""
|
100
101
|
GET /simple/test HTTP/1.1
|
101
|
-
|
102
|
+
|
102
103
|
"""
|
103
104
|
|
104
105
|
Scenario: simple get request with path and query parameters
|
@@ -109,7 +110,7 @@ Scenario: simple get request with path and query parameters
|
|
109
110
|
|
110
111
|
get :simple_endpoint do
|
111
112
|
path "/simple/{{name}}"
|
112
|
-
query_parameters [:name]
|
113
|
+
query_parameters [:name]
|
113
114
|
responses 302 => true
|
114
115
|
end
|
115
116
|
|
@@ -120,5 +121,5 @@ Scenario: simple get request with path and query parameters
|
|
120
121
|
Then the endpoint should receive request
|
121
122
|
"""
|
122
123
|
GET /simple/test?name=test HTTP/1.1
|
123
|
-
|
124
|
+
|
124
125
|
"""
|
@@ -1,7 +1,6 @@
|
|
1
1
|
Feature: Handling Non-Json Response
|
2
2
|
|
3
|
-
|
4
|
-
@wip
|
3
|
+
@ok
|
5
4
|
Scenario: mapping to false
|
6
5
|
Given following service definition
|
7
6
|
"""
|
@@ -16,7 +15,7 @@ Feature: Handling Non-Json Response
|
|
16
15
|
|
17
16
|
get :simple_endpoint do
|
18
17
|
path "/simple"
|
19
|
-
|
18
|
+
|
20
19
|
responses 0 => false
|
21
20
|
end
|
22
21
|
|
@@ -24,7 +23,7 @@ Feature: Handling Non-Json Response
|
|
24
23
|
"""
|
25
24
|
And the service endpoint at port 8765 responds with following http response:
|
26
25
|
"""
|
27
|
-
HTTP/1.1 200 OK
|
26
|
+
HTTP/1.1 200 OK
|
28
27
|
Connection: close
|
29
28
|
Content-Type: text/plain
|
30
29
|
|
data/lib/restful_mapper.rb
CHANGED
@@ -4,7 +4,7 @@ require "restful_mapper/version"
|
|
4
4
|
require 'structure_mapper'
|
5
5
|
require 'multi_json'
|
6
6
|
require 'mustache'
|
7
|
-
|
7
|
+
require 'faraday_middleware'
|
8
8
|
|
9
9
|
class Object # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
|
10
10
|
def meta_def name, &blk
|
@@ -13,21 +13,32 @@ class Object # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.htm
|
|
13
13
|
end
|
14
14
|
|
15
15
|
|
16
|
+
class Exception
|
17
|
+
def self.from_content type, content_type, data
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
16
22
|
module RestfulMapper
|
17
23
|
|
18
24
|
class EndpointDefinition
|
19
25
|
|
20
|
-
def initialize base_url, method, basic_authentication
|
26
|
+
def initialize base_url, method, basic_authentication, token
|
21
27
|
@base_url=base_url
|
22
28
|
@query_parameters=[]
|
23
29
|
@method=method
|
24
30
|
@basic_authentication=basic_authentication
|
31
|
+
@token=token
|
25
32
|
end
|
26
33
|
|
27
34
|
def path path, options={}
|
28
35
|
@path=path
|
29
36
|
end
|
30
37
|
|
38
|
+
def verbose
|
39
|
+
@verbose=true
|
40
|
+
end
|
41
|
+
|
31
42
|
def responses response_mapping={}
|
32
43
|
@response_mapping=response_mapping
|
33
44
|
end
|
@@ -49,8 +60,14 @@ module RestfulMapper
|
|
49
60
|
end
|
50
61
|
|
51
62
|
def call_service params
|
52
|
-
|
53
|
-
|
63
|
+
|
64
|
+
puts "base url: %s" % @base_url
|
65
|
+
|
66
|
+
conn = Faraday.new(url: Mustache.render(@base_url, params)) do |faraday|
|
67
|
+
faraday.use FaradayMiddleware::FollowRedirects, limit: 5
|
68
|
+
if @verbose
|
69
|
+
faraday.response :logger
|
70
|
+
end
|
54
71
|
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
55
72
|
end
|
56
73
|
|
@@ -58,38 +75,43 @@ module RestfulMapper
|
|
58
75
|
conn.basic_auth(*basic_authentication_data(params))
|
59
76
|
end
|
60
77
|
|
61
|
-
|
78
|
+
if has_token?
|
79
|
+
conn.authorization :Bearer, Mustache.render(@token, params)
|
80
|
+
end
|
81
|
+
|
82
|
+
path = Mustache.render(@path, params)
|
83
|
+
|
84
|
+
response=conn.run_request(@method, path, nil, {'Content-Type' => 'application/json'}) { |request|
|
62
85
|
request.params.update(filter_parameters(params)) if filter_parameters(params)
|
63
86
|
if @body_parameter
|
64
87
|
request.body=MultiJson.dump(params[@body_parameter].to_structure)
|
65
88
|
end
|
66
|
-
|
67
|
-
|
68
89
|
}
|
69
90
|
|
70
|
-
|
71
91
|
status=response.status
|
72
92
|
status_class=@response_mapping[status]
|
73
93
|
status_class||=@response_mapping[0]
|
74
94
|
body=response.body
|
75
|
-
|
76
|
-
if Exception === result
|
77
|
-
raise result
|
78
|
-
end
|
79
|
-
result
|
95
|
+
deserialize body, response.headers['Content-Type'], status_class
|
80
96
|
end
|
81
97
|
|
82
98
|
def has_basic_authentication?
|
83
99
|
@basic_authentication
|
84
100
|
end
|
85
101
|
|
102
|
+
def has_token?
|
103
|
+
@token
|
104
|
+
end
|
105
|
+
|
86
106
|
def basic_authentication_data params
|
87
107
|
@basic_authentication.map{|name| Symbol === name ? params[name] : name}
|
88
108
|
end
|
89
109
|
|
90
|
-
|
91
110
|
def deserialize json, content_type, mapping
|
92
|
-
if
|
111
|
+
if mapping.is_a?(Class) && Exception >= mapping
|
112
|
+
raise mapping, json
|
113
|
+
end
|
114
|
+
if content_type && content_type.start_with?('application/json')
|
93
115
|
if json && !json.empty?
|
94
116
|
mapping.from_structure(MultiJson.load(json))
|
95
117
|
else
|
@@ -99,9 +121,12 @@ module RestfulMapper
|
|
99
121
|
mapping
|
100
122
|
end
|
101
123
|
end
|
102
|
-
|
124
|
+
elsif mapping.respond_to?(:from_content)
|
103
125
|
mapping.from_content(content_type, json)
|
126
|
+
else
|
127
|
+
mapping
|
104
128
|
end
|
129
|
+
|
105
130
|
end
|
106
131
|
|
107
132
|
|
@@ -143,10 +168,14 @@ module RestfulMapper
|
|
143
168
|
@basic_authentication=[username,password]
|
144
169
|
end
|
145
170
|
|
171
|
+
def self.bearer_authentication token
|
172
|
+
@token=token
|
173
|
+
end
|
174
|
+
|
146
175
|
private
|
147
176
|
|
148
177
|
def self.service_method name, definition, method
|
149
|
-
endpoint_definition=EndpointDefinition.new @base_url, method, @basic_authentication
|
178
|
+
endpoint_definition=EndpointDefinition.new @base_url, method, @basic_authentication, @token
|
150
179
|
endpoint_definition.instance_exec(&definition)
|
151
180
|
self.meta_def(name.to_sym) do |params={}|
|
152
181
|
copy=(@default_parameters || {}).merge(params)
|
data/restful_mapper.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency "sinatra"
|
28
28
|
spec.add_development_dependency "agent"
|
29
29
|
spec.add_dependency "faraday"
|
30
|
+
spec.add_dependency "faraday_middleware"
|
30
31
|
spec.add_dependency "multi_json"
|
31
32
|
spec.add_dependency "structure_mapper"
|
32
33
|
spec.add_dependency "mustache"
|
metadata
CHANGED
@@ -1,183 +1,197 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restful_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dragan Milic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
|
-
- -
|
16
|
+
- - ~>
|
18
17
|
- !ruby/object:Gem::Version
|
19
18
|
version: '1.5'
|
20
|
-
type: :development
|
21
19
|
prerelease: false
|
20
|
+
name: bundler
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
|
-
- -
|
23
|
+
- - ~>
|
25
24
|
- !ruby/object:Gem::Version
|
26
25
|
version: '1.5'
|
26
|
+
type: :development
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
|
-
- -
|
30
|
+
- - '>='
|
32
31
|
- !ruby/object:Gem::Version
|
33
32
|
version: '0'
|
34
|
-
type: :development
|
35
33
|
prerelease: false
|
34
|
+
name: rake
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
37
36
|
requirements:
|
38
|
-
- -
|
37
|
+
- - '>='
|
39
38
|
- !ruby/object:Gem::Version
|
40
39
|
version: '0'
|
40
|
+
type: :development
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
|
-
- -
|
44
|
+
- - '>='
|
46
45
|
- !ruby/object:Gem::Version
|
47
46
|
version: '0'
|
48
|
-
type: :development
|
49
47
|
prerelease: false
|
48
|
+
name: rspec
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
51
50
|
requirements:
|
52
|
-
- -
|
51
|
+
- - '>='
|
53
52
|
- !ruby/object:Gem::Version
|
54
53
|
version: '0'
|
54
|
+
type: :development
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: autotest
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
|
-
- -
|
58
|
+
- - '>='
|
60
59
|
- !ruby/object:Gem::Version
|
61
60
|
version: '0'
|
62
|
-
type: :development
|
63
61
|
prerelease: false
|
62
|
+
name: autotest
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
65
64
|
requirements:
|
66
|
-
- -
|
65
|
+
- - '>='
|
67
66
|
- !ruby/object:Gem::Version
|
68
67
|
version: '0'
|
68
|
+
type: :development
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name: cucumber
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
72
71
|
requirements:
|
73
|
-
- -
|
72
|
+
- - '>='
|
74
73
|
- !ruby/object:Gem::Version
|
75
74
|
version: '0'
|
76
|
-
type: :development
|
77
75
|
prerelease: false
|
76
|
+
name: cucumber
|
78
77
|
version_requirements: !ruby/object:Gem::Requirement
|
79
78
|
requirements:
|
80
|
-
- -
|
79
|
+
- - '>='
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
82
|
+
type: :development
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: puma
|
85
84
|
requirement: !ruby/object:Gem::Requirement
|
86
85
|
requirements:
|
87
|
-
- -
|
86
|
+
- - '>='
|
88
87
|
- !ruby/object:Gem::Version
|
89
88
|
version: '0'
|
90
|
-
type: :development
|
91
89
|
prerelease: false
|
90
|
+
name: puma
|
92
91
|
version_requirements: !ruby/object:Gem::Requirement
|
93
92
|
requirements:
|
94
|
-
- -
|
93
|
+
- - '>='
|
95
94
|
- !ruby/object:Gem::Version
|
96
95
|
version: '0'
|
96
|
+
type: :development
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name: sinatra
|
99
98
|
requirement: !ruby/object:Gem::Requirement
|
100
99
|
requirements:
|
101
|
-
- -
|
100
|
+
- - '>='
|
102
101
|
- !ruby/object:Gem::Version
|
103
102
|
version: '0'
|
104
|
-
type: :development
|
105
103
|
prerelease: false
|
104
|
+
name: sinatra
|
106
105
|
version_requirements: !ruby/object:Gem::Requirement
|
107
106
|
requirements:
|
108
|
-
- -
|
107
|
+
- - '>='
|
109
108
|
- !ruby/object:Gem::Version
|
110
109
|
version: '0'
|
110
|
+
type: :development
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name: agent
|
113
112
|
requirement: !ruby/object:Gem::Requirement
|
114
113
|
requirements:
|
115
|
-
- -
|
114
|
+
- - '>='
|
116
115
|
- !ruby/object:Gem::Version
|
117
116
|
version: '0'
|
118
|
-
type: :development
|
119
117
|
prerelease: false
|
118
|
+
name: agent
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
|
-
- -
|
121
|
+
- - '>='
|
123
122
|
- !ruby/object:Gem::Version
|
124
123
|
version: '0'
|
124
|
+
type: :development
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name: faraday
|
127
126
|
requirement: !ruby/object:Gem::Requirement
|
128
127
|
requirements:
|
129
|
-
- -
|
128
|
+
- - '>='
|
130
129
|
- !ruby/object:Gem::Version
|
131
130
|
version: '0'
|
132
|
-
type: :runtime
|
133
131
|
prerelease: false
|
132
|
+
name: faraday
|
134
133
|
version_requirements: !ruby/object:Gem::Requirement
|
135
134
|
requirements:
|
136
|
-
- -
|
135
|
+
- - '>='
|
137
136
|
- !ruby/object:Gem::Version
|
138
137
|
version: '0'
|
138
|
+
type: :runtime
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name: multi_json
|
141
140
|
requirement: !ruby/object:Gem::Requirement
|
142
141
|
requirements:
|
143
|
-
- -
|
142
|
+
- - '>='
|
144
143
|
- !ruby/object:Gem::Version
|
145
144
|
version: '0'
|
146
|
-
type: :runtime
|
147
145
|
prerelease: false
|
146
|
+
name: faraday_middleware
|
148
147
|
version_requirements: !ruby/object:Gem::Requirement
|
149
148
|
requirements:
|
150
|
-
- -
|
149
|
+
- - '>='
|
151
150
|
- !ruby/object:Gem::Version
|
152
151
|
version: '0'
|
152
|
+
type: :runtime
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name: structure_mapper
|
155
154
|
requirement: !ruby/object:Gem::Requirement
|
156
155
|
requirements:
|
157
|
-
- -
|
156
|
+
- - '>='
|
158
157
|
- !ruby/object:Gem::Version
|
159
158
|
version: '0'
|
160
|
-
type: :runtime
|
161
159
|
prerelease: false
|
160
|
+
name: multi_json
|
162
161
|
version_requirements: !ruby/object:Gem::Requirement
|
163
162
|
requirements:
|
164
|
-
- -
|
163
|
+
- - '>='
|
165
164
|
- !ruby/object:Gem::Version
|
166
165
|
version: '0'
|
166
|
+
type: :runtime
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name: mustache
|
169
168
|
requirement: !ruby/object:Gem::Requirement
|
170
169
|
requirements:
|
171
|
-
- -
|
170
|
+
- - '>='
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
prerelease: false
|
174
|
+
name: structure_mapper
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - '>='
|
172
178
|
- !ruby/object:Gem::Version
|
173
179
|
version: '0'
|
174
180
|
type: :runtime
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - '>='
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
175
187
|
prerelease: false
|
188
|
+
name: mustache
|
176
189
|
version_requirements: !ruby/object:Gem::Requirement
|
177
190
|
requirements:
|
178
|
-
- -
|
191
|
+
- - '>='
|
179
192
|
- !ruby/object:Gem::Version
|
180
193
|
version: '0'
|
194
|
+
type: :runtime
|
181
195
|
description: Mapper of RESTful services to ruby objects. Makes calling RESTful services
|
182
196
|
and parsing responses a breeze.
|
183
197
|
email:
|
@@ -186,7 +200,7 @@ executables: []
|
|
186
200
|
extensions: []
|
187
201
|
extra_rdoc_files: []
|
188
202
|
files:
|
189
|
-
-
|
203
|
+
- .gitignore
|
190
204
|
- Gemfile
|
191
205
|
- LICENSE.txt
|
192
206
|
- README.md
|
@@ -217,12 +231,12 @@ require_paths:
|
|
217
231
|
- lib
|
218
232
|
required_ruby_version: !ruby/object:Gem::Requirement
|
219
233
|
requirements:
|
220
|
-
- -
|
234
|
+
- - '>='
|
221
235
|
- !ruby/object:Gem::Version
|
222
236
|
version: '0'
|
223
237
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
224
238
|
requirements:
|
225
|
-
- -
|
239
|
+
- - '>='
|
226
240
|
- !ruby/object:Gem::Version
|
227
241
|
version: '0'
|
228
242
|
requirements: []
|