rdomino 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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