yaccl 0.1.5 → 1.0.pre.alpha
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/lib/yaccl/children.rb +55 -0
- data/lib/yaccl/connection.rb +147 -0
- data/lib/yaccl/document.rb +62 -0
- data/lib/yaccl/folder.rb +76 -0
- data/lib/yaccl/helpers.rb +59 -0
- data/lib/yaccl/item.rb +11 -0
- data/lib/yaccl/object.rb +122 -0
- data/lib/yaccl/object_factory.rb +27 -0
- data/lib/yaccl/policy.rb +26 -0
- data/lib/yaccl/property_definition.rb +32 -0
- data/lib/yaccl/query.rb +53 -0
- data/lib/yaccl/query_result.rb +15 -0
- data/lib/yaccl/relationship.rb +18 -0
- data/lib/yaccl/repository.rb +108 -0
- data/lib/yaccl/server.rb +37 -0
- data/lib/yaccl/type.rb +106 -0
- data/lib/yaccl/version.rb +1 -1
- data/lib/yaccl.rb +21 -11
- data/readme.md +0 -3
- data/spec/{model/document_spec.rb → document_spec.rb} +4 -4
- data/spec/{model/folder_spec.rb → folder_spec.rb} +6 -6
- data/spec/helper.rb +12 -12
- data/spec/{model/object_spec.rb → object_spec.rb} +6 -6
- data/spec/relationship_spec.rb +19 -0
- data/spec/repository_spec.rb +150 -0
- data/spec/server_spec.rb +22 -0
- data/spec/{model/type_spec.rb → type_spec.rb} +6 -4
- data/yaccl.gemspec +1 -0
- metadata +48 -50
- data/examples/create_type_manual.rb +0 -40
- data/lib/yaccl/model/document.rb +0 -68
- data/lib/yaccl/model/folder.rb +0 -74
- data/lib/yaccl/model/item.rb +0 -9
- data/lib/yaccl/model/object.rb +0 -159
- data/lib/yaccl/model/object_factory.rb +0 -24
- data/lib/yaccl/model/policy.rb +0 -20
- data/lib/yaccl/model/property_definition.rb +0 -66
- data/lib/yaccl/model/relationship.rb +0 -22
- data/lib/yaccl/model/repository.rb +0 -155
- data/lib/yaccl/model/server.rb +0 -13
- data/lib/yaccl/model/type.rb +0 -146
- data/lib/yaccl/model.rb +0 -11
- data/lib/yaccl/services/acl_services.rb +0 -23
- data/lib/yaccl/services/discovery_services.rb +0 -29
- data/lib/yaccl/services/internal/browser_binding_service.rb +0 -170
- data/lib/yaccl/services/internal/simple_cache.rb +0 -103
- data/lib/yaccl/services/multi_filing_services.rb +0 -22
- data/lib/yaccl/services/navigation_services.rb +0 -84
- data/lib/yaccl/services/object_services.rb +0 -211
- data/lib/yaccl/services/policy_services.rb +0 -30
- data/lib/yaccl/services/relationship_services.rb +0 -18
- data/lib/yaccl/services/repository_services.rb +0 -67
- data/lib/yaccl/services/versioning_services.rb +0 -69
- data/lib/yaccl/services.rb +0 -34
- data/spec/model/relationship_spec.rb +0 -15
- data/spec/model/repository_spec.rb +0 -138
- data/spec/model/server_spec.rb +0 -16
- data/spec/services/navigation_services_spec.rb +0 -64
- data/spec/services/object_services_spec.rb +0 -44
- data/spec/services/repository_services_spec.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9199d278a1744c0fcfd31a290d40171fbba57a9d
|
4
|
+
data.tar.gz: 40f3bae9069f48696fe544760a44b90bf263d9c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0dc47bf5bb0cc9d71f5eb37fedc6f2dec2f204665d3d82bb0d2921583f225727136fb78c01d30f875fc69a32466ffadf6017d28eab17669886060dc035707d59
|
7
|
+
data.tar.gz: fb01d554a6688a03804b950df00a72eafb3d01a461d42feae11265cdfd2046c70f891439a01fa44eab98f4b8f5c021bfa1392a13cb2b4bd1daf22be2d00694ad
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Children
|
3
|
+
|
4
|
+
def initialize(folder, options)
|
5
|
+
options.stringify_keys!
|
6
|
+
|
7
|
+
@folder = folder
|
8
|
+
@repository = folder.repository
|
9
|
+
@connection = folder.repository.connection
|
10
|
+
|
11
|
+
@max_items = options['max_items'] || 10
|
12
|
+
@skip_count = options['skip_count'] || 0
|
13
|
+
@order_by = options['order_by']
|
14
|
+
|
15
|
+
@has_next = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def next_results
|
19
|
+
result = do_get_children
|
20
|
+
|
21
|
+
@skip_count += result.results.size
|
22
|
+
@has_next = result.has_more_items
|
23
|
+
@total = result.num_items
|
24
|
+
|
25
|
+
result.results
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_next?
|
29
|
+
@has_next
|
30
|
+
end
|
31
|
+
|
32
|
+
def total
|
33
|
+
@total ||= do_get_children.num_items
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def do_get_children
|
40
|
+
result = @connection.execute!({ cmisselector: 'children',
|
41
|
+
repositoryId: @repository.id,
|
42
|
+
objectId: @folder.cmis_object_id,
|
43
|
+
maxItems: @max_items,
|
44
|
+
skipCount: @skip_count,
|
45
|
+
orderBy: @order_by })
|
46
|
+
|
47
|
+
results = result['objects'].map do |r|
|
48
|
+
ObjectFactory.create(r['object'], @repository)
|
49
|
+
end
|
50
|
+
|
51
|
+
QueryResult.new(results, result['numItems'], result['hasMoreItems'])
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
require 'date'
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'net/http/post/multipart'
|
5
|
+
require 'multi_json'
|
6
|
+
|
7
|
+
module YACCL
|
8
|
+
|
9
|
+
class CMISRequestError < Exception; end
|
10
|
+
|
11
|
+
class Connection
|
12
|
+
|
13
|
+
def initialize(service_url, username, password, headers = {})
|
14
|
+
@service_url = service_url
|
15
|
+
@username = username
|
16
|
+
@password = password
|
17
|
+
@headers = headers
|
18
|
+
|
19
|
+
@url_cache = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute!(params = {}, query = {}, headers = {})
|
23
|
+
|
24
|
+
url = get_url(params.delete(:repositoryId), params[:objectId])
|
25
|
+
|
26
|
+
params = transform_hash(params)
|
27
|
+
|
28
|
+
if params.has_key?(:cmisaction)
|
29
|
+
method = params.has_key?(:content) ? 'multipart_post' : 'post'
|
30
|
+
body = params
|
31
|
+
else
|
32
|
+
method = 'get'
|
33
|
+
body = nil
|
34
|
+
query.merge!(params)
|
35
|
+
end
|
36
|
+
|
37
|
+
response = perform_request(method: method,
|
38
|
+
url: url,
|
39
|
+
query: query,
|
40
|
+
body: body,
|
41
|
+
headers: headers)
|
42
|
+
|
43
|
+
result = response.body
|
44
|
+
|
45
|
+
content_type = if response.respond_to?(:content_type)
|
46
|
+
response.content_type
|
47
|
+
else
|
48
|
+
response.headers['Content-Type']
|
49
|
+
end
|
50
|
+
|
51
|
+
result = MultiJson.load(result) if content_type =~ /application\/json/
|
52
|
+
result = result.with_indifferent_access if result.is_a? Hash
|
53
|
+
|
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
|
61
|
+
|
62
|
+
result
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def get_url(repository_id, cmis_object_id)
|
68
|
+
if repository_id.nil?
|
69
|
+
@service_url
|
70
|
+
else
|
71
|
+
urls = repository_urls(repository_id)
|
72
|
+
if cmis_object_id
|
73
|
+
urls[:root_folder_url]
|
74
|
+
else
|
75
|
+
urls[:repository_url]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def repository_urls(repository_id)
|
81
|
+
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)
|
84
|
+
repository_info = repository_infos[repository_id]
|
85
|
+
@url_cache[repository_id] = { repository_url: repository_info['repositoryUrl'],
|
86
|
+
root_folder_url: repository_info['rootFolderUrl'] }
|
87
|
+
end
|
88
|
+
@url_cache[repository_id]
|
89
|
+
end
|
90
|
+
|
91
|
+
def transform_hash(hash)
|
92
|
+
hash.reject! { |_, v| v.nil? }
|
93
|
+
|
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 { |v, idx|
|
110
|
+
hash.merge!("propertyValue[#{index}][#{idx}]" => value[idx])
|
111
|
+
}
|
112
|
+
else
|
113
|
+
hash.merge!("propertyId[#{index}]" => id,
|
114
|
+
"propertyValue[#{index}]" => value)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
hash
|
120
|
+
end
|
121
|
+
|
122
|
+
def perform_request(options)
|
123
|
+
if options[:method] == 'multipart_post'
|
124
|
+
multipart_post(options)
|
125
|
+
else
|
126
|
+
typhoeus_request(options)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def typhoeus_request(options)
|
131
|
+
options[:params] = options.delete(:query)
|
132
|
+
options[:followlocation] = true
|
133
|
+
options[:userpwd] = "#{@username}:#{@password}" if @username
|
134
|
+
Typhoeus::Request.new(options.delete(:url), options).run
|
135
|
+
end
|
136
|
+
|
137
|
+
def multipart_post(options)
|
138
|
+
url = URI.parse(options[:url])
|
139
|
+
req = Net::HTTP::Post::Multipart.new(url.path, options[:body])
|
140
|
+
options[:headers].each {|key, value| req[key] = value }
|
141
|
+
req.basic_auth @username, @password if @username
|
142
|
+
opts = url.scheme == 'https' ? { use_ssl: true , verify_mode: OpenSSL::SSL::VERIFY_NONE } : {}
|
143
|
+
Net::HTTP.start(url.host, url.port, opts) { |http| http.request(req) }
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Document < Object
|
3
|
+
|
4
|
+
def initialize(raw, repository)
|
5
|
+
super
|
6
|
+
cmis_properties %w( cmis:isImmutable cmis:isLatestVersion
|
7
|
+
cmis:isMajorVersion cmis:isLatestMajorVersion
|
8
|
+
cmis:isPrivateWorkingCopy cmis:versionLabel
|
9
|
+
cmis:versionSeriesId cmis:isVersionSeriesCheckedOut
|
10
|
+
cmis:versionSeriesCheckedOutBy
|
11
|
+
cmis:versionSeriesCheckedOutId cmis:checkinComment
|
12
|
+
cmis:contentStreamLength cmis:contentStreamMimeType
|
13
|
+
cmis:contentStreamFileName cmis:contentStreamId )
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_in_folder(folder)
|
17
|
+
r = connection.execute!({ cmisaction: 'createDocument',
|
18
|
+
repositoryId: repository.id,
|
19
|
+
properties: properties,
|
20
|
+
objectId: folder.cmis_object_id,
|
21
|
+
folderId: folder.cmis_object_id,
|
22
|
+
content: @local_content })
|
23
|
+
|
24
|
+
ObjectFactory.create(r, repository)
|
25
|
+
end
|
26
|
+
|
27
|
+
def copy_in_folder(folder)
|
28
|
+
id = connection.execute!({ cmisaction: 'createDocument',
|
29
|
+
repositoryId: repository.id,
|
30
|
+
sourceId: cmis_object_id,
|
31
|
+
objectId: folder.cmis_object_id })
|
32
|
+
|
33
|
+
repository.object(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
def content
|
37
|
+
connection.execute!({ cmisselector: 'content',
|
38
|
+
repositoryId: repository.id,
|
39
|
+
objectId: cmis_object_id })
|
40
|
+
|
41
|
+
rescue YACCL::CMISRequestError
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_content(stream, mime_type, filename)
|
46
|
+
content = { stream: stream,
|
47
|
+
mime_type: mime_type,
|
48
|
+
filename: filename }
|
49
|
+
|
50
|
+
if detached?
|
51
|
+
@local_content = content
|
52
|
+
else
|
53
|
+
update_change_token connection.execute!({ cmisaction: 'setContent',
|
54
|
+
repositoryId: repository.id,
|
55
|
+
objectId: cmis_object_id,
|
56
|
+
content: content,
|
57
|
+
changeToken:change_token })
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/yaccl/folder.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Folder < Object
|
3
|
+
|
4
|
+
def initialize(raw, repository)
|
5
|
+
super
|
6
|
+
cmis_properties %w( cmis:parentId cmis:path
|
7
|
+
cmis:allowedChildObjectTypeIds )
|
8
|
+
end
|
9
|
+
|
10
|
+
def parent
|
11
|
+
repository.object(parent_id) if parent_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def allowed_child_object_types
|
15
|
+
return nil unless allowed_child_object_type_ids
|
16
|
+
allowed_child_object_type_ids.map { |type_id| repository.type(type_id) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def children(options = {})
|
20
|
+
Children.new(self, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def create(object)
|
24
|
+
case object
|
25
|
+
when Relationship
|
26
|
+
raise "'cmis:relationship' is not fileable. Use Repository#create_relationship"
|
27
|
+
|
28
|
+
when Document
|
29
|
+
return object.create_in_folder(self)
|
30
|
+
|
31
|
+
when Folder
|
32
|
+
o = connection.execute!({ cmisaction: 'createFolder',
|
33
|
+
repositoryId: repository.id,
|
34
|
+
properties: object.properties,
|
35
|
+
objectId: cmis_object_id })
|
36
|
+
|
37
|
+
when Policy
|
38
|
+
o = connection.execute!({ cmisaction: 'createPolicy',
|
39
|
+
repositoryId: repository.id,
|
40
|
+
properties: object.properties,
|
41
|
+
objectId: cmis_object_id })
|
42
|
+
when Item
|
43
|
+
o = connection.execute!({ cmisaction: 'createItem',
|
44
|
+
repositoryId: repository.id,
|
45
|
+
properties: object.properties,
|
46
|
+
objectId: cmis_object_id })
|
47
|
+
|
48
|
+
else
|
49
|
+
raise "Unexpected base_type_id: #{object.base_type_id}"
|
50
|
+
end
|
51
|
+
|
52
|
+
ObjectFactory.create(o, repository)
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_tree
|
56
|
+
connection.execute!({ cmisaction: 'deleteTree',
|
57
|
+
repositoryId: repository.id,
|
58
|
+
objectId: cmis_object_id })
|
59
|
+
end
|
60
|
+
|
61
|
+
def add(object)
|
62
|
+
connection.execute!({ cmisaction: 'addObjectToFolder',
|
63
|
+
repositoryId: repository.id,
|
64
|
+
objectId: object.cmis_object_id,
|
65
|
+
folderId: cmis_object_id })
|
66
|
+
end
|
67
|
+
|
68
|
+
def remove(object)
|
69
|
+
connection.execute!({ cmisaction: 'removeObjectFromFolder',
|
70
|
+
repositoryId: repository.id,
|
71
|
+
objectId: object.cmis_object_id,
|
72
|
+
folderId: cmis_object_id })
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
module YACCL
|
4
|
+
module Helpers
|
5
|
+
|
6
|
+
def initialize_properties(raw)
|
7
|
+
@properties = get_properties_map(raw)
|
8
|
+
end
|
9
|
+
|
10
|
+
def cmis_properties(properties)
|
11
|
+
properties.each do |property_name|
|
12
|
+
method_name = method_name(property_name)
|
13
|
+
class_eval "def #{method_name};@properties['#{property_name}'];end"
|
14
|
+
class_eval "def #{method_name}=(value);@properties['#{property_name}']=value;end"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_change_token(r)
|
19
|
+
if r['properties']
|
20
|
+
@change_token = r['properties']['cmis:changeToken']['value']
|
21
|
+
elsif r['succinctProperties']
|
22
|
+
@change_token = r['succinctProperties']['cmis:changeToken']
|
23
|
+
else
|
24
|
+
raise "Unexpected hash: #{r}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def method_name(property_name)
|
32
|
+
if property_name == 'cmis:objectId'
|
33
|
+
'cmis_object_id'
|
34
|
+
else
|
35
|
+
property_name.gsub('cmis:', '').underscore
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_properties_map(raw)
|
40
|
+
raw = raw.with_indifferent_access
|
41
|
+
|
42
|
+
if raw['succinctProperties']
|
43
|
+
result = raw['succinctProperties']
|
44
|
+
elsif raw['properties']
|
45
|
+
result = raw['properties'].inject({}) do |h, (k, v)|
|
46
|
+
val = v['value']
|
47
|
+
val = v['value'].first if v['value'].is_a?(Array) and v['cardinality'] == 'single'
|
48
|
+
val = Time.at(val / 1000) if val and v['type'] == 'datetime'
|
49
|
+
h.merge(k => val)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
result = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
result.with_indifferent_access
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/lib/yaccl/item.rb
ADDED
data/lib/yaccl/object.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Object
|
3
|
+
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
attr_reader :connection
|
7
|
+
attr_reader :repository
|
8
|
+
attr_accessor :properties
|
9
|
+
|
10
|
+
def initialize(raw, repository)
|
11
|
+
initialize_properties(raw)
|
12
|
+
cmis_properties %w( cmis:objectId cmis:baseTypeId cmis:objectTypeId
|
13
|
+
cmis:secondaryObjectTypeIds cmis:name cmis:description
|
14
|
+
cmis:createdBy cmis:creationDate cmis:lastModifiedBy
|
15
|
+
cmis:lastModificationDate cmis:changeToken )
|
16
|
+
|
17
|
+
@repository = repository
|
18
|
+
@connection = repository.connection
|
19
|
+
end
|
20
|
+
|
21
|
+
def object_type
|
22
|
+
repository.type(object_type_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete
|
26
|
+
connection.execute!({ cmisaction: 'delete',
|
27
|
+
repositoryId: repository.id,
|
28
|
+
objectId: cmis_object_id,
|
29
|
+
allVersions: true })
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_properties(properties)
|
33
|
+
update_change_token connection.execute!({ cmisaction: 'update',
|
34
|
+
repositoryId: repository.id,
|
35
|
+
objectId: cmis_object_id,
|
36
|
+
properties: properties,
|
37
|
+
changeToken: change_token })
|
38
|
+
end
|
39
|
+
|
40
|
+
def parents
|
41
|
+
result = connection.execute!({ cmisselector: 'parents',
|
42
|
+
repositoryId: repository.id,
|
43
|
+
objectId: cmis_object_id })
|
44
|
+
|
45
|
+
result.map { |o| ObjectFactory.create(o['object'], repository) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def allowable_actions
|
49
|
+
connection.execute!({ cmisselector: 'allowableActions',
|
50
|
+
repositoryId: repository.id,
|
51
|
+
objectId: cmis_object_id })
|
52
|
+
end
|
53
|
+
|
54
|
+
def relationships(direction = :either)
|
55
|
+
result = connection.execute!({ cmisselector: 'relationships',
|
56
|
+
repositoryId: repository.id,
|
57
|
+
objectId: cmis_object_id,
|
58
|
+
relationshipDirection: direction })
|
59
|
+
|
60
|
+
result['objects'].map { |r| Relationship.new(r, repository) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def policies
|
64
|
+
result = connection.execute!({ cmisselector: 'policies',
|
65
|
+
repositoryId: repository.id,
|
66
|
+
objectId: cmis_object_id })
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
result.map { |r| Policy.new(r, repository) }
|
71
|
+
end
|
72
|
+
|
73
|
+
# By default removes from all folders
|
74
|
+
def unfile(folder = nil)
|
75
|
+
options = { repositoryId: repository.id,
|
76
|
+
cmisaction: 'removeObjectFromFolder',
|
77
|
+
objectId: cmis_object_id }
|
78
|
+
options[:folderId] = folder.cmis_object_id if folder
|
79
|
+
|
80
|
+
connection.execute!(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def move(target_folder)
|
84
|
+
object_parents = parents
|
85
|
+
|
86
|
+
unless object_parents.size == 1
|
87
|
+
raise 'Cannot move object because it is not in excatly one folder'
|
88
|
+
end
|
89
|
+
|
90
|
+
connection.execute!({ cmisaction: 'move',
|
91
|
+
repositoryId: repository.id,
|
92
|
+
objectId: cmis_object_id,
|
93
|
+
targetFolderId: target_folder.cmis_object_id,
|
94
|
+
sourceFolderId: object_parents.first.cmis_object_id })
|
95
|
+
end
|
96
|
+
|
97
|
+
def acls
|
98
|
+
connection.execute!({ cmisselector: 'acl',
|
99
|
+
repositoryId: repository.id,
|
100
|
+
objectId: cmis_object_id })
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_aces(aces)
|
104
|
+
connection.execute!({ cmisaction: 'applyACL',
|
105
|
+
repositoryId: repository.id,
|
106
|
+
objectId: cmis_object_id,
|
107
|
+
addACEs: aces })
|
108
|
+
end
|
109
|
+
|
110
|
+
def remove_aces(aces)
|
111
|
+
connection.execute!({ cmisaction: 'applyACL',
|
112
|
+
repositoryId: repository.id,
|
113
|
+
objectId: cmis_object_id,
|
114
|
+
removeACEs: aces })
|
115
|
+
end
|
116
|
+
|
117
|
+
def detached?
|
118
|
+
cmis_object_id.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module YACCL
|
2
|
+
class ObjectFactory
|
3
|
+
|
4
|
+
def self.create(raw, repository)
|
5
|
+
case base_type_id(raw)
|
6
|
+
when 'cmis:folder' then Folder.new(raw, repository)
|
7
|
+
when 'cmis:document' then Document.new(raw, repository)
|
8
|
+
when 'cmis:relationship' then Relationship.new(raw, repository)
|
9
|
+
when 'cmis:policy' then Policy.new(raw, repository)
|
10
|
+
when 'cmis:item' then Item.new(raw, repository)
|
11
|
+
else raise "Unexpected baseTypeId: #{base_type_id}."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.base_type_id(raw)
|
18
|
+
if raw['properties']
|
19
|
+
raw['properties']['cmis:baseTypeId']['value']
|
20
|
+
elsif raw['succinctProperties']
|
21
|
+
raw['succinctProperties']['cmis:baseTypeId']
|
22
|
+
else
|
23
|
+
raise "Unexpected json: #{raw}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/yaccl/policy.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Policy < Object
|
3
|
+
|
4
|
+
attr_reader :policy_text
|
5
|
+
|
6
|
+
def initialize(raw, repository)
|
7
|
+
super
|
8
|
+
cmis_properties %w( cmis:policyText )
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply_to(object)
|
12
|
+
connection.execute!({ cmisaction: 'applyPolicy',
|
13
|
+
repositoryId: repository_id,
|
14
|
+
policyId: cmis_object_id,
|
15
|
+
objectId: object.cmis_object_id })
|
16
|
+
end
|
17
|
+
|
18
|
+
def remove_from(object)
|
19
|
+
connection.execute!({ cmisaction: 'removePolicy',
|
20
|
+
repositoryId: repository_id,
|
21
|
+
policyId: cmis_object_id,
|
22
|
+
objectId: object.cmis_object_id })
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
module YACCL
|
4
|
+
class PropertyDefinition
|
5
|
+
|
6
|
+
def initialize(hash = {})
|
7
|
+
@hash = hash.with_indifferent_access
|
8
|
+
|
9
|
+
@hash.each_key do |key|
|
10
|
+
class_eval "def #{key.underscore};@hash['#{key}'];end"
|
11
|
+
class_eval "def #{key.underscore}=(value);@hash['#{key}']=value;end"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def readonly?
|
16
|
+
updatability == 'readonly'
|
17
|
+
end
|
18
|
+
|
19
|
+
def oncreate?
|
20
|
+
updatability == 'oncreate'
|
21
|
+
end
|
22
|
+
|
23
|
+
def readwrite?
|
24
|
+
updatability == 'readwrite'
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
@hash
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/yaccl/query.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module YACCL
|
2
|
+
class Query
|
3
|
+
|
4
|
+
def initialize(repository, statement, options)
|
5
|
+
options.stringify_keys!
|
6
|
+
|
7
|
+
@repository = repository
|
8
|
+
@connection = repository.connection
|
9
|
+
|
10
|
+
@statement = statement
|
11
|
+
@max_items = options['max_items'] || 10
|
12
|
+
@skip_count = options['skip_count'] || 0
|
13
|
+
|
14
|
+
@has_next = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def next_results
|
18
|
+
result = do_query
|
19
|
+
|
20
|
+
@skip_count += result.results.size
|
21
|
+
@has_next = result.has_more_items
|
22
|
+
@total = result.num_items
|
23
|
+
|
24
|
+
result.results
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_next?
|
28
|
+
@has_next
|
29
|
+
end
|
30
|
+
|
31
|
+
def total
|
32
|
+
@total ||= do_query.num_items
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def do_query
|
39
|
+
result = @connection.execute!({ cmisselector: 'query',
|
40
|
+
repositoryId: @repository.id,
|
41
|
+
q: @statement,
|
42
|
+
maxItems: @max_items,
|
43
|
+
skipCount: @skip_count })
|
44
|
+
|
45
|
+
results = result['results'].map do |r|
|
46
|
+
ObjectFactory.create(r, @repository)
|
47
|
+
end
|
48
|
+
|
49
|
+
QueryResult.new(results, result['numItems'], result['hasMoreItems'])
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|