cmis-ruby 0.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 107af5f3b660dfdeb4a37320f00df2dcd1f90482
4
- data.tar.gz: fd8d344df8996b58419b6f2919b0fb0fed6fa58d
3
+ metadata.gz: 7687556cd432a42906b9d22bb5126864a2504746
4
+ data.tar.gz: aae0936ee6a12b24c9e5853ff53a84a68e9e5b7d
5
5
  SHA512:
6
- metadata.gz: b05da4dcef03c6c98e164027e3e3ea019696cf4fce952efbf19d02c75293d8693f6ac248bb4536ca51afac7a154e0a93ba30295acdce48e80ded87064f683ce4
7
- data.tar.gz: 1af4ac5bb0fdcb9395f26388e8d8c2fe372a68195dd3c460c05fd75c336e5f220143eea43064b440bd5261d21e75789e03ac03e69c3b6a6c1c3a5e3c2bd31bfc
6
+ metadata.gz: d4236426c4fb12577adaebf6de386a5caa27c02125deebc227c715c773524439ca009237d521ea4f0fde4359d714adb58419f54b85a911c3523b0e6459a7ac0f
7
+ data.tar.gz: 370f0c6e50f0fe80d684eef49f1b4b1d96ab9274b5c1fc53983f3eedb0a4cc5b45b481d2040698816a2044df43bfd68e73955a3ee6d23abb19cdd8f81c8d7198
data/cmis-ruby.gemspec CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_dependency 'typhoeus', '~> 0.6'
20
20
  s.add_dependency 'multipart-post', '~> 1.1'
21
- s.add_dependency 'multi_json', '~> 1.5'
22
21
  s.add_dependency 'activesupport', '>= 3.2'
23
22
 
24
23
  s.description = <<-DESC.gsub(/^ /, '')
data/lib/cmis-ruby.rb CHANGED
@@ -1,20 +1,17 @@
1
1
  require 'cmis/connection'
2
+ require 'cmis/exceptions'
2
3
  require 'cmis/server'
3
-
4
4
  require 'cmis/helpers'
5
+ require 'cmis/object_factory'
5
6
  require 'cmis/query_result'
6
7
  require 'cmis/query'
7
8
  require 'cmis/children'
8
-
9
9
  require 'cmis/repository'
10
-
11
10
  require 'cmis/object'
12
- require 'cmis/object_factory'
13
11
  require 'cmis/document'
14
12
  require 'cmis/folder'
15
13
  require 'cmis/item'
16
14
  require 'cmis/policy'
17
15
  require 'cmis/relationship'
18
-
19
- require 'cmis/type'
20
16
  require 'cmis/property_definition'
17
+ require 'cmis/type'
data/lib/cmis/children.rb CHANGED
@@ -1,6 +1,7 @@
1
+ require 'active_support/core_ext/hash/slice'
2
+
1
3
  module CMIS
2
4
  class Children
3
-
4
5
  # Options: from, page_size
5
6
  def initialize(folder, options = {})
6
7
  @folder = folder
@@ -10,8 +11,8 @@ module CMIS
10
11
  end
11
12
 
12
13
  # Options: limit
13
- def each_result(options = {}, &block)
14
- return enum_for(:each_result, options) unless block_given?
14
+ def each_child(options = {}, &block)
15
+ return enum_for(:each_child, options) unless block_given?
15
16
 
16
17
  init_options
17
18
  limit = parse_limit(options)
@@ -66,6 +67,8 @@ module CMIS
66
67
  @skip_count = @options['from'] || 0
67
68
  @order_by = @options['order_by']
68
69
  @has_next = true
70
+
71
+ @opts = @options.slice('query', 'headers')
69
72
  end
70
73
 
71
74
  def parse_limit(options)
@@ -82,7 +85,7 @@ module CMIS
82
85
  objectId: @folder.cmis_object_id,
83
86
  maxItems: @max_items,
84
87
  skipCount: @skip_count,
85
- orderBy: @order_by })
88
+ orderBy: @order_by }, @opts)
86
89
 
87
90
  results = result['objects'].map do |r|
88
91
  ObjectFactory.create(r['object'], @folder.repository)
@@ -90,6 +93,5 @@ module CMIS
90
93
 
91
94
  QueryResult.new(results, result['numItems'], result['hasMoreItems'])
92
95
  end
93
-
94
96
  end
95
97
  end
@@ -1,16 +1,11 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
2
- require 'date'
1
+ require 'active_support'
3
2
  require 'typhoeus'
4
3
  require 'net/http/post/multipart'
5
- require 'multi_json'
6
4
 
7
5
  module CMIS
8
-
9
- class CMISRequestError < Exception; end
10
-
11
6
  class Connection
12
7
 
13
- def initialize(service_url, username, password, headers = {})
8
+ def initialize(service_url, username, password, headers)
14
9
  @service_url = service_url
15
10
  @username = username
16
11
  @password = password
@@ -19,14 +14,17 @@ module CMIS
19
14
  @url_cache = {}
20
15
  end
21
16
 
22
- def execute!(params = {}, query = {}, headers = {})
17
+ def execute!(params = {}, options = {})
18
+ options.stringify_keys!
19
+ query = options['query'] || {}
20
+ headers = @headers.merge(options['headers'] || {})
23
21
 
24
22
  url = get_url(params.delete(:repositoryId), params[:objectId])
