filebound_client 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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +14 -0
- data/CODE_OF_CONDUCT.md +73 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +57 -0
- data/LICENSE.txt +21 -0
- data/README.md +200 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example_test.yml +9 -0
- data/filebound_client.gemspec +29 -0
- data/lib/ext/hash.rb +8 -0
- data/lib/ext/object.rb +19 -0
- data/lib/filebound_client.rb +102 -0
- data/lib/filebound_client/config.rb +33 -0
- data/lib/filebound_client/configuration.rb +6 -0
- data/lib/filebound_client/connection.rb +183 -0
- data/lib/filebound_client/endpoints.rb +52 -0
- data/lib/filebound_client/endpoints/assignments.rb +21 -0
- data/lib/filebound_client/endpoints/dividers.rb +14 -0
- data/lib/filebound_client/endpoints/document_binary_data.rb +53 -0
- data/lib/filebound_client/endpoints/documents.rb +102 -0
- data/lib/filebound_client/endpoints/eform_data.rb +14 -0
- data/lib/filebound_client/endpoints/eform_detail.rb +14 -0
- data/lib/filebound_client/endpoints/files.rb +69 -0
- data/lib/filebound_client/endpoints/projects.rb +160 -0
- data/lib/filebound_client/endpoints/separators.rb +14 -0
- data/lib/filebound_client/endpoints/version.rb +12 -0
- data/lib/filebound_client/version.rb +4 -0
- data/test.txt +1 -0
- metadata +135 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for Assignments resource endpoint
|
4
|
+
module Assignments
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :assignment
|
9
|
+
allow_all :assignments
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets the projects that the user has assignments in
|
14
|
+
# @param [Hash] query_params optional query params to pass to the request
|
15
|
+
# @return [Array] array of assignments
|
16
|
+
def assignments_projects(query_params = nil)
|
17
|
+
get('/assignments/projects', query_params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for Dividers resource endpoint
|
4
|
+
module Dividers
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :divider
|
9
|
+
allow_all :dividers
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for DocumentBinaryData resource endpoint
|
4
|
+
module DocumentBinaryData
|
5
|
+
# Retrieves document binary data
|
6
|
+
# @param [int] document_id the document key
|
7
|
+
# @param [Hash] query_params optional query parameters to pass to the request
|
8
|
+
# @return [binary] binary data for the document
|
9
|
+
def retrieve_binary_data(document_id, query_params = nil)
|
10
|
+
get_binary("/documentBinaryData/#{document_id}", query_params)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds binary data
|
14
|
+
# @param [String] extension the file extension
|
15
|
+
# @param [int] file_id the file id to add the binary data to
|
16
|
+
# @param [String] binary_data the Base64 encoded binary data to add
|
17
|
+
# @return [Hash] the new document
|
18
|
+
def add_binary_data(extension, file_id, binary_data)
|
19
|
+
raise FileboundClientException.new('extension is required', 0) if extension.blank?
|
20
|
+
# rubocop:disable Metrics/LineLength
|
21
|
+
raise FileboundClientException.new('file_id is required and must be greater than 0 when adding binary data', 0) if file_id.blank? || file_id.zero?
|
22
|
+
# rubocop:enable Metrics/LineLength
|
23
|
+
raise FileboundClientException.new('binary_data is required', 0) if binary_data.blank?
|
24
|
+
post('/documentBinaryData/0', nil, id: 0, extension: extension, fileId: file_id, documentToUpload: binary_data)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Updates binary data
|
28
|
+
# @param [int] document_id the document key
|
29
|
+
# @param [String] extension the file extension
|
30
|
+
# @param [String] binary_data the Base64 encoded binary data to update
|
31
|
+
# @return [Hash] the updated document
|
32
|
+
def update_binary_data(document_id, extension, binary_data)
|
33
|
+
raise FileboundClientException.new('extension is required', 0) if extension.blank?
|
34
|
+
raise FileboundClientException.new('binary_data is required', 0) if binary_data.blank?
|
35
|
+
post("/documentBinaryData/#{document_id}", nil, id: document_id, extension: extension,
|
36
|
+
documentToUpload: binary_data)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adds binary data to the indexing queue
|
40
|
+
# @param [String] extension the file extension
|
41
|
+
# @param [String] binary_data the Base-64 encoded binary data to send to the indexing queue
|
42
|
+
# @param [int] project_id the optional project_id to assign the binary data to
|
43
|
+
# @return [Hash] the new document
|
44
|
+
def add_to_indexing_queue(extension, binary_data, project_id = nil)
|
45
|
+
raise FileboundClientException.new('extension is required', 0) if extension.blank?
|
46
|
+
raise FileboundClientException.new('binary_data is required', 0) if binary_data.blank?
|
47
|
+
body = { extension: extension, documentToUpload: binary_data }
|
48
|
+
body[:projectId] = project_id unless project_id.blank?
|
49
|
+
put('/documentBinaryData', nil, body)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for Documents resource endpoint
|
4
|
+
module Documents
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :document
|
9
|
+
allow_all :documents
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieves a single document
|
14
|
+
# @param [int] document_id the document key
|
15
|
+
# @return [Hash] the document hash
|
16
|
+
def document(document_id, query_params = nil)
|
17
|
+
get("/documents/#{document_id}", query_params)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the eform data for the document key
|
21
|
+
# @param [int] document_id the document key
|
22
|
+
# @param [Hash] query_params the additional query params to send in the request
|
23
|
+
# @return [Hash] the EFormData hash
|
24
|
+
def document_eform_data(document_id, query_params = nil)
|
25
|
+
get("/documents/#{document_id}/eformdata", query_params)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the eform detail for the document key
|
29
|
+
# @param [int] document_id the document key
|
30
|
+
# @param [Hash] query_params the additional query params to send in the request
|
31
|
+
# @return [Hash] the EFormDetail hash
|
32
|
+
def document_eform_detail(document_id, query_params = nil)
|
33
|
+
get("/documents/#{document_id}/eformdetail", query_params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a rendition for the document key
|
37
|
+
# @param [int] document_id the document key
|
38
|
+
# @param [Hash] query_params the additional query params to send in the request (optional: page(int))
|
39
|
+
# @return [String] rendition for the document
|
40
|
+
def document_rendition(document_id, query_params = nil)
|
41
|
+
get("/documents/#{document_id}/rendition", query_params)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Adds eform data to document
|
45
|
+
# @param [int] document_id the document key
|
46
|
+
# @param [Hash] eform_data the eform data hash to add
|
47
|
+
# @return [Hash] the newly added eform data hash
|
48
|
+
def document_add_eformdata(document_id, eform_data)
|
49
|
+
put("/documents/#{document_id}/eformdata", nil, eform_data)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adds eform detail to document
|
53
|
+
# @param [int] document_id the document key
|
54
|
+
# @param [Hash] eform_detail the eform detail to add
|
55
|
+
# @return [Hash] the newly added eform detail hash
|
56
|
+
def document_add_eformdetail(document_id, eform_detail)
|
57
|
+
put("/documents/#{document_id}/eformdetail", nil, eform_detail)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Updates eform data for the document
|
61
|
+
# @param [int] document_id the document key
|
62
|
+
# @param [Hash] eform_data the eform data hash to update
|
63
|
+
# @param [Hash] query_params additional query parameters to pass to the request (optional: deleteNonMatches(bool))
|
64
|
+
# @return [Hash] the updated eform data hash
|
65
|
+
def document_update_eformdata(document_id, eform_data, query_params = nil)
|
66
|
+
post("/documents/#{document_id}/eformdata", query_params, eform_data)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Updates eform detail for the document
|
70
|
+
# @param [int] document_id the document key
|
71
|
+
# @param [Hash] eform_detail the eform detail hash to update
|
72
|
+
# @param [Hash] query_params additional query parameters to pass to the request (optional: deleteNonMatches(bool))
|
73
|
+
# @return [Hash] the updated eform detail hash
|
74
|
+
def document_update_eformdetail(document_id, eform_detail, query_params = nil)
|
75
|
+
put("/documents/#{document_id}/eformdetail", query_params, eform_detail)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Updates a document
|
79
|
+
# @param [Hash] document the document hash to update
|
80
|
+
# @param [Hash] query_params additional query parameters to pass to the request (optional: setBinaryData(bool))
|
81
|
+
# @return [int] the document id that was updated
|
82
|
+
def document_update(document, query_params = nil)
|
83
|
+
post("/documents/#{document[:id]}", query_params, document)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Adds a document
|
87
|
+
# @param [Hash] document the document hash to add
|
88
|
+
# @return [Hash] the newly added document hash
|
89
|
+
def document_add(document)
|
90
|
+
raise FileboundClientException.new('File Id is required', 0) unless document && document[:fileId] > 0
|
91
|
+
put("/documents/#{document[:fileId]}", nil, document)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Delete a document
|
95
|
+
# @param [int] document_id the document key
|
96
|
+
# @return [bool] true if document was deleted successfully
|
97
|
+
def document_delete(document_id)
|
98
|
+
delete("/documents/#{document_id}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for EFormData resource endpoint
|
4
|
+
module EFormData
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :eformdata
|
9
|
+
allow_all :eformdata
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for EFormDetail resource endpoint
|
4
|
+
module EFormDetail
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :eformdetail
|
9
|
+
allow_all :eformdetail
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for Files resource endpoint
|
4
|
+
module Files
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :file
|
9
|
+
allow_all :files
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieves a single file by its key
|
14
|
+
# @param [int] file_id the file key
|
15
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter)
|
16
|
+
# @return [Hash] the file hash
|
17
|
+
def file(file_id, query_params = nil)
|
18
|
+
get("/files/#{file_id}", query_params)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieves all documents for the specified file key
|
22
|
+
# @param [int] file_id the file key
|
23
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter)
|
24
|
+
# @return [Array] an array of document hashes
|
25
|
+
def file_documents(file_id, query_params = nil)
|
26
|
+
get("/files/#{file_id}/documents", query_params)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Retrieves file_id by specifying a project id and key value
|
30
|
+
# @param [int] project_id the project key
|
31
|
+
# @param [String] key_value the key value to search on
|
32
|
+
# @return [int] the file id
|
33
|
+
def file_by_key_value(project_id, key_value)
|
34
|
+
get("/files/#{project_id}/ByKeyValue", value: key_value)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Updates a file
|
38
|
+
# @param [int] file_id the file key
|
39
|
+
# @param [Hash] file the file hash with updated fields
|
40
|
+
# @return [Hash] the updated file hash
|
41
|
+
def file_update(file_id, file)
|
42
|
+
post("files/#{file_id}", nil, file)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Adds a file
|
46
|
+
# @param [Hash] file the file hash to add
|
47
|
+
# @return [Hash] the newly added file hash
|
48
|
+
def file_add(file)
|
49
|
+
put('/files', nil, file)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adds file based on project key value
|
53
|
+
# @param [int] project_id the project key value
|
54
|
+
# @param [String] key_value the key value
|
55
|
+
# @param [Hash] file the file hash with updated fields
|
56
|
+
# @return [Hash] the updated file hash
|
57
|
+
def file_update_by_key_value(project_id, key_value, file)
|
58
|
+
put("/files/#{project_id}/ByKeyValue", { value: key_value }, file)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Deletes a file
|
62
|
+
# @param [int] file_id the file key
|
63
|
+
# @return [bool] true if the file deleted successfully
|
64
|
+
def file_delete(file_id)
|
65
|
+
delete("/files/#{file_id}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module FileboundClient
|
2
|
+
module Endpoints
|
3
|
+
# Module for Projects resource endpoint
|
4
|
+
module Projects
|
5
|
+
# This will call macros to create resource methods on the fly
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
allow_new :project
|
9
|
+
allow_all :projects
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieves a single project by its key
|
14
|
+
# @param [int] project_id the project key
|
15
|
+
# @param [Hash] query_params additional query params to send in the request
|
16
|
+
# @return [Project] project object
|
17
|
+
def project(project_id, query_params = nil)
|
18
|
+
get("/projects/#{project_id}", query_params)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieves fields for a project
|
22
|
+
# @param [int] project_id the project key
|
23
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String),
|
24
|
+
# includeProjectLinkOptions(bool))
|
25
|
+
# @return [Array] array of fields
|
26
|
+
def project_fields(project_id, query_params = nil)
|
27
|
+
get_project_children(project_id, __method__, query_params)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Retrieves files for a project
|
31
|
+
# @param [int] project_id the project key
|
32
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String))
|
33
|
+
# @return [Array] array of files
|
34
|
+
def project_files(project_id, query_params = nil)
|
35
|
+
get_project_children(project_id, __method__, query_params)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Retrieves groups for a project
|
39
|
+
# @param [int] project_id the project key
|
40
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String))
|
41
|
+
# @return [Array] array of groups
|
42
|
+
def project_groups(project_id, query_params = nil)
|
43
|
+
get_project_children(project_id, __method__, query_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Retrieves dividers for a project
|
47
|
+
# @param [int] project_id the project key
|
48
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String))
|
49
|
+
# @return [Array] array of dividers
|
50
|
+
def project_dividers(project_id, query_params = nil)
|
51
|
+
get_project_children(project_id, __method__, query_params)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Retrieves routed items for a project
|
55
|
+
# @param [int] project_id the project key
|
56
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String),
|
57
|
+
# userId(int), type(int))
|
58
|
+
# @return [Array] array of routed items
|
59
|
+
def project_routeditems(project_id, query_params = nil)
|
60
|
+
get_project_children(project_id, __method__, query_params)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retrieves separators for a project
|
64
|
+
# @param [int] project_id the project key
|
65
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String))
|
66
|
+
# @return [Array] array of separators
|
67
|
+
def project_separators(project_id, query_params = nil)
|
68
|
+
get_project_children(project_id, __method__, query_params)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Retrieves assignments for a project
|
72
|
+
# @param [int] project_id the project key
|
73
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String))
|
74
|
+
# @return [Array] array of assignments
|
75
|
+
def project_assignments(project_id, query_params = nil)
|
76
|
+
get_project_children(project_id, __method__, query_params)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Retrieves routes for a project
|
80
|
+
# @param [int] project_id the project key
|
81
|
+
# @param [Hash] query_params additional query params to send in the request (optional params: filter(String),
|
82
|
+
# xml(bool), hiddenRoutes(bool))
|
83
|
+
# @return [Array] array of routes
|
84
|
+
def project_routes(project_id, query_params = nil)
|
85
|
+
get_project_children(project_id, __method__, query_params)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Adds a project. The project.ProjectId must be nil or 0.
|
89
|
+
# @param [Project] project the project to add
|
90
|
+
# @return [int] the id of the newly created project
|
91
|
+
# @example Add a project
|
92
|
+
# c = FileboundClient::Client.connect(host: url, username: 'username', password: 'password', use_ntlm: true,
|
93
|
+
# ntlm_user: 'ntlm_user', ntlm_password: 'ntlm_password',
|
94
|
+
# ntlm_domain: 'ntlm_domain')
|
95
|
+
# c.project_add(ProjectId: 165, Name: 'Test API Project', ProjectType: 'HR')
|
96
|
+
def project_add(project)
|
97
|
+
raise Client::FileboundClientException.new('Id is required', 0) if project[:projectId].greater_than_zero?
|
98
|
+
put('/projects', nil, project)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Edits a project. The project.ProjectId must be not nil and > 0.
|
102
|
+
# @param [Hash] project the project to edit
|
103
|
+
# @return [int] the project id updated
|
104
|
+
# @example Update an existing project
|
105
|
+
# c = FileboundClient::Client.connect(host: url, username: 'username', password: 'password', use_ntlm: true,
|
106
|
+
# ntlm_user: 'ntlm_user', ntlm_password: 'ntlm_password',
|
107
|
+
# ntlm_domain: 'ntlm_domain')
|
108
|
+
# c.project_update(ProjectId: 165, Name: 'Test API Project', ProjectType: 'HR', EnableMultiKeySearch: true)
|
109
|
+
def project_update(project)
|
110
|
+
raise Client::FileboundClientException.new('Id is required', 0) unless project[:projectId].greater_than_zero?
|
111
|
+
put('/projects', nil, project)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Adds a divider to a project
|
115
|
+
# @param [int] project_id the project key to add the divider to
|
116
|
+
# @param [Hash] divider the divider hash to add to the project
|
117
|
+
# @return [int] the divider id
|
118
|
+
def project_divider_add(project_id, divider)
|
119
|
+
put("/projects/#{project_id}/dividers", nil, divider)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Adds a separator to a project
|
123
|
+
# @param [int] project_id the project key to add the separator to
|
124
|
+
# @param [Hash] separator the separator hash to add to the project
|
125
|
+
# @return [int] the separator id
|
126
|
+
def project_separator_add(project_id, separator)
|
127
|
+
put("/projects/#{project_id}/separators", nil, separator)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Adds a file to a project
|
131
|
+
# @param [int] project_id the project key to add the file to
|
132
|
+
# @param [Hash] file the file hash to add
|
133
|
+
# @return [int] the file id created
|
134
|
+
def project_file_add(project_id, file)
|
135
|
+
put("/projects/#{project_id}/files", nil, file)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Adds an array of files to a project
|
139
|
+
# @param [int] project_id the project key to add the files to
|
140
|
+
# @param [Array] files the array of file hashes to add
|
141
|
+
# @return [Hash] true if adding the files was successful
|
142
|
+
def project_files_add(project_id, files)
|
143
|
+
put("/projects/#{project_id}/listfiles", nil, files)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Deletes a project
|
147
|
+
# @param [int] project_id the project key of the project to delete
|
148
|
+
# @return [bool] true if deleting the project was successful
|
149
|
+
def project_delete(project_id)
|
150
|
+
delete("/projects/#{project_id}")
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def get_project_children(project_id, child_name, query_params = nil)
|
156
|
+
get("/projects/#{project_id}/#{child_name.to_s.split('_')[1]}", query_params)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|