libisi 0.3.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.
Files changed (91) hide show
  1. data/LICENSE +677 -0
  2. data/Manifest +89 -0
  3. data/Rakefile +34 -0
  4. data/lib/inifile.rb +119 -0
  5. data/lib/libisi.rb +948 -0
  6. data/lib/libisi/attribute.rb +32 -0
  7. data/lib/libisi/attribute/activerecord.rb +34 -0
  8. data/lib/libisi/attribute/base.rb +33 -0
  9. data/lib/libisi/base.rb +109 -0
  10. data/lib/libisi/bridge.rb +21 -0
  11. data/lib/libisi/bridge/base.rb +23 -0
  12. data/lib/libisi/bridge/java.rb +71 -0
  13. data/lib/libisi/bridge/python.rb +37 -0
  14. data/lib/libisi/cache.rb +21 -0
  15. data/lib/libisi/cache/base.rb +67 -0
  16. data/lib/libisi/cache/file_cache.rb +24 -0
  17. data/lib/libisi/chart.rb +21 -0
  18. data/lib/libisi/chart/base.rb +320 -0
  19. data/lib/libisi/chart/jfreechart.rb +682 -0
  20. data/lib/libisi/chart/jfreechart_generator.rb +206 -0
  21. data/lib/libisi/color.rb +21 -0
  22. data/lib/libisi/color/base.rb +66 -0
  23. data/lib/libisi/color/colortools.rb +92 -0
  24. data/lib/libisi/color/java.rb +44 -0
  25. data/lib/libisi/concept.rb +33 -0
  26. data/lib/libisi/concept/activerecord.rb +39 -0
  27. data/lib/libisi/concept/base.rb +58 -0
  28. data/lib/libisi/doc.rb +35 -0
  29. data/lib/libisi/doc/base.rb +414 -0
  30. data/lib/libisi/doc/html.rb +85 -0
  31. data/lib/libisi/doc/text.rb +98 -0
  32. data/lib/libisi/doc/wiki.rb +55 -0
  33. data/lib/libisi/environment.rb +21 -0
  34. data/lib/libisi/environment/base.rb +36 -0
  35. data/lib/libisi/environment/http.rb +105 -0
  36. data/lib/libisi/environment/rails.rb +27 -0
  37. data/lib/libisi/environment/root.rb +23 -0
  38. data/lib/libisi/fake_logger/logger.rb +61 -0
  39. data/lib/libisi/function/base.rb +30 -0
  40. data/lib/libisi/hal.rb +558 -0
  41. data/lib/libisi/instance.rb +27 -0
  42. data/lib/libisi/instance/activerecord.rb +21 -0
  43. data/lib/libisi/instance/base.rb +42 -0
  44. data/lib/libisi/log.rb +237 -0
  45. data/lib/libisi/mail/base.rb +32 -0
  46. data/lib/libisi/mail/tmail.rb +120 -0
  47. data/lib/libisi/parameter/base.rb +41 -0
  48. data/lib/libisi/property.rb +27 -0
  49. data/lib/libisi/property/base.rb +28 -0
  50. data/lib/libisi/reciever/base.rb +31 -0
  51. data/lib/libisi/reciever/socket.rb +31 -0
  52. data/lib/libisi/relation.rb +23 -0
  53. data/lib/libisi/request.rb +22 -0
  54. data/lib/libisi/request/base.rb +29 -0
  55. data/lib/libisi/request/http.rb +129 -0
  56. data/lib/libisi/response/base.rb +27 -0
  57. data/lib/libisi/task/base.rb +27 -0
  58. data/lib/libisi/task/http.rb +90 -0
  59. data/lib/libisi/tee.rb +296 -0
  60. data/lib/libisi/ui/base.rb +116 -0
  61. data/lib/libisi/ui/console.rb +238 -0
  62. data/lib/libisi/ui/kde.rb +94 -0
  63. data/lib/libisi/ui/nobody.rb +29 -0
  64. data/lib/libisi/ui/rails.rb +150 -0
  65. data/lib/libisi/ui/x11.rb +55 -0
  66. data/lib/libisi/uri.rb +42 -0
  67. data/lib/libisi/uri/activerecord.rb +152 -0
  68. data/lib/libisi/uri/base.rb +115 -0
  69. data/lib/libisi/uri/file.rb +43 -0
  70. data/lib/libisi/uri/ldap.rb +72 -0
  71. data/lib/libisi/uri/mysql.rb +98 -0
  72. data/lib/libisi/value.rb +31 -0
  73. data/lib/libisi/value/attribute_value.rb +19 -0
  74. data/lib/libisi/value/base.rb +55 -0
  75. data/lib/libisi/value/property_value.rb +19 -0
  76. data/lib/libisi/value/relation_value.rb +19 -0
  77. data/lib/ordered_hash.rb +228 -0
  78. data/libisi.gemspec +31 -0
  79. data/test/bridge_test.rb +77 -0
  80. data/test/cache_test.rb +65 -0
  81. data/test/chart_test.rb +179 -0
  82. data/test/color_test.rb +64 -0
  83. data/test/concept_test.rb +56 -0
  84. data/test/doc_test.rb +172 -0
  85. data/test/fixtures/test.db +0 -0
  86. data/test/ordered_hash_test.rb +39 -0
  87. data/test/profile_test.rb +36 -0
  88. data/test/request_test.rb +121 -0
  89. data/test/test +0 -0
  90. data/test/ui_test.rb +62 -0
  91. metadata +244 -0
@@ -0,0 +1,39 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/attribute"
19
+ require "libisi/property"
20
+ require "libisi/relation"
21
+ class ActiverecordConcept < BaseConcept
22
+
23
+ def attribute_names
24
+ base_class.column_names
25
+ end
26
+
27
+ def attributes
28
+ base_class.columns.map {|c| Attribute.create(self, c)}
29
+ end
30
+
31
+ def relation_names
32
+ base_class.reflections.keys.map {|r| r.to_s}
33
+ end
34
+
35
+ def relations
36
+ base_class.reflections.map {|r| Relation.create(self, r)}
37
+ end
38
+
39
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class BaseConcept
19
+
20
+ VALUE_TYPES = [:attributes, :properties, :relations]
21
+
22
+ attr_reader :base_class
23
+
24
+ def initialize(base_class, options = {})
25
+ @base_class = base_class
26
+ end
27
+
28
+ # There are by default no attributes
29
+ def attribute_names; []; end
30
+ def attributes; []; end
31
+
32
+ def property_names
33
+ ans = attribute_names
34
+ rns = relation_names
35
+ base_class.instance_methods.reject {|mn|
36
+ base_class.instance_method(mn).arity != 0 or
37
+ mn =~ /^to_/ or
38
+ mn =~/^get_/ or
39
+ mn =~/^set_/ or
40
+ mn =~ /=$/ or
41
+ mn =~ /_type$/ or
42
+ mn =~ /_unit$/ or
43
+ ans.include?(mn) or
44
+ rns.include?(mn)
45
+ }
46
+ end
47
+
48
+ def properties
49
+ property_names.map {|p|
50
+ Property.create(base_class, p)
51
+ }
52
+ end
53
+
54
+ def value_accessors
55
+ VALUE_TYPES.map {|vt| self.send(vt)}.flatten
56
+ end
57
+
58
+ end
data/lib/libisi/doc.rb ADDED
@@ -0,0 +1,35 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/base.rb"
19
+ class Doc < Base
20
+
21
+ def self.output_types
22
+ {"text" => ["txt","text"],
23
+ "html" => ["html","htm"]}
24
+ end
25
+
26
+ def self.create(doc, options = {})
27
+ doc = doc.to_s
28
+ raise "Hacking attack!!" unless doc.class == String
29
+ raise "Unexpected Doc name #{doc}." unless doc =~ /^[a-zA-Z][a-zA-Z0-9]*$/
30
+ require "libisi/doc/#{doc}.rb"
31
+ klass = eval("#{doc.capitalize}Doc")
32
+ klass.new(options)
33
+ end
34
+
35
+ end
@@ -0,0 +1,414 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class BaseDoc
19
+
20
+ def initialize(options = {})
21
+ @writer = options[:writer] if options[:writer]
22
+ @init = options[:doc_started] if options[:doc_started]
23
+ end
24
+
25
+ def print(options = {}, &block)
26
+ writer(options, &block) << yield
27
+ end
28
+ def p(options = {}, &block)
29
+ writer(options, &block) << yield + "\n\n"
30
+ end
31
+
32
+ def title(text, options = {}, &block)
33
+ @title_depth ||= 0
34
+ @title_depth += 1
35
+ generate_title(text, options, &block)
36
+ @title_depth -= 1
37
+ end
38
+
39
+ def flatten_columns(columns, options)
40
+ # we will use this for grouping
41
+ options[:columns] ||= []
42
+
43
+ case columns
44
+ when Array
45
+ options[:columns] << columns
46
+ when Hash
47
+ options[:group_bys] ||= []
48
+ columns.each {|key,columns|
49
+ unless key.nil?
50
+ options[:group_bys] << Proc.new {|element|
51
+ case element
52
+ when Hash
53
+ element[key]
54
+ else
55
+ element.send(key)
56
+ end
57
+ }
58
+ end
59
+ flatten_columns(columns, options)
60
+ }
61
+ else
62
+ raise "Unexpected columns type #{columns.class.name}"
63
+ end
64
+ options
65
+ end
66
+
67
+ def generate_table(options = {}, &block); generate_bare_table(options, &block) end
68
+ def generate_bare_table(options = {},&block)
69
+ return yield if options[:columns].nil? and options[:items].nil?
70
+
71
+ options = flatten_columns(options.delete(:columns),options) if options[:columns].class == Hash
72
+
73
+ if options[:group_bys]
74
+ raise "No items given" unless options[:items]
75
+ # group the items
76
+ benchmark("Table group bys") {
77
+ options[:items] = options[:items].group_bys(*options[:group_bys])
78
+ }
79
+ options[:grouped] = true
80
+ end
81
+
82
+ if options[:items] and options[:columns] and not options[:no_header]
83
+ # create header
84
+ tr(options) { options[:columns].flatten.each_with_index{|c,i| th(options) {
85
+ if f = options[:header_function]
86
+ case f
87
+ when Proc
88
+ if f.arity == 1
89
+ f.call(c)
90
+ else
91
+ f.call(c,i)
92
+ end
93
+ when Symbol, String
94
+ c.send(f)
95
+ else
96
+ raise "Unexpected header function #{f.inspect}"
97
+ end
98
+ else
99
+ c
100
+ end
101
+ }}}
102
+ end
103
+
104
+ if options[:items]
105
+ options[:header_function].call(options_for_functions(options) ) if options[:header_function]
106
+ table_items(options[:items],options,&block)
107
+ options[:footer_function].call(options_for_functions(options) ) if options[:footer_function]
108
+ else
109
+ options[:columns].flatten.each_with_index {|column, column_index|
110
+ tr(options) {
111
+ th(options) {column}
112
+ # td(options) {
113
+ # problem with tee here
114
+ td {options[:columns].inspect}
115
+ case block.arity
116
+ when 2
117
+ yield(column,column_index)
118
+ else
119
+ yield(column)
120
+ end
121
+ }
122
+ # }
123
+ }
124
+ end
125
+ end
126
+ def bare_table(options = {}, &block)
127
+ generate_bare_table(options, &block)
128
+ end
129
+ def table(options = {}, &block)
130
+ # options[:writer] = writer(options, &block) unless options[:writer]
131
+ generate_table(options,&block)
132
+ end
133
+
134
+ def options_for_functions(options)
135
+ options[:item_tree] = options[:items].to_hash(true) unless options[:item_tree]
136
+ o = options.dup
137
+ if o[:group_bys]
138
+ benchmark("Doc.options_for_functions") {
139
+ total_groupings = o[:group_bys].length
140
+ if o[:group_column_index]
141
+ # we are at item output
142
+ depth = o[:group_column_index]
143
+ else
144
+ # we are at grouping
145
+ depth = (o[:group_keys] or []).length - 1
146
+ end
147
+
148
+ # correct group_keys because we are maybe already
149
+ # in a gouping
150
+ o[:group_keys] = (o[:group_keys] or []).dup[0..depth]
151
+
152
+ o[:group_tree] = options[:item_tree]
153
+
154
+ o[:group_keys].each {|k|
155
+ o[:group_tree] = o[:group_tree][k]
156
+ }
157
+
158
+ o[:group_items] = o[:group_tree]
159
+ o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
160
+ # while !o[:group_items].nil? and o[:group_items][0].class == Hash
161
+ (total_groupings - depth - 2).times {
162
+ o[:group_items] = o[:group_items].map {|h| h.values}.flatten
163
+ }
164
+ # end
165
+ }
166
+ end
167
+ o
168
+ end
169
+
170
+
171
+ def options_for_functions_orig(options)
172
+ o = options.dup
173
+ if o[:group_bys]
174
+ benchmark("Doc.options_for_functions") {
175
+ total_groupings = o[:group_bys].length
176
+ if o[:group_column_index]
177
+ # we are at item output
178
+ depth = o[:group_column_index]
179
+ else
180
+ # we are at grouping
181
+ depth = o[:group_keys].length - 1
182
+ end
183
+
184
+ # correct group_keys because we are maybe already
185
+ # in a gourping
186
+ o[:group_keys] = o[:group_keys].dup[0..depth]
187
+
188
+ o[:group_tree] = options[:items].to_hash(true)
189
+ o[:group_keys].each {|k|
190
+ o[:group_tree] = o[:group_tree][k]
191
+ }
192
+
193
+ o[:group_items] = o[:group_tree]
194
+ o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
195
+ # while !o[:group_items].nil? and o[:group_items][0].class == Hash
196
+ (total_groupings - depth - 2).times {
197
+ o[:group_items] = o[:group_items].map {|h| h.values}.flatten
198
+ }
199
+ # end
200
+ }
201
+ end
202
+ o
203
+ end
204
+
205
+ def call_total_function(function_name, options = {})
206
+ level = options[:group_keys].length - 1
207
+ function = options[(function_name.to_s + level.to_s).to_sym]
208
+ return unless function
209
+ function.call(options_for_functions(options))
210
+ end
211
+
212
+ def table_items(items, options = {}, &block)
213
+ redo_item = false
214
+ if options[:grouped]
215
+ options[:group_elements] ||= []
216
+ options[:group_keys] ||= []
217
+ options[:item_index] ||= 0
218
+
219
+ if items[0].class == Array and
220
+ items[0].length == 2
221
+ # this is still a group
222
+ items.each_with_index {|val, group_index|
223
+ key, group = val
224
+ options[:group_elements] << key
225
+ options[:group_keys] << key
226
+ call_total_function(:before_group_function, options)
227
+ table_items(group, options, &block)
228
+ call_total_function(:after_group_function, options)
229
+ options[:group_elements].pop
230
+ options[:group_keys].pop
231
+ }
232
+ else
233
+ # finished grouping, do output
234
+ if options[:return_group_at_once]
235
+ tr(options) {
236
+ redo_item = table_item(items, options[:item_index], options, &block)
237
+ }
238
+ else
239
+ items.each_with_index {|item, item_index|
240
+ tr(options) {
241
+ redo_item = table_item(item, options[:item_index], options, &block)
242
+ }
243
+ redo if redo_item
244
+ }
245
+ end
246
+ end
247
+ else
248
+ options[:items].each_with_index {|item, item_index|
249
+ tr(options) {
250
+ redo_item = table_item(item, item_index, options, &block)
251
+ }
252
+ redo if redo_item
253
+ }
254
+ end
255
+ end
256
+
257
+ def table_item(item, item_index, options = {}, &block)
258
+ redo_item = false
259
+ options[:item_index] += 1 if options[:item_index]
260
+ if (cols = options[:columns])
261
+ # yield one per column
262
+ column_index = -1
263
+
264
+ # cols in format
265
+ # [ [groupcol,groupcol,groupcol], # columns for group element 1
266
+ # [groupcol,groupcol,groupcol], # columns for group element 2
267
+ # col,col,col ]
268
+ cols.each_with_index {|subcolumns, group_column_index|
269
+ options[:group_column_index] = group_column_index
270
+
271
+ if subcolumns.class == Array
272
+ # ok these are subcolumns of a group
273
+ else
274
+ subcolumns = [subcolumns]
275
+ end
276
+
277
+ subcolumns.each_with_index {|column,subcol_index|
278
+ # column_index counts trough each column (including group cols)
279
+ column_index += 1
280
+
281
+ el = item
282
+
283
+ group_column = (options[:group_elements] and
284
+ options[:group_elements].length > group_column_index)
285
+ if group_column
286
+ # This is a group column
287
+
288
+ if options[:group_elements][group_column_index] == NilClass
289
+ # we already yielded this group element
290
+ td(options) {}
291
+ next
292
+ else
293
+ el = options[:group_elements][group_column_index]
294
+ # mark group element as visited if all group columns
295
+ # for that group element have been yielded
296
+ if (subcolumns.length - 1) == subcol_index
297
+ options[:group_elements][group_column_index] = NilClass
298
+ if options[:span_grouping]
299
+ redo_item = true
300
+
301
+ # TODO: this is not right, but works for group items with one column
302
+ total_columns = options[:columns].flatten.length
303
+ grouped_columns = (options[:group_elements].length - 1)
304
+
305
+ options = { :colspan => total_columns - grouped_columns}.merge(options)
306
+ # td({:colspan => grouped_columns}.merge(options)) {} unless grouped_columns == 0
307
+ # th({:colspan => total_columns - grouped_columns}.merge(options)) {yield(key}
308
+ end
309
+
310
+ end
311
+
312
+ if block_given? and block.arity == 1
313
+ td(options) {
314
+ if options[:span_grouping]
315
+ # we already printed grouping
316
+ ""
317
+ else
318
+ el.to_s
319
+ end
320
+ }
321
+ next
322
+ end
323
+ end
324
+ end
325
+
326
+ next td(options){el.to_s} unless block_given?
327
+ case block.arity
328
+ when 2
329
+ td(options) {yield(el,column)}
330
+ when 3
331
+ td(options) {yield(el,column,item_index)}
332
+ when 4
333
+ td(options) {yield(el,column,item_index,column_index)}
334
+ when 5
335
+ o = options_for_functions(options)
336
+ td(options) {yield(el,column,item_index,column_index,o)}
337
+ else
338
+ yield(el)
339
+ # class is handling columns themself
340
+ break
341
+ end
342
+ if redo_item
343
+ options.delete(:group_column_index)
344
+ return true
345
+ end
346
+ }
347
+ options.delete(:group_column_index)
348
+ }
349
+ false
350
+ else
351
+ if options[:group_elements]
352
+ options[:group_elements].each_with_index {|group_element, group_element_index|
353
+ if group_element
354
+ td(options) { group_element}
355
+ else
356
+ td(options) {}
357
+ end
358
+ options[:group_elements][group_element_index] = nil
359
+ }
360
+ end
361
+
362
+ return td(options) {item.to_s} unless block_given?
363
+
364
+ case block.arity
365
+ when 2
366
+ yield(item,item_index)
367
+ else
368
+ return yield(item)
369
+ end
370
+ end
371
+ end
372
+
373
+ def tn(options = {}, &block);
374
+ options[:text_align] ||= "right"
375
+ td(options, &block)
376
+ end
377
+
378
+ def start_doc; end
379
+ def end_doc; end
380
+
381
+ def close
382
+ to_stdout(@writer)
383
+ @writer.close if @writer and @writer.respond_to?(:close)
384
+ end
385
+
386
+ private
387
+ def to_stdout(text)
388
+ STDOUT << ("#{text.inspect}\n")
389
+ end
390
+
391
+ def writer(options = {}, &block)
392
+ @writer = options[:writer] if options[:writer]
393
+ if @writer and @writer.respond_to?(:call)
394
+ @writer = @writer.call(block)
395
+ end
396
+
397
+ unless @init
398
+ @init = true
399
+ self.start_doc
400
+ end
401
+
402
+ return @writer if @writer
403
+ return STDOUT
404
+ # klass = eval("self.class",block.binding)
405
+ # case klass
406
+ # when BaseDoc
407
+ end
408
+
409
+ def generate_title(text, options, &block)
410
+ print(options) { text.to_s.upcase + "\n"}
411
+ yield
412
+ end
413
+
414
+ end