25
23
 
26
24
  params = transform_hash(params)
27
25
 
28
- if params.has_key?(:cmisaction)
29
- method = params.has_key?(:content) ? 'multipart_post' : 'post'
26
+ if params[:cmisaction]
27
+ method = params[:content] ? 'multipart_post' : 'post'
30
28
  body = params
31
29
  else
32
30
  method = 'get'
@@ -34,13 +32,8 @@ module CMIS
34
32
  query.merge!(params)
35
33
  end
36
34
 
37
- response = perform_request(method: method,
38
- url: url,
39
- query: query,
40
- body: body,
41
- headers: headers)
42
-
43
- result = response.body
35
+ response = perform_request(method: method, url: url,
36
+ body: body, query: query, headers: headers)
44
37
 
45
38
  content_type = if response.respond_to?(:content_type)
46
39
  response.content_type
@@ -48,22 +41,26 @@ module CMIS
48
41
  response.headers['Content-Type']
49
42
  end
50
43
 
51
- result = MultiJson.load(result) if content_type =~ /application\/json/
44
+ result = response.body
45
+ result = JSON.parse(result) if content_type =~ /application\/json/
52
46
  result = result.with_indifferent_access if result.is_a? Hash
53
47
 
54
- unless (200...300).include?(response.code.to_i)
55
- if result.is_a?(Hash) && result.has_key?(:exception)
56
- raise CMISRequestError, "#{response.code} -- #{result[:exception]} -- #{result[:message]}"
57
- else
58
- raise CMISRequestError, "#{response.code} -- #{result}"
59
- end
60
- end
48
+ check_for_exception!(response.code.to_i, result)
61
49
 
62
50
  result
63
51
  end
64
52
 
65
53
  private
66
54
 
55
+ def check_for_exception!(code, result)
56
+ unless (200...300).include?(code)
57
+ if result.is_a?(Hash) && result['exception']
58
+ exception_class = "CMIS::Exceptions::#{result['exception'].camelize}"
59
+ raise exception_class.constantize, "#{result['message']}"
60
+ end
61
+ end
62
+ end
63
+
67
64
  def get_url(repository_id, cmis_object_id)
68
65
  if repository_id.nil?
69
66
  @service_url
@@ -79,8 +76,8 @@ module CMIS
79
76
 
80
77
  def repository_urls(repository_id)
81
78
  if @url_cache[repository_id].nil?
82
- repository_infos = MultiJson.load(perform_request(url: @service_url).body , symbolize_keys: false)
83
- raise "No repository found with ID #{repository_id}." unless repository_infos.has_key?(repository_id)
79
+ repository_infos = JSON.parse(perform_request(url: @service_url).body)
80
+ raise Exceptions::ObjectNotFound, "repositoryId: #{repository_id}" unless repository_infos.has_key?(repository_id)
84
81
  repository_info = repository_infos[repository_id]
85
82
  @url_cache[repository_id] = { repository_url: repository_info['repositoryUrl'],
86
83
  root_folder_url: repository_info['rootFolderUrl'] }
@@ -91,28 +88,22 @@ module CMIS
91
88
  def transform_hash(hash)
92
89
  hash.reject! { |_, v| v.nil? }
93
90
 
94
- if hash.has_key?(:content)
95
- content = hash.delete(:content)
96
- hash[:content] = UploadIO.new(content[:stream],
97
- content[:mime_type],
98
- content[:filename])
99
- end # Move to multipart_post?
100
-
101
- if hash.has_key?(:properties)
102
- props = hash.delete(:properties)
103
- if props.is_a?(Hash)
104
- props.each_with_index do |(id, value), index|
105
- value = value.to_time if value.is_a?(Date) or value.is_a?(DateTime)
106
- value = (value.to_f * 1000).to_i if value.is_a?(Time)
107
- if value.is_a?(Array)
108
- hash.merge!("propertyId[#{index}]" => id)
109
- value.each_with_index do |v, idx|
110
- hash.merge!("propertyValue[#{index}][#{idx}]" => value[idx])
111
- end
112
- else
113
- hash.merge!("propertyId[#{index}]" => id,
114
- "propertyValue[#{index}]" => value)
91
+ if content_hash = hash[:content]
92
+ hash[:content] = UploadIO.new(content_hash[:stream], content_hash[:mime_type], content_hash[:filename])
93
+ end
94
+
95
+ if props = hash.delete(:properties)
96
+ props.each_with_index do |(id, value), index|
97
+ value = value.to_time if value.is_a?(Date) or value.is_a?(DateTime)
98
+ value = (value.to_f * 1000).to_i if value.is_a?(Time)
99
+ if value.is_a?(Array)
100
+ hash.merge!("propertyId[#{index}]" => id)
101
+ value.each_with_index do |v, idx|
102
+ hash.merge!("propertyValue[#{index}][#{idx}]" => value[idx])
115
103
  end
104
+ else
105
+ hash.merge!("propertyId[#{index}]" => id,
106
+ "propertyValue[#{index}]" => value)
116
107
  end
117
108
  end
118
109
  end
@@ -142,6 +133,5 @@ module CMIS
142
133
  opts = url.scheme == 'https' ? { use_ssl: true , verify_mode: OpenSSL::SSL::VERIFY_NONE } : {}
