omf_web 0.9.1 → 0.9.3

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 (243) hide show
  1. data/.gitignore +0 -1
  2. data/README.md +8 -2
  3. data/doc/screenshot.png +0 -0
  4. data/example/{basic → NOT_WORKING/basic}/hello-world-wired.rb +0 -0
  5. data/example/{basic → NOT_WORKING/basic}/visualisation.yml +0 -0
  6. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklynDemo.sq3 +0 -0
  7. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_gps.dat +0 -0
  8. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_server.rb +0 -0
  9. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_wimax.dat +0 -0
  10. data/example/{brooklyn → NOT_WORKING/brooklyn}/sql_source.rb +0 -0
  11. data/example/{code → NOT_WORKING/code}/code_server.rb +0 -0
  12. data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/parse_log.rb +0 -0
  13. data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/pxe_slice-2012-06-02t02.25.00-04.00.log +0 -0
  14. data/example/{frisbee → NOT_WORKING/frisbee}/progress_chart.yaml +0 -0
  15. data/example/{frisbee → NOT_WORKING/frisbee}/progress_tab.yaml +0 -0
  16. data/example/{frisbee → NOT_WORKING/frisbee}/progress_table.yaml +0 -0
  17. data/example/{frisbee → NOT_WORKING/frisbee}/viz_server.rb +0 -0
  18. data/example/{gec12 → NOT_WORKING/gec12}/gec12-53.rb +0 -0
  19. data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo.sq3 +0 -0
  20. data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo_server.rb +0 -0
  21. data/example/{gec12 → NOT_WORKING/gec12}/visualization.rb +0 -0
  22. data/example/{incoming → NOT_WORKING/incoming}/ofpu_barchart_widget.yaml +0 -0
  23. data/example/{log → NOT_WORKING/log}/log_config.xml +0 -0
  24. data/example/{log → NOT_WORKING/log}/log_server.rb +0 -0
  25. data/example/{network → NOT_WORKING/network}/flow_tab.yaml +0 -0
  26. data/example/{network → NOT_WORKING/network}/network_server.rb +0 -0
  27. data/example/{text → NOT_WORKING/text}/test.md +0 -0
  28. data/example/{text → NOT_WORKING/text}/test.rb +0 -0
  29. data/example/{wimax → NOT_WORKING/wimax}/downlink.yaml +0 -0
  30. data/example/{wimax → NOT_WORKING/wimax}/power.yaml +0 -0
  31. data/example/{wimax → NOT_WORKING/wimax}/snapshot.db +0 -0
  32. data/example/{wimax → NOT_WORKING/wimax}/snapshot.sql +0 -0
  33. data/example/{wimax → NOT_WORKING/wimax}/test.rb +0 -0
  34. data/example/{wimax → NOT_WORKING/wimax}/uplink.yaml +0 -0
  35. data/example/{wimax → NOT_WORKING/wimax}/viz_server.rb +0 -0
  36. data/example/demo/data_sources/mobile_network.rb +3 -0
  37. data/example/demo/data_sources/static_network.rb +54 -0
  38. data/example/demo/widgets/charts_tab.yaml +21 -16
  39. data/example/demo/widgets/linked_graphs_tab.yaml +95 -0
  40. data/example/demo/widgets/mobile_network_widget.yaml +1 -1
  41. data/example/demo/widgets/pie_chart_widget.yaml +1 -1
  42. data/lib/omf-web/config.ru +2 -2
  43. data/lib/omf-web/data_source_proxy.rb +81 -19
  44. data/lib/omf-web/rack/websocket_handler.rb +77 -23
  45. data/lib/omf-web/theme/abstract_page.rb +43 -26
  46. data/lib/omf-web/theme/bright/code_renderer.rb +1 -1
  47. data/lib/omf-web/theme/bright/page.rb +1 -0
  48. data/lib/omf-web/theme/bright/tabbed_renderer.rb +7 -0
  49. data/lib/omf-web/version.rb +7 -0
  50. data/lib/omf-web/widget/data_widget.rb +38 -46
  51. data/lib/omf-web/widget/layout/stacked_layout.rb +2 -1
  52. data/lib/omf-web/widget/layout/tabbed_layout.rb +1 -2
  53. data/{MARUKU-LICENSE → lib/omf-web/widget/text/maruku/MARUKU-LICENSE} +0 -0
  54. data/lib/{maruku → omf-web/widget/text/maruku}/helpers.rb +0 -0
  55. data/lib/{maruku → omf-web/widget/text/maruku}/input/parse_block.rb +0 -0
  56. data/lib/{maruku → omf-web/widget/text/maruku}/output/to_html.rb +26 -21
  57. data/lib/omf-web/widget/text/maruku.rb +5 -0
  58. data/omf_web.gemspec +2 -1
  59. data/share/htdocs/{js → UNUSED}/log/table.js +0 -0
  60. data/share/htdocs/{css → graph/css}/graph.css +0 -0
  61. data/share/htdocs/{image/graph → graph/img}/bar_chart.png +0 -0
  62. data/share/htdocs/{image/graph → graph/img}/donut_chart.png +0 -0
  63. data/share/htdocs/{image/graph → graph/img}/funnel.png +0 -0
  64. data/share/htdocs/{image/graph → graph/img}/info.png +0 -0
  65. data/share/htdocs/{image/graph → graph/img}/line_chart.png +0 -0
  66. data/share/htdocs/{image/graph → graph/img}/line_chart_fill.png +0 -0
  67. data/share/htdocs/{image/graph → graph/img}/misc.png +0 -0
  68. data/share/htdocs/{image/graph → graph/img}/overview.png +0 -0
  69. data/share/htdocs/{image/graph → graph/img}/pie_chart.png +0 -0
  70. data/share/htdocs/{image/graph → graph/img}/scatter_plot.png +0 -0
  71. data/share/htdocs/{image/graph → graph/img}/stacked_bar_chart.png +0 -0
  72. data/share/htdocs/{image/graph → graph/img}/stacked_line_chart.png +0 -0
  73. data/share/htdocs/{image/graph → graph/img}/table.png +0 -0
  74. data/share/htdocs/{js/graph → graph/js}/abstract_chart.js +1 -1
  75. data/share/htdocs/{js/graph → graph/js}/abstract_nv_chart.js +8 -13
  76. data/share/htdocs/{js/graph → graph/js}/abstract_widget.js +9 -16
  77. data/share/htdocs/{js/graph → graph/js}/axis.js +1 -1
  78. data/share/htdocs/{js/graph → graph/js}/barchart.js +2 -2
  79. data/share/htdocs/{js/graph → graph/js}/code_mirror.js +1 -5
  80. data/share/htdocs/{js/graph → graph/js}/discrete_bar_chart.js +1 -1
  81. data/share/htdocs/{js/graph → graph/js}/histogram2.js +1 -1
  82. data/share/htdocs/{js/graph → graph/js}/holt_winters_chart.js +1 -1
  83. data/share/htdocs/{js/graph → graph/js}/line_chart3.js +1 -1
  84. data/share/htdocs/{js/graph → graph/js}/line_chart_with_focus.js +1 -1
  85. data/share/htdocs/{js/graph → graph/js}/map2.js +1 -1
  86. data/share/htdocs/{js/graph → graph/js}/multi_barchart.js +1 -1
  87. data/share/htdocs/graph/js/network2.js +412 -0
  88. data/share/htdocs/{js/graph → graph/js}/pie_chart2.js +1 -1
  89. data/share/htdocs/{js/graph → graph/js}/scatter_plot.js +1 -1
  90. data/share/htdocs/{js/graph → graph/js}/table2.js +17 -20
  91. data/share/htdocs/js/data_source2.js +187 -60
  92. data/share/htdocs/js/require3.js +38 -57
  93. data/share/htdocs/theme/bright/css/bright.css +4 -4
  94. data/share/htdocs/vendor/jquery/jquery.js +9404 -0
  95. data/share/htdocs/vendor/osa/LICENSE.txt +11 -0
  96. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_green_left.svg +0 -0
  97. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_yellow_right.svg +0 -0
  98. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_awareness.svg +0 -0
  99. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_camera-web.svg +0 -0
  100. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_cloud.svg +0 -0
  101. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_contract.svg +0 -0
  102. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_database.svg +0 -0
  103. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop.svg +0 -0
  104. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop_imac.svg +0 -0
  105. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-music.svg +0 -0
  106. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-scanner.svg +0 -0
  107. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb-wifi.svg +0 -0
  108. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb.svg +0 -0
  109. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-wireless-router.svg +0 -0
  110. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_disposal.svg +0 -0
  111. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-harddisk.svg +0 -0
  112. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-optical.svg +0 -0
  113. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_firewall.svg +0 -0
  114. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_home.svg +0 -0
  115. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_hub.svg +0 -0
  116. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_iPhone.svg +0 -0
  117. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_drive.svg +0 -0
  118. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_plc.svg +0 -0
  119. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_thermometer.svg +0 -0
  120. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_id_card.svg +0 -0
  121. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_image-generic.svg +0 -0
  122. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_laptop.svg +0 -0
  123. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lifecycle.svg +0 -0
  124. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lightning.svg +0 -0
  125. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-flash.svg +0 -0
  126. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-optical.svg +0 -0
  127. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-tape.svg +0 -0
  128. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_mobile_pda.svg +0 -0
  129. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_padlock.svg +0 -0
  130. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_printer.svg +0 -0
  131. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server.svg +0 -0
  132. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_application.svg +0 -0
  133. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_database.svg +0 -0
  134. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_directory.svg +0 -0
  135. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_distribution.svg +0 -0
  136. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_file.svg +0 -0
  137. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_gateway.svg +0 -0
  138. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_identity.svg +0 -0
  139. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_mail.svg +0 -0
  140. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_media.svg +0 -0
  141. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_monitor.svg +0 -0
  142. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_proxy.svg +0 -0
  143. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_terminal.svg +0 -0
  144. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_web.svg +0 -0
  145. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-branch.svg +0 -0
  146. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-factory.svg +0 -0
  147. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-head-office.svg +0 -0
  148. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-neighbourhood.svg +0 -0
  149. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_audit.svg +0 -0
  150. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_black_hat.svg +0 -0
  151. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue.svg +0 -0
  152. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_security_specialist.svg +0 -0
  153. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_sysadmin.svg +0 -0
  154. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tester.svg +0 -0
  155. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tie.svg +0 -0
  156. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green.svg +0 -0
  157. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_architect.svg +0 -0
  158. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_business_manager.svg +0 -0
  159. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_developer.svg +0 -0
  160. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_operations.svg +0 -0
  161. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_project_manager.svg +0 -0
  162. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_service_manager.svg +0 -0
  163. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_warning.svg +0 -0
  164. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_large_group.svg +0 -0
  165. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_users_blue_green.svg +0 -0
  166. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_vpn.svg +0 -0
  167. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_warning.svg +0 -0
  168. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_wireless_network.svg +0 -0
  169. data/share/htdocs/{image → vendor/unknown/image}/.DS_Store +0 -0
  170. data/share/htdocs/{image → vendor/unknown/image}/add_icon.gif +0 -0
  171. data/share/htdocs/{image → vendor/unknown/image}/alertbad_icon.gif +0 -0
  172. data/share/htdocs/{image → vendor/unknown/image}/alertgood_icon.gif +0 -0
  173. data/share/htdocs/{image → vendor/unknown/image}/back_disabled.jpg +0 -0
  174. data/share/htdocs/{image → vendor/unknown/image}/back_disabled.png +0 -0
  175. data/share/htdocs/{image → vendor/unknown/image}/back_enabled.jpg +0 -0
  176. data/share/htdocs/{image → vendor/unknown/image}/back_enabled.png +0 -0
  177. data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.jpg +0 -0
  178. data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.png +0 -0
  179. data/share/htdocs/{image → vendor/unknown/image}/bottom-bg.gif +0 -0
  180. data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.jpg +0 -0
  181. data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.png +0 -0
  182. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.jpg +0 -0
  183. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.png +0 -0
  184. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.jpg +0 -0
  185. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.png +0 -0
  186. data/share/htdocs/{image → vendor/unknown/image}/icon-remove.gif +0 -0
  187. data/share/htdocs/{image → vendor/unknown/image}/indicator.gif +0 -0
  188. data/share/htdocs/{image → vendor/unknown/image}/laptop.png +0 -0
  189. data/share/htdocs/{image → vendor/unknown/image}/logo-bottom.gif +0 -0
  190. data/share/htdocs/{image → vendor/unknown/image}/nav-tab-arrow.gif +0 -0
  191. data/share/htdocs/{image → vendor/unknown/image}/norbit_big.gif +0 -0
  192. data/share/htdocs/{image → vendor/unknown/image}/norbit_clipart.png +0 -0
  193. data/share/htdocs/{image → vendor/unknown/image}/progress_bar.gif +0 -0
  194. data/share/htdocs/{image → vendor/unknown/image}/right-bg.gif +0 -0
  195. data/share/htdocs/{image → vendor/unknown/image}/sort_asc.png +0 -0
  196. data/share/htdocs/{image → vendor/unknown/image}/sort_asc_disabled.png +0 -0
  197. data/share/htdocs/{image → vendor/unknown/image}/sort_both.png +0 -0
  198. data/share/htdocs/{image → vendor/unknown/image}/sort_desc.png +0 -0
  199. data/share/htdocs/{image → vendor/unknown/image}/sort_desc_disabled.png +0 -0
  200. data/share/htdocs/{image → vendor/unknown/image}/spinner.gif +0 -0
  201. data/share/htdocs/{svg → vendor/unknown/svg}/ap.svg +0 -0
  202. data/share/htdocs/{svg → vendor/unknown/svg}/router.svg +0 -0
  203. metadata +198 -216
  204. data/example/demo/widgets/dashboard_tab.yaml +0 -28
  205. data/example/demo/widgets/download_tab.yaml +0 -42
  206. data/example/demo/widgets/edit_tab.yaml +0 -20
  207. data/example/demo/widgets/generator_tab.yaml +0 -12
  208. data/lib/omf-oml/endpoint.rb +0 -175
  209. data/lib/omf-oml/indexed_table.rb +0 -57
  210. data/lib/omf-oml/network.rb +0 -413
  211. data/lib/omf-oml/oml_tuple.rb +0 -62
  212. data/lib/omf-oml/schema.rb +0 -191
  213. data/lib/omf-oml/sequel/sequel_server.rb +0 -412
  214. data/lib/omf-oml/sql_row.rb +0 -302
  215. data/lib/omf-oml/sql_source.rb +0 -131
  216. data/lib/omf-oml/table.rb +0 -131
  217. data/lib/omf-oml/tuple.rb +0 -97
  218. data/lib/omf_oml.rb +0 -4
  219. data/share/htdocs/css/coderay.css +0 -127
  220. data/share/htdocs/css/ie.css +0 -40
  221. data/share/htdocs/css/lightbox.css +0 -62
  222. data/share/htdocs/css/scaffold.css +0 -74
  223. data/share/htdocs/css/screen.css +0 -1313
  224. data/share/htdocs/css/search.css +0 -102
  225. data/share/htdocs/css/table.css +0 -538
  226. data/share/htdocs/css/table2.css +0 -191
  227. data/share/htdocs/css/welcome.css +0 -103
  228. data/share/htdocs/css/wfob.css +0 -171
  229. data/share/htdocs/css/wshow.css +0 -69
  230. data/share/htdocs/gec9_demo.html +0 -39
  231. data/share/htdocs/images +0 -1
  232. data/share/htdocs/js/graph/histogram.js +0 -229
  233. data/share/htdocs/js/graph/line_chart.js +0 -342
  234. data/share/htdocs/js/graph/line_chart2.js +0 -232
  235. data/share/htdocs/js/graph/line_chart_fc.js +0 -94
  236. data/share/htdocs/js/graph/map.js +0 -85
  237. data/share/htdocs/js/graph/network.js +0 -591
  238. data/share/htdocs/js/graph/network2.js +0 -318
  239. data/share/htdocs/js/graph/pie_chart.js +0 -130
  240. data/share/htdocs/js/graph/table.js +0 -94
  241. data/share/htdocs/js/require2.js +0 -1998
  242. data/share/htdocs/js/timelines.js +0 -101
  243. data/share/htdocs/stylesheet/grid.css +0 -31
