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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +36 -0
- data/.rspec +3 -0
- data/.rubocop.yml +89 -0
- data/.yardopts +22 -0
- data/CHANGELOG.md +196 -0
- data/CLI.md +439 -0
- data/DEPENDENCIES.md +817 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/LICENSE.rb +5 -0
- data/README.md +75 -0
- data/Rakefile +179 -0
- data/TODO.md +32 -0
- data/authors.sh +4 -0
- data/bin/gooddata +7 -0
- data/dependency_decisions.yml +104 -0
- data/gooddata +9 -0
- data/gooddata.gemspec +63 -0
- data/lib/gooddata.rb +31 -0
- data/lib/gooddata/app/app.rb +16 -0
- data/lib/gooddata/bricks/base_downloader.rb +86 -0
- data/lib/gooddata/bricks/brick.rb +38 -0
- data/lib/gooddata/bricks/bricks.rb +15 -0
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/base_middleware.rb +56 -0
- data/lib/gooddata/bricks/middleware/bench_middleware.rb +24 -0
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +37 -0
- data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +20 -0
- data/lib/gooddata/bricks/middleware/fs_download_middleware.rb +48 -0
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +36 -0
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +39 -0
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/middleware.rb +12 -0
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +61 -0
- data/lib/gooddata/bricks/middleware/stdout_middleware.rb +23 -0
- data/lib/gooddata/bricks/middleware/twitter_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +37 -0
- data/lib/gooddata/bricks/pipeline.rb +32 -0
- data/lib/gooddata/bricks/utils.rb +18 -0
- data/lib/gooddata/cli/cli.rb +27 -0
- data/lib/gooddata/cli/commands/auth_cmd.rb +29 -0
- data/lib/gooddata/cli/commands/domain_cmd.rb +28 -0
- data/lib/gooddata/cli/commands/project_cmd.rb +45 -0
- data/lib/gooddata/cli/hooks.rb +57 -0
- data/lib/gooddata/cli/shared.rb +61 -0
- data/lib/gooddata/cli/terminal.rb +20 -0
- data/lib/gooddata/client.rb +67 -0
- data/lib/gooddata/commands/api.rb +64 -0
- data/lib/gooddata/commands/auth.rb +107 -0
- data/lib/gooddata/commands/base.rb +12 -0
- data/lib/gooddata/commands/commands.rb +12 -0
- data/lib/gooddata/commands/datasets.rb +148 -0
- data/lib/gooddata/commands/datawarehouse.rb +20 -0
- data/lib/gooddata/commands/domain.rb +40 -0
- data/lib/gooddata/commands/process.rb +67 -0
- data/lib/gooddata/commands/project.rb +175 -0
- data/lib/gooddata/commands/projects.rb +20 -0
- data/lib/gooddata/commands/role.rb +36 -0
- data/lib/gooddata/commands/runners.rb +47 -0
- data/lib/gooddata/commands/scaffold.rb +69 -0
- data/lib/gooddata/commands/user.rb +39 -0
- data/lib/gooddata/connection.rb +127 -0
- data/lib/gooddata/core/core.rb +12 -0
- data/lib/gooddata/core/logging.rb +105 -0
- data/lib/gooddata/core/nil_logger.rb +23 -0
- data/lib/gooddata/core/project.rb +74 -0
- data/lib/gooddata/core/rest.rb +149 -0
- data/lib/gooddata/core/user.rb +20 -0
- data/lib/gooddata/data/data.rb +12 -0
- data/lib/gooddata/data/guesser.rb +122 -0
- data/lib/gooddata/exceptions/attr_element_not_found.rb +16 -0
- data/lib/gooddata/exceptions/command_failed.rb +11 -0
- data/lib/gooddata/exceptions/exceptions.rb +12 -0
- data/lib/gooddata/exceptions/execution_limit_exceeded.rb +13 -0
- data/lib/gooddata/exceptions/filter_maqlization.rb +16 -0
- data/lib/gooddata/exceptions/malformed_user.rb +15 -0
- data/lib/gooddata/exceptions/no_project_error.rb +15 -0
- data/lib/gooddata/exceptions/object_migration.rb +32 -0
- data/lib/gooddata/exceptions/project_not_found.rb +13 -0
- data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
- data/lib/gooddata/exceptions/uncomputable_report.rb +13 -0
- data/lib/gooddata/exceptions/user_in_different_domain.rb +15 -0
- data/lib/gooddata/exceptions/validation_error.rb +16 -0
- data/lib/gooddata/extensions/big_decimal.rb +17 -0
- data/lib/gooddata/extensions/enumerable.rb +39 -0
- data/lib/gooddata/extensions/extensions.rb +10 -0
- data/lib/gooddata/extensions/false.rb +15 -0
- data/lib/gooddata/extensions/hash.rb +38 -0
- data/lib/gooddata/extensions/nil.rb +15 -0
- data/lib/gooddata/extensions/numeric.rb +15 -0
- data/lib/gooddata/extensions/object.rb +27 -0
- data/lib/gooddata/extensions/symbol.rb +15 -0
- data/lib/gooddata/extensions/true.rb +15 -0
- data/lib/gooddata/extract.rb +21 -0
- data/lib/gooddata/goodzilla/goodzilla.rb +159 -0
- data/lib/gooddata/helpers/auth_helpers.rb +75 -0
- data/lib/gooddata/helpers/csv_helper.rb +61 -0
- data/lib/gooddata/helpers/data_helper.rb +116 -0
- data/lib/gooddata/helpers/global_helpers.rb +331 -0
- data/lib/gooddata/helpers/global_helpers_params.rb +172 -0
- data/lib/gooddata/helpers/helpers.rb +10 -0
- data/lib/gooddata/mixins/author.rb +26 -0
- data/lib/gooddata/mixins/content_getter.rb +15 -0
- data/lib/gooddata/mixins/content_property_reader.rb +17 -0
- data/lib/gooddata/mixins/content_property_writer.rb +17 -0
- data/lib/gooddata/mixins/contributor.rb +20 -0
- data/lib/gooddata/mixins/data_getter.rb +15 -0
- data/lib/gooddata/mixins/data_property_reader.rb +19 -0
- data/lib/gooddata/mixins/data_property_writer.rb +19 -0
- data/lib/gooddata/mixins/inspector.rb +53 -0
- data/lib/gooddata/mixins/is_attribute.rb +17 -0
- data/lib/gooddata/mixins/is_dimension.rb +17 -0
- data/lib/gooddata/mixins/is_fact.rb +17 -0
- data/lib/gooddata/mixins/is_label.rb +19 -0
- data/lib/gooddata/mixins/links.rb +15 -0
- data/lib/gooddata/mixins/md_finders.rb +77 -0
- data/lib/gooddata/mixins/md_grantees.rb +42 -0
- data/lib/gooddata/mixins/md_id_to_uri.rb +34 -0
- data/lib/gooddata/mixins/md_json.rb +15 -0
- data/lib/gooddata/mixins/md_lock.rb +87 -0
- data/lib/gooddata/mixins/md_object_id.rb +15 -0
- data/lib/gooddata/mixins/md_object_indexer.rb +64 -0
- data/lib/gooddata/mixins/md_object_query.rb +128 -0
- data/lib/gooddata/mixins/md_relations.rb +43 -0
- data/lib/gooddata/mixins/meta_getter.rb +17 -0
- data/lib/gooddata/mixins/meta_property_reader.rb +19 -0
- data/lib/gooddata/mixins/meta_property_writer.rb +19 -0
- data/lib/gooddata/mixins/mixins.rb +19 -0
- data/lib/gooddata/mixins/not_attribute.rb +17 -0
- data/lib/gooddata/mixins/not_exportable.rb +15 -0
- data/lib/gooddata/mixins/not_fact.rb +17 -0
- data/lib/gooddata/mixins/not_group.rb +17 -0
- data/lib/gooddata/mixins/not_label.rb +19 -0
- data/lib/gooddata/mixins/not_metric.rb +19 -0
- data/lib/gooddata/mixins/obj_id.rb +15 -0
- data/lib/gooddata/mixins/rest_getters.rb +17 -0
- data/lib/gooddata/mixins/rest_resource.rb +47 -0
- data/lib/gooddata/mixins/root_key_getter.rb +15 -0
- data/lib/gooddata/mixins/root_key_setter.rb +15 -0
- data/lib/gooddata/mixins/timestamps.rb +19 -0
- data/lib/gooddata/mixins/to_json.rb +11 -0
- data/lib/gooddata/mixins/uri_getter.rb +9 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +64 -0
- data/lib/gooddata/models/blueprint/attribute_field.rb +29 -0
- data/lib/gooddata/models/blueprint/blueprint.rb +11 -0
- data/lib/gooddata/models/blueprint/blueprint_field.rb +70 -0
- data/lib/gooddata/models/blueprint/dashboard_builder.rb +30 -0
- data/lib/gooddata/models/blueprint/dataset_blueprint.rb +449 -0
- data/lib/gooddata/models/blueprint/date_dimension.rb +14 -0
- data/lib/gooddata/models/blueprint/fact_field.rb +20 -0
- data/lib/gooddata/models/blueprint/label_field.rb +43 -0
- data/lib/gooddata/models/blueprint/project_blueprint.rb +746 -0
- data/lib/gooddata/models/blueprint/project_builder.rb +83 -0
- data/lib/gooddata/models/blueprint/reference_field.rb +43 -0
- data/lib/gooddata/models/blueprint/schema_blueprint.rb +160 -0
- data/lib/gooddata/models/blueprint/schema_builder.rb +89 -0
- data/lib/gooddata/models/blueprint/to_manifest.rb +181 -0
- data/lib/gooddata/models/blueprint/to_wire.rb +154 -0
- data/lib/gooddata/models/client.rb +182 -0
- data/lib/gooddata/models/client_synchronization_result.rb +31 -0
- data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
- data/lib/gooddata/models/datawarehouse.rb +92 -0
- data/lib/gooddata/models/domain.rb +479 -0
- data/lib/gooddata/models/execution.rb +115 -0
- data/lib/gooddata/models/execution_detail.rb +81 -0
- data/lib/gooddata/models/from_wire.rb +160 -0
- data/lib/gooddata/models/invitation.rb +75 -0
- data/lib/gooddata/models/links.rb +50 -0
- data/lib/gooddata/models/membership.rb +441 -0
- data/lib/gooddata/models/metadata.rb +272 -0
- data/lib/gooddata/models/metadata/attribute.rb +134 -0
- data/lib/gooddata/models/metadata/dashboard.rb +108 -0
- data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +76 -0
- data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
- data/lib/gooddata/models/metadata/dashboard/filter_item.rb +64 -0
- data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
- data/lib/gooddata/models/metadata/dashboard/report_item.rb +92 -0
- data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
- data/lib/gooddata/models/metadata/dashboard_tab.rb +141 -0
- data/lib/gooddata/models/metadata/dataset.rb +64 -0
- data/lib/gooddata/models/metadata/dimension.rb +54 -0
- data/lib/gooddata/models/metadata/fact.rb +44 -0
- data/lib/gooddata/models/metadata/label.rb +128 -0
- data/lib/gooddata/models/metadata/metadata.rb +12 -0
- data/lib/gooddata/models/metadata/metric.rb +198 -0
- data/lib/gooddata/models/metadata/report.rb +247 -0
- data/lib/gooddata/models/metadata/report_definition.rb +264 -0
- data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
- data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
- data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
- data/lib/gooddata/models/metadata/variable.rb +91 -0
- data/lib/gooddata/models/model.rb +282 -0
- data/lib/gooddata/models/models.rb +12 -0
- data/lib/gooddata/models/module_constants.rb +31 -0
- data/lib/gooddata/models/process.rb +316 -0
- data/lib/gooddata/models/profile.rb +426 -0
- data/lib/gooddata/models/project.rb +1514 -0
- data/lib/gooddata/models/project_creator.rb +126 -0
- data/lib/gooddata/models/project_metadata.rb +67 -0
- data/lib/gooddata/models/project_role.rb +79 -0
- data/lib/gooddata/models/report_data_result.rb +266 -0
- data/lib/gooddata/models/schedule.rb +518 -0
- data/lib/gooddata/models/segment.rb +201 -0
- data/lib/gooddata/models/tab_builder.rb +27 -0
- data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +76 -0
- data/lib/gooddata/models/user_filters/user_filter.rb +100 -0
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +512 -0
- data/lib/gooddata/models/user_filters/user_filters.rb +13 -0
- data/lib/gooddata/models/user_filters/variable_user_filter.rb +31 -0
- data/lib/gooddata/models/user_group.rb +241 -0
- data/lib/gooddata/rest/README.md +37 -0
- data/lib/gooddata/rest/client.rb +389 -0
- data/lib/gooddata/rest/connection.rb +765 -0
- data/lib/gooddata/rest/object.rb +69 -0
- data/lib/gooddata/rest/object_factory.rb +76 -0
- data/lib/gooddata/rest/resource.rb +27 -0
- data/lib/gooddata/rest/rest.rb +24 -0
- data/lib/gooddata/version.rb +23 -0
- data/lib/templates/bricks/brick.rb.erb +7 -0
- data/lib/templates/bricks/main.rb.erb +5 -0
- data/lib/templates/project/Goodfile.erb +4 -0
- data/lib/templates/project/data/commits.csv +4 -0
- data/lib/templates/project/data/devs.csv +4 -0
- data/lib/templates/project/data/repos.csv +3 -0
- data/lib/templates/project/model/model.rb.erb +20 -0
- data/spec/bricks/bricks_spec.rb +112 -0
- data/spec/bricks/default-config.json +8 -0
- data/spec/data/.gooddata +4 -0
- data/spec/data/blueprints/additional_dataset_module.json +32 -0
- data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
- data/spec/data/blueprints/invalid_blueprint.json +103 -0
- data/spec/data/blueprints/m_n_model.json +104 -0
- data/spec/data/blueprints/model_module.json +25 -0
- data/spec/data/blueprints/test_blueprint.json +38 -0
- data/spec/data/blueprints/test_project_model_spec.json +106 -0
- data/spec/data/cc/data/source/commits.csv +4 -0
- data/spec/data/cc/data/source/devs.csv +4 -0
- data/spec/data/cc/data/source/repos.csv +3 -0
- data/spec/data/cc/devel.prm +0 -0
- data/spec/data/cc/graph/graph.grf +11 -0
- data/spec/data/cc/workspace.prm +19 -0
- data/spec/data/column_based_permissions.csv +7 -0
- data/spec/data/column_based_permissions2.csv +6 -0
- data/spec/data/gd_gse_data_blueprint.json +1371 -0
- data/spec/data/gd_gse_data_manifest.json +1424 -0
- data/spec/data/gd_gse_data_model.json +1772 -0
- data/spec/data/gooddata_version_process/gooddata_version.rb +9 -0
- data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
- data/spec/data/hello_world_process/hello_world.rb +9 -0
- data/spec/data/hello_world_process/hello_world.zip +0 -0
- data/spec/data/line_based_permissions.csv +3 -0
- data/spec/data/manifests/test_blueprint.json +32 -0
- data/spec/data/manifests/test_project.json +107 -0
- data/spec/data/reports/left_attr_report.json +108 -0
- data/spec/data/reports/metric_only_one_line.json +83 -0
- data/spec/data/reports/report_1.json +197 -0
- data/spec/data/reports/top_attr_report.json +108 -0
- data/spec/data/ruby_params_process/ruby_params.rb +9 -0
- data/spec/data/ruby_process/deep_files/deep_stuff.txt +1 -0
- data/spec/data/ruby_process/process.rb +8 -0
- data/spec/data/ruby_process/stuff.txt +1 -0
- data/spec/data/superfluous_titles_view.json +81 -0
- data/spec/data/test-ci-data.csv +2 -0
- data/spec/data/users.csv +12 -0
- data/spec/data/wire_models/model_view.json +1775 -0
- data/spec/data/wire_models/nu_model.json +3046 -0
- data/spec/data/wire_models/test_blueprint.json +63 -0
- data/spec/data/wire_test_project.json +150 -0
- data/spec/environment/default.rb +41 -0
- data/spec/environment/develop.rb +31 -0
- data/spec/environment/environment.rb +18 -0
- data/spec/environment/hotfix.rb +21 -0
- data/spec/environment/production.rb +35 -0
- data/spec/environment/release.rb +21 -0
- data/spec/environment/staging.rb +30 -0
- data/spec/environment/staging_3.rb +36 -0
- data/spec/helpers/blueprint_helper.rb +26 -0
- data/spec/helpers/cli_helper.rb +36 -0
- data/spec/helpers/connection_helper.rb +41 -0
- data/spec/helpers/crypto_helper.rb +17 -0
- data/spec/helpers/csv_helper.rb +18 -0
- data/spec/helpers/process_helper.rb +33 -0
- data/spec/helpers/project_helper.rb +59 -0
- data/spec/helpers/schedule_helper.rb +31 -0
- data/spec/helpers/spec_helper.rb +15 -0
- data/spec/integration/blueprint_updates_spec.rb +101 -0
- data/spec/integration/blueprint_with_grain_spec.rb +72 -0
- data/spec/integration/clients_spec.rb +134 -0
- data/spec/integration/command_datawarehouse_spec.rb +39 -0
- data/spec/integration/command_projects_spec.rb +32 -0
- data/spec/integration/create_from_template_spec.rb +22 -0
- data/spec/integration/create_project_spec.rb +24 -0
- data/spec/integration/date_dim_switch_spec.rb +142 -0
- data/spec/integration/deprecated_load_spec.rb +58 -0
- data/spec/integration/full_process_schedule_spec.rb +298 -0
- data/spec/integration/full_project_spec.rb +569 -0
- data/spec/integration/over_to_user_filters_spec.rb +94 -0
- data/spec/integration/partial_md_export_import_spec.rb +42 -0
- data/spec/integration/project_spec.rb +264 -0
- data/spec/integration/rest_spec.rb +213 -0
- data/spec/integration/schedule_spec.rb +626 -0
- data/spec/integration/segments_spec.rb +141 -0
- data/spec/integration/user_filters_spec.rb +290 -0
- data/spec/integration/user_group_spec.rb +127 -0
- data/spec/integration/variables_spec.rb +188 -0
- data/spec/logging_in_logging_out_spec.rb +93 -0
- data/spec/spec_helper.rb +95 -0
- data/spec/unit/bricks/bricks_spec.rb +35 -0
- data/spec/unit/bricks/middleware/aws_middelware_spec.rb +51 -0
- data/spec/unit/bricks/middleware/bench_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/logger_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +15 -0
- data/spec/unit/cli/cli_spec.rb +17 -0
- data/spec/unit/cli/commands/cmd_auth_spec.rb +17 -0
- data/spec/unit/commands/command_projects_spec.rb +22 -0
- data/spec/unit/core/connection_spec.rb +57 -0
- data/spec/unit/core/logging_spec.rb +133 -0
- data/spec/unit/core/nil_logger_spec.rb +13 -0
- data/spec/unit/core/project_spec.rb +54 -0
- data/spec/unit/extensions/hash_spec.rb +23 -0
- data/spec/unit/godzilla/goodzilla_spec.rb +78 -0
- data/spec/unit/helpers/csv_helper_spec.rb +22 -0
- data/spec/unit/helpers/data_helper_spec.rb +61 -0
- data/spec/unit/helpers/global_helpers_spec.rb +111 -0
- data/spec/unit/helpers_spec.rb +86 -0
- data/spec/unit/models/blueprint/attributes_spec.rb +29 -0
- data/spec/unit/models/blueprint/dataset_spec.rb +121 -0
- data/spec/unit/models/blueprint/labels_spec.rb +44 -0
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +648 -0
- data/spec/unit/models/blueprint/reference_spec.rb +29 -0
- data/spec/unit/models/blueprint/schema_builder_spec.rb +38 -0
- data/spec/unit/models/blueprint/to_wire_spec.rb +174 -0
- data/spec/unit/models/domain_spec.rb +144 -0
- data/spec/unit/models/execution_spec.rb +108 -0
- data/spec/unit/models/from_wire_spec.rb +296 -0
- data/spec/unit/models/invitation_spec.rb +17 -0
- data/spec/unit/models/membership_spec.rb +132 -0
- data/spec/unit/models/metadata_spec.rb +104 -0
- data/spec/unit/models/metric_spec.rb +117 -0
- data/spec/unit/models/model_spec.rb +82 -0
- data/spec/unit/models/params_spec.rb +118 -0
- data/spec/unit/models/profile_spec.rb +215 -0
- data/spec/unit/models/project_creator_spec.rb +127 -0
- data/spec/unit/models/project_role_spec.rb +94 -0
- data/spec/unit/models/project_spec.rb +162 -0
- data/spec/unit/models/report_result_data_spec.rb +199 -0
- data/spec/unit/models/schedule_spec.rb +418 -0
- data/spec/unit/models/to_manifest_spec.rb +63 -0
- data/spec/unit/models/unit_project_spec.rb +125 -0
- data/spec/unit/models/user_filters_spec.rb +95 -0
- data/spec/unit/models/variable_spec.rb +265 -0
- data/spec/unit/rest/polling_spec.rb +89 -0
- data/spec/unit/rest/resource_spec.rb +10 -0
- data/yard-server.sh +3 -0
- 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
|