143
134
  Net::HTTP.start(url.host, url.port, opts) { |http| http.request(req) }
144
135
  end
145
-
146
136
  end
147
137
  end
data/lib/cmis/document.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module CMIS
2
2
  class Document < Object
3
-
4
3
  def initialize(raw, repository)
5
4
  super
6
5
  cmis_properties %w( cmis:isImmutable cmis:isLatestVersion
@@ -13,39 +12,45 @@ module CMIS
13
12
  cmis:contentStreamFileName cmis:contentStreamId )
14
13
  end
15
14
 
16
- def create_in_folder(folder)
15
+ def create_in_folder(folder, opts = {})
17
16
  r = connection.execute!({ cmisaction: 'createDocument',
18
17
  repositoryId: repository.id,
19
18
  properties: properties,
20
19
  objectId: folder.cmis_object_id,
21
20
  folderId: folder.cmis_object_id,
22
- content: @local_content })
21
+ content: @local_content }, opts)
23
22
 
24
23
  ObjectFactory.create(r, repository)
25
24
  end
26
25
 
27
- def copy_in_folder(folder)
26
+ def copy_in_folder(folder, opts = {})
28
27
  id = connection.execute!({ cmisaction: 'createDocument',
29
28
  repositoryId: repository.id,
30
29
  sourceId: cmis_object_id,
31
- objectId: folder.cmis_object_id })
30
+ objectId: folder.cmis_object_id }, opts)
32
31
 
33
32
  repository.object(id)
34
33
  end
35
34
 
36
- def content
35
+ def content(opts = {})
37
36
  connection.execute!({ cmisselector: 'content',
38
37
  repositoryId: repository.id,
39
- objectId: cmis_object_id })
38
+ objectId: cmis_object_id }, opts)
40
39
 
41
- rescue CMIS::CMISRequestError
40
+ rescue Exceptions::Constraint
41
+ # Check for specific constraint?
42
42
  nil
43
43
  end
44
44
 
45
- def set_content(stream, mime_type, filename)
46
- content = { stream: stream,
47
- mime_type: mime_type,
48
- filename: filename }
45
+ def set_content(opts = {})
46
+ opts.stringify_keys!
47
+ content = { stream: opts.delete('stream'),
48
+ mime_type: opts.delete('mime_type'),
49
+ filename: opts.delete('filename') }
50
+
51
+ if content[:stream].is_a? String
52
+ content[:stream] = StringIO.new(content[:stream])
53
+ end
49
54
 
50
55
  if detached?
51
56
  @local_content = content
@@ -54,9 +59,8 @@ module CMIS
54
59
  repositoryId: repository.id,
55
60
  objectId: cmis_object_id,
56
61
  content: content,
57
- changeToken: change_token })
62
+ changeToken: change_token }, opts)
58
63
  end
59
64
  end
60
-
61
65
  end
62
66
  end
@@ -0,0 +1,17 @@
1
+ module CMIS
2
+ module Exceptions
3
+ class InvalidArgument < Exception; end
4
+ class NotSupported < Exception; end
5
+ class ObjectNotFound < Exception; end
6
+ class PermissionDenied < Exception; end
7
+ class Runtime < Exception; end
8
+ class Constraint < Exception; end
9
+ class ContentAlreadyExists < Exception; end
10
+ class FilterNotValid < Exception; end
11
+ class NameConstraintViolation < Exception; end
12
+ class Storage < Exception; end
13
+ class StreamNotSupported < Exception; end
14
+ class UpdateConflict < Exception; end
15
+ class Versioning < Exception; end
16
+ end
17
+ end
data/lib/cmis/folder.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  module CMIS
2
2
  class Folder < Object
3
-
4
3
  def initialize(raw, repository)
5
4
  super
6
5
  cmis_properties %w( cmis:parentId cmis:path
7
6
  cmis:allowedChildObjectTypeIds )
8
7
  end
9
8
 
10
- def parent
11
- repository.object(parent_id) if parent_id
9
+ def parent(opts = {})
10
+ repository.object(parent_id, opts) if parent_id
12
11
  end
13
12
 
14
13
  def allowed_child_object_types
@@ -16,34 +15,34 @@ module CMIS
16
15
  allowed_child_object_type_ids.map { |type_id| repository.type(type_id) }
17
16
  end
18
17
 
19
- def children(options = {})
20
- Children.new(self, options)
18
+ def children(opts = {})
19
+ Children.new(self, opts)
21
20
  end
22
21
 
23
- def create(object)
22
+ def create(object, opts = {})
24
23
  case object
25
24
  when Relationship
26
25
  raise "'cmis:relationship' is not fileable. Use Repository#create_relationship"
27
26
 
28
27
  when Document
29
- return object.create_in_folder(self)
28
+ return object.create_in_folder(self, opts)
30
29
 
31
30
  when Folder
32
31
  o = connection.execute!({ cmisaction: 'createFolder',
33
32
  repositoryId: repository.id,
34
33
  properties: object.properties,
35
- objectId: cmis_object_id })
34
+ objectId: cmis_object_id }, opts)
36
35
 
37
36
  when Policy
38
37
  o = connection.execute!({ cmisaction: 'createPolicy',
39
38
  repositoryId: repository.id,
40
39
  properties: object.properties,
41
- objectId: cmis_object_id })
40
+ objectId: cmis_object_id }, opts)
42
41
  when Item
