gooddata-edge 0.6.27.edge

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 (364) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +36 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +89 -0
  6. data/.yardopts +22 -0
  7. data/CHANGELOG.md +196 -0
  8. data/CLI.md +439 -0
  9. data/DEPENDENCIES.md +817 -0
  10. data/Gemfile +4 -0
  11. data/Guardfile +5 -0
  12. data/LICENSE +22 -0
  13. data/LICENSE.rb +5 -0
  14. data/README.md +75 -0
  15. data/Rakefile +179 -0
  16. data/TODO.md +32 -0
  17. data/authors.sh +4 -0
  18. data/bin/gooddata +7 -0
  19. data/dependency_decisions.yml +104 -0
  20. data/gooddata +9 -0
  21. data/gooddata.gemspec +63 -0
  22. data/lib/gooddata.rb +31 -0
  23. data/lib/gooddata/app/app.rb +16 -0
  24. data/lib/gooddata/bricks/base_downloader.rb +86 -0
  25. data/lib/gooddata/bricks/brick.rb +38 -0
  26. data/lib/gooddata/bricks/bricks.rb +15 -0
  27. data/lib/gooddata/bricks/middleware/aws_middleware.rb +29 -0
  28. data/lib/gooddata/bricks/middleware/base_middleware.rb +56 -0
  29. data/lib/gooddata/bricks/middleware/bench_middleware.rb +24 -0
  30. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +37 -0
  31. data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +20 -0
  32. data/lib/gooddata/bricks/middleware/fs_download_middleware.rb +48 -0
  33. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +36 -0
  34. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +39 -0
  35. data/lib/gooddata/bricks/middleware/logger_middleware.rb +29 -0
  36. data/lib/gooddata/bricks/middleware/middleware.rb +12 -0
  37. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +61 -0
  38. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +23 -0
  39. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +29 -0
  40. data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +37 -0
  41. data/lib/gooddata/bricks/pipeline.rb +32 -0
  42. data/lib/gooddata/bricks/utils.rb +18 -0
  43. data/lib/gooddata/cli/cli.rb +27 -0
  44. data/lib/gooddata/cli/commands/auth_cmd.rb +29 -0
  45. data/lib/gooddata/cli/commands/domain_cmd.rb +28 -0
  46. data/lib/gooddata/cli/commands/project_cmd.rb +45 -0
  47. data/lib/gooddata/cli/hooks.rb +57 -0
  48. data/lib/gooddata/cli/shared.rb +61 -0
  49. data/lib/gooddata/cli/terminal.rb +20 -0
  50. data/lib/gooddata/client.rb +67 -0
  51. data/lib/gooddata/commands/api.rb +64 -0
  52. data/lib/gooddata/commands/auth.rb +107 -0
  53. data/lib/gooddata/commands/base.rb +12 -0
  54. data/lib/gooddata/commands/commands.rb +12 -0
  55. data/lib/gooddata/commands/datasets.rb +148 -0
  56. data/lib/gooddata/commands/datawarehouse.rb +20 -0
  57. data/lib/gooddata/commands/domain.rb +40 -0
  58. data/lib/gooddata/commands/process.rb +67 -0
  59. data/lib/gooddata/commands/project.rb +175 -0
  60. data/lib/gooddata/commands/projects.rb +20 -0
  61. data/lib/gooddata/commands/role.rb +36 -0
  62. data/lib/gooddata/commands/runners.rb +47 -0
  63. data/lib/gooddata/commands/scaffold.rb +69 -0
  64. data/lib/gooddata/commands/user.rb +39 -0
  65. data/lib/gooddata/connection.rb +127 -0
  66. data/lib/gooddata/core/core.rb +12 -0
  67. data/lib/gooddata/core/logging.rb +105 -0
  68. data/lib/gooddata/core/nil_logger.rb +23 -0
  69. data/lib/gooddata/core/project.rb +74 -0
  70. data/lib/gooddata/core/rest.rb +149 -0
  71. data/lib/gooddata/core/user.rb +20 -0
  72. data/lib/gooddata/data/data.rb +12 -0
  73. data/lib/gooddata/data/guesser.rb +122 -0
  74. data/lib/gooddata/exceptions/attr_element_not_found.rb +16 -0
  75. data/lib/gooddata/exceptions/command_failed.rb +11 -0
  76. data/lib/gooddata/exceptions/exceptions.rb +12 -0
  77. data/lib/gooddata/exceptions/execution_limit_exceeded.rb +13 -0
  78. data/lib/gooddata/exceptions/filter_maqlization.rb +16 -0
  79. data/lib/gooddata/exceptions/malformed_user.rb +15 -0
  80. data/lib/gooddata/exceptions/no_project_error.rb +15 -0
  81. data/lib/gooddata/exceptions/object_migration.rb +32 -0
  82. data/lib/gooddata/exceptions/project_not_found.rb +13 -0
  83. data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
  84. data/lib/gooddata/exceptions/uncomputable_report.rb +13 -0
  85. data/lib/gooddata/exceptions/user_in_different_domain.rb +15 -0
  86. data/lib/gooddata/exceptions/validation_error.rb +16 -0
  87. data/lib/gooddata/extensions/big_decimal.rb +17 -0
  88. data/lib/gooddata/extensions/enumerable.rb +39 -0
  89. data/lib/gooddata/extensions/extensions.rb +10 -0
  90. data/lib/gooddata/extensions/false.rb +15 -0
  91. data/lib/gooddata/extensions/hash.rb +38 -0
  92. data/lib/gooddata/extensions/nil.rb +15 -0
  93. data/lib/gooddata/extensions/numeric.rb +15 -0
  94. data/lib/gooddata/extensions/object.rb +27 -0
  95. data/lib/gooddata/extensions/symbol.rb +15 -0
  96. data/lib/gooddata/extensions/true.rb +15 -0
  97. data/lib/gooddata/extract.rb +21 -0
  98. data/lib/gooddata/goodzilla/goodzilla.rb +159 -0
  99. data/lib/gooddata/helpers/auth_helpers.rb +75 -0
  100. data/lib/gooddata/helpers/csv_helper.rb +61 -0
  101. data/lib/gooddata/helpers/data_helper.rb +116 -0
  102. data/lib/gooddata/helpers/global_helpers.rb +331 -0
  103. data/lib/gooddata/helpers/global_helpers_params.rb +172 -0
  104. data/lib/gooddata/helpers/helpers.rb +10 -0
  105. data/lib/gooddata/mixins/author.rb +26 -0
  106. data/lib/gooddata/mixins/content_getter.rb +15 -0
  107. data/lib/gooddata/mixins/content_property_reader.rb +17 -0
  108. data/lib/gooddata/mixins/content_property_writer.rb +17 -0
  109. data/lib/gooddata/mixins/contributor.rb +20 -0
  110. data/lib/gooddata/mixins/data_getter.rb +15 -0
  111. data/lib/gooddata/mixins/data_property_reader.rb +19 -0
  112. data/lib/gooddata/mixins/data_property_writer.rb +19 -0
  113. data/lib/gooddata/mixins/inspector.rb +53 -0
  114. data/lib/gooddata/mixins/is_attribute.rb +17 -0
  115. data/lib/gooddata/mixins/is_dimension.rb +17 -0
  116. data/lib/gooddata/mixins/is_fact.rb +17 -0
  117. data/lib/gooddata/mixins/is_label.rb +19 -0
  118. data/lib/gooddata/mixins/links.rb +15 -0
  119. data/lib/gooddata/mixins/md_finders.rb +77 -0
  120. data/lib/gooddata/mixins/md_grantees.rb +42 -0
  121. data/lib/gooddata/mixins/md_id_to_uri.rb +34 -0
  122. data/lib/gooddata/mixins/md_json.rb +15 -0
  123. data/lib/gooddata/mixins/md_lock.rb +87 -0
  124. data/lib/gooddata/mixins/md_object_id.rb +15 -0
  125. data/lib/gooddata/mixins/md_object_indexer.rb +64 -0
  126. data/lib/gooddata/mixins/md_object_query.rb +128 -0
  127. data/lib/gooddata/mixins/md_relations.rb +43 -0
  128. data/lib/gooddata/mixins/meta_getter.rb +17 -0
  129. data/lib/gooddata/mixins/meta_property_reader.rb +19 -0
  130. data/lib/gooddata/mixins/meta_property_writer.rb +19 -0
  131. data/lib/gooddata/mixins/mixins.rb +19 -0
  132. data/lib/gooddata/mixins/not_attribute.rb +17 -0
  133. data/lib/gooddata/mixins/not_exportable.rb +15 -0
  134. data/lib/gooddata/mixins/not_fact.rb +17 -0
  135. data/lib/gooddata/mixins/not_group.rb +17 -0
  136. data/lib/gooddata/mixins/not_label.rb +19 -0
  137. data/lib/gooddata/mixins/not_metric.rb +19 -0
  138. data/lib/gooddata/mixins/obj_id.rb +15 -0
  139. data/lib/gooddata/mixins/rest_getters.rb +17 -0
  140. data/lib/gooddata/mixins/rest_resource.rb +47 -0
  141. data/lib/gooddata/mixins/root_key_getter.rb +15 -0
  142. data/lib/gooddata/mixins/root_key_setter.rb +15 -0
  143. data/lib/gooddata/mixins/timestamps.rb +19 -0
  144. data/lib/gooddata/mixins/to_json.rb +11 -0
  145. data/lib/gooddata/mixins/uri_getter.rb +9 -0
  146. data/lib/gooddata/models/blueprint/anchor_field.rb +64 -0
  147. data/lib/gooddata/models/blueprint/attribute_field.rb +29 -0
  148. data/lib/gooddata/models/blueprint/blueprint.rb +11 -0
  149. data/lib/gooddata/models/blueprint/blueprint_field.rb +70 -0
  150. data/lib/gooddata/models/blueprint/dashboard_builder.rb +30 -0
  151. data/lib/gooddata/models/blueprint/dataset_blueprint.rb +449 -0
  152. data/lib/gooddata/models/blueprint/date_dimension.rb +14 -0
  153. data/lib/gooddata/models/blueprint/fact_field.rb +20 -0
  154. data/lib/gooddata/models/blueprint/label_field.rb +43 -0
  155. data/lib/gooddata/models/blueprint/project_blueprint.rb +746 -0
  156. data/lib/gooddata/models/blueprint/project_builder.rb +83 -0
  157. data/lib/gooddata/models/blueprint/reference_field.rb +43 -0
  158. data/lib/gooddata/models/blueprint/schema_blueprint.rb +160 -0
  159. data/lib/gooddata/models/blueprint/schema_builder.rb +89 -0
  160. data/lib/gooddata/models/blueprint/to_manifest.rb +181 -0
  161. data/lib/gooddata/models/blueprint/to_wire.rb +154 -0
  162. data/lib/gooddata/models/client.rb +182 -0
  163. data/lib/gooddata/models/client_synchronization_result.rb +31 -0
  164. data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
  165. data/lib/gooddata/models/datawarehouse.rb +92 -0
  166. data/lib/gooddata/models/domain.rb +479 -0
  167. data/lib/gooddata/models/execution.rb +115 -0
  168. data/lib/gooddata/models/execution_detail.rb +81 -0
  169. data/lib/gooddata/models/from_wire.rb +160 -0
  170. data/lib/gooddata/models/invitation.rb +75 -0
  171. data/lib/gooddata/models/links.rb +50 -0
  172. data/lib/gooddata/models/membership.rb +441 -0
  173. data/lib/gooddata/models/metadata.rb +272 -0
  174. data/lib/gooddata/models/metadata/attribute.rb +134 -0
  175. data/lib/gooddata/models/metadata/dashboard.rb +108 -0
  176. data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +76 -0
  177. data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
  178. data/lib/gooddata/models/metadata/dashboard/filter_item.rb +64 -0
  179. data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
  180. data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
  181. data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
  182. data/lib/gooddata/models/metadata/dashboard/report_item.rb +92 -0
  183. data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
  184. data/lib/gooddata/models/metadata/dashboard_tab.rb +141 -0
  185. data/lib/gooddata/models/metadata/dataset.rb +64 -0
  186. data/lib/gooddata/models/metadata/dimension.rb +54 -0
  187. data/lib/gooddata/models/metadata/fact.rb +44 -0
  188. data/lib/gooddata/models/metadata/label.rb +128 -0
  189. data/lib/gooddata/models/metadata/metadata.rb +12 -0
  190. data/lib/gooddata/models/metadata/metric.rb +198 -0
  191. data/lib/gooddata/models/metadata/report.rb +247 -0
  192. data/lib/gooddata/models/metadata/report_definition.rb +264 -0
  193. data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
  194. data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
  195. data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
  196. data/lib/gooddata/models/metadata/variable.rb +91 -0
  197. data/lib/gooddata/models/model.rb +282 -0
  198. data/lib/gooddata/models/models.rb +12 -0
  199. data/lib/gooddata/models/module_constants.rb +31 -0
  200. data/lib/gooddata/models/process.rb +316 -0
  201. data/lib/gooddata/models/profile.rb +426 -0
  202. data/lib/gooddata/models/project.rb +1514 -0
  203. data/lib/gooddata/models/project_creator.rb +126 -0
  204. data/lib/gooddata/models/project_metadata.rb +67 -0
  205. data/lib/gooddata/models/project_role.rb +79 -0
  206. data/lib/gooddata/models/report_data_result.rb +266 -0
  207. data/lib/gooddata/models/schedule.rb +518 -0
  208. data/lib/gooddata/models/segment.rb +201 -0
  209. data/lib/gooddata/models/tab_builder.rb +27 -0
  210. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +76 -0
  211. data/lib/gooddata/models/user_filters/user_filter.rb +100 -0
  212. data/lib/gooddata/models/user_filters/user_filter_builder.rb +512 -0
  213. data/lib/gooddata/models/user_filters/user_filters.rb +13 -0
  214. data/lib/gooddata/models/user_filters/variable_user_filter.rb +31 -0
  215. data/lib/gooddata/models/user_group.rb +241 -0
  216. data/lib/gooddata/rest/README.md +37 -0
  217. data/lib/gooddata/rest/client.rb +389 -0
  218. data/lib/gooddata/rest/connection.rb +765 -0
  219. data/lib/gooddata/rest/object.rb +69 -0
  220. data/lib/gooddata/rest/object_factory.rb +76 -0
  221. data/lib/gooddata/rest/resource.rb +27 -0
  222. data/lib/gooddata/rest/rest.rb +24 -0
  223. data/lib/gooddata/version.rb +23 -0
  224. data/lib/templates/bricks/brick.rb.erb +7 -0
  225. data/lib/templates/bricks/main.rb.erb +5 -0
  226. data/lib/templates/project/Goodfile.erb +4 -0
  227. data/lib/templates/project/data/commits.csv +4 -0
  228. data/lib/templates/project/data/devs.csv +4 -0
  229. data/lib/templates/project/data/repos.csv +3 -0
  230. data/lib/templates/project/model/model.rb.erb +20 -0
  231. data/spec/bricks/bricks_spec.rb +112 -0
  232. data/spec/bricks/default-config.json +8 -0
  233. data/spec/data/.gooddata +4 -0
  234. data/spec/data/blueprints/additional_dataset_module.json +32 -0
  235. data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
  236. data/spec/data/blueprints/invalid_blueprint.json +103 -0
  237. data/spec/data/blueprints/m_n_model.json +104 -0
  238. data/spec/data/blueprints/model_module.json +25 -0
  239. data/spec/data/blueprints/test_blueprint.json +38 -0
  240. data/spec/data/blueprints/test_project_model_spec.json +106 -0
  241. data/spec/data/cc/data/source/commits.csv +4 -0
  242. data/spec/data/cc/data/source/devs.csv +4 -0
  243. data/spec/data/cc/data/source/repos.csv +3 -0
  244. data/spec/data/cc/devel.prm +0 -0
  245. data/spec/data/cc/graph/graph.grf +11 -0
  246. data/spec/data/cc/workspace.prm +19 -0
  247. data/spec/data/column_based_permissions.csv +7 -0
  248. data/spec/data/column_based_permissions2.csv +6 -0
  249. data/spec/data/gd_gse_data_blueprint.json +1371 -0
  250. data/spec/data/gd_gse_data_manifest.json +1424 -0
  251. data/spec/data/gd_gse_data_model.json +1772 -0
  252. data/spec/data/gooddata_version_process/gooddata_version.rb +9 -0
  253. data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
  254. data/spec/data/hello_world_process/hello_world.rb +9 -0
  255. data/spec/data/hello_world_process/hello_world.zip +0 -0
  256. data/spec/data/line_based_permissions.csv +3 -0
  257. data/spec/data/manifests/test_blueprint.json +32 -0
  258. data/spec/data/manifests/test_project.json +107 -0
  259. data/spec/data/reports/left_attr_report.json +108 -0
  260. data/spec/data/reports/metric_only_one_line.json +83 -0
  261. data/spec/data/reports/report_1.json +197 -0
  262. data/spec/data/reports/top_attr_report.json +108 -0
  263. data/spec/data/ruby_params_process/ruby_params.rb +9 -0
  264. data/spec/data/ruby_process/deep_files/deep_stuff.txt +1 -0
  265. data/spec/data/ruby_process/process.rb +8 -0
  266. data/spec/data/ruby_process/stuff.txt +1 -0
  267. data/spec/data/superfluous_titles_view.json +81 -0
  268. data/spec/data/test-ci-data.csv +2 -0
  269. data/spec/data/users.csv +12 -0
  270. data/spec/data/wire_models/model_view.json +1775 -0
  271. data/spec/data/wire_models/nu_model.json +3046 -0
  272. data/spec/data/wire_models/test_blueprint.json +63 -0
  273. data/spec/data/wire_test_project.json +150 -0
  274. data/spec/environment/default.rb +41 -0
  275. data/spec/environment/develop.rb +31 -0
  276. data/spec/environment/environment.rb +18 -0
  277. data/spec/environment/hotfix.rb +21 -0
  278. data/spec/environment/production.rb +35 -0
  279. data/spec/environment/release.rb +21 -0
  280. data/spec/environment/staging.rb +30 -0
  281. data/spec/environment/staging_3.rb +36 -0
  282. data/spec/helpers/blueprint_helper.rb +26 -0
  283. data/spec/helpers/cli_helper.rb +36 -0
  284. data/spec/helpers/connection_helper.rb +41 -0
  285. data/spec/helpers/crypto_helper.rb +17 -0
  286. data/spec/helpers/csv_helper.rb +18 -0
  287. data/spec/helpers/process_helper.rb +33 -0
  288. data/spec/helpers/project_helper.rb +59 -0
  289. data/spec/helpers/schedule_helper.rb +31 -0
  290. data/spec/helpers/spec_helper.rb +15 -0
  291. data/spec/integration/blueprint_updates_spec.rb +101 -0
  292. data/spec/integration/blueprint_with_grain_spec.rb +72 -0
  293. data/spec/integration/clients_spec.rb +134 -0
  294. data/spec/integration/command_datawarehouse_spec.rb +39 -0
  295. data/spec/integration/command_projects_spec.rb +32 -0
  296. data/spec/integration/create_from_template_spec.rb +22 -0
  297. data/spec/integration/create_project_spec.rb +24 -0
  298. data/spec/integration/date_dim_switch_spec.rb +142 -0
  299. data/spec/integration/deprecated_load_spec.rb +58 -0
  300. data/spec/integration/full_process_schedule_spec.rb +298 -0
  301. data/spec/integration/full_project_spec.rb +569 -0
  302. data/spec/integration/over_to_user_filters_spec.rb +94 -0
  303. data/spec/integration/partial_md_export_import_spec.rb +42 -0
  304. data/spec/integration/project_spec.rb +264 -0
  305. data/spec/integration/rest_spec.rb +213 -0
  306. data/spec/integration/schedule_spec.rb +626 -0
  307. data/spec/integration/segments_spec.rb +141 -0
  308. data/spec/integration/user_filters_spec.rb +290 -0
  309. data/spec/integration/user_group_spec.rb +127 -0
  310. data/spec/integration/variables_spec.rb +188 -0
  311. data/spec/logging_in_logging_out_spec.rb +93 -0
  312. data/spec/spec_helper.rb +95 -0
  313. data/spec/unit/bricks/bricks_spec.rb +35 -0
  314. data/spec/unit/bricks/middleware/aws_middelware_spec.rb +51 -0
  315. data/spec/unit/bricks/middleware/bench_middleware_spec.rb +15 -0
  316. data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +15 -0
  317. data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +15 -0
  318. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +15 -0
  319. data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +15 -0
  320. data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +15 -0
  321. data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +15 -0
  322. data/spec/unit/cli/cli_spec.rb +17 -0
  323. data/spec/unit/cli/commands/cmd_auth_spec.rb +17 -0
  324. data/spec/unit/commands/command_projects_spec.rb +22 -0
  325. data/spec/unit/core/connection_spec.rb +57 -0
  326. data/spec/unit/core/logging_spec.rb +133 -0
  327. data/spec/unit/core/nil_logger_spec.rb +13 -0
  328. data/spec/unit/core/project_spec.rb +54 -0
  329. data/spec/unit/extensions/hash_spec.rb +23 -0
  330. data/spec/unit/godzilla/goodzilla_spec.rb +78 -0
  331. data/spec/unit/helpers/csv_helper_spec.rb +22 -0
  332. data/spec/unit/helpers/data_helper_spec.rb +61 -0
  333. data/spec/unit/helpers/global_helpers_spec.rb +111 -0
  334. data/spec/unit/helpers_spec.rb +86 -0
  335. data/spec/unit/models/blueprint/attributes_spec.rb +29 -0
  336. data/spec/unit/models/blueprint/dataset_spec.rb +121 -0
  337. data/spec/unit/models/blueprint/labels_spec.rb +44 -0
  338. data/spec/unit/models/blueprint/project_blueprint_spec.rb +648 -0
  339. data/spec/unit/models/blueprint/reference_spec.rb +29 -0
  340. data/spec/unit/models/blueprint/schema_builder_spec.rb +38 -0
  341. data/spec/unit/models/blueprint/to_wire_spec.rb +174 -0
  342. data/spec/unit/models/domain_spec.rb +144 -0
  343. data/spec/unit/models/execution_spec.rb +108 -0
  344. data/spec/unit/models/from_wire_spec.rb +296 -0
  345. data/spec/unit/models/invitation_spec.rb +17 -0
  346. data/spec/unit/models/membership_spec.rb +132 -0
  347. data/spec/unit/models/metadata_spec.rb +104 -0
  348. data/spec/unit/models/metric_spec.rb +117 -0
  349. data/spec/unit/models/model_spec.rb +82 -0
  350. data/spec/unit/models/params_spec.rb +118 -0
  351. data/spec/unit/models/profile_spec.rb +215 -0
  352. data/spec/unit/models/project_creator_spec.rb +127 -0
  353. data/spec/unit/models/project_role_spec.rb +94 -0
  354. data/spec/unit/models/project_spec.rb +162 -0
  355. data/spec/unit/models/report_result_data_spec.rb +199 -0
  356. data/spec/unit/models/schedule_spec.rb +418 -0
  357. data/spec/unit/models/to_manifest_spec.rb +63 -0
  358. data/spec/unit/models/unit_project_spec.rb +125 -0
  359. data/spec/unit/models/user_filters_spec.rb +95 -0
  360. data/spec/unit/models/variable_spec.rb +265 -0
  361. data/spec/unit/rest/polling_spec.rb +89 -0
  362. data/spec/unit/rest/resource_spec.rb +10 -0
  363. data/yard-server.sh +3 -0
  364. metadata +1125 -0
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ require_relative 'blueprint_field'
8
+
9
+ module GoodData
10
+ module Model
11
+ class FactBlueprintField < BlueprintField
12
+ # Returns gd_data_type
13
+ #
14
+ # @return [String] returns gd_data_type of the fact
15
+ def gd_data_type
16
+ data[:gd_data_type] || Model::DEFAULT_FACT_DATATYPE
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ require_relative 'blueprint_field'
8
+
9
+ module GoodData
10
+ module Model
11
+ class LabelBlueprintField < BlueprintField
12
+ # Returns the attribute this label is referencing to
13
+ #
14
+ # @return [AttributeBlueprintField] the object representing attribute in the blueprint
15
+ def attribute
16
+ dataset_blueprint.attribute_for_label(self)
17
+ end
18
+
19
+ # Returns gd_data_type
20
+ #
21
+ # @return [String] returns gd_data_type of the label
22
+ def gd_data_type
23
+ data[:gd_data_type] || Model::DEFAULT_ATTRIBUTE_DATATYPE
24
+ end
25
+
26
+ # Returns gd_data_type
27
+ #
28
+ # @return [String] returns gd_type of the label
29
+ def gd_type
30
+ data[:gd_type] || Model::DEFAULT_TYPE
31
+ end
32
+
33
+ # Validates the fields in the label
34
+ #
35
+ # @return [Array] returns list of the errors represented by hash structures
36
+ def validate
37
+ validate_presence_of(:id, :reference).map do |e|
38
+ { type: :error, message: "Field \"#{e}\" is not defined or empty for label \"#{id}\"" }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,746 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ module GoodData
8
+ module Model
9
+ class ProjectBlueprint
10
+ attr_accessor :data
11
+
12
+ # Instantiates a project blueprint either from a file or from a string containing
13
+ # json. Also eats Hash for convenience.
14
+ #
15
+ # @param spec [String | Hash] value of an label you are looking for
16
+ # @return [GoodData::Model::ProjectBlueprint]
17
+ class << self
18
+ def from_json(spec)
19
+ if spec.is_a?(String)
20
+ if File.file?(spec)
21
+ ProjectBlueprint.new(MultiJson.load(File.read(spec), :symbolize_keys => true))
22
+ else
23
+ ProjectBlueprint.new(MultiJson.load(spec, :symbolize_keys => true))
24
+ end
25
+ else
26
+ ProjectBlueprint.new(spec)
27
+ end
28
+ end
29
+
30
+ def build(title, &block)
31
+ pb = ProjectBuilder.create(title, &block)
32
+ pb.to_blueprint
33
+ end
34
+ end
35
+
36
+ # Removes column from from the blueprint
37
+ #
38
+ # @param project [Hash | GoodData::Model::ProjectBlueprint] Project blueprint
39
+ # @param dataset [Hash | GoodData::Model::DatasetBlueprint] Dataset blueprint
40
+ # @param column_id [String] Column id
41
+ # @return [Hash | GoodData::Model::ProjectBlueprint] Returns changed blueprint
42
+ def self.remove_column!(project, dataset, column_id)
43
+ dataset = find_dataset(project, dataset)
44
+ col = dataset[:columns].find { |c| c[:id] == column_id }
45
+ dataset[:columns].delete(col)
46
+ project
47
+ end
48
+
49
+ # Removes dataset from blueprint. Dataset can be given as either a name
50
+ # or a DatasetBlueprint or a Hash representation.
51
+ #
52
+ # @param project [Hash | GoodData::Model::ProjectBlueprint] Project blueprint
53
+ # @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
54
+ # @return [Hash] new project with removed dataset
55
+ def self.remove_dataset(project, dataset_id)
56
+ dataset = dataset_id.is_a?(String) ? find_dataset(project, dataset_id) : dataset_name
57
+ index = project[:datasets].index(dataset)
58
+ dupped_project = GoodData::Helpers.deep_dup(project)
59
+ dupped_project[:datasets].delete_at(index)
60
+ dupped_project
61
+ end
62
+
63
+ # Removes dataset from blueprint. Dataset can be given as either a name
64
+ # or a DatasetBlueprint or a Hash representation. This version mutates
65
+ # the dataset in place
66
+ #
67
+ # @param project [Hash | GoodData::Model::ProjectBlueprint] Project blueprint
68
+ # @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
69
+ # @return [Hash] project with removed dataset
70
+ def self.remove_dataset!(project, dataset_id)
71
+ project = project.to_hash
72
+ dataset = dataset_id.is_a?(String) ? find_dataset(project, dataset_id) : dataset_id
73
+ index = project[:datasets].index(dataset)
74
+ project[:datasets].delete_at(index)
75
+ project
76
+ end
77
+
78
+ # Returns datasets of blueprint. Those can be optionally including
79
+ # date dimensions
80
+ #
81
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
82
+ # @param options [Hash] options
83
+ # @return [Array<Hash>]
84
+ def self.datasets(project_blueprint, options = {})
85
+ project_blueprint = project_blueprint.to_hash
86
+ include_date_dimensions = options[:include_date_dimensions] || options[:dd]
87
+ ds = (project_blueprint.to_hash[:datasets] || [])
88
+ if include_date_dimensions
89
+ ds + date_dimensions(project_blueprint)
90
+ else
91
+ ds
92
+ end
93
+ end
94
+
95
+ # Returns blueprint with all references to one date dimensions changed to reference to the other. Changes the Blueprint in place.
96
+ #
97
+ # @param what [GoodData::Model::ReferenceBlueprintField | String] Date dimension reference field to be replaced.
98
+ # @param for_what [GoodData::Model::ReferenceBlueprintField | String] Date dimension reference field to be used as a replacement.
99
+ # @return [GoodData::Model::ProjectBlueprint]
100
+ def swap_date_dimension!(what, for_what)
101
+ what_id = what.respond_to?(:id) ? what.id : what
102
+ for_what_id = what.respond_to?(:id) ? for_what.id : for_what
103
+
104
+ fields = to_hash[:datasets].flat_map { |x| x[:columns] }.select { |x| x[:type] == :date }.select { |i| i[:dataset] == what_id }
105
+ fields.each { |f| f[:dataset] = for_what_id }
106
+ self
107
+ end
108
+
109
+ # Returns true if a dataset contains a particular dataset false otherwise
110
+ #
111
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
112
+ # @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
113
+ # @return [Boolean]
114
+ def self.dataset?(project, name, options = {})
115
+ find_dataset(project, name, options)
116
+ true
117
+ rescue
118
+ false
119
+ end
120
+
121
+ # Returns dataset specified. It can check even for a date dimension
122
+ #
123
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
124
+ # @param obj [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
125
+ # @param options [Hash] options
126
+ # @return [GoodData::Model::DatasetBlueprint]
127
+ def self.find_dataset(project_blueprint, obj, options = {})
128
+ return obj.to_hash if DatasetBlueprint.dataset_blueprint?(obj)
129
+ all_datasets = datasets(project_blueprint, options)
130
+ name = obj.respond_to?(:to_hash) ? obj.to_hash[:id] : obj
131
+ ds = all_datasets.find { |d| d[:id] == name }
132
+ fail "Dataset #{name} could not be found" if ds.nil?
133
+ ds
134
+ end
135
+
136
+ # Returns list of date dimensions
137
+ #
138
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
139
+ # @return [Array<Hash>]
140
+ def self.date_dimensions(project_blueprint)
141
+ project_blueprint.to_hash[:date_dimensions] || []
142
+ # dims.map {|dim| DateDimension.new(dim, project_blueprint)}
143
+ end
144
+
145
+ # Returns true if a date dimension of a given name exists in a bleuprint
146
+ #
147
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
148
+ # @param name [string] Date dimension
149
+ # @return [Boolean]
150
+ def self.date_dimension?(project, name)
151
+ find_date_dimension(project, name)
152
+ true
153
+ rescue
154
+ false
155
+ end
156
+
157
+ # Finds a date dimension of a given name in a bleuprint. If a dataset is
158
+ # not found it throws an exeception
159
+ #
160
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
161
+ # @param name [string] Date dimension
162
+ # @return [Hash]
163
+ def self.find_date_dimension(project, name)
164
+ ds = date_dimensions(project).find { |d| d[:id] == name }
165
+ fail "Date dimension #{name} could not be found" unless ds
166
+ ds
167
+ end
168
+
169
+ # Returns fields from all datasets
170
+ #
171
+ # @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
172
+ # @return [Array<Hash>]
173
+ def self.fields(project)
174
+ datasets(project).mapcat { |d| DatasetBlueprint.fields(d) }
175
+ end
176
+
177
+ # Changes the dataset through a builder. You provide a block and an istance of
178
+ # GoodData::Model::ProjectBuilder is passed in as the only parameter
179
+ #
180
+ # @return [GoodData::Model::ProjectBlueprint] returns changed project blueprint
181
+ def change(&block)
182
+ builder = ProjectBuilder.create_from_data(self)
183
+ block.call(builder)
184
+ @data = builder.to_hash
185
+ self
186
+ end
187
+
188
+ # Returns datasets of blueprint. Those can be optionally including
189
+ # date dimensions
190
+ #
191
+ # @param options [Hash] options
192
+ # @return [Array<GoodData::Model::DatasetBlueprint>]
193
+ def datasets(id = :all, options = {})
194
+ id = id.respond_to?(:id) ? id.id : id
195
+ dss = ProjectBlueprint.datasets(self, options).map do |d|
196
+ case d[:type]
197
+ when :date_dimension
198
+ DateDimension.new(d, self)
199
+ when :dataset
200
+ DatasetBlueprint.new(d, self)
201
+ end
202
+ end
203
+ id == :all ? dss : dss.find { |d| d.id == id }
204
+ end
205
+
206
+ # Adds dataset to the blueprint
207
+ #
208
+ # @param a_dataset [Hash | GoodData::Model::SchemaBlueprint] dataset to be added
209
+ # @param index [Integer] number specifying at which position the new dataset should be added. If not specified it is added at the end
210
+ # @return [GoodData::Model::ProjectBlueprint] returns project blueprint
211
+ def add_dataset!(a_dataset, index = nil)
212
+ if index.nil? || index > datasets.length
213
+ data[:datasets] << a_dataset.to_hash
214
+ else
215
+ data[:datasets].insert(index, a_dataset.to_hash)
216
+ end
217
+ self
218
+ end
219
+
220
+ def add_date_dimension!(a_dimension, index = nil)
221
+ dim = a_dimension.to_hash
222
+ if index.nil? || index > date_dimensions.length
223
+ data[:date_dimensions] << dim
224
+ else
225
+ data[:date_dimensions].insert(index, dim)
226
+ end
227
+ self
228
+ end
229
+
230
+ # Adds column to particular dataset in the blueprint
231
+ #
232
+ # @param dataset [Hash | GoodData::Model::SchemaBlueprint] dataset to be added
233
+ # @param column_definition [Hash] Column definition to be added
234
+ # @return [GoodData::Model::ProjectBlueprint] returns project blueprint
235
+ def add_column!(dataset, column_definition)
236
+ ds = ProjectBlueprint.find_dataset(to_hash, dataset)
237
+ ds[:columns] << column_definition
238
+ self
239
+ end
240
+
241
+ # Removes column to particular dataset in the blueprint
242
+ #
243
+ # @param dataset [Hash | GoodData::Model::SchemaBlueprint] dataset to be added
244
+ # @param id [String] id of the column to be removed
245
+ # @return [GoodData::Model::ProjectBlueprint] returns project blueprint
246
+ def remove_column!(dataset, id)
247
+ ProjectBlueprint.remove_column!(to_hash, dataset, id)
248
+ self
249
+ end
250
+
251
+ # Moves column to particular dataset in the blueprint. It currently supports moving
252
+ # of attributes and facts only. The rest of the fields probably does not make sense
253
+ # In case of attribute it moves its labels as well.
254
+ #
255
+ # @param id [GoodData::Model::BlueprintField] column to be moved
256
+ # @param from_dataset [Hash | GoodData::Model::SchemaBlueprint] dataset from which the field should be moved
257
+ # @param to_dataset [Hash | GoodData::Model::SchemaBlueprint] dataset to which the field should be moved
258
+ # @return [GoodData::Model::ProjectBlueprint] returns project blueprint
259
+ def move!(col, from_dataset, to_dataset)
260
+ from_dataset = find_dataset(from_dataset)
261
+ to_dataset = find_dataset(to_dataset)
262
+ column = if col.is_a?(String)
263
+ from_dataset.find_column_by_id(col)
264
+ else
265
+ from_dataset.find_column(col)
266
+ end
267
+ fail "Column #{col} cannot be found in dataset #{from_dataset.id}" unless column
268
+ stuff = case column.type
269
+ when :attribute
270
+ [column] + column.labels
271
+ when :fact
272
+ [column]
273
+ when :reference
274
+ [column]
275
+ else
276
+ fail 'Duplicate does not support moving #{col.type} type of field'
277
+ end
278
+ stuff = stuff.map(&:data)
279
+ stuff.each { |c| remove_column!(from_dataset, c[:id]) }
280
+ stuff.each { |c| add_column!(to_dataset, c) }
281
+ self
282
+ end
283
+
284
+ def duplicate!(col, from_dataset, to_dataset)
285
+ from_dataset = find_dataset(from_dataset)
286
+ to_dataset = find_dataset(to_dataset)
287
+ column = if col.is_a?(String)
288
+ from_dataset.find_column_by_id(col)
289
+ else
290
+ from_dataset.find_column(col)
291
+ end
292
+ fail "Column #{col} cannot be found in dataset #{from_dataset.id}" unless column
293
+ stuff = case column.type
294
+ when :attribute
295
+ [column] + column.labels
296
+ when :fact
297
+ [column]
298
+ when :reference
299
+ [column]
300
+ else
301
+ fail 'Duplicate does not support moving #{col.type} type of field'
302
+ end
303
+ stuff.map(&:data).each { |c| add_column!(to_dataset, c) }
304
+ self
305
+ end
306
+
307
+ # Returns list of attributes from all the datasets in a blueprint
308
+ #
309
+ # @return [Array<Hash>]
310
+ def attributes
311
+ datasets.reduce([]) { |a, e| a.concat(e.attributes) }
312
+ end
313
+
314
+ # Returns list of attributes and anchors from all the datasets in a blueprint
315
+ #
316
+ # @return [Array<Hash>]
317
+ def attributes_and_anchors
318
+ datasets.mapcat(&:attributes_and_anchors)
319
+ end
320
+
321
+ # Is this a project blueprint?
322
+ #
323
+ # @return [Boolean] if it is
324
+ def project_blueprint?
325
+ true
326
+ end
327
+
328
+ # Returns list of date dimensions
329
+ #
330
+ # @return [Array<Hash>]
331
+ def date_dimensions
332
+ ProjectBlueprint.date_dimensions(self).map { |dd| GoodData::Model::DateDimension.new(dd, self) }
333
+ end
334
+
335
+ # Returns true if a dataset contains a particular dataset false otherwise
336
+ #
337
+ # @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
338
+ # @return [Boolean]
339
+ def dataset?(name, options = {})
340
+ ProjectBlueprint.dataset?(to_hash, name, options)
341
+ end
342
+
343
+ # Returns SLI manifest for one dataset. This is used by our API to allow
344
+ # loading data. The method is on project blueprint because you need
345
+ # acces to whole project to be able to generate references
346
+ #
347
+ # @param dataset [GoodData::Model::DatasetBlueprint | Hash | String] Dataset
348
+ # @param mode [String] Method of loading. FULL or INCREMENTAL
349
+ # @return [Array<Hash>] a title
350
+ def dataset_to_manifest(dataset, mode = 'FULL')
351
+ ToManifest.dataset_to_manifest(self, dataset, mode)
352
+ end
353
+
354
+ # Duplicated blueprint
355
+ #
356
+ # @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
357
+ # @return [GoodData::Model::DatasetBlueprint]
358
+ def dup
359
+ ProjectBlueprint.new(GoodData::Helpers.deep_dup(data))
360
+ end
361
+
362
+ # Returns list of facts from all the datasets in a blueprint
363
+ #
364
+ # @return [Array<Hash>]
365
+ def facts
366
+ datasets.mapcat(&:facts)
367
+ end
368
+
369
+ # Returns list of fields from all the datasets in a blueprint
370
+ #
371
+ # @return [Array<Hash>]
372
+ def fields
373
+ datasets.flat_map(&:fields)
374
+ end
375
+
376
+ # Returns dataset specified. It can check even for a date dimension
377
+ #
378
+ # @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
379
+ # @param options [Hash] options
380
+ # @return [GoodData::Model::DatasetBlueprint]
381
+ def find_dataset(name, options = {})
382
+ ds = datasets(name, options)
383
+ fail "Dataset \"#{name}\" could not be found" unless ds
384
+ ds
385
+ end
386
+
387
+ # Returns a dataset of a given name. If a dataset is not found it throws an exeception
388
+ #
389
+ # @param project [String] Dataset title
390
+ # @return [Array<Hash>]
391
+ def find_dataset_by_title(title)
392
+ ds = ProjectBlueprint.find_dataset_by_title(to_hash, title)
393
+ DatasetBlueprint.new(ds)
394
+ end
395
+
396
+ # Return list of datasets that are centers of the stars in datamart.
397
+ # This means these datasets are not referenced by anybody else
398
+ # In a good blueprint design these should be fact tables
399
+ #
400
+ # @return [Array<Hash>]
401
+ def find_star_centers
402
+ datasets.select { |d| d.referenced_by.empty? }
403
+ end
404
+
405
+ # Constructor
406
+ #
407
+ # @param init_data [ProjectBlueprint | Hash] Blueprint or a blueprint definition. If passed a hash it is used as data for new instance. If there is a ProjectBlueprint passed it is duplicated and a new instance is created.
408
+ # @return [ProjectBlueprint] A new project blueprint instance
409
+ def initialize(init_data)
410
+ some_data = if init_data.respond_to?(:project_blueprint?) && init_data.project_blueprint?
411
+ init_data.to_hash
412
+ elsif init_data.respond_to?(:to_blueprint)
413
+ init_data.to_blueprint.to_hash
414
+ else
415
+ init_data
416
+ end
417
+ @data = GoodData::Helpers.symbolize_keys(GoodData::Helpers.deep_dup(some_data))
418
+ (@data[:datasets] || []).each do |d|
419
+ d[:type] = d[:type].to_sym
420
+ d[:columns].each do |c|
421
+ c[:type] = c[:type].to_sym
422
+ end
423
+ end
424
+ (@data[:date_dimensions] || []).each do |d|
425
+ d[:type] = d[:type].to_sym
426
+ end
427
+ end
428
+
429
+ def id
430
+ data[:id]
431
+ end
432
+
433
+ # Returns list of labels from all the datasets in a blueprint
434
+ #
435
+ # @return [Array<Hash>]
436
+ def labels
437
+ datasets.mapcat(&:labels)
438
+ end
439
+
440
+ # Experimental but a basis for automatic check of health of a project
441
+ #
442
+ # @param project [GoodData::Model::DatasetBlueprint | Hash | String] Dataset blueprint
443
+ # @return [Array<Hash>]
444
+ def lint(full = false)
445
+ errors = []
446
+ find_star_centers.each do |dataset|
447
+ next unless dataset.anchor?
448
+ errors << {
449
+ type: :anchor_on_fact_dataset,
450
+ dataset_name: dataset.name,
451
+ anchor_name: dataset.anchor[:name]
452
+ }
453
+ end
454
+ date_facts = datasets.mapcat(&:date_facts)
455
+ date_facts.each do |date_fact|
456
+ errors << {
457
+ type: :date_fact,
458
+ date_fact: date_fact[:name]
459
+ }
460
+ end
461
+
462
+ unique_titles = fields.map { |f| Model.title(f) }.uniq
463
+ (fields.map { |f| Model.title(f) } - unique_titles).each do |duplicate_title|
464
+ errors << {
465
+ type: :duplicate_title,
466
+ title: duplicate_title
467
+ }
468
+ end
469
+
470
+ datasets.select(&:wide?).each do |wide_dataset|
471
+ errors << {
472
+ type: :wide_dataset,
473
+ dataset: wide_dataset.name
474
+ }
475
+ end
476
+
477
+ if full
478
+ # GoodData::Attributes.all(:full => true).select { |attr| attr.used_by}
479
+ end
480
+ errors
481
+ end
482
+
483
+ # Merging two blueprints. The self blueprint is changed in place
484
+ #
485
+ # @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
486
+ # @return [GoodData::Model::ProjectBlueprint]
487
+ def merge!(a_blueprint)
488
+ temp_blueprint = merge(a_blueprint)
489
+ @data = temp_blueprint.data
490
+ self
491
+ end
492
+
493
+ # Returns list of datasets which are referenced by given dataset. This can be
494
+ # optionally switched to return even date dimensions
495
+ #
496
+ # @param project [GoodData::Model::DatasetBlueprint | Hash | String] Dataset blueprint
497
+ # @return [Array<Hash>]
498
+ def referenced_by(dataset)
499
+ find_dataset(dataset, include_date_dimensions: true).referencing
500
+ end
501
+
502
+ def referencing(dataset)
503
+ datasets(:all, include_date_dimensions: true)
504
+ .flat_map(&:references)
505
+ .select { |r| r.dataset == dataset }
506
+ .map(&:dataset_blueprint)
507
+ end
508
+
509
+ # Removes dataset from blueprint. Dataset can be given as either a name
510
+ # or a DatasetBlueprint or a Hash representation.
511
+ #
512
+ # @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
513
+ # @return [Hash] project with removed dataset
514
+ def remove_dataset(dataset_name)
515
+ ProjectBlueprint.remove_dataset(to_hash, dataset_name)
516
+ self
517
+ end
518
+
519
+ # Removes dataset from blueprint. Dataset can be given as either a name
520
+ # or a DatasetBlueprint or a Hash representation.
521
+ #
522
+ # @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
523
+ # @return [Hash] project with removed dataset
524
+ def remove_dataset!(dataset_id)
525
+ ProjectBlueprint.remove_dataset!(to_hash, dataset_id)
526
+ self
527
+ end
528
+
529
+ # Removes all the labels from the anchor. This is a typical operation that people want to
530
+ # perform on fact tables
531
+ #
532
+ # @return [GoodData::Model::ProjectBlueprint] Returns changed blueprint
533
+ def strip_anchor!(dataset)
534
+ from_dataset = find_dataset(dataset)
535
+ stuff = dataset.anchor.labels.map(&:data)
536
+ stuff.each { |column| remove_column!(from_dataset, column[:id]) }
537
+ self
538
+ end
539
+
540
+ # Returns some reports that might get you started. They are just simple
541
+ # reports. Currently it is implemented by getting facts from star centers
542
+ # and randomly picking attributes form referenced datasets.
543
+ #
544
+ # @return [Array<Hash>]
545
+ def suggest_reports(options = {})
546
+ strategy = options[:strategy] || :stupid
547
+ case strategy
548
+ when :stupid
549
+ reports = suggest_metrics.reduce([]) do |a, e|
550
+ star, metrics = e
551
+ metrics.each(&:save)
552
+ reports_stubs = metrics.map do |m|
553
+ breaks = broken_by(star).map { |ds, a_m| ds.identifier_for(a_m) }
554
+ [breaks, m]
555
+ end
556
+ a.concat(reports_stubs)
557
+ end
558
+ reports.reduce([]) do |a, e|
559
+ attrs, metric = e
560
+
561
+ attrs.each do |attr|
562
+ a << GoodData::Report.create(:title => 'Fantastic report',
563
+ :top => [attr],
564
+ :left => metric)
565
+ end
566
+ a
567
+ end
568
+ end
569
+ end
570
+
571
+ # Returns some metrics that might get you started. They are just simple
572
+ # reports. Currently it is implemented by getting facts from star centers
573
+ # and randomly picking attributes form referenced datasets.
574
+ #
575
+ # @return [Array<Hash>]
576
+ def suggest_metrics
577
+ stars = find_star_centers
578
+ metrics = stars.map(&:suggest_metrics)
579
+ stars.zip(metrics)
580
+ end
581
+
582
+ alias_method :suggest_measures, :suggest_metrics
583
+
584
+ def to_blueprint
585
+ self
586
+ end
587
+
588
+ def refactor_split_df(dataset)
589
+ fail ValidationError unless valid?
590
+ o = find_dataset(dataset)
591
+ new_dataset = GoodData::Model::DatasetBlueprint.new({ type: :dataset, id: "#{o.id}_dim", columns: [] }, self)
592
+ new_dataset.change do |d|
593
+ d.add_anchor('vymysli_id')
594
+ d.add_label('label.vymysli_id', reference: 'vymysli_id')
595
+ end
596
+ nb = merge(new_dataset.to_blueprint)
597
+ o.attributes.each { |a| nb.move!(a, o, new_dataset.id) }
598
+ old = nb.find_dataset(dataset)
599
+ old.attributes.each do |a|
600
+ remove_column!(old, a)
601
+ end
602
+ old.change do |d|
603
+ d.add_reference(new_dataset.id)
604
+ end
605
+ nb
606
+ end
607
+
608
+ def refactor_split_facts(dataset, column_names, new_dataset_title)
609
+ fail ValidationError unless valid?
610
+ change do |p|
611
+ p.add_dataset(new_dataset_title) do |d|
612
+ d.add_anchor("#{new_dataset_title}.id")
613
+ end
614
+ end
615
+ dataset_to_refactor = find_dataset(dataset)
616
+ new_dataset = find_dataset(new_dataset_title)
617
+ column_names.each { |c| move!(c, dataset_to_refactor, new_dataset) }
618
+ dataset_to_refactor.references.each { |ref| duplicate!(ref, dataset_to_refactor, new_dataset) }
619
+ self
620
+ end
621
+
622
+ # Merging two blueprints. A new blueprint is created. The self one
623
+ # is nto mutated
624
+ #
625
+ # @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
626
+ # @return [GoodData::Model::ProjectBlueprint]
627
+ def merge(a_blueprint)
628
+ temp_blueprint = dup
629
+ return temp_blueprint unless a_blueprint
630
+ a_blueprint.datasets.each do |dataset|
631
+ if temp_blueprint.dataset?(dataset.id)
632
+ local_dataset = temp_blueprint.find_dataset(dataset.id)
633
+ index = temp_blueprint.datasets.index(local_dataset)
634
+ local_dataset.merge!(dataset)
635
+ temp_blueprint.remove_dataset!(local_dataset.id)
636
+ temp_blueprint.add_dataset!(local_dataset, index)
637
+ else
638
+ temp_blueprint.add_dataset!(dataset.dup)
639
+ end
640
+ end
641
+ a_blueprint.date_dimensions.each do |dd|
642
+ if temp_blueprint.dataset?(dd.id, dd: true)
643
+ local_dim = temp_blueprint.find_dataset(dd.id, dd: true)
644
+ fail "Unable to merge date dimensions #{dd.id} with defintion #{dd.data} with #{local_dim.data}" unless local_dim.data == dd.data
645
+ else
646
+ temp_blueprint.add_date_dimension!(dd.dup)
647
+ end
648
+ end
649
+ temp_blueprint
650
+ end
651
+
652
+ # Helper for storing the project blueprint into a file as JSON.
653
+ #
654
+ # @param filename [String] Name of the file where the blueprint should be stored
655
+ def store_to_file(filename)
656
+ File.open(filename, 'w') do |f|
657
+ f << JSON.pretty_generate(to_hash)
658
+ end
659
+ end
660
+
661
+ # Returns title of a dataset. If not present it is generated from the name
662
+ #
663
+ # @return [String] a title
664
+ def title
665
+ Model.title(to_hash) if to_hash[:title]
666
+ end
667
+
668
+ # Returns title of a dataset. If not present it is generated from the name
669
+ #
670
+ # @return [String] a title
671
+ def title=(a_title)
672
+ @data[:title] = a_title
673
+ end
674
+
675
+ # Returns Wire representation. This is used by our API to generate and
676
+ # change projects
677
+ #
678
+ # @return [Hash] a title
679
+ def to_wire
680
+ validate
681
+ ToWire.to_wire(data)
682
+ end
683
+
684
+ # Returns SLI manifest representation. This is used by our API to allow
685
+ # loading data
686
+ #
687
+ # @return [Array<Hash>] a title
688
+ def to_manifest
689
+ validate
690
+ ToManifest.to_manifest(to_hash)
691
+ end
692
+
693
+ # Returns hash representation of blueprint
694
+ #
695
+ # @return [Hash] a title
696
+ def to_hash
697
+ @data
698
+ end
699
+
700
+ # Validate the blueprint in particular if all references reference existing datasets and valid fields inside them.
701
+ #
702
+ # @return [Array] array of errors
703
+ def validate_references
704
+ stuff = datasets(:all, include_date_dimensions: true).flat_map(&:references).select do |ref|
705
+ begin
706
+ ref.dataset
707
+ false
708
+ rescue RuntimeError
709
+ true
710
+ end
711
+ end
712
+ stuff.map { |r| { type: :bad_reference, reference: r.data, referencing_dataset: r.data[:dataset] } }
713
+ end
714
+
715
+ # Validate the blueprint and all its datasets return array of errors that are found.
716
+ #
717
+ # @return [Array] array of errors
718
+ def validate
719
+ errors = []
720
+ errors.concat validate_references
721
+ errors.concat datasets.reduce([]) { |a, e| a.concat(e.validate) }
722
+ errors.concat datasets.reduce([]) { |a, e| a.concat(e.validate_gd_data_type_errors) }
723
+ errors
724
+ rescue
725
+ raise GoodData::ValidationError
726
+ end
727
+
728
+ # Validate the blueprint and all its datasets and return true if model is valid. False otherwise.
729
+ #
730
+ # @return [Boolean] is model valid?
731
+ def valid?
732
+ validate.empty?
733
+ end
734
+
735
+ def ==(other)
736
+ # to_hash == other.to_hash
737
+ return false unless id == other.id
738
+ return false unless title == other.title
739
+ left = to_hash[:datasets].map { |d| d[:columns].to_set }.to_set
740
+ right = other.to_hash[:datasets].map { |d| d[:columns].to_set }.to_set
741
+ return false unless left == right
742
+ true
743
+ end
744
+ end
745
+ end
746
+ end