coupler 0.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (258) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +3 -0
  3. data/.rvmrc +1 -0
  4. data/.vimrc +40 -0
  5. data/Gemfile +27 -0
  6. data/Gemfile.lock +71 -0
  7. data/LICENSE +20 -0
  8. data/NOTES +6 -0
  9. data/README.rdoc +18 -0
  10. data/Rakefile +42 -0
  11. data/TODO +11 -0
  12. data/VERSION +1 -0
  13. data/bin/coupler +7 -0
  14. data/db/.gitignore +6 -0
  15. data/db/migrate/001_initial_schema.rb +166 -0
  16. data/db/migrate/002_stub.rb +4 -0
  17. data/db/migrate/003_stub.rb +4 -0
  18. data/db/migrate/004_create_comparisons.rb +28 -0
  19. data/db/migrate/005_move_database_name.rb +19 -0
  20. data/db/migrate/006_upgrade_comparisons.rb +34 -0
  21. data/db/migrate/007_add_which_to_comparisons.rb +23 -0
  22. data/db/migrate/008_add_result_field_to_transformations.rb +33 -0
  23. data/db/migrate/009_add_generated_flag_to_fields.rb +13 -0
  24. data/db/migrate/010_create_imports.rb +24 -0
  25. data/db/migrate/011_add_primary_key_type.rb +13 -0
  26. data/db/migrate/012_add_transformed_with_to_resources.rb +13 -0
  27. data/db/migrate/013_add_run_count_to_scenarios.rb +13 -0
  28. data/db/migrate/014_add_last_accessed_at_to_some_tables.rb +13 -0
  29. data/db/migrate/015_add_run_number_to_results.rb +15 -0
  30. data/db/migrate/016_fix_scenario_run_count.rb +27 -0
  31. data/db/migrate/017_rename_comparison_columns.rb +14 -0
  32. data/db/migrate/018_fix_scenario_linkage_type.rb +8 -0
  33. data/db/migrate/019_add_columns_to_imports.rb +24 -0
  34. data/db/migrate/020_rename_import_columns.rb +12 -0
  35. data/db/migrate/021_add_fields_to_connections.rb +15 -0
  36. data/db/migrate/022_remove_database_name_from_resources.rb +11 -0
  37. data/features/connections.feature +28 -0
  38. data/features/matchers.feature +35 -0
  39. data/features/projects.feature +11 -0
  40. data/features/resources.feature +62 -0
  41. data/features/scenarios.feature +45 -0
  42. data/features/step_definitions/coupler_steps.rb +145 -0
  43. data/features/step_definitions/matchers_steps.rb +26 -0
  44. data/features/step_definitions/resources_steps.rb +12 -0
  45. data/features/step_definitions/scenarios_steps.rb +7 -0
  46. data/features/step_definitions/transformations_steps.rb +3 -0
  47. data/features/support/env.rb +128 -0
  48. data/features/transformations.feature +22 -0
  49. data/features/wizard.feature +10 -0
  50. data/gfx/coupler-header.svg +213 -0
  51. data/gfx/coupler-sidebar.svg +656 -0
  52. data/gfx/coupler.svg +184 -0
  53. data/gfx/icon.svg +75 -0
  54. data/lib/coupler/base.rb +63 -0
  55. data/lib/coupler/config.rb +128 -0
  56. data/lib/coupler/data_uploader.rb +20 -0
  57. data/lib/coupler/database.rb +31 -0
  58. data/lib/coupler/extensions/connections.rb +57 -0
  59. data/lib/coupler/extensions/exceptions.rb +58 -0
  60. data/lib/coupler/extensions/imports.rb +43 -0
  61. data/lib/coupler/extensions/jobs.rb +21 -0
  62. data/lib/coupler/extensions/matchers.rb +64 -0
  63. data/lib/coupler/extensions/projects.rb +62 -0
  64. data/lib/coupler/extensions/resources.rb +89 -0
  65. data/lib/coupler/extensions/results.rb +100 -0
  66. data/lib/coupler/extensions/scenarios.rb +50 -0
  67. data/lib/coupler/extensions/transformations.rb +70 -0
  68. data/lib/coupler/extensions/transformers.rb +58 -0
  69. data/lib/coupler/extensions.rb +16 -0
  70. data/lib/coupler/helpers.rb +121 -0
  71. data/lib/coupler/import_buffer.rb +48 -0
  72. data/lib/coupler/logger.rb +16 -0
  73. data/lib/coupler/models/common_model.rb +104 -0
  74. data/lib/coupler/models/comparison.rb +166 -0
  75. data/lib/coupler/models/connection.rb +59 -0
  76. data/lib/coupler/models/field.rb +55 -0
  77. data/lib/coupler/models/import.rb +238 -0
  78. data/lib/coupler/models/job.rb +42 -0
  79. data/lib/coupler/models/jobify.rb +17 -0
  80. data/lib/coupler/models/matcher.rb +36 -0
  81. data/lib/coupler/models/project.rb +40 -0
  82. data/lib/coupler/models/resource.rb +287 -0
  83. data/lib/coupler/models/result.rb +92 -0
  84. data/lib/coupler/models/scenario/runner.rb +357 -0
  85. data/lib/coupler/models/scenario.rb +115 -0
  86. data/lib/coupler/models/transformation.rb +117 -0
  87. data/lib/coupler/models/transformer/runner.rb +28 -0
  88. data/lib/coupler/models/transformer.rb +110 -0
  89. data/lib/coupler/models.rb +30 -0
  90. data/lib/coupler/runner.rb +76 -0
  91. data/lib/coupler/scheduler.rb +56 -0
  92. data/lib/coupler.rb +34 -0
  93. data/log/.gitignore +1 -0
  94. data/misc/README +5 -0
  95. data/misc/jruby-json.license +57 -0
  96. data/misc/rack-flash.license +22 -0
  97. data/script/dbconsole.rb +5 -0
  98. data/src/edu/vanderbilt/coupler/Main.java +116 -0
  99. data/src/edu/vanderbilt/coupler/jruby.properties +1 -0
  100. data/tasks/annotations.rake +84 -0
  101. data/tasks/db.rake +120 -0
  102. data/tasks/environment.rake +12 -0
  103. data/tasks/jeweler.rake +43 -0
  104. data/tasks/package.rake +58 -0
  105. data/tasks/rdoc.rake +13 -0
  106. data/tasks/test.rake +63 -0
  107. data/tasks/vendor.rake +43 -0
  108. data/test/README.txt +6 -0
  109. data/test/config.yml +9 -0
  110. data/test/coupler/models/test_import.rb +221 -0
  111. data/test/factories.rb +91 -0
  112. data/test/fixtures/duplicate-keys.csv +5 -0
  113. data/test/fixtures/no-headers.csv +50 -0
  114. data/test/fixtures/people.csv +51 -0
  115. data/test/fixtures/varying-row-size.csv +4 -0
  116. data/test/helper.rb +156 -0
  117. data/test/integration/extensions/test_connections.rb +80 -0
  118. data/test/integration/extensions/test_imports.rb +94 -0
  119. data/test/integration/extensions/test_jobs.rb +52 -0
  120. data/test/integration/extensions/test_matchers.rb +134 -0
  121. data/test/integration/extensions/test_projects.rb +82 -0
  122. data/test/integration/extensions/test_resources.rb +150 -0
  123. data/test/integration/extensions/test_results.rb +89 -0
  124. data/test/integration/extensions/test_scenarios.rb +88 -0
  125. data/test/integration/extensions/test_transformations.rb +113 -0
  126. data/test/integration/extensions/test_transformers.rb +80 -0
  127. data/test/integration/test_field.rb +45 -0
  128. data/test/integration/test_import.rb +78 -0
  129. data/test/integration/test_running_scenarios.rb +379 -0
  130. data/test/integration/test_transformation.rb +56 -0
  131. data/test/integration/test_transforming.rb +154 -0
  132. data/test/table_sets.rb +76 -0
  133. data/test/unit/models/test_common_model.rb +130 -0
  134. data/test/unit/models/test_comparison.rb +619 -0
  135. data/test/unit/models/test_connection.rb +115 -0
  136. data/test/unit/models/test_field.rb +99 -0
  137. data/test/unit/models/test_import.rb +130 -0
  138. data/test/unit/models/test_job.rb +115 -0
  139. data/test/unit/models/test_matcher.rb +82 -0
  140. data/test/unit/models/test_project.rb +102 -0
  141. data/test/unit/models/test_resource.rb +564 -0
  142. data/test/unit/models/test_result.rb +90 -0
  143. data/test/unit/models/test_scenario.rb +199 -0
  144. data/test/unit/models/test_transformation.rb +193 -0
  145. data/test/unit/models/test_transformer.rb +188 -0
  146. data/test/unit/test_base.rb +60 -0
  147. data/test/unit/test_data_uploader.rb +27 -0
  148. data/test/unit/test_database.rb +23 -0
  149. data/test/unit/test_helpers.rb +58 -0
  150. data/test/unit/test_logger.rb +10 -0
  151. data/test/unit/test_models.rb +12 -0
  152. data/test/unit/test_runner.rb +76 -0
  153. data/test/unit/test_scheduler.rb +66 -0
  154. data/uploads/.gitignore +2 -0
  155. data/vendor/java/.gitignore +5 -0
  156. data/webroot/public/css/960.css +1 -0
  157. data/webroot/public/css/dataTables.css +1057 -0
  158. data/webroot/public/css/jquery-ui.css +572 -0
  159. data/webroot/public/css/jquery.treeview.css +68 -0
  160. data/webroot/public/css/reset.css +1 -0
  161. data/webroot/public/css/style.css +504 -0
  162. data/webroot/public/css/text.css +1 -0
  163. data/webroot/public/favicon.ico +0 -0
  164. data/webroot/public/images/12_col.gif +0 -0
  165. data/webroot/public/images/16_col.gif +0 -0
  166. data/webroot/public/images/add.png +0 -0
  167. data/webroot/public/images/ajax-loader.gif +0 -0
  168. data/webroot/public/images/cog.png +0 -0
  169. data/webroot/public/images/coupler.png +0 -0
  170. data/webroot/public/images/foo.png +0 -0
  171. data/webroot/public/images/hammer.png +0 -0
  172. data/webroot/public/images/header.png +0 -0
  173. data/webroot/public/images/home.gif +0 -0
  174. data/webroot/public/images/jobs.gif +0 -0
  175. data/webroot/public/images/sidebar-bottom.png +0 -0
  176. data/webroot/public/images/sidebar.png +0 -0
  177. data/webroot/public/images/treeview-default-line.gif +0 -0
  178. data/webroot/public/images/treeview-default.gif +0 -0
  179. data/webroot/public/images/ui-anim_basic_16x16.gif +0 -0
  180. data/webroot/public/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  181. data/webroot/public/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  182. data/webroot/public/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  183. data/webroot/public/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  184. data/webroot/public/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  185. data/webroot/public/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  186. data/webroot/public/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  187. data/webroot/public/images/ui-bg_highlight-hard_30_565356_1x100.png +0 -0
  188. data/webroot/public/images/ui-bg_highlight-hard_75_888588_1x100.png +0 -0
  189. data/webroot/public/images/ui-bg_highlight-soft_30_6e3b3a_1x100.png +0 -0
  190. data/webroot/public/images/ui-bg_highlight-soft_35_8e8b8e_1x100.png +0 -0
  191. data/webroot/public/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  192. data/webroot/public/images/ui-icons_222222_256x240.png +0 -0
  193. data/webroot/public/images/ui-icons_2e83ff_256x240.png +0 -0
  194. data/webroot/public/images/ui-icons_454545_256x240.png +0 -0
  195. data/webroot/public/images/ui-icons_888888_256x240.png +0 -0
  196. data/webroot/public/images/ui-icons_cd0a0a_256x240.png +0 -0
  197. data/webroot/public/images/ui-icons_ffffff_256x240.png +0 -0
  198. data/webroot/public/js/ajaxupload.js +673 -0
  199. data/webroot/public/js/application.js +40 -0
  200. data/webroot/public/js/jquery-ui.combobox.js +98 -0
  201. data/webroot/public/js/jquery-ui.js +9867 -0
  202. data/webroot/public/js/jquery-ui.min.js +559 -0
  203. data/webroot/public/js/jquery.dataTables.min.js +587 -0
  204. data/webroot/public/js/jquery.min.js +154 -0
  205. data/webroot/public/js/jquery.timeago.js +140 -0
  206. data/webroot/public/js/jquery.tooltip.min.js +19 -0
  207. data/webroot/public/js/jquery.treeview.min.js +15 -0
  208. data/webroot/public/js/resource.js +11 -0
  209. data/webroot/public/js/results.js +56 -0
  210. data/webroot/public/js/transformations.js +95 -0
  211. data/webroot/views/connections/index.erb +5 -0
  212. data/webroot/views/connections/list.erb +34 -0
  213. data/webroot/views/connections/new.erb +55 -0
  214. data/webroot/views/connections/show.erb +36 -0
  215. data/webroot/views/imports/edit.erb +60 -0
  216. data/webroot/views/imports/form.erb +81 -0
  217. data/webroot/views/imports/new.erb +89 -0
  218. data/webroot/views/index.erb +12 -0
  219. data/webroot/views/jobs/index.erb +7 -0
  220. data/webroot/views/jobs/list.erb +24 -0
  221. data/webroot/views/layout.erb +38 -0
  222. data/webroot/views/matchers/form.erb +250 -0
  223. data/webroot/views/matchers/list.erb +32 -0
  224. data/webroot/views/projects/form.erb +14 -0
  225. data/webroot/views/projects/index.erb +96 -0
  226. data/webroot/views/projects/show.erb +24 -0
  227. data/webroot/views/resources/edit.erb +88 -0
  228. data/webroot/views/resources/index.erb +5 -0
  229. data/webroot/views/resources/list.erb +27 -0
  230. data/webroot/views/resources/new.erb +121 -0
  231. data/webroot/views/resources/show.erb +86 -0
  232. data/webroot/views/resources/transform.erb +2 -0
  233. data/webroot/views/results/csv.erb +12 -0
  234. data/webroot/views/results/details.erb +15 -0
  235. data/webroot/views/results/index.erb +2 -0
  236. data/webroot/views/results/list.erb +22 -0
  237. data/webroot/views/results/record.erb +24 -0
  238. data/webroot/views/results/show.erb +68 -0
  239. data/webroot/views/scenarios/index.erb +5 -0
  240. data/webroot/views/scenarios/list.erb +20 -0
  241. data/webroot/views/scenarios/new.erb +99 -0
  242. data/webroot/views/scenarios/run.erb +2 -0
  243. data/webroot/views/scenarios/show.erb +50 -0
  244. data/webroot/views/sidebar.erb +106 -0
  245. data/webroot/views/transformations/create.erb +115 -0
  246. data/webroot/views/transformations/for.erb +16 -0
  247. data/webroot/views/transformations/index.erb +2 -0
  248. data/webroot/views/transformations/list.erb +29 -0
  249. data/webroot/views/transformations/new.erb +126 -0
  250. data/webroot/views/transformations/preview.erb +46 -0
  251. data/webroot/views/transformers/edit.erb +6 -0
  252. data/webroot/views/transformers/form.erb +58 -0
  253. data/webroot/views/transformers/index.erb +2 -0
  254. data/webroot/views/transformers/list.erb +25 -0
  255. data/webroot/views/transformers/new.erb +5 -0
  256. data/webroot/views/transformers/preview.erb +23 -0
  257. data/webroot/views/transformers/show.erb +0 -0
  258. metadata +558 -0