43
42
  o = connection.execute!({ cmisaction: 'createItem',
44
43
  repositoryId: repository.id,
45
44
  properties: object.properties,
46
- objectId: cmis_object_id })
45
+ objectId: cmis_object_id }, opts)
47
46
 
48
47
  else
49
48
  raise "Unexpected base_type_id: #{object.base_type_id}"
@@ -52,25 +51,24 @@ module CMIS
52
51
  ObjectFactory.create(o, repository)
53
52
  end
54
53
 
55
- def delete_tree
54
+ def delete_tree(opts = {})
56
55
  connection.execute!({ cmisaction: 'deleteTree',
57
56
  repositoryId: repository.id,
58
- objectId: cmis_object_id })
57
+ objectId: cmis_object_id }, opts)
59
58
  end
60
59
 
61
- def add(object)
60
+ def add(object, opts = {})
62
61
  connection.execute!({ cmisaction: 'addObjectToFolder',
63
62
  repositoryId: repository.id,
64
63
  objectId: object.cmis_object_id,
65
- folderId: cmis_object_id })
64
+ folderId: cmis_object_id }, opts)
66
65
  end
67
66
 
68
- def remove(object)
67
+ def remove(object, opts = {})
69
68
  connection.execute!({ cmisaction: 'removeObjectFromFolder',
70
69
  repositoryId: repository.id,
71
70
  objectId: object.cmis_object_id,
72
- folderId: cmis_object_id })
71
+ folderId: cmis_object_id }, opts)
73
72
  end
74
-
75
73
  end
76
74
  end
data/lib/cmis/helpers.rb CHANGED
@@ -2,7 +2,6 @@ require 'active_support/core_ext'
2
2
 
3
3
  module CMIS
4
4
  module Helpers
5
-
6
5
  def initialize_properties(raw)
7
6
  @properties = get_properties_map(raw)
8
7
  end
@@ -21,7 +20,7 @@ module CMIS
21
20
  elsif r['succinctProperties']
22
21
  @change_token = r['succinctProperties']['cmis:changeToken']
23
22
  else
24
- raise "Unexpected hash: #{r}"
23
+ raise "Unexpected input: #{r}"
25
24
  end
26
25
  end
27
26
 
@@ -53,6 +52,5 @@ module CMIS
53
52
 
54
53
  result.with_indifferent_access
55
54
  end
56
-
57
55
  end
58
56
  end
data/lib/cmis/item.rb CHANGED
@@ -1,11 +1,7 @@
1
1
  module CMIS
2
-
3
2
  class Item < Object
4
-
5
3
  def initialize(raw, repository)
6
4
  super
7
5
  end
8
-
9
6
  end
10
-
11
7
  end
data/lib/cmis/object.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module CMIS
2
2
  class Object
3
-
4
3
  include Helpers
5
4
 
6
5
  attr_reader :connection
@@ -18,103 +17,102 @@ module CMIS
18
17
  @connection = repository.connection
19
18
  end
20
19
 
21
- def object_type
22
- repository.type(object_type_id)
20
+ def object_type(opts = {})
21
+ repository.type(object_type_id, opts)
23
22
  end
24
23
 
25
- def delete
24
+ def delete(opts = {})
26
25
  connection.execute!({ cmisaction: 'delete',
27
26
  repositoryId: repository.id,
28
27
  objectId: cmis_object_id,
29
- allVersions: true })
28
+ allVersions: true }, opts)
30
29
  end
31
30
 
32
- def update_properties(properties)
31
+ def update_properties(properties, opts = {})
33
32
  update_change_token connection.execute!({ cmisaction: 'update',
34
33
  repositoryId: repository.id,
35
34
  objectId: cmis_object_id,
36
35
  properties: properties,
37
- changeToken: change_token })
36
+ changeToken: change_token }, opts)
38
37
  end
39
38
 
40
- def parents
39
+ def parents(opts = {})
41
40
  result = connection.execute!({ cmisselector: 'parents',
42
41
  repositoryId: repository.id,
43
- objectId: cmis_object_id })
42
+ objectId: cmis_object_id }, opts)
44
43
 
45
44
  result.map { |o| ObjectFactory.create(o['object'], repository) }
46
45
  end
47
46
 
48
- def allowable_actions
47
+ def allowable_actions(opts = {})
49
48
  connection.execute!({ cmisselector: 'allowableActions',
50
49
  repositoryId: repository.id,
51
- objectId: cmis_object_id })
50
+ objectId: cmis_object_id }, opts)
52
51
  end
53
52
 
54
- def relationships(direction = :either)
53
+ def relationships(direction = :either, opts = {})
55
54
  result = connection.execute!({ cmisselector: 'relationships',
56
55
  repositoryId: repository.id,
57
56
  objectId: cmis_object_id,
58
- relationshipDirection: direction })
57
+ relationshipDirection: direction }, opts)
59
58
 
60
59
  result['objects'].map { |r| Relationship.new(r, repository) }
61
60
  end
62
61
 
63
- def policies
62
+ def policies(opts = {})
64
63
  result = connection.execute!({ cmisselector: 'policies',
65
64
  repositoryId: repository.id,
66
- objectId: cmis_object_id })
65
+ objectId: cmis_object_id }, opts)
67
66
 
68
67
  result.map { |r| Policy.new(r, repository) }
69
68
  end