@@ -1,191 +0,0 @@
1
-
2
- require 'omf_common/lobject'
3
- require 'omf_oml'
4
-
5
- module OMF::OML
6
-
7
- # This class represents the schema of an OML measurement stream.
8
- #
9
- class OmlSchema < OMF::Common::LObject
10
-
11
- CLASS2TYPE = {
12
- TrueClass => 'boolean',
13
- FalseClass => 'boolean',
14
- String => 'string',
15
- Symbol => 'string',
16
- Fixnum => 'decimal',
17
- Float => 'double',
18
- Time => 'dateTime'
19
- }
20
-
21
- # Map various type definitions (all lower case) into a single one
22
- ANY2TYPE = {
23
- 'integer' => :integer,
24
- 'int' => :integer,
25
- 'bigint' => :integer,
26
- 'unsigned integer' => :integer,
27
- 'float' => :float,
28
- 'real' => :float,
29
- 'double' => :float,
30
- 'text' => :string,
31
- 'string' => :string,
32
- 'date' => :date,
33
- 'dateTime'.downcase => :dateTime, # should be 'datetime' but we downcase the string for comparison
34
- 'key' => :key,
35
- }
36
-
37
- def self.create(schema_description)
38
- if schema_description.kind_of? self
39
- return schema_description
40
- end
41
- return self.new(schema_description)
42
- end
43
-
44
- # Return the col name at a specific index
45
- #
46
- def name_at(index)
47
- @schema[index][:name]
48
- end
49
-
50
- # Return the col index for column named +name+
51
- #
52
- def index_for_col(name)
53
- name = name.to_sym
54
- @schema.each_with_index do |col, i|
55
- return i if col[:name] == name
56
- end
57
- raise "Unknonw column '#{name}'"
58
- end
59
-
60
- # Return the column names as an array
61
- #
62
- def names
63
- @schema.collect do |col| col[:name] end
64
- end
65
-
66
- # Return the col type at a specific index
67
- #
68
- def type_at(index)
69
- @schema[index][:type]
70
- end
71
-
72
- def columns
73
- @schema
74
- end
75
-
76
- def insert_column_at(index, col)
77
- if col.kind_of?(Symbol) || col.kind_of?(String)
78
- col = [col]
79
- end
80
- if col.kind_of? Array
81
- # should be [name, type]
82
- if col.length == 1
83
- col = {:name => col[0].to_sym,
84
- :type => :string,
85
- :title => col[0].to_s.split('_').collect {|s| s.capitalize}.join(' ')}
86
- elsif col.length == 2
87
- col = {:name => col[0].to_sym,
88
- :type => col[1].to_sym,
89
- :title => col[0].to_s.split('_').collect {|s| s.capitalize}.join(' ')}
90
- elsif col.length == 3
91
- col = {:name => col[0].to_sym, :type => col[1].to_sym, :title => col[2]}
92
- else
93
- throw "Simple column schema should consist of [name, type, title] array, but found '#{col.inspect}'"
94
- end
95
- elsif col.kind_of? Hash
96
- # ensure there is a :title property
97
- unless col[:title]
98
- col[:title] = col[:name].to_s.split('_').collect {|s| s.capitalize}.join(' ')
99
- end
100
- end
101
-
102
- # should normalize type
103
- if type = col[:type]
104
- unless type = ANY2TYPE[type.to_s.downcase]
105
- warn "Unknown type definition '#{col[:type]}', default to 'string'"
106
- type = :string
107
- end
108
- else
109
- warn "Missing type definition in '#{col[:name]}', default to 'string'"
110
- type = :string
111
- end
112
- col[:type] = type
113
-
114
- col[:type_conversion] = case type
115
- when :string
116
- lambda do |r| r end
117
- when :key
118
- lambda do |r| r end
119
- when :integer
120
- lambda do |r| r.to_i end
121
- when :float
122
- lambda do |r| r.to_f end
123
- when :date
124
- lambda do |r| Date.parse(r) end
125
- when :dateTime
126
- lambda do |r| Time.parse(r) end
127
- else raise "Unrecognized Schema type '#{type}'"
128
- end
129
-
130
- @schema.insert(index, col)
131
- end
132
-
133
- def each_column(&block)
134
- @schema.each do |c|
135
- block.call(c)
136
- end
137
- end
138
-
139
- # Translate a record described in a hash of 'col_name => value'
140
- # to a row array
141
- #
142
- def hash_to_row(hrow, set_nil_when_missing = false)
143
- @schema.collect do |cdescr|
144
- cname = cdescr[:name]
145
- unless hrow.key? cname
146
- next nil if set_nil_when_missing
147
- raise "Missing record element '#{cname}' in record '#{hrow}'"
148
- end
149
- cdescr[:type_conversion].call(hrow[cname])
150
- end
151
- end
152
-
153
- # Cast each element in 'row' into its proper type according to this schema
154
- #
155
- def cast_row(raw_row)
156
- unless raw_row.length == @schema.length
157
- raise "Row needs to have same size as schema (#{raw_row.inspect})"
158
- end
159
- # This can be done more elegantly in 1.9
160
- row = []
161
- raw_row.each_with_index do |el, i|
162
- row << @schema[i][:type_conversion].call(el)
163
- end
164
- row
165
- end
166
-
167
- def describe
168
- @schema.map {|c| {:name => c[:name], :type => c[:type], :title => c[:title] }}
169
- end
170
-
171
- def to_json(*opt)
172
- describe.to_json(*opt)
173
- end
174
-
175
- protected
176
-
177
- # schema_description - Array containing [name, type*] for every column in table
178
- # TODO: define format of TYPE
179
- #
180
- def initialize(schema_description)
181
- # check if columns are described by hashes or 2-arrays
182
- @schema = []
183
- schema_description.each_with_index do |cdesc, i|
184
- insert_column_at(i, cdesc)
185
- end
186
- debug "schema: '#{describe.inspect}'"
187
-
188
- end
189
- end # OmlSchema
190
-
191
- end
@@ -1,412 +0,0 @@
1
- require 'rubygems'
2
- require 'rexml/document'
3
- require 'time'
4
- require 'logger'
5
- require 'sequel'
6
-
7
- require 'omf_common/lobject'
8
- require 'omf_oml'
9
-
10
- # module OMF::OML
11
- # module Sequel; end
12
- # end
13
-
14
- module OMF::OML::Sequel
15
- module Server
16
-
17
- class Query < OMF::Common::LObject
18
-
19
- def self.parse(xmls, repoFactory = RepositoryFactory.new, logger = Logger.new(STDOUT))
20
- if xmls.kind_of? String
21
- doc = REXML::Document.new(xmls)
22
- root = doc.root
23
- else
24
- root = xmls
25
- end
26
- unless root.name == 'query'
27
- raise "XML fragment needs to start with 'query' but does start with '#{root.name}"
28
- end
29
- q = self.new(root, repoFactory, logger)
30
- q.relation
31
- end
32
-
33
- def initialize(queryEl, repoFactory, logger)
34
- @queryEl = queryEl
35
- @repoFactory = repoFactory || RepositoryFactory.new
36
- @logger = logger || Logger.new(STDOUT)
37
- @tables = {}
38
- @lastRel = nil
39
- @offset = 0
40
- @limit = 0
41
- queryEl.children.each do |el|
42
- @lastRel = parse_el(el, @lastRel)
43
- end
44
- if @limit > 0
45
- @lastRel = @lastRel.limit(@limit, @offset)
46
- end
47
- end
48
-
49
- def each(&block)
50
- # sel_mgr = relation
51
- # unless sel_mgr.kind_of? SelectionManager
52
- # raise "Can only be called on SELECT statement"
53
- # end
54
- # puts sel_mgr.engine
55
- relation.each(&block)
56
- end
57
-
58
- def relation
59
- raise "No query defined, yet" unless @lastRel
60
- @lastRel
61
- end
62
-
63
- # Requested format for result. Default is 'xml'
64
- def rformat
65
- @queryEl.attributes['rformat'] || 'xml'
66
- end
67
-
68
- def parse_el(el, lastRel)
69
- if (el.kind_of? REXML::Text)
70
- # skip
71
- return lastRel
72
- end
73
- args = parse_args(el)
74
- @logger.debug "CHILD #{el.name}"
75
- # keep the last table for this level to be used
76
- # to create proper columns.
77
- # NOTE: This is not fool-proof but we need columns
78
- # to later resolve the column type.
79
- #
80
- name = el.name.downcase
81
- if lastRel.nil?
82
- case name
83
- when /repository/
84
- lastRel = repo = parse_repository(el)
85
- @tables = repo.tables
86
- @logger.debug "Created repository: #{lastRel}"
87
- else
88
- raise "Need to start with 'table' declaration, but does with '#{name}'"
89
- end
90
- elsif name == 'table'
91
- lastRel = parse_table(el)
92
- elsif name == 'project'
93
- # turn all arguments into proper columns
94
- # cols = convert_to_cols(args)
95
- lastRel = lastRel.select(*args)
96
- # elsif lastRel.kind_of?(::Arel::Table) && name == 'as'
97
- # # keep track of all created tables
98
- # lastRel = lastRel.alias(*args)
99
- # @repository.add_table(args[0], lastRel)
100
- elsif name == 'skip'
101
- @offset = args[0].to_i
102
- elsif name == 'take'
103
- @limit = args[0].to_i
104
- else
105
- @logger.debug "Sending '#{name}' to #{lastRel.class}"
106
- lastRel = lastRel.send(name, *args)
107
- end
108
- @logger.debug "lastRel for <#{el}> is #{lastRel.class}"
109
- lastRel
110
- end
111
-
112
- def parse_repository(el)
113
- @repository = @repoFactory.create_from_xml(el, @logger)
114
- end
115
-
116
-
117
- # Return the arguments defined in @parentEl as array
118
- def parse_args(parentEl)
119
- args = []
120
- parentEl.children.each do |el|
121
- next if (el.kind_of? REXML::Text)
122
- unless el.name == 'arg'
123
- raise "Expected argument definition but got element '#{el.name}"
124
- end
125
- args << parse_arg(el)
126
- end
127
- args
128
- end
129
-
130
- # Return the arguments defined in @parentEl as array
131
- def parse_arg(pel)
132
- res = nil
133
- #col = nil
134
- pel.children.each do |el|
135
- if (el.kind_of? REXML::Text)
136
- val = el.value
137
- next if val.strip.empty? # skip text between els
138
- return parse_arg_primitive(pel, val)
139
- else
140
- name = el.name.downcase
141
- case name
142
- when /col/
143
- res = parse_column(el)
144
- when /eq/
145
- if res.nil?
146
- raise "Missing 'col' definiton before 'eq'."
147
- end
148
- p = parse_args(el)
149
- unless p.length == 1
150
- raise "'eq' can only hnadle 1 argument, but is '#{p.inspect}'"
151
- end
152
- res = {res => p[0]}
153
- else
154
- raise "Need to be 'col' declaration, but is '#{name}'"
155
- end
156
- end
157
- end
158
- res
159
- end
160
-
161
- def parse_arg_primitive(pel, value)
162
- type = pel.attributes['type'] || 'string'
163
- case type
164
- when /string/
165
- value
166
- when /boolean/
167
- value.downcase == 'true' || value == '1'
168
- when /decimal/
169
- value.to_i
170
- when /double/
171
- value.to_f
172
- when /dateTime/
173
- Time.xmlschema
174
- else
175
- raise "Unknown arg type '#{type}"
176
- end
177
- end
178
-
179
- def convert_to_cols(args)
180
- args.collect do |arg|
181
- if arg.kind_of? String
182
- table = @repository.get_first_table()
183
- raise "Unknown table for column '#{arg}'" unless table
184
- table[arg]
185
- else
186
- arg
187
- end
188
- end
189
- end
190
-
191
- # <col name='oml_sender_id' table='iperf_TCP_Info'/>
192
- def parse_column(el)
193
- unless colName = el.attributes['name']
194
- raise "Missing 'name' attribute for 'col' element"
195
- end
196
- col = colName
197
- unless tblName = el.attributes['table']
198
- raise "Missing 'table' attribute for col '#{colName}'"
199
- end
200
- unless @tables.member?(tblName.to_sym)
201
- raise "Unknown table name '#{tblName}' (#{el})"
202
- end
203
- col = "#{tblName}__#{colName}"
204
-
205
- if colAlias = el.attributes['alias']
206
- col = "#{col}___#{colAlias}"
207
- end
208
- col.to_sym
209
- end
210
-
211
- def parse_table(el)
212
- unless name = el.attributes['tname']
213
- raise "Missing 'tname' attribute for 'table' element"
214
- end
215
- if talias = el.attributes['talias']
216
- name = "#{name}___#{talias}"
217
- @tables << talias.to_sym
218
- end
219
-
220
- @repository[name.to_sym]
221
- end
222
-
223
- end # Query
224
-
225
- class RepositoryFactory < OMF::Common::LObject
226
-
227
- def initialize(opts = {})
228
- @opts = opts
229
- end
230
-
231
- def create_from_xml(el, logger)
232
- name = el ? el.attributes['name'] : nil
233
- raise "<repository> is missing attribute 'name'" unless name
234
- create(name, logger)
235
- end
236
-
237
- def create(database, logger = Logger.new(STDOUT))
238
- opts = @opts.dup
239
- if pre = opts[:database_prefix]
240
- database = pre + database
241
- opts.delete(:database_prefix)
242
- end
243
- if post = opts[:database_postfix]
244
- database = database + post
245
- opts.delete(:database_postfix)
246
- end
247
- opts[:database] = database
248
- ::Sequel.connect(opts)
249
- end
250
-
251
- end # RepositoryFactory
252
- end # Server
253
- end
254
-
255
- module Sequel
256
- class Dataset
257
- CLASS2TYPE = {
258
- TrueClass => 'boolean',
259
- FalseClass => 'boolean',
260
- String => 'string',
261
- Symbol => 'string',
262
- Fixnum => 'decimal',
263
- Float => 'double',
264
- Time => 'dateTime'
265
- }
266
-
267
- def row_description(row)
268
- n = naked
269
- cols = n.columns
270
- descr = {}
271
- cols.collect do |cn|
272
- cv = row[cn]
273
- descr[cn] = CLASS2TYPE[cv.class]
274
- end
275
- descr
276
- end
277
-
278
- def schema_for_row(row)
279
- n = naked
280
- cols = n.columns
281
- descr = {}
282
- cols.collect do |cn|
283
- cv = row[cn]
284
- {:name => cn, :type => CLASS2TYPE[cv.class]}
285
- end
286
- end
287
- end
288
- end
289
-
290
-
291
-
292
- def test_sequel_server()
293
-
294
- tests = []
295
-
296
- tests << %{
297
- <query>
298
- <repository name='test'/>
299
- <table tname='iperf_TCP_Info'/>
300
- <project>
301
- <arg><col name='Bandwidth_avg' table='iperf_TCP_Info'/></arg>
302
- </project>
303
- </query>
304
- }
305
-
306
- tests << %{
307
- <query>
308
- <repository name='test'/>
309
- <table tname='iperf_TCP_Info' talias='t'/>
310
- <project>
311
- <arg>
312
- <col name='oml_sender_id' alias='foo' table='t'/>
313
- </arg>
314
- <arg>
315
- <col name='oml_ts_server' table='t' alias='goo'/>
316
- </arg>
317
- <arg><col name='Bandwidth_avg' table='t'/></arg>
318
- </project>
319
- <where>
320
- <arg>
321
- <col name='oml_sender_id' table='t'/>
322
- <eq>
323
- <arg type='decimal'> 2</arg>
324
- </eq>
325
- </arg>
326
- </where>
327
- </query>
328
- }
329
-
330
- # mc = repo[:mediacontent]
331
- # mc2 = mc.alias
332
- # accessed = mc2.where(mc2[:status].eq('Accessed')).project(:oml_ts_server, :name)
333
- # q = mc.project(:name).join(accessed).on(mc[:name].eq(mc2[:name]))
334
-
335
- # tests << %{
336
- # <query>
337
- # <repository name='prefetching_4'/>
338
- # <table tname='mediacontent'/>
339
- # <project>
340
- # <arg type='string'>name</arg>
341
- # </project>
342
- # <join>
343
- # <arg>
344
- # <table tname='mediacontent' talias='mediacontent1'/>
345
- # <where>
346
- # <arg>
347
- # <col name='status' table='mediacontent' talias='mediacontent1'/>
348
- # <eq>
349
- # <arg type='string'>Accessed</arg>
350
- # </eq>
351
- # </arg>
352
- # </where>
353
- # <project>
354
- # <arg type='string'>oml_ts_server</arg>
355
- # <arg type='string'>name</arg>
356
- # </project>
357
- # </arg>
358
- # </join>
359
- # <on>
360
- # <arg>
361
- # <col name='name' table='mediacontent'/>
362
- # <eq>
363
- # <arg>
364
- # <col name='name' table='mediacontent' talias='mediacontent1'/>
365
- # </arg>
366
- # </eq>
367
- # </arg>
368
- # </on>
369
- # </query>
370
- # }
371
-
372
- factory = OMF::OML::Sequel::Server::RepositoryFactory.new(
373
- :adapter => 'sqlite',
374
- :database_prefix => '/Users/max/src/omf_mytestbed_net/omf-common/test/',
375
- :database_postfix => '.sq3'
376
- )
377
-
378
- repo = factory.create('test')
379
- puts repo.tables
380
-
381
- tests.each do |t|
382
- ds = OMF::OML::Sequel::Server::Query.parse(t, factory)
383
- puts ds.inspect
384
- puts ds.columns.inspect
385
- puts ds.first.inspect
386
- end
387
-
388
- first = true
389
- types = []
390
- ds = OMF::OML::Sequel::Server::Query.parse(tests[1], factory).limit(10)
391
- ds.each do |r|
392
- if (first)
393
- puts ds.row_description(r).inspect
394
- puts ds.schema_for_row(r).inspect
395
- #puts (ds.schema_for_row(r).methods - Object.new.methods).sort
396
- # cols = ds.columns
397
- # #cols.collect do |c|
398
- # cols.each do |c|
399
- # puts "#{c} : #{OML::Sequel::XML::Server::Query::CLASS2TYPE[r[c].class]}"
400
- # end
401
- first = false
402
- # puts types.inspect
403
- end
404
- puts r.inspect
405
- end
406
- puts "QUERY: done"
407
- end
408
-
409
- if $0 == __FILE__
410
- test_sequel_server
411
- end
412
-