omf_web 0.9.1 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/README.md +8 -2
- data/doc/screenshot.png +0 -0
- data/example/{basic → NOT_WORKING/basic}/hello-world-wired.rb +0 -0
- data/example/{basic → NOT_WORKING/basic}/visualisation.yml +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklynDemo.sq3 +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_gps.dat +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_server.rb +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_wimax.dat +0 -0
- data/example/{brooklyn → NOT_WORKING/brooklyn}/sql_source.rb +0 -0
- data/example/{code → NOT_WORKING/code}/code_server.rb +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/parse_log.rb +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/pxe_slice-2012-06-02t02.25.00-04.00.log +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_chart.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_tab.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/progress_table.yaml +0 -0
- data/example/{frisbee → NOT_WORKING/frisbee}/viz_server.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12-53.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo.sq3 +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo_server.rb +0 -0
- data/example/{gec12 → NOT_WORKING/gec12}/visualization.rb +0 -0
- data/example/{incoming → NOT_WORKING/incoming}/ofpu_barchart_widget.yaml +0 -0
- data/example/{log → NOT_WORKING/log}/log_config.xml +0 -0
- data/example/{log → NOT_WORKING/log}/log_server.rb +0 -0
- data/example/{network → NOT_WORKING/network}/flow_tab.yaml +0 -0
- data/example/{network → NOT_WORKING/network}/network_server.rb +0 -0
- data/example/{text → NOT_WORKING/text}/test.md +0 -0
- data/example/{text → NOT_WORKING/text}/test.rb +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/downlink.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/power.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/snapshot.db +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/snapshot.sql +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/test.rb +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/uplink.yaml +0 -0
- data/example/{wimax → NOT_WORKING/wimax}/viz_server.rb +0 -0
- data/example/demo/data_sources/mobile_network.rb +3 -0
- data/example/demo/data_sources/static_network.rb +54 -0
- data/example/demo/widgets/charts_tab.yaml +21 -16
- data/example/demo/widgets/linked_graphs_tab.yaml +95 -0
- data/example/demo/widgets/mobile_network_widget.yaml +1 -1
- data/example/demo/widgets/pie_chart_widget.yaml +1 -1
- data/lib/omf-web/config.ru +2 -2
- data/lib/omf-web/data_source_proxy.rb +81 -19
- data/lib/omf-web/rack/websocket_handler.rb +77 -23
- data/lib/omf-web/theme/abstract_page.rb +43 -26
- data/lib/omf-web/theme/bright/code_renderer.rb +1 -1
- data/lib/omf-web/theme/bright/page.rb +1 -0
- data/lib/omf-web/theme/bright/tabbed_renderer.rb +7 -0
- data/lib/omf-web/version.rb +7 -0
- data/lib/omf-web/widget/data_widget.rb +38 -46
- data/lib/omf-web/widget/layout/stacked_layout.rb +2 -1
- data/lib/omf-web/widget/layout/tabbed_layout.rb +1 -2
- data/{MARUKU-LICENSE → lib/omf-web/widget/text/maruku/MARUKU-LICENSE} +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/helpers.rb +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/input/parse_block.rb +0 -0
- data/lib/{maruku → omf-web/widget/text/maruku}/output/to_html.rb +26 -21
- data/lib/omf-web/widget/text/maruku.rb +5 -0
- data/omf_web.gemspec +2 -1
- data/share/htdocs/{js → UNUSED}/log/table.js +0 -0
- data/share/htdocs/{css → graph/css}/graph.css +0 -0
- data/share/htdocs/{image/graph → graph/img}/bar_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/donut_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/funnel.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/info.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/line_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/line_chart_fill.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/misc.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/overview.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/pie_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/scatter_plot.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/stacked_bar_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/stacked_line_chart.png +0 -0
- data/share/htdocs/{image/graph → graph/img}/table.png +0 -0
- data/share/htdocs/{js/graph → graph/js}/abstract_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/abstract_nv_chart.js +8 -13
- data/share/htdocs/{js/graph → graph/js}/abstract_widget.js +9 -16
- data/share/htdocs/{js/graph → graph/js}/axis.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/barchart.js +2 -2
- data/share/htdocs/{js/graph → graph/js}/code_mirror.js +1 -5
- data/share/htdocs/{js/graph → graph/js}/discrete_bar_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/histogram2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/holt_winters_chart.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/line_chart3.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/line_chart_with_focus.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/map2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/multi_barchart.js +1 -1
- data/share/htdocs/graph/js/network2.js +412 -0
- data/share/htdocs/{js/graph → graph/js}/pie_chart2.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/scatter_plot.js +1 -1
- data/share/htdocs/{js/graph → graph/js}/table2.js +17 -20
- data/share/htdocs/js/data_source2.js +187 -60
- data/share/htdocs/js/require3.js +38 -57
- data/share/htdocs/theme/bright/css/bright.css +4 -4
- data/share/htdocs/vendor/jquery/jquery.js +9404 -0
- data/share/htdocs/vendor/osa/LICENSE.txt +11 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_green_left.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_yellow_right.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_awareness.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_camera-web.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_cloud.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_contract.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_database.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop_imac.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-music.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-scanner.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb-wifi.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-wireless-router.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_disposal.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-harddisk.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-optical.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_firewall.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_home.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_hub.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_iPhone.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_drive.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_plc.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_thermometer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_id_card.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_image-generic.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_laptop.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lifecycle.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lightning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-flash.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-optical.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-tape.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_mobile_pda.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_padlock.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_printer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_application.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_database.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_directory.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_distribution.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_file.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_gateway.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_identity.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_mail.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_media.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_monitor.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_proxy.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_terminal.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_web.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-branch.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-factory.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-head-office.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-neighbourhood.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_audit.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_black_hat.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_security_specialist.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_sysadmin.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tester.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tie.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_architect.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_business_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_developer.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_operations.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_project_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_service_manager.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_warning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_large_group.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_users_blue_green.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_vpn.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_warning.svg +0 -0
- data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_wireless_network.svg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/.DS_Store +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/add_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/alertbad_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/alertgood_icon.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_disabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/bottom-bg.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.jpg +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/icon-remove.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/indicator.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/laptop.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/logo-bottom.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/nav-tab-arrow.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/norbit_big.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/norbit_clipart.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/progress_bar.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/right-bg.gif +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_asc.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_asc_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_both.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_desc.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/sort_desc_disabled.png +0 -0
- data/share/htdocs/{image → vendor/unknown/image}/spinner.gif +0 -0
- data/share/htdocs/{svg → vendor/unknown/svg}/ap.svg +0 -0
- data/share/htdocs/{svg → vendor/unknown/svg}/router.svg +0 -0
- metadata +198 -216
- data/example/demo/widgets/dashboard_tab.yaml +0 -28
- data/example/demo/widgets/download_tab.yaml +0 -42
- data/example/demo/widgets/edit_tab.yaml +0 -20
- data/example/demo/widgets/generator_tab.yaml +0 -12
- data/lib/omf-oml/endpoint.rb +0 -175
- data/lib/omf-oml/indexed_table.rb +0 -57
- data/lib/omf-oml/network.rb +0 -413
- data/lib/omf-oml/oml_tuple.rb +0 -62
- data/lib/omf-oml/schema.rb +0 -191
- data/lib/omf-oml/sequel/sequel_server.rb +0 -412
- data/lib/omf-oml/sql_row.rb +0 -302
- data/lib/omf-oml/sql_source.rb +0 -131
- data/lib/omf-oml/table.rb +0 -131
- data/lib/omf-oml/tuple.rb +0 -97
- data/lib/omf_oml.rb +0 -4
- data/share/htdocs/css/coderay.css +0 -127
- data/share/htdocs/css/ie.css +0 -40
- data/share/htdocs/css/lightbox.css +0 -62
- data/share/htdocs/css/scaffold.css +0 -74
- data/share/htdocs/css/screen.css +0 -1313
- data/share/htdocs/css/search.css +0 -102
- data/share/htdocs/css/table.css +0 -538
- data/share/htdocs/css/table2.css +0 -191
- data/share/htdocs/css/welcome.css +0 -103
- data/share/htdocs/css/wfob.css +0 -171
- data/share/htdocs/css/wshow.css +0 -69
- data/share/htdocs/gec9_demo.html +0 -39
- data/share/htdocs/images +0 -1
- data/share/htdocs/js/graph/histogram.js +0 -229
- data/share/htdocs/js/graph/line_chart.js +0 -342
- data/share/htdocs/js/graph/line_chart2.js +0 -232
- data/share/htdocs/js/graph/line_chart_fc.js +0 -94
- data/share/htdocs/js/graph/map.js +0 -85
- data/share/htdocs/js/graph/network.js +0 -591
- data/share/htdocs/js/graph/network2.js +0 -318
- data/share/htdocs/js/graph/pie_chart.js +0 -130
- data/share/htdocs/js/graph/table.js +0 -94
- data/share/htdocs/js/require2.js +0 -1998
- data/share/htdocs/js/timelines.js +0 -101
- data/share/htdocs/stylesheet/grid.css +0 -31
data/lib/omf-oml/schema.rb
DELETED
@@ -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
|
-
|