active_cmis 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.
@@ -0,0 +1,88 @@
1
+ module ActiveCMIS
2
+ # This class is used to manage different CMIS servers.
3
+ class Server
4
+ include Internal::Caching
5
+ # @return [URI] The location of the server
6
+ attr_reader :endpoint
7
+ # @return [Logger] A default logger for derived repositories
8
+ attr_reader :logger
9
+
10
+ # @return [Server] Cached by endpoint and logger
11
+ def self.new(endpoint, logger = nil)
12
+ endpoint = case endpoint
13
+ when URI; endpoint
14
+ else URI(endpoint.to_s)
15
+ end
16
+ endpoints[[endpoint, logger]] ||= super(endpoint, logger || ActiveCMIS.default_logger)
17
+ end
18
+
19
+ # @return [{(URI, Logger) => Server}] The cache of known Servers
20
+ def self.endpoints
21
+ @endpoints ||= {}
22
+ end
23
+
24
+ # @return [String]
25
+ def inspect
26
+ "Server #{@endpoint}"
27
+ end
28
+ # @return [String]
29
+ def to_s
30
+ "Server " + @endpoint.to_s + " : " + repositories.map {|h| h[:name] + "(#{h[:id]})"}.join(", ")
31
+ end
32
+
33
+ # A connection needs the URL to a CMIS REST endpoint.
34
+ #
35
+ # It's used to manage all communication with the CMIS Server
36
+ def initialize(endpoint, logger)
37
+ @endpoint = endpoint
38
+ @logger = logger
39
+ end
40
+
41
+ # @param (see ActiveCMIS::Internal::Connection#authenticate)
42
+ # @see Internal::Connection#authenticate
43
+ # @return [void]
44
+ def authenticate(method, *params)
45
+ conn.authenticate(method, *params)
46
+ end
47
+
48
+ # Returns the _Repository identified by the ID
49
+ #
50
+ # Cached by the repository_id, no way to reset cache yet
51
+ # @param [String] repository_id
52
+ # @return [Repository]
53
+ def repository(repository_id)
54
+ cached_repositories[repository_id] ||= begin
55
+ repository_data = repository_info.
56
+ xpath("/app:service/app:workspace[cra:repositoryInfo/c:repositoryId[child::text() = '#{repository_id}']]", NS::COMBINED)
57
+ if repository_data.empty?
58
+ raise Error::ObjectNotFound.new("The repository #{repository_id} doesn't exist")
59
+ else
60
+ Repository.new(conn.dup, logger.dup, repository_data)
61
+ end
62
+ end
63
+ end
64
+
65
+ # Lists all the available repositories
66
+ #
67
+ # @return [<{:id, :name} => String>]
68
+ def repositories
69
+ repositories = repository_info.xpath("/app:service/app:workspace/cra:repositoryInfo", NS::COMBINED)
70
+ repositories.map {|ri| next {:id => ri.xpath("ns:repositoryId", "ns" => NS::CMIS_CORE).text,
71
+ :name => ri.xpath("ns:repositoryName", "ns" => NS::CMIS_CORE).text }}
72
+ end
73
+
74
+ private
75
+ def repository_info
76
+ @repository_info ||= conn.get_xml(endpoint)
77
+ end
78
+ cache :repository_info
79
+
80
+ def cached_repositories
81
+ @cached_repositories ||= {}
82
+ end
83
+
84
+ def conn
85
+ @conn ||= Internal::Connection.new(logger.dup)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,193 @@
1
+ module ActiveCMIS
2
+ module Type
3
+ # @private
4
+ def self.create(param_conn, repository, klass_data)
5
+ parent_id = klass_data.xpath("cra:type/c:parentId/text()", NS::COMBINED)
6
+ superclass = if parent = parent_id.first
7
+ repository.type_by_id(parent.to_s)
8
+ else
9
+ base_type_id = klass_data.xpath("cra:type/c:baseId", NS::COMBINED).text
10
+ case base_type_id
11
+ when "cmis:document"
12
+ Document
13
+ when "cmis:folder"
14
+ Folder
15
+ when "cmis:relationship"
16
+ Relationship
17
+ when "cmis:policy"
18
+ Policy
19
+ else
20
+ raise ActiveCMIS::Error.new("Type #{klass_data.xpath("cra:type/c:id", NS::COMBINED).text} without supertype, and not actually a valid base_type (#{base_type_id.inspect})\n" + klass_data.to_s)
21
+ end
22
+ end
23
+
24
+ klass = ::Class.new(superclass) do
25
+ extend ActiveCMIS::Type::ClassMethods
26
+ include ActiveCMIS::Type::InstanceMethods
27
+
28
+ @repository = repository
29
+ @conn = param_conn
30
+ @data = klass_data
31
+ @self_link = klass_data.xpath("at:link[@rel = 'self']/@href", NS::COMBINED).text
32
+
33
+ end
34
+ klass
35
+ end
36
+
37
+ # Instance Methods on CMIS Types
38
+ module InstanceMethods
39
+ # Creates a new CMIS Object
40
+ # @overload initialize(attributes)
41
+ # @param [Hash] attributes Attributes for a newly created object of the current type
42
+ # @return [Object]
43
+ def initialize(rep = nil, data = nil, parameters = {})
44
+ case rep
45
+ when Hash
46
+ attributes = rep
47
+ rep = nil
48
+ data = nil # Force data and parameters to be empty in that case (NOTE: assert may be better?)
49
+ parameters = {}
50
+ when NilClass
51
+ else
52
+ if rep != self.class.repository
53
+ raise "Trying to create element in different repository than type"
54
+ end
55
+ end
56
+ super(rep || self.class.repository, data, parameters)
57
+ unless attributes.nil?
58
+ update(attributes)
59
+ end
60
+ end
61
+ end
62
+
63
+ # Class Methods on CMIS Types
64
+ #
65
+ # The following info is also available:
66
+ # id, local_name, local_namespace, display_name, query_name, description, base_id, parent_id, creatable, fileable,
67
+ # queryable, fulltext_indexed, controllable_policy, controllable_acl, versionable, content_stream_allowed
68
+ module ClassMethods
69
+ include Internal::Caching
70
+
71
+ cached_reader :id, :local_name, :local_namespace, :display_name, :query_name, :description, :base_id,
72
+ :parent_id, :creatable, :fileable, :queryable, :fulltext_indexed, :controllable_policy, :controllable_acl,
73
+ :versionable, :content_stream_allowed
74
+
75
+ # @param [Boolean] inherited (false) *Ignored*
76
+ # @return [{String => PropertyDefinition}] A list of propery definitions for all properties on the type
77
+ def attributes(inherited = false)
78
+ load_from_data unless defined?(@attributes)
79
+ if inherited && superclass.respond_to?(:attributes)
80
+ super.merge(@attributes)
81
+ else
82
+ @attributes
83
+ end
84
+ end
85
+
86
+ # @return [{String => PropertyDefinition}] A list of all required definitions (includes inherited attributes)
87
+ def required_attributes
88
+ attributes(true).reject {|key, value| !value.required}
89
+ end
90
+
91
+ # @return [<String>] A list of prefixes that can be used for adressing attributes (like cmis:)
92
+ def attribute_prefixes
93
+ @prefixes ||= attributes(true).keys.map do |key|
94
+ if key =~ /^([^:]+):/
95
+ $1
96
+ end
97
+ end.compact.uniq
98
+ end
99
+
100
+ # @return [void]
101
+ def reload
102
+ remove_instance_variable(:@attributes) if defined? @attributes
103
+ [:attributes] + __reload # Could also do if defined?(super) then super else __reload end, but we don't do anything but remove_instance_variable @attributes in superclasses anyway
104
+ end
105
+
106
+ # @return [String]
107
+ def inspect
108
+ "#<#{repository.key}::Class #{key}>"
109
+ end
110
+
111
+ # @return [String] The CMIS ID of the type
112
+ def key
113
+ @key ||= data.xpath("cra:type/c:id", NS::COMBINED).text
114
+ end
115
+
116
+ # @return [Collection<Class>] All direct subtypes (1 level deep)
117
+ def subtypes
118
+ types_feed = Internal::Utils.extract_links(data, 'down', 'application/atom+xml', 'type' => 'feed')
119
+ raise "No subtypes link for #{id}" if types_feed.empty?
120
+
121
+ Collection.new(repository, types_feed.first) do |entry|
122
+ id = entry.xpath("cra:type/c:id", NS::COMBINED).text
123
+ repository.type_by_id id
124
+ end
125
+ end
126
+ cache :subtypes
127
+
128
+ # @return [Array<Class>] All subtypes
129
+ def all_subtypes
130
+ subtypes.map do |t|
131
+ t.all_subtypes
132
+ end.flatten << self
133
+ end
134
+ cache :all_subtypes
135
+
136
+ private
137
+ # @private
138
+ attr_reader :self_link, :conn
139
+ def data
140
+ @data ||= conn.get_atom_entry(self_link)
141
+ end
142
+ cache :data
143
+
144
+ def load_from_data
145
+ @attributes = {}
146
+ data.xpath('cra:type', NS::COMBINED).children.each do |node|
147
+ next unless node.namespace
148
+ next unless node.namespace.href == NS::CMIS_CORE
149
+
150
+ case node.node_name
151
+ when "id"
152
+ @id = node.text
153
+ when "localName"
154
+ @local_name = node.text
155
+ when "localNamespace"
156
+ @local_namespace = node.text
157
+ when "displayName"
158
+ @display_name = node.text
159
+ when "queryName"
160
+ @query_name = node.text
161
+ when "description"
162
+ @description = node.text
163
+ when "baseId"
164
+ @base_id = node.text
165
+ when "parentId"
166
+ @parent_id = node.text
167
+ when "creatable"
168
+ @creatable = AtomicType::Boolean.xml_to_bool(node.text)
169
+ when "fileable"
170
+ @fileable = AtomicType::Boolean.xml_to_bool(node.text)
171
+ when "queryable"
172
+ @queryable = AtomicType::Boolean.xml_to_bool(node.text)
173
+ when "fulltextIndexed"
174
+ @fulltext_indexed = AtomicType::Boolean.xml_to_bool(node.text)
175
+ when "controllablePolicy"
176
+ @controllable_policy = AtomicType::Boolean.xml_to_bool(node.text)
177
+ when "controllableACL"
178
+ @controllable_acl = AtomicType::Boolean.xml_to_bool(node.text)
179
+ when "versionable"
180
+ @versionable = AtomicType::Boolean.xml_to_bool(node.text)
181
+ when "contentStreamAllowed"
182
+ # FIXME? this is an enumeration, should perhaps wrap
183
+ @content_stream_allowed = node.text
184
+ when /^property(?:DateTime|String|Html|Id|Boolean|Integer|Decimal)Definition$/
185
+ attr = PropertyDefinition.new(self, node.children)
186
+ @attributes[attr.id] = attr
187
+ end
188
+ end
189
+ @attributes.freeze
190
+ end
191
+ end
192
+ end
193
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_cmis
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Joeri Samson
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-09 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: nokogiri
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 4
30
+ - 1
31
+ version: 1.4.1
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: A CMIS library implementing both reading and updating capabilities through the AtomPub/REST binding to CMIS.
35
+ email: joeri@xaop.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - TODO
42
+ files:
43
+ - .gitignore
44
+ - LICENSE
45
+ - README.md
46
+ - Rakefile
47
+ - TODO
48
+ - VERSION
49
+ - lib/active_cmis.rb
50
+ - lib/active_cmis/acl.rb
51
+ - lib/active_cmis/acl_entry.rb
52
+ - lib/active_cmis/active_cmis.rb
53
+ - lib/active_cmis/atomic_types.rb
54
+ - lib/active_cmis/attribute_prefix.rb
55
+ - lib/active_cmis/collection.rb
56
+ - lib/active_cmis/document.rb
57
+ - lib/active_cmis/exceptions.rb
58
+ - lib/active_cmis/folder.rb
59
+ - lib/active_cmis/internal/caching.rb
60
+ - lib/active_cmis/internal/connection.rb
61
+ - lib/active_cmis/internal/utils.rb
62
+ - lib/active_cmis/ns.rb
63
+ - lib/active_cmis/object.rb
64
+ - lib/active_cmis/policy.rb
65
+ - lib/active_cmis/property_definition.rb
66
+ - lib/active_cmis/rel.rb
67
+ - lib/active_cmis/relationship.rb
68
+ - lib/active_cmis/rendition.rb
69
+ - lib/active_cmis/repository.rb
70
+ - lib/active_cmis/server.rb
71
+ - lib/active_cmis/type.rb
72
+ has_rdoc: yard
73
+ homepage: http://xaop.com/labs/activecmis/
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --charset=UTF-8
79
+ - --default-return
80
+ - "::Object"
81
+ - --query
82
+ - "!@private"
83
+ - --hide-void-return
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 1
92
+ - 8
93
+ - 6
94
+ version: 1.8.6
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ requirements: []
103
+
104
+ rubyforge_project:
105
+ rubygems_version: 1.3.6
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: A library to interact with CMIS repositories through the AtomPub/REST binding
109
+ test_files: []
110
+