70
69
 
71
70
  # By default removes from all folders
72
- def unfile(folder = nil)
73
- options = { repositoryId: repository.id,
74
- cmisaction: 'removeObjectFromFolder',
75
- objectId: cmis_object_id }
76
- options[:folderId] = folder.cmis_object_id if folder
71
+ def unfile(folder = nil, opts = {})
72
+ params = { repositoryId: repository.id,
73
+ cmisaction: 'removeObjectFromFolder',
74
+ objectId: cmis_object_id }
75
+ params.update!(folderId: folder.cmis_object_id) if folder
77
76
 
78
- connection.execute!(options)
77
+ connection.execute!(params, opts)
79
78
  end
80
79
 
81
- def move(target_folder)
80
+ def move(target_folder, opts = {})
82
81
  object_parents = parents
83
82
 
84
83
  unless object_parents.size == 1
85
- raise 'Cannot move object because it is not in excatly one folder'
84
+ raise 'Cannot move object because it is not in exactly one folder'
86
85
  end
87
86
 
88
87
  connection.execute!({ cmisaction: 'move',
89
88
  repositoryId: repository.id,
90
89
  objectId: cmis_object_id,
91
90
  targetFolderId: target_folder.cmis_object_id,
92
- sourceFolderId: object_parents.first.cmis_object_id })
91
+ sourceFolderId: object_parents.first.cmis_object_id }, opts)
93
92
  end
94
93
 
95
- def acls
94
+ def acls(opts = {})
96
95
  connection.execute!({ cmisselector: 'acl',
97
96
  repositoryId: repository.id,
98
- objectId: cmis_object_id })
97
+ objectId: cmis_object_id }, opts)
99
98
  end
100
99
 
101
- def add_aces(aces)
100
+ def add_aces(aces, opts = {})
102
101
  connection.execute!({ cmisaction: 'applyACL',
103
102
  repositoryId: repository.id,
104
103
  objectId: cmis_object_id,
105
- addACEs: aces })
104
+ addACEs: aces }, opts)
106
105
  end
107
106
 
108
- def remove_aces(aces)
107
+ def remove_aces(aces, opts = {})
109
108
  connection.execute!({ cmisaction: 'applyACL',
110
109
  repositoryId: repository.id,
111
110
  objectId: cmis_object_id,
112
- removeACEs: aces })
111
+ removeACEs: aces }, opts)
113
112
  end
114
113
 
115
114
  def detached?
116
115
  cmis_object_id.nil?
117
116
  end
118
-
119
117
  end
120
118
  end
@@ -1,26 +1,26 @@
1
1
  module CMIS
2
2
  class ObjectFactory
3
-
4
3
  def self.create(raw, repository)
5
4
  case base_type_id(raw)
5
+ when 'cmis:object' then Object.new(raw, repository)
6
6
  when 'cmis:folder' then Folder.new(raw, repository)
7
7
  when 'cmis:document' then Document.new(raw, repository)
8
8
  when 'cmis:relationship' then Relationship.new(raw, repository)
9
9
  when 'cmis:policy' then Policy.new(raw, repository)
10
10
  when 'cmis:item' then Item.new(raw, repository)
11
- else raise "Unexpected baseTypeId: #{base_type_id}."
11
+ else raise "Unexpected baseTypeId: #{base_type_id}"
12
12
  end
13
13
  end
14
14
 
15
15
  private
16
16
 
17
17
  def self.base_type_id(raw)
18
- if raw['properties']
18
+ if raw['properties'] && raw['properties']['cmis:baseTypeId']
19
19
  raw['properties']['cmis:baseTypeId']['value']
20
- elsif raw['succinctProperties']
20
+ elsif raw['succinctProperties'] && raw['succinctProperties']['cmis:baseTypeId']
21
21
  raw['succinctProperties']['cmis:baseTypeId']
22
22
  else
23
- raise "Unexpected json: #{raw}"
23
+ 'cmis:object' # no base type id, construct a poco
24
24
  end
25
25
  end
26
26
  end
data/lib/cmis/policy.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module CMIS
2
2
  class Policy < Object
3
-
4
3
  attr_reader :policy_text
5
4
 
6
5
  def initialize(raw, repository)
@@ -8,19 +7,18 @@ module CMIS
8
7
  cmis_properties %w( cmis:policyText )
9
8
  end
10
9
 
11
- def apply_to(object)
10
+ def apply_to(object, opts = {})
12
11
  connection.execute!({ cmisaction: 'applyPolicy',
13
12
  repositoryId: repository_id,
14
13
  policyId: cmis_object_id,
15
- objectId: object.cmis_object_id })
14
+ objectId: object.cmis_object_id }, opts)
16
15
  end
17
16
 
18
- def remove_from(object)
17
+ def remove_from(object, opts = {})
19
18
  connection.execute!({ cmisaction: 'removePolicy',
20
19
  repositoryId: repository_id,
21
20
  policyId: cmis_object_id,
22
- objectId: object.cmis_object_id })
21
+ objectId: object.cmis_object_id }, opts)
23
22
  end
24
-
25
23
  end
26
24
  end
@@ -1,8 +1,7 @@
1
- require 'active_support/core_ext'
1
+ require 'active_support/core_ext/string/inflections'
2
2
 
3
3
  module CMIS
4
4
  class PropertyDefinition
