rdomino 0.0.2

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,32 @@
1
+ #require 'rubygems'
2
+ require 'win32ole'
3
+ require 'highline/import'
4
+ require 'active_support'
5
+
6
+ Dir[File.dirname(__FILE__).gsub(/\\/,'/') + '/*/*.rb'].each{|f| require f}
7
+ module Rdomino
8
+
9
+ class Datetime
10
+ include DomObject
11
+ def initialize(time)
12
+ @obj = Session.session.createDatetime(time.strftime("%d.%m.%Y %H:%M:%S"))
13
+ end
14
+
15
+ end
16
+
17
+ class Daterange
18
+ include DomObject
19
+ def initialize(sdt,edt)
20
+ @obj = Session.session.Createdaterange
21
+ @obj.StartDateTime = sdt.obj
22
+ @obj.EndDateTime = edt.obj
23
+ end
24
+ end
25
+
26
+ class Agent
27
+ include DomObject
28
+ end
29
+
30
+ puts "rdomino(#{VERSION}) loaded"
31
+
32
+ end
@@ -0,0 +1,77 @@
1
+ module Rdomino
2
+
3
+ module DomObject
4
+
5
+ def method_missing(m,*args)
6
+ # puts "#{@obj}.send #{m} #{args.inspect}"
7
+ @obj.__send__(m,*args)
8
+ end
9
+
10
+ def obj
11
+ @obj
12
+ end
13
+
14
+ def empty?
15
+ @obj.nil?
16
+ end
17
+
18
+ def initialize(obj)
19
+ @obj = obj
20
+ end
21
+
22
+ end
23
+
24
+ module DbDcDoc
25
+
26
+ def dxl_to_file(filename)
27
+ File.open(filename, "w") do |f|
28
+ f << dxl
29
+ end
30
+ end
31
+
32
+ def dxl
33
+ dxl_exporter = Session.session.createDXLExporter
34
+ dxl_exporter.export(@obj)
35
+ end
36
+
37
+ end
38
+
39
+ module DcView
40
+
41
+ def each
42
+ doc = @obj.getLastDocument
43
+ while doc
44
+ next_doc = @obj.getPrevDocument(doc)
45
+ yield(Document.new(doc))
46
+ doc = next_doc
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ module DatabaseHelper
53
+ def is_replica_id?(s)
54
+ ( s =~ /[A-F0-9]{16}/ ? true : false)
55
+ end
56
+ end
57
+
58
+ module PersonDoc
59
+ def maildb
60
+ Session.get["#{get :mailserver}!!#{get :mailfile}"]
61
+ end
62
+
63
+ def maildb_cluster
64
+ Session.get["#{cluster(get(:mailserver)[0])}!!#{get :mailfile}"]
65
+ end
66
+
67
+ def cluster(s) # CN=EU-MAIL36/OU=DE/O=BAYER"
68
+ server,*ou = s.split("/")
69
+ nr = server[-2..-1]
70
+ h={'35'=>'36','37' => '38'}
71
+ clnr = h[nr] || h.invert[nr]
72
+ raise "cluster not defined" unless clnr
73
+ ou.insert(0,server[0..-3]+clnr).join("/")
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,380 @@
1
+ # autoload database specific modules
2
+ Dir["#{File.dirname(__FILE__).gsub(/\\/,'/')}/databases/*.rb"].each{|f| require f}
3
+
4
+ module Rdomino
5
+
6
+ class Database
7
+ attr_reader :name,:server_path
8
+ include Enumerable,DomObject,DbDcDoc, DatabaseHelper
9
+
10
+ def replication
11
+ @replication ||= self.replicationInfo
12
+ end
13
+
14
+ def cut_off_intervall
15
+ replication.cutoffInterval
16
+ end
17
+
18
+ def cut_off_intervall=(v)
19
+ replication.cutoffInterval = v
20
+ replication.save()
21
+ end
22
+
23
+ def each(&b)
24
+ dc = DocumentCollection.new(@obj.allDocuments)
25
+ dc.each(&b)
26
+ end
27
+
28
+ def [](view_string)
29
+ if view_string =~ /^search:(.*)/
30
+ search( $1 )
31
+ else
32
+ v = get_view( view_string )
33
+ v.obj ? v : nil
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ "#{obj.title} (#{server_path})"
39
+ end
40
+
41
+ # server,path or object
42
+ def initialize(name,obj)
43
+ m = Rdomino::Databases.const_get(name.to_s.camelize) rescue nil
44
+ self.extend(m) if m
45
+ @name = name
46
+ case obj
47
+ when String
48
+ @server_path = obj
49
+ server, path = obj.split("!!")
50
+ @obj = Session.session.getDatabase(server, path)
51
+ flag = @obj.OpenByReplicaID( server, path ) if is_replica_id?(path)
52
+ else
53
+ @obj = obj
54
+ @server_path = "#{obj.server}!!#{obj.filepath}"
55
+ end
56
+ print "\ndb.open:#{self}"
57
+ end
58
+
59
+ def open!
60
+ unless isopen
61
+ @obj = Session.session.getDatabase(@obj.server, @obj.filepath)
62
+ end
63
+ self
64
+ end
65
+
66
+ def get_view(v)
67
+ View.new(@obj,v)
68
+ end
69
+
70
+ def get_agent(v)
71
+ Agent.new(obj.getAgent(v))
72
+ end
73
+
74
+ # contains deleted documents
75
+ def all_documents
76
+ DocumentCollection.new(@obj.allDocuments)
77
+ end
78
+ alias :all :all_documents
79
+
80
+ def count
81
+ all_documents.count
82
+ end
83
+
84
+ # search(:Memo) => all Memos
85
+ # only documents modified within cutoff_days
86
+ def search(filter,since=Time.local(1980,1,1,0,0,0),count=0)
87
+ filter = "Form='#{filter}'" if filter.kind_of? Symbol
88
+ DocumentCollection.new(@obj.search(filter,Datetime.new(since).obj,count))
89
+ end
90
+
91
+ def create_document(attributes={})
92
+ doc = Document.new( obj.CreateDocument )
93
+ attributes.each do |field,value|
94
+ doc.replaceItemValue(field.to_s,value)
95
+ end
96
+ doc.save(true, false)
97
+ doc
98
+ end
99
+
100
+ def fixtures
101
+ Session.get.configuration[name][:fixtures]
102
+ end
103
+
104
+ # :xml from test/fixtures/db.xml
105
+ # :yml from config.yml [db][fixtures]
106
+ # hash or Array of
107
+ # tabular text: f1|f2\nv1|v2
108
+ def load_fixtures(p=:xml)
109
+ delete_documents
110
+ p = ( [] << p ) if p.kind_of? Hash
111
+ p = fixtures if p == :yml
112
+ case p
113
+ when String
114
+ f,*d = p.split("\n")
115
+ fields = f.split("|")
116
+ d.each do |line|
117
+ hash = {}
118
+ values = line.split("|")
119
+ values.each_index{ |i| hash[fields[i]] = values[i] }
120
+ create_document(hash)
121
+ end
122
+ when Array
123
+ p.map{|h|
124
+ create_document(h) }[0]
125
+ else
126
+ dxl_import(IO.read(fixture_file))
127
+ end
128
+ self
129
+ end
130
+
131
+ def fixture_file
132
+ File.dirname(__FILE__)+"/../../test/fixtures/#{name}.xml"
133
+ end
134
+
135
+ def dump
136
+ all_documents.dxl_to_file( fixture_file )
137
+ end
138
+
139
+ def import_all_documents_by_dxl(db)
140
+ d = db.all_documents.dxl
141
+ dxl_import(d)
142
+ end
143
+
144
+ # returns number al deleted documents
145
+ def delete_documents(*form)
146
+ if form.empty?
147
+ dc = allDocuments
148
+ else
149
+ filter = "Form='#{form.map{|i| i.to_s}.join("':'")}'"
150
+ dc = search( filter )
151
+ end
152
+ c = dc.count
153
+ dc.removeAll true
154
+ c == 0 ? nil : c
155
+ end
156
+
157
+ def dxl_import(s)
158
+ imp = Session.session.createDXLImporter
159
+ imp.replaceDBProperties = false
160
+ imp.replicaRequiredForReplaceOrUpdate = false
161
+ imp.aCLImportOption = 5 # DXLIMPORTOPTION_REPLACE_ELSE_IGNORE
162
+ imp.designImportOption = 2 # DXLIMPORTOPTION_CREATE
163
+ imp.import(s, obj)
164
+ end
165
+
166
+ # multiple Documents are yielded to a block
167
+ # returns the number of documents found
168
+ # ReplicationFormulas Actions DataConnections Documents
169
+ # Agents Folders Forms ScriptLibraries Subforms Views
170
+ # FrameSets Navigators Pages Outlines
171
+ # ImageResources JavaResources MiscCodeElements MiscFormatElements MiscIndexElements
172
+ # Profiles SharedFields StyleSheetResources
173
+ def design_documents(*elements)
174
+ elements.map!{|e| "#{e}=" }
175
+ elements << :alldesignelements if elements.empty?
176
+ # its nv.alldesignelements(true)
177
+ # but nv.views = true
178
+ nc = @obj.CreateNoteCollection false
179
+ elements.each{|v|
180
+ nc.send("select#{v}",true)}
181
+ nc.BuildCollection
182
+ id = nc.GetFirstNoteId
183
+ # check if its a single element which doesn't end with 's'
184
+ if elements.length == 1 && elements[0].to_s !~ /s=?$/
185
+ find(id)
186
+ else
187
+ while id != ''
188
+ yield find(id)
189
+ id = nc.GetNextNoteId(id)
190
+ end
191
+ nc.count
192
+ end
193
+ end
194
+
195
+ # single returns the document
196
+ [:acl,:databasescript,:helpabout,:helpindex,:helpusing].each do |m|
197
+ define_method(m) do
198
+ design_documents m
199
+ end
200
+ end
201
+
202
+ def icon
203
+ find('FFFF0010')
204
+ end
205
+
206
+ def flags
207
+ f = icon.g(:$flags)
208
+ r =[f]
209
+ (f.length).times {|i| c = f[i].chr; r << "#{c} - #{FLAGS[c]}" }
210
+ r
211
+ end
212
+
213
+ # underscored will be omitted (as in selection list)
214
+ def default_frameset
215
+ icon.g(:$DefaultFrameset)
216
+ end
217
+
218
+ def default_frameset=(value)
219
+ icon.replace :$DefaultFrameset => value
220
+ icon.save
221
+ end
222
+
223
+ # options(:open => true) => :no_action, :refreshed, :pasted
224
+ def refresh_view_design(template_view,options={})
225
+ view_name = template_view.name
226
+ view = get_view( view_name )
227
+ if view.obj
228
+ if view == template_view
229
+ remove,paste,result = false,false, :no_action
230
+ else
231
+ remove,paste,result = true,true,:refreshed
232
+ end
233
+ else
234
+ remove,paste,result = false,true,:pasted
235
+ end
236
+ view.document.removepermanently(true) if remove
237
+ if paste
238
+ template_view.document.copytodatabase(@obj)
239
+ get_view( view_name ).refresh if options[:open]
240
+ end
241
+ result
242
+ end
243
+
244
+ # defaults :duration => 1, :location => '' , :body => nil
245
+ def create_meeting(start_time,subject,p={})
246
+ end_time = start_time + (p[:duration]||1) * 3600
247
+ sdt = Datetime.new(start_time)
248
+ edt = Datetime.new(end_time)
249
+ date_range = Daterange.new(sdt,edt)
250
+ target = create_document(
251
+ :form => 'Appointment',
252
+ :subject => subject,
253
+ :chair => 'CN=Frank Behrens/OU=IMBEH/OU=BBS/O=BAYER',
254
+ :principal => 'CN=Frank Behrens/OU=IMBEH/OU=BBS/O=BAYER',
255
+ :location => p[:location]||'' ,
256
+ :appointmentType => '3',
257
+ :KLCategories_2 => "",
258
+ :Alarms => "0",
259
+ :Logo => "StdNotesLtr14",
260
+ :BookFreeTime => "",
261
+ :Duration => 105,
262
+ :SequenceNum => 1,
263
+ :OrgTable => "CO",
264
+ :tmpOwnerHW => "1",
265
+ :WebDateTimeInit => "1",
266
+ :TimeRange => date_range.obj,
267
+ :CalendarDateTime => sdt.obj,
268
+ :startDate => sdt.obj,
269
+ :startDateTime => sdt.obj,
270
+ :startTime => sdt.obj,
271
+ :endDate => edt.obj,
272
+ :endDateTime => edt.obj,
273
+ :endTime => edt.obj,
274
+ :_ViewIcon => 9,
275
+ :Org_Table=> "")
276
+ # Call doc.ReplaceItemValue("Org_Table", ORS_ITEM_PLANNER)
277
+ # Set newitem = New NotesItem(doc,"_ViewIcon",9)
278
+ # newitem.issummary = True
279
+ # doc.PostedDate = Now
280
+ target.obj.CopyItem( p[:body], "" ) if p[:body]
281
+ target.ComputeWithForm false, false
282
+ target.save(true, false)
283
+ target
284
+ end
285
+
286
+ def copy(destination)
287
+ server, path = destination.split("!!")
288
+ new(obj.CreateReplica( server, path ))
289
+ end
290
+
291
+ def move(destination)
292
+ target = copy(destination)
293
+ obj.Remove
294
+ @obj = nil
295
+ target
296
+ end
297
+
298
+ # finds document by noteid or unid
299
+ def find(id)
300
+ if id.length == 32
301
+ Document.new(obj.getdocumentbyunid(id))
302
+ else
303
+ Document.new(obj.getdocumentbyid(id))
304
+ end
305
+ end
306
+
307
+ def by( f=:Form, s=nil)
308
+ field = f.to_s
309
+ h = Hash.new { |hash, key| hash[key] = 0 }
310
+ (s ? search(s) : all_documents).each do |d|
311
+ h[d.getItemValue(field)[0]] += 1 unless d.isDeleted
312
+ end
313
+ puts "-----------------------------"
314
+ h.keys.sort.each{|k| puts "%10s %10d"%[k,h[k]]}
315
+ h
316
+ # while dc.count > 0
317
+ # doc = dc.GetFirstDocument
318
+ # value = doc.getitemValue(field)[0]
319
+ # dc_sub = search("#{field}='#{value}'")
320
+ # h[field] = dc_sub.count
321
+ # dc.obj.Subtract( dc_sub ) # doesn't work
322
+ # end
323
+ end
324
+
325
+ def first
326
+ all.first
327
+ end
328
+
329
+ def last
330
+ all.last
331
+ end
332
+
333
+ FLAGS = {
334
+ '4' => :allow_soft_deletes_,
335
+ 'Z' => :enable_lz1_compression,
336
+ 'f' => :do_not_allow_stored_forms,
337
+ 'z' => :do_not_maintain_unread_marks,
338
+ 'h' => :mark_parent_document_on_reply_or_forward,
339
+ 'J' => :use_javascript_when_generating_web_pages,
340
+ 'n' => :never_show_policy_never_show_about_database_when_first_opened,
341
+ '7' => :large_unk_table_allow_more_fields_in_database,
342
+ '6' => :allow_design_locking,
343
+ 'K' => :restore_as_lasted_viewed_by_user,
344
+ 'c' => :show_about_database_if_modified,
345
+ 'Q' => :replicate_unread_marks_to_clustered_servers_only,
346
+ 'U' => :replicate_unread_marks_to_all_servers_appears_with_q_set,
347
+ '2' => :optimise_document_table_bitmap,
348
+ '3' => :maintain_lastaccessed_property,
349
+ '1' => :dont_support_specialised_response_hierarchy,
350
+ 'M' => :multilingual_database,
351
+ 'X' => :web_access_requires_ssl_connection,
352
+ '8' => :web_access_dont_allow_url_open,
353
+ 'i' => :display_images_after_loading,
354
+ '5' => :allow_document_locking,
355
+ 'g' => :database_type_library,
356
+ 'j' => :database_type_personal_journal,
357
+ 'b' => :database_type_domino_directory,
358
+ 'B' => :database_type_directory_catalog,
359
+ 'm' => :database_type_multi_db_search,
360
+ 'u' => :database_type_portfolio,
361
+ 'A' => :database_type_mailbox,
362
+ 'r' => :database_type_mailfile,
363
+ 'p' => :always_show_about_database_document_when_opened_in_the_client_property,
364
+ 'F' => :launch_designated_frameset,
365
+ 'l' => :launch_designated_navigator,
366
+ 's' => :launch_designated_navigator_in_own_window_used_in_conjuction_with_l_above,
367
+ 'a' => :launch_first_attachment_in_about_database_document,
368
+ 'd' => :launch_first_doclink_in_about_database_document,
369
+ 'P' => :web_launch_show_about_database_document,
370
+ 'S' => :web_launch_open_designated_frameset,
371
+ 'E' => :web_launch_open_designated_page,
372
+ 'L' => :web_launch_open_designated_navigator_in_its_own_window,
373
+ 'D' => :web_launch_open_first_doclink_in_about_database_document,
374
+ 'T' => :web_launch_open_designated_doclink,
375
+ 'V' => :web_launch_open_first_document_in_designated_view
376
+ }
377
+
378
+ end
379
+
380
+ end