@@ -0,0 +1,21 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Jobs
4
+ def self.registered(app)
5
+ app.get "/jobs" do
6
+ @jobs = Models::Job.order("id DESC")
7
+ erb 'jobs/index'.to_sym
8
+ end
9
+
10
+ app.get "/jobs/count" do
11
+ Models::Job.filter(:completed_at => nil).count.to_s
12
+ end
13
+
14
+ app.get "/jobs/:id/progress" do
15
+ @job = Models::Job[:id => params[:id]]
16
+ { :completed => @job.completed, :total => @job.total }.to_json
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Matchers
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/scenarios/:scenario_id/matchers/new" do
6
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
7
+ raise ScenarioNotFound unless @scenario
8
+ @resources = @scenario.resources
9
+ @matcher = Models::Matcher.new
10
+ erb 'matchers/form'.to_sym
11
+ end
12
+
13
+ app.get "/projects/:project_id/scenarios/:scenario_id/matchers/:id/edit" do
14
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
15
+ raise ScenarioNotFound unless @scenario
16
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
17
+ raise MatcherNotFound unless @matcher
18
+ @resources = @scenario.resources
19
+ erb 'matchers/form'.to_sym
20
+ end
21
+
22
+ app.post "/projects/:project_id/scenarios/:scenario_id/matchers" do
23
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
24
+ raise ScenarioNotFound unless @scenario
25
+ @matcher = Models::Matcher.new(params[:matcher])
26
+ @matcher.scenario = @scenario
27
+
28
+ if @matcher.save
29
+ flash[:notice] = "Matcher was successfully created."
30
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
31
+ else
32
+ @resources = @scenario.resources
33
+ erb 'matchers/form'.to_sym
34
+ end
35
+ end
36
+
37
+ app.put "/projects/:project_id/scenarios/:scenario_id/matchers/:id" do
38
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
39
+ raise ScenarioNotFound unless @scenario
40
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
41
+ raise MatcherNotFound unless @matcher
42
+ @matcher.set(params[:matcher])
43
+
44
+ if @matcher.valid?
45
+ @matcher.save
46
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
47
+ else
48
+ @resources = @scenario.resources
49
+ erb 'matchers/form'.to_sym
50
+ end
51
+ end
52
+
53
+ app.delete "/projects/:project_id/scenarios/:scenario_id/matchers/:id" do
54
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
55
+ raise ScenarioNotFound unless @scenario
56
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
57
+ raise MatcherNotFound unless @matcher
58
+ @matcher.destroy
59
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Projects
4
+ def self.registered(app)
5
+ app.before do
6
+ md = request.path_info.match(%r{/projects/(\d+)/?})
7
+ if md
8
+ # NOTE: Using regex matching here sucks, but apparently Sinatra
9
+ # calls before filters before params are parsed.
10
+ @project = Models::Project[:id => md[1]]
11
+ raise ProjectNotFound unless @project
12
+ @project.touch!
13
+ end
14
+ end
15
+
16
+ app.get "/projects" do
17
+ @projects = Models::Project.order(:id)
18
+ @resource_counts = Models::Resource.count_by_project
19
+ @scenario_counts = Models::Scenario.count_by_project
20
+ erb 'projects/index'.to_sym
21
+ end
22
+
23
+ app.get "/projects/new" do
24
+ @project = Models::Project.new
25
+ erb 'projects/form'.to_sym
26
+ end
27
+
28
+ app.post "/projects" do
29
+ @project = Models::Project.create(params['project'])
30
+ flash[:newly_created] = true
31
+ redirect "/projects/#{@project.id}"
32
+ end
33
+
34
+ app.get "/projects/:project_id" do
35
+ @resources = @project.resources
36
+ @scenarios = @project.scenarios
37
+ erb 'projects/show'.to_sym
38
+ end
39
+
40
+ app.get "/projects/:project_id/edit" do
41
+ erb 'projects/form'.to_sym
42
+ end
43
+
44
+ app.put "/projects/:project_id" do
45
+ @project.set(params[:project])
46
+ if @project.valid?
47
+ @project.save
48
+ redirect '/projects'
49
+ else
50
+ erb 'projects/form'.to_sym
51
+ end
52
+ end
53
+
54
+ app.delete "/projects/:project_id" do
55
+ @project.delete_versions_on_destroy = true if params[:nuke] == "true"
56
+ @project.destroy
57
+ redirect '/projects'
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,89 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Resources
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/resources" do
6
+ @resources = @project.resources
7
+ erb 'resources/index'.to_sym
8
+ end
9
+
10
+ app.get "/projects/:project_id/resources/new" do
11
+ @connections = Models::Connection.all
12
+ @resource = Models::Resource.new
13
+ if @connections.empty?
14
+ @resource.connection_attributes = {}
15
+ end
16
+ erb 'resources/new'.to_sym
17
+ end
18
+
19
+ app.post "/projects/:project_id/resources" do
20
+ @resource = Models::Resource.new(params[:resource])
21
+ @resource.project = @project
22
+
23
+ if @resource.save
24
+ flash[:notice] = "Resource was created successfully! Now you can choose which fields you wish to select."
25
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}/edit"
26
+ else
27
+ @connections = Models::Connection.all
28
+ erb 'resources/new'.to_sym
29
+ end
30
+ end
31
+
32
+ app.get "/projects/:project_id/resources/:id" do
33
+ @resource = @project.resources_dataset[:id => params[:id]]
34
+ raise ResourceNotFound unless @resource
35
+ @fields = @resource.fields_dataset.filter(:is_selected => 1).all
36
+ @transformers = Models::Transformer.all
37
+ @transformations = @resource.transformations_dataset.order(:position)
38
+ @scenarios = @resource.scenarios
39
+ @job = @resource.jobs_dataset[:status => %w{running scheduled}]
40
+ erb 'resources/show'.to_sym
41
+ end
42
+
43
+ app.get "/projects/:project_id/resources/:id/transform" do
44
+ @resource = @project.resources_dataset[:id => params[:id]]
45
+ raise ResourceNotFound unless @resource
46
+ Scheduler.instance.schedule_transform_job(@resource)
47
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
48
+ end
49
+
50
+ app.get "/projects/:project_id/resources/:id/edit" do
51
+ @resource = @project.resources_dataset[:id => params[:id]]
52
+ raise ResourceNotFound unless @resource
53
+ @fields = @resource.fields
54
+ @selection_count = @resource.fields_dataset.filter(:is_selected => true).count
55
+ erb 'resources/edit'.to_sym
56
+ end
57
+
58
+ app.put "/projects/:project_id/resources/:id" do
59
+ @resource = @project.resources_dataset[:id => params[:id]]
60
+ raise ResourceNotFound unless @resource
61
+
62
+ @resource.set(params[:resource]) if params[:resource]
63
+ if @resource.valid?
64
+ # FIXME
65
+ #flash[:notice] = "Resource successfully created! Next, if you want to change this resource's fields, you'll need to add transformations."
66
+
67
+ @resource.save
68
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
69
+ else
70
+ @fields = @resource.fields
71
+ @selection_count = @resource.fields_dataset.filter(:is_selected => true).count
72
+ erb 'resources/edit'.to_sym
73
+ end
74
+ end
75
+
76
+ app.get "/projects/:project_id/resources/:id/record/:record_id" do
77
+ @resource = @project.resources_dataset[:id => params[:id]]
78
+ raise ResourceNotFound unless @resource
79
+
80
+ @record = nil
81
+ @resource.final_dataset do |ds|
82
+ @record = ds.filter(@resource.primary_key_sym => params[:record_id]).first
83
+ end
84
+ @record.to_json
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,100 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Results
4
+ module Helpers
5
+ def resource_optgroup_tag(resource_id)
6
+ if resource_id.is_a?(String)
7
+ id, which = resource_id.split(/_/).collect(&:to_i)
8
+ %{<optgroup class="resource-#{id}" label="#{@resources[id].name} [#{which+1}]">}
9
+ else
10
+ %{<optgroup class="resource-#{resource_id}" label="#{@resources[resource_id].name}">}
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.registered(app)
16
+ app.helpers Helpers
17
+
18
+ app.get '/projects/:project_id/scenarios/:scenario_id/results' do
19
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
20
+ raise ScenarioNotFound unless @scenario
21
+ @results = @scenario.results_dataset.order(:id.desc)
22
+ erb 'results/index'.to_sym
23
+ end
24
+
25
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id' do
26
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
27
+ raise ScenarioNotFound unless @scenario
28
+
29
+ id, format = params[:id].split('.')
30
+ @result = @scenario.results_dataset[:id => id]
31
+ raise ResultNotFound unless @result
32
+
33
+ if format == 'csv'
34
+ filename = "#{@scenario.slug}-run-#{@result.created_at.strftime('%Y%m%d-%H%M')}.csv"
35
+ content_type('text/csv')
36
+ attachment(filename)
37
+ @result.to_csv
38
+ else
39
+ html = nil
40
+ @result.groups_dataset do |groups_dataset|
41
+ html = erb(:"results/show", {}, {:groups_dataset => groups_dataset})
42
+ end
43
+ html
44
+ end
45
+ end
46
+
47
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id/details/:group_id' do
48
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
49
+ raise ScenarioNotFound unless @scenario
50
+ @result = @scenario.results_dataset[:id => params[:id]]
51
+
52
+ @scenario.local_database do |scenario_db|
53
+ groups_ds = scenario_db[@result.groups_table_name]
54
+ @group = groups_ds.filter(:id => params[:group_id]).first
55
+ end
56
+ erb(:"results/details", :layout => false)
57
+ end
58
+
59
+ app.post '/projects/:project_id/scenarios/:scenario_id/results/:id/details/:group_id/record' do
60
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
61
+ raise ScenarioNotFound unless @scenario
62
+ @result = @scenario.results_dataset[:id => params[:id]]
63
+ @index = params[:index].to_i
64
+ @which = params[:which] ? params[:which].to_i : nil
65
+
66
+ # FIXME: this could be in a model method or stored in the resources table
67
+ @num_columns = @scenario.resources.collect { |r| r.selected_fields_dataset.count }.max
68
+
69
+ # Get total for group
70
+ # FIXME: Result method instead yo
71
+ @result.groups_dataset do |ds|
72
+ @total = ds.filter(:id => params[:group_id]).get(:"resource_#{@which ? @which + 1 : 1}_count")
73
+ end
74
+
75
+ # FIXME: Result method instead yo
76
+ record_id = nil
77
+ @result.groups_records_dataset do |ds|
78
+ record_id = ds.filter(:group_id => params[:group_id], :which => @which).
79
+ limit(1, @index).first[:record_id]
80
+ end
81
+ resource = @which == 1 ? @scenario.resource_2 : @scenario.resource_1
82
+ resource.final_dataset do |ds|
83
+ @columns = ds.columns
84
+ @record = ds.select(*@columns).filter(resource.primary_key_sym => record_id).first
85
+ end
86
+ erb(:"results/record", :layout => false)
87
+ end
88
+
89
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id.csv' do
90
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
91
+ raise ScenarioNotFound unless @scenario
92
+ @result = @scenario.results_dataset[:id => params[:id]]
93
+ raise ResultNotFound unless @result
94
+
95
+ #erb :'results/show', :layout => false
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,50 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Scenarios
4
+ def self.registered(app)
5
+ app.get '/projects/:project_id/scenarios' do
6
+ @scenarios = @project.scenarios
7
+ erb :'scenarios/index'
8
+ end
9
+
10
+ app.get '/projects/:project_id/scenarios/new' do
11
+ @scenario = Models::Scenario.new
12
+ erb 'scenarios/new'.to_sym
13
+ end
14
+
15
+ app.post "/projects/:project_id/scenarios" do
16
+ @scenario = Models::Scenario.new(params[:scenario])
17
+ @scenario.project = @project
18
+
19
+ if @scenario.save
20
+ flash[:newly_created] = true
21
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
22
+ else
23
+ erb 'scenarios/new'.to_sym
24
+ end
25
+ end
26
+
27
+ app.get '/projects/:project_id/scenarios/:id' do
28
+ @scenario = @project.scenarios_dataset[:id => params[:id]]
29
+ @resources = @scenario.resources
30
+ @matcher = @scenario.matcher
31
+ @results = @scenario.results
32
+ @running_jobs = @scenario.running_jobs
33
+ @scheduled_jobs = @scenario.scheduled_jobs
34
+ erb 'scenarios/show'.to_sym
35
+ end
36
+
37
+ app.get "/projects/:project_id/scenarios/:id/run" do
38
+ @scenario = @project.scenarios_dataset[:id => params[:id]]
39
+ Scheduler.instance.schedule_run_scenario_job(@scenario)
40
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
41
+ end
42
+
43
+ #app.get "/projects/:project_id/scenarios/:id/progress" do
44
+ #scenario = Models::Scenario[:id => params[:id], :project_id => params[:project_id]]
45
+ #(scenario[:completed] * 100 / scenario[:total]).to_s
46
+ #end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Transformations
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/resources/:resource_id/transformations" do
6
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
7
+ raise ResourceNotFound unless @resource
8
+ @transformations = @resource.transformations
9
+ erb('transformations/index'.to_sym)
10
+ end
11
+
12
+ app.get "/projects/:project_id/resources/:resource_id/transformations/new" do
13
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
14
+ raise ResourceNotFound unless @resource
15
+ @fields = @resource.selected_fields_dataset.order(:id).all
16
+ @transformers = Models::Transformer.all
17
+ @transformation = Models::Transformation.new()
18
+ erb 'transformations/new'.to_sym
19
+ end
20
+
21
+ app.post "/projects/:project_id/resources/:resource_id/transformations" do
22
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
23
+ raise ResourceNotFound unless @resource
24
+ @fields = @resource.selected_fields_dataset.order(:id).all
25
+ @transformation = Models::Transformation.new(params[:transformation])
26
+ @transformation.resource = @resource
27
+
28
+ if @transformation.save
29
+ flash[:notice] = "Transformation was successfully created."
30
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
31
+ else
32
+ @transformers = Models::Transformer.all
33
+ @preview = @resource.preview_transformation(@transformation)
34
+ erb :'transformations/create'
35
+ end
36
+ end
37
+
38
+ app.delete "/projects/:project_id/resources/:resource_id/transformations/:id" do
39
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
40
+ raise ResourceNotFound unless @resource
41
+ @transformation = @resource.transformations_dataset[:id => params[:id]]
42
+ raise TransformationNotFound unless @transformation
43
+ @transformation.destroy
44
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
45
+ end
46
+
47
+ app.get "/projects/:project_id/resources/:resource_id/transformations/for/:field_name" do
48
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
49
+ raise ResourceNotFound unless @resource
50
+ @field = @resource.fields_dataset[:name => params[:field_name]]
51
+ if @field
52
+ @transformations = @field.transformations
53
+ erb('transformations/for'.to_sym, :layout => false)
54
+ else
55
+ ''
56
+ end
57
+ end
58
+
59
+ app.post "/projects/:project_id/resources/:resource_id/transformations/preview" do
60
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
61
+ raise ResourceNotFound unless @resource
62
+
63
+ @transformation = Models::Transformation.new(params[:transformation])
64
+ @preview = @resource.preview_transformation(@transformation)
65
+ erb(:"transformations/preview", :layout => false)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,58 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Transformers
4
+ def self.registered(app)
5
+ app.get "/transformers" do
6
+ @transformers = Models::Transformer.all
7
+ erb :'transformers/index'
8
+ end
9
+
10
+ app.post "/transformers/preview" do
11
+ @transformer = Models::Transformer.new(params[:transformer])
12
+ erb(:'transformers/preview', :layout => false)
13
+ end
14
+
15
+ app.get "/transformers/new" do
16
+ @transformer = Models::Transformer.new
17
+ erb :'transformers/new'
18
+ end
19
+
20
+ app.get '/transformers/:id' do
21
+ @transformer = Models::Transformer[:id => params[:id]]
22
+ erb :'transformers/show'
23
+ end
24
+
25
+ app.get "/transformers/:id/edit" do
26
+ @transformer = Models::Transformer[:id => params[:id]]
27
+ erb :'transformers/edit'
28
+ end
29
+
30
+ app.post "/transformers" do
31
+ @transformer = Models::Transformer.new(params[:transformer])
32
+ if @transformer.save
33
+ redirect "/transformers"
34
+ else
35
+ erb :'transformers/new'
36
+ end
37
+ end
38
+
39
+ app.put '/transformers/:id' do
40
+ @transformer = Models::Transformer[:id => params[:id]]
41
+ @transformer.set(params[:transformer])
42
+ if @transformer.valid?
43
+ @transformer.save
44
+ redirect '/transformers'
45
+ else
46
+ erb :'transformers/edit'
47
+ end
48
+ end
49
+
50
+ app.delete '/transformers/:id' do
51
+ @transformer = Models::Transformer[:id => params[:id]]
52
+ @transformer.destroy
53
+ redirect '/transformers'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ module Coupler
2
+ module Extensions
3
+ end
4
+ end
5
+
6
+ require File.dirname(__FILE__) + "/extensions/connections"
7
+ require File.dirname(__FILE__) + "/extensions/projects"
8
+ require File.dirname(__FILE__) + "/extensions/resources"
9
+ require File.dirname(__FILE__) + "/extensions/transformations"
10
+ require File.dirname(__FILE__) + "/extensions/scenarios"
11
+ require File.dirname(__FILE__) + "/extensions/matchers"
12
+ require File.dirname(__FILE__) + "/extensions/results"
13
+ require File.dirname(__FILE__) + "/extensions/jobs"
14
+ require File.dirname(__FILE__) + "/extensions/transformers"
15
+ require File.dirname(__FILE__) + "/extensions/imports"
16
+ require File.dirname(__FILE__) + "/extensions/exceptions"
@@ -0,0 +1,121 @@
1
+ module Coupler
2
+ module Helpers
3
+ def error_messages_for(object)
4
+ return "" if object.errors.empty?
5
+
6
+ retval = "<div class='errors'><h3>Errors detected:</h3><ul>"
7
+ object.errors.each do |(attr, messages)|
8
+ messages.each do |message|
9
+ retval += "<li>"
10
+ retval += attr.to_s.tr("_", " ").capitalize + " " if attr != :base
11
+ retval += "#{message}</li>"
12
+ end
13
+ end
14
+ retval += "</ul></div><div class='clear'></div>"
15
+
16
+ retval
17
+ end
18
+
19
+ def javascripts
20
+ @javascripts ||= %w{jquery.min.js jquery.timeago.js jquery-ui.min.js application.js}
21
+ end
22
+
23
+ def javascript_includes
24
+ javascripts.collect do |name|
25
+ %{<script type="text/javascript" src="/js/#{name}"></script>}
26
+ end.join("\n ")
27
+ end
28
+
29
+ def add_javascript(*names)
30
+ javascripts.push(*names)
31
+ end
32
+
33
+ def stylesheets
34
+ @stylesheets ||= %w{reset.css text.css 960.css jquery-ui.css jquery.treeview.css style.css}
35
+ end
36
+
37
+ def stylesheet_links
38
+ stylesheets.collect do |name|
39
+ %{<link rel="stylesheet" type="text/css" media="all" href="/css/#{name}" />}
40
+ end.join("\n ")
41
+ end
42
+
43
+ def add_stylesheet(*names)
44
+ stylesheets.push(*names)
45
+ end
46
+
47
+ def delete_link(text, url)
48
+ %^<a href="#{url}" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m); f.submit(); }; return false;">#{text}</a>^
49
+ end
50
+
51
+ def breadcrumbs
52
+ # This method is fun but silly.
53
+ if @breadcrumbs
54
+ url = ""
55
+ %{<div id="breadcrumbs">} +
56
+ @breadcrumbs.inject([]) do |arr, obj|
57
+ strings =
58
+ case obj
59
+ when String
60
+ [obj]
61
+ when nil
62
+ []
63
+ else
64
+ class_name = obj.class.to_s.split("::")[-1]
65
+ if obj.new?
66
+ ["New #{class_name}"]
67
+ elsif
68
+ url += "/#{class_name.downcase}s/#{obj.id}"
69
+ if obj.respond_to?(:name)
70
+ ["#{class_name}s", %{<a href="#{url}">#{obj.name}</a>}]
71
+ else
72
+ [%{<a href="#{url}">#{class_name} ##{obj.id}</a>}]
73
+ end
74
+ end
75
+ end
76
+ arr.push(*strings.collect { |x| %{<div class="crumb">#{x}</div>} })
77
+ end.join(%{<div class="crumb">/</div>}) +
78
+ %{</div><div class="clear"></div>}
79
+ end
80
+ end
81
+
82
+ def humanize(string)
83
+ string.to_s.gsub(/_+/, " ").capitalize
84
+ end
85
+
86
+ def timeago(time, klass = nil, tag = "div")
87
+ if time.nil?
88
+ "Never"
89
+ else
90
+ dt = time.send(:to_datetime)
91
+ klass = "timeago" + (klass.nil? ? "" : " #{klass}")
92
+ %{<#{tag} class="#{klass}" title="#{dt.to_s}">#{time.to_s}</#{tag}>}
93
+ end
94
+ end
95
+
96
+ def form_tag_for(obj, options)
97
+ base_url = options[:base_url]
98
+ action, method = if obj.new?
99
+ [base_url, ""]
100
+ else
101
+ ["#{base_url}/#{obj.id}", %{<div style="display: none;"><input type="hidden" name="_method" value="put" /></div>}]
102
+ end
103
+ %{<form action="#{action}" method="post">#{method}}
104
+ end
105
+
106
+ def local_ip
107
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
108
+
109
+ UDPSocket.open do |s|
110
+ s.connect '64.233.187.99', 1
111
+ s.addr.last
112
+ end
113
+ ensure
114
+ Socket.do_not_reverse_lookup = orig
115
+ end
116
+
117
+ def cycle(even, odd)
118
+ (@_cycle = !@_cycle) ? even : odd
119
+ end
120
+ end
121
+ end