5
-
6
5
  def initialize(hash = {})
7
6
  @hash = hash.with_indifferent_access
8
7
 
@@ -27,6 +26,5 @@ module CMIS
27
26
  def to_hash
28
27
  @hash
29
28
  end
30
-
31
29
  end
32
30
  end
data/lib/cmis/query.rb CHANGED
@@ -1,6 +1,7 @@
1
+ require 'active_support/core_ext/hash/slice'
2
+
1
3
  module CMIS
2
4
  class Query
3
-
4
5
  # Options: from, page_size
5
6
  def initialize(repository, statement, options = {})
6
7
  @repository = repository
@@ -67,6 +68,8 @@ module CMIS
67
68
  @max_items = @options['page_size'] || 10
68
69
  @skip_count = @options['from'] || 0
69
70
  @has_next = true
71
+
72
+ @opts = @options.slice('query', 'headers')
70
73
  end
71
74
 
72
75
  def parse_limit(options)
@@ -87,7 +90,7 @@ module CMIS
87
90
  params.merge!(cmisaction: 'query', statement: @statement)
88
91
  end
89
92
 
90
- result = @repository.connection.execute!(params)
93
+ result = @repository.connection.execute!(params, @opts)
91
94
 
92
95
  results = result['results'].map do |r|
93
96
  ObjectFactory.create(r, @repository)
@@ -95,6 +98,5 @@ module CMIS
95
98
 
96
99
  QueryResult.new(results, result['numItems'], result['hasMoreItems'])
97
100
  end
98
-
99
101
  end
100
102
  end
@@ -1,6 +1,5 @@
1
1
  module CMIS
2
2
  class QueryResult
3
-
4
3
  attr_reader :results
5
4
  attr_reader :num_items
6
5
  attr_reader :has_more_items
@@ -10,6 +9,5 @@ module CMIS
10
9
  @num_items = num_items
11
10
  @has_more_items = has_more_items
12
11
  end
13
-
14
12
  end
15
13
  end
@@ -1,18 +1,16 @@
1
1
  module CMIS
2
2
  class Relationship < Object
3
-
4
3
  def initialize(raw, repository)
5
4
  super
6
5
  cmis_properties %w( cmis:sourceId cmis:targetId )
7
6
  end
8
7
 
9
- def source
10
- repository.object(source_id)
8
+ def source(opts = {})
9
+ repository.object(source_id, opts)
11
10
  end
12
11
 
13
- def target
14
- repository.object(target_id)
12
+ def target(opts = {})
13
+ repository.object(target_id, opts)
15
14
  end
16
-
17
15
  end
18
16
  end
@@ -1,6 +1,7 @@
1
+ require 'active_support/core_ext/date_time'
2
+
1
3
  module CMIS
2
4
  class Repository
3
-
4
5
  attr_reader :connection
5
6
 
6
7
  def initialize(raw, connection)
@@ -33,72 +34,107 @@ module CMIS
33
34
  Policy.new({}, self)
34
35
  end
35
36
 
36
- def root
37
+ def new_type
38
+ Type.new({}, self)
39
+ end
40
+
41
+ def root(opts = {})
37
42
  result = connection.execute!({ cmisselector: 'object',
38
43
  repositoryId: id,
39
- objectId: root_folder_id })
44
+ objectId: root_folder_id }, opts)
40
45
 
41
46
  ObjectFactory.create(result, self)
42
47
  end
43
48
 
44
- def object(cmis_object_id)
49
+ def object(cmis_object_id, opts = {})
45
50
  result = connection.execute!({ cmisselector: 'object',
46
51
  repositoryId: id,
47
- objectId: cmis_object_id })
52
+ objectId: cmis_object_id }, opts)
48
53
 
49
54
  ObjectFactory.create(result, self)
50
55
  end
51
56
 
52
- def types
57
+ def types(opts = {})
53
58
  result = connection.execute!({ cmisselector: 'typeDescendants',
54
59
  repositoryId: id,
55
- includePropertyDefinitions: true })
60
+ includePropertyDefinitions: true }, opts)
56
61
 
57
62
  construct_types(result)
58
63
  end
59
64
 
60
- def type(type_id)
65
+ def type(type_id, opts = {})
61
66
  result = connection.execute!({ cmisselector: 'typeDefinition',
62
67
  repositoryId: id,
63
- typeId: type_id })
68
+ typeId: type_id }, opts)
64
69
 
65
70
  Type.new(result, self)
66
71
  end
67
72
 
68
73
  def has_type?(type_id)
69
- types.map(&:id).include?(type_id)
74
+ type(type_id)
75
+ true
76
+ rescue Exceptions::ObjectNotFound
77
+ false
70
78
  end
71
79
 
72
- def create_type(type)
80
+ def create_type(type, opts = {})
73
81
  result = connection.execute!({ cmisaction: 'createType',
74
82
  repositoryId: id,
75
- type: MultiJson.dump(type.to_hash) })
83
+ type: JSON.generate(type.to_hash) }, opts)
76
84
 
77
85
  Type.new(result, self)
78
86
  end
79
87
 
80
- def create_relationship(object)
88
+ def create_relationship(object, opts = {})
81
89
  raise 'Object is not a Relationship' unless object.is_a?(Relationship)
82
90
 
83
91
  result = connection.execute!({ cmisaction: 'createRelationship',
84
92
  repositoryId: id,
85
- properties: object.properties })
93
+ properties: object.properties }, opts)
86
94
 
87
95
  ObjectFactory.create(result, self)
88
96
  end
89
97
 
90
- def content_changes(change_log_token)
98
+ def content_changes(change_log_token, opts = {})
91
99
  connection.execute!({ cmisselector: 'contentChanges',
92
100
  repositoryId: id,
93
- changeLogToken: change_log_token })
101
+ changeLogToken: change_log_token }, opts)
102
+ end
103
+
104
+ def query(statement, opts = {})
105
+ Query.new(self, statement, opts)
94
106
  end
95
107
 
96
- def query(statement, options = {})
97
- Query.new(self, statement, options)
108
+ def find_object(type_id, properties, opts = {})
109
+ clause = properties.map { |k, v| "#{k}=#{normalize(v)}" }.join(' and ')
110
+ statement = "select * from #{type_id} where #{clause}"
111
+ opts.merge!(page_size: 1)
112
+ query(statement, opts).results.first
98
113
  end
99
114
 
100
115
  private
101
116
 
117
+ BACKSLASH = "\\"
118
+ QUOTE = "\'"
119
+
120
+ def normalize(value)
121
+ case value
122
+ when DateTime
123
+ value = value.strftime('%Y-%m-%dT%H:%M:%S.%L')
124
+ "TIMESTAMP '#{value}'"
125
+ when Time
126
+ value = value.strftime('%Y-%m-%dT%H:%M:%S.%L')
127
+ "TIMESTAMP '#{value}'"
128
+ when Date
129
+ value = value.strftime('%Y-%m-%dT%H:%M:%S.%L')
130
+ "TIMESTAMP '#{value}'"
131
+ else
132
+ # TODO Correct escaping for find_object
133
+ # value = value.gsub(BACKSLASH, BACKSLASH * 4).gsub(QUOTE, "#{BACKSLASH * 2}#{QUOTE}")
134
+ "'#{value}'"
135
+ end
136
+ end
137
+
102
138
  def construct_types(a)
103
139
  types = []
104
140
  a.each do |t|
@@ -107,6 +143,5 @@ module CMIS
107
143
  end
108
144
  types.flatten
109
145
  end
110
-
111
146
  end
112
147
  end
data/lib/cmis/server.rb CHANGED
@@ -2,7 +2,6 @@ require 'active_support/core_ext/hash/indifferent_access'
2
2
 
3
3
  module CMIS
4
4
  class Server
5
-
6
5
  attr_reader :connection
7
6
 
8
7
  def initialize(options = {})
@@ -11,33 +10,33 @@ module CMIS
11
10
  service_url = options['service_url'] || ENV['CMIS_BROWSER_URL']
12
11
  username = options['username'] || ENV['CMIS_USER']
13
12
  password = options['password'] || ENV['CMIS_PASSWORD']
14
- headers = options['headers']
13
+ headers = options['headers'] || {}
15
14
 
16
- raise "'service_url' must be set" unless service_url
15
+ raise "`service_url` must be set" unless service_url
17
16
 
18
17
  @connection = Connection.new(service_url, username, password, headers)
19
18
  end
20
19
 
21
- def repositories
22
- result = connection.execute!
20
+ def repositories(opts = {})
21
+ result = connection.execute!({}, opts)
23
22
 
24
23
  result.values.map do |r|
25
24
  Repository.new(r, connection)
26
25
  end
27
26
  end
28
27
 
29
- def repository(repository_id)
28
+ def repository(repository_id, opts = {})
30
29
  result = connection.execute!({ cmisselector: 'repositoryInfo',
31
- repositoryId: repository_id })
30
+ repositoryId: repository_id }, opts)
32
31
 
33
32
  Repository.new(result[repository_id], connection)
34
33
  end
35
34
 
36
35
  def has_repository?(repository_id)
37
- result = connection.execute!
38
-
39
- result.keys.include?(repository_id)
36
+ repository(repository_id)
37
+ true
38
+ rescue Exceptions::ObjectNotFound
39
+ false
40
40
  end
41
-
42
41
  end
43
42
  end
data/lib/cmis/type.rb CHANGED
@@ -1,12 +1,11 @@
1
- require 'active_support/core_ext'
1
+ require 'active_support/core_ext/string/inflections'
2
2
 
3
3
  module CMIS
4
4
  class Type
5
-
6
5
  attr_accessor :connection
7
6
  attr_accessor :repository
8
7
 
9
- def initialize(hash = {}, repository = nil)
8
+ def initialize(hash, repository)
10
9
  @repository = repository
11
10
  @connection = repository.connection if repository
12
11
 
@@ -37,7 +36,7 @@ module CMIS
37
36
  repository.create_type(self)
38
37
  end
39
38
 
40
- def update(changed_property_defs)
39
+ def update(changed_property_defs, opts = {})
41
40
  new_defs = changed_property_defs.map(&:to_hash).reduce({}) do |result, element|
42
41
  result[element[:id]] = element
43
42
  result
@@ -46,17 +45,17 @@ module CMIS
46
45
  hash = to_hash
47
46
  hash['propertyDefinitions'] = new_defs
48
47
 
49
- result = connection.execute! ({ cmisaction: 'updateType',
50
- repositoryId: repository.id,
51
- type: MultiJson.dump(hash) })
48
+ result = connection.execute!({ cmisaction: 'updateType',
49
+ repositoryId: repository.id,
50
+ type: JSON.generate(hash) }, opts)
52
51
 
53
52
  Type.new(result, repository)
54
53
  end
55
54
 
56
- def delete
55
+ def delete(opts = {})
57
56
  connection.execute!({ cmisaction: 'deleteType',
58
57
  repositoryId: repository.id,
59
- typeId: id })
58
+ typeId: id }, opts)
60
59
  end
61
60
 
62
61
  def document_type?
@@ -101,6 +100,5 @@ module CMIS
101
100
  def to_hash
102
101
  @hash
103
102
  end
104
-
105
103
  end
106
104
  end
data/lib/cmis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CMIS
2
- VERSION = '0.2'
2
+ VERSION = '0.3'
3
3
  end
data/readme.md CHANGED
@@ -10,12 +10,8 @@ Running the tests requires a running CMIS server.
10
10
 
11
11
  ## TODO
12
12
 
13
- * query properties, not *
14
- * string / symbol consistency
15
- * better exceptions and handling
16
- * headers / params in low level (options)
13
+ * cleanup Connection class
17
14
  * facilitate copy between servers (make a flow)
18
- * improve exists for repo / type
19
15
  * caching
20
16
 
21
17
  ## Contributing
@@ -14,7 +14,9 @@ describe CMIS::Document do
14
14
  new_object = @repo.new_document
15
15
  new_object.name = 'doc1'
16
16
  new_object.object_type_id = 'cmis:document'
17
- new_object.set_content(StringIO.new('content1'), 'text/plain', 'doc1.txt') # set content on detached doc
17
+ new_object.set_content(stream: StringIO.new('content1'),
18
+ mime_type: 'text/plain',
19
+ filename: 'doc1.txt')
18
20
  doc = new_object.create_in_folder(@repo.root)
19
21
  doc.name.should eq 'doc1'
20
22
  doc.content_stream_mime_type.should eq 'text/plain'
data/spec/folder_spec.rb CHANGED
@@ -27,7 +27,9 @@ describe CMIS::Folder do
27
27
  new_object = @repo.new_document
28
28
  new_object.name = 'doc1'
29
29
  new_object.object_type_id = 'cmis:document'
30
- new_object.set_content(StringIO.new('apple is a fruit'), 'text/plain', 'apple.txt')
30
+ new_object.set_content(stream: StringIO.new('apple is a fruit'),
31
+ mime_type: 'text/plain',
32
+ filename: 'apple.txt')
31
33
  object = @repo.root.create(new_object)
32
34
  object.should be_a_kind_of CMIS::Document
33
35
  object.name.should eq 'doc1'
data/spec/helper.rb CHANGED
@@ -23,5 +23,5 @@ end
23
23
 
24
24
  def delete_repository(id)
25
25
  META.object(id).delete
26
- rescue CMIS::CMISRequestError => ex
26
+ rescue CMIS::Exceptions::ObjectNotFound => ex
27
27
  end
@@ -105,7 +105,7 @@ describe CMIS::Repository do
105
105
  it 'create, get, delete type - document' do
106
106
  type_id = 'apple'
107
107
 
108
- type = CMIS::Type.new
108
+ type = @repo.new_type
109
109
  type.id = type_id
110
110
  type.local_name = 'apple'
111
111
  type.query_name = 'apple'
@@ -136,7 +136,7 @@ describe CMIS::Repository do
136
136
  queryable: true,
137
137
  orderable: true)
138
138
 
139
- @repo.create_type(type)
139
+ type.create
140
140
 
141
141
  @repo.type(type_id).tap do |t|
142
142
  t.should be_a_kind_of CMIS::Type
data/spec/type_spec.rb CHANGED
@@ -11,7 +11,7 @@ describe CMIS::Type do
11
11
  end
12
12
 
13
13
  it 'shoud update types' do
14
- type = CMIS::Type.new
14
+ type = @repo.new_type
15
15
  type.id = 'apple'
16
16
  type.local_name = 'apple'
17
17
  type.query_name = 'apple'
@@ -44,7 +44,7 @@ describe CMIS::Type do
44
44
  orderable: true
45
45
  )
46
46
 
47
- full_type = @repo.create_type(type)
47
+ full_type = type.create
48
48
 
49
49
  new_prop = CMIS::PropertyDefinition.new(
50
50
  id: 'taste',
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmis-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenneth Geerts
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-23 00:00:00.000000000 Z
12
+ date: 2014-02-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: typhoeus
@@ -39,20 +39,6 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1.1'
42
- - !ruby/object:Gem::Dependency
43
- name: multi_json
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: '1.5'
49
- type: :runtime
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: '1.5'
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: activesupport
58
44
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +70,7 @@ files:
84
70
  - lib/cmis/children.rb
85
71
  - lib/cmis/connection.rb
86
72
  - lib/cmis/document.rb
73
+ - lib/cmis/exceptions.rb
87
74
  - lib/cmis/folder.rb
88
75
  - lib/cmis/helpers.rb
89
76
  - lib/cmis/item.rb
@@ -139,3 +126,4 @@ test_files:
139
126
  - spec/repository_spec.rb
140
127
  - spec/server_spec.rb
141
128
  - spec/type_spec.rb
129
+ has_rdoc: