libisi 0.3.0

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