rubiks 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/CHANGELOG.md +12 -12
  2. data/Gemfile +2 -0
  3. data/README.md +90 -72
  4. data/lib/rubiks/calculated_measure.rb +26 -0
  5. data/lib/rubiks/cube.rb +80 -0
  6. data/lib/rubiks/dimension.rb +48 -0
  7. data/lib/rubiks/hierarchy.rb +46 -0
  8. data/lib/rubiks/jars/commons-collections.jar +0 -0
  9. data/lib/rubiks/jars/commons-dbcp.jar +0 -0
  10. data/lib/rubiks/jars/commons-logging.jar +0 -0
  11. data/lib/rubiks/jars/commons-math.jar +0 -0
  12. data/lib/rubiks/jars/commons-pool.jar +0 -0
  13. data/lib/rubiks/jars/commons-vfs.jar +0 -0
  14. data/lib/rubiks/jars/eigenbase-properties.jar +0 -0
  15. data/lib/rubiks/jars/eigenbase-resgen.jar +0 -0
  16. data/lib/rubiks/jars/eigenbase-xom.jar +0 -0
  17. data/lib/rubiks/jars/log4j.jar +0 -0
  18. data/lib/rubiks/jars/mondrian.jar +0 -0
  19. data/lib/rubiks/jars/olap4j-1.2.0-SNAPSHOT.jar +0 -0
  20. data/lib/rubiks/jars/olap4j-xmla-1.2.0-SNAPSHOT.jar +0 -0
  21. data/lib/rubiks/jars/olap4j-xmla.jar.orig +0 -0
  22. data/lib/rubiks/jars/olap4j-xmlaserver-0.0.1-SNAPSHOT.jar +0 -0
  23. data/lib/rubiks/jars/olap4j.jar.orig +0 -0
  24. data/lib/rubiks/jars/postgresql-9.2-1002.jdbc3.jar +0 -0
  25. data/lib/rubiks/jars/postgresql-9.2-1002.jdbc4.jar +0 -0
  26. data/lib/rubiks/level.rb +57 -0
  27. data/lib/rubiks/measure.rb +28 -0
  28. data/lib/rubiks/mondrian/cell_set.rb +148 -0
  29. data/lib/rubiks/mondrian/connection.rb +131 -0
  30. data/lib/rubiks/mondrian/errors.rb +56 -0
  31. data/lib/rubiks/mondrian/jars/commons-collections-3.2.jar +0 -0
  32. data/lib/rubiks/mondrian/jars/commons-dbcp-1.2.2.jar +0 -0
  33. data/lib/rubiks/mondrian/jars/commons-logging-1.1.1.jar +0 -0
  34. data/lib/rubiks/mondrian/jars/commons-math-1.2.jar +0 -0
  35. data/lib/rubiks/mondrian/jars/commons-pool-1.4.jar +0 -0
  36. data/lib/rubiks/mondrian/jars/eigenbase-properties-1.1.2.jar +0 -0
  37. data/lib/rubiks/mondrian/jars/eigenbase-resgen-1.3.1.jar +0 -0
  38. data/lib/rubiks/mondrian/jars/eigenbase-xom-1.3.1.jar +0 -0
  39. data/lib/rubiks/mondrian/jars/log4j-1.2.17.jar +0 -0
  40. data/lib/rubiks/mondrian/jars/mondrian-4.0.0-SNAPSHOT.jar +0 -0
  41. data/lib/rubiks/mondrian/jars/olap4j-1.2.0-SNAPSHOT.jar +0 -0
  42. data/lib/rubiks/mondrian/jars/olap4j-xmla-1.2.0-SNAPSHOT.jar +0 -0
  43. data/lib/rubiks/mondrian/jars/olap4j-xmlaserver-0.0.1-SNAPSHOT.jar +0 -0
  44. data/lib/rubiks/mondrian/member.rb +107 -0
  45. data/lib/rubiks/mondrian.rb +44 -0
  46. data/lib/rubiks/named_object.rb +121 -0
  47. data/lib/rubiks/schema.rb +28 -0
  48. data/lib/rubiks/version.rb +1 -1
  49. data/lib/rubiks.rb +28 -4
  50. data/rubiks.gemspec +2 -1
  51. data/spec/examples/simple_mondrian_schema_spec.rb +56 -0
  52. data/spec/rubiks/calculated_measure_spec.rb +12 -0
  53. data/spec/rubiks/cube_spec.rb +29 -0
  54. data/spec/rubiks/dimension_spec.rb +12 -0
  55. data/spec/rubiks/hierarchy_spec.rb +15 -0
  56. data/spec/rubiks/level_spec.rb +20 -0
  57. data/spec/rubiks/measure_spec.rb +11 -0
  58. data/spec/rubiks/schema_spec.rb +32 -0
  59. data/spec/spec_helper.rb +10 -3
  60. data/spec/support/shared_examples.rb +12 -0
  61. metadata +85 -47
  62. data/lib/rubiks/examples.rb +0 -61
  63. data/lib/rubiks/nodes/annotated_node.rb +0 -26
  64. data/lib/rubiks/nodes/calculated_member.rb +0 -81
  65. data/lib/rubiks/nodes/cube.rb +0 -149
  66. data/lib/rubiks/nodes/dimension.rb +0 -72
  67. data/lib/rubiks/nodes/hierarchy.rb +0 -100
  68. data/lib/rubiks/nodes/level.rb +0 -133
  69. data/lib/rubiks/nodes/measure.rb +0 -75
  70. data/lib/rubiks/nodes/schema.rb +0 -72
  71. data/lib/rubiks/nodes/validated_node.rb +0 -79
  72. data/spec/examples/mondrian_docs_example_spec.rb +0 -108
  73. data/spec/examples/simple_mondrian_example_spec.rb +0 -84
  74. data/spec/rubiks/nodes/annotated_node_spec.rb +0 -24
  75. data/spec/rubiks/nodes/calculated_member_spec.rb +0 -50
  76. data/spec/rubiks/nodes/cube_spec.rb +0 -63
  77. data/spec/rubiks/nodes/dimension_spec.rb +0 -41
  78. data/spec/rubiks/nodes/hierarchy_spec.rb +0 -48
  79. data/spec/rubiks/nodes/level_spec.rb +0 -93
  80. data/spec/rubiks/nodes/measure_spec.rb +0 -55
  81. data/spec/rubiks/nodes/schema_spec.rb +0 -38
  82. data/spec/rubiks/nodes/validated_node_spec.rb +0 -49
  83. data/spec/support/examples/mondrian_docs.yml +0 -36
  84. data/spec/support/examples/shared_dimensions.yml +0 -45
  85. data/spec/support/matchers/be_like.rb +0 -24
  86. data/spec/support/schema_context.rb +0 -59
data/CHANGELOG.md CHANGED
@@ -1,26 +1,26 @@
1
- 0.0.6
2
- -----
1
+ ## 0.1.0
2
+ * Remove RLTK
3
+ * Generate Mondrian 3 schema
4
+ * Generate JSON schema
5
+ * Include Mondrian
6
+
7
+ ## 0.0.6
3
8
  * [0.0.6 release](https://github.com/moneydesktop/rubiks/pull/3)
4
9
  * [Nodes deep_dup the input hash in .new_from_hash](https://github.com/moneydesktop/rubiks/commit/81b2d68eddf5551abd0f360aee4c91d237e10c3c)
5
10
 
6
- 0.0.5
7
- -----
11
+ ## 0.0.5
8
12
  * [0.0.5 release](https://github.com/moneydesktop/rubiks/pull/2)
9
13
 
10
- 0.0.4
11
- -----
14
+ ## 0.0.4
12
15
  * [Bump to v0.0.4](https://github.com/moneydesktop/rubiks/commit/38dfd1f82e947f39457670adfdc6ca67da2728c6)
13
16
  * [Add GemVersion badge to README](https://github.com/moneydesktop/rubiks/commit/2d92097c4ba73d92690fab78455fc7db6ed0b3d9)
14
17
 
15
- 0.0.3
16
- -----
18
+ ## 0.0.3
17
19
  * [Bump to v0.0.3](https://github.com/moneydesktop/rubiks/commit/23ceb29936f663605527a12ca2d2a5c623abe99e)
18
20
  * Need to fill in other commits here
19
21
 
20
- 0.0.2
21
- -----
22
+ ## 0.0.2
22
23
  * [Bump to v0.0.2](https://github.com/moneydesktop/rubiks/commit/14a55449be9552268c66cbf8b902af02cf7b73c6)
23
24
 
24
- 0.0.1
25
- -----
25
+ ## 0.0.1
26
26
  * [Initial RubyGem project](https://github.com/moneydesktop/rubiks/commit/fa8be4badf70e86fda7e14bf23f9230a926893d2)
data/Gemfile CHANGED
@@ -12,6 +12,8 @@ group :test do
12
12
  gem 'simplecov', :require => false
13
13
  gem 'rspec'
14
14
  gem 'rspec-pride'
15
+ gem 'equivalent-xml'
16
+ gem 'json_expressions'
15
17
  end
16
18
 
17
19
  group :development do
data/README.md CHANGED
@@ -12,102 +12,120 @@
12
12
  [codeclimate]: https://codeclimate.com/github/moneydesktop/rubiks
13
13
  [coveralls]: https://coveralls.io/r/moneydesktop/rubiks
14
14
 
15
- A gem to allow defining an OLAP schema from a hash and generating an XML schema for Mondrian.
15
+ [jruby]: http://jruby.org
16
+ [wiki_cube]: http://en.wikipedia.org/wiki/OLAP_cube
17
+ [wiki_olap]: http://en.wikipedia.org/wiki/Online_analytical_processing
18
+ [wiki_mdx]: http://en.wikipedia.org/wiki/MultiDimensional_eXpressions
19
+ [wiki_open_source]: http://en.wikipedia.org/wiki/Open-source_software
20
+ [wiki_java]: http://en.wikipedia.org/wiki/Java_(programming_language)
21
+ [wiki_data_warehouse]: http://en.wikipedia.org/wiki/Data_warehouse
22
+ [wiki_star_schema]: http://en.wikipedia.org/wiki/Star_schema
23
+ [wiki_dimensional_modeling]: http://en.wikipedia.org/wiki/Dimensional_modeling
24
+ [postgresql]: http://www.postgresql.org
25
+ [mondrian]: http://mondrian.pentaho.com
26
+ [mondrian_schema]: http://mondrian.pentaho.com/documentation/schema.php
27
+ [rails]: http://rubyonrails.org
16
28
 
17
- ## Installation
29
+ Rubiks is a [Online Analytical Processing](wiki_olap) ( **OLAP** ) library written in [JRuby](jruby).
30
+ It runs on top of [Mondrian](mondrian) (an [Open-source](wiki_open_source) [OLAP](wiki_olap) server
31
+ written in [Java](wiki_java)) and provides the ability to:
18
32
 
19
- Run `gem install rubiks` to install the gem on its own.
20
-
21
- Or you can add the following to your Gemfile and run the `bundle` command to install it.
33
+ * define a [OLAP](wiki_olap) schema in Ruby
34
+ * generate a [Mondrian XML schema](mondrian_schema) from this definition
35
+ * execute [MultiDimensional eXpressions](wiki_mdx) ( **MDX** ) queries against the OLAP server
22
36
 
23
- gem 'rubiks'
24
37
 
25
- ## Examples
38
+ ### Assumptions
26
39
 
27
- This is an example taken from the [Mondrian documentation](http://mondrian.pentaho.com/documentation/schema.php#Cubes_and_dimensions) (then simplified a little and modified to use some Rails/Rubiks conventions)
40
+ * You are using [JRuby](jruby)
41
+ * You are using [PostgreSQL](postgresql)
42
+ * You have designed and populated your [Data Warehouse](wiki_data_warehouse) (see [Dimensional Modeling](wiki_dimensional_modeling) and [Star Schema](wiki_star_schema))
43
+ * You are using [Ruby on Rails](rails) database naming conventions
28
44
 
29
- After installing the gem, fire up an IRB session with `irb` or `bundle exec irb` if you are using Bundler, and follow this (or even paste it into your session):
30
45
 
31
- ```ruby
32
- require 'rubiks/examples'
46
+ ### Installation
33
47
 
34
- md = Rubiks::Examples::MondrianDocs
48
+ Run `gem install rubiks` to install the gem on its own.
35
49
 
36
- md.filename # => "/path/to/rubiks/examples/mondrian_docs.yml"
50
+ Or you can add the following to your Gemfile and run the `bundle` command to install it.
37
51
 
38
- puts md.file_contents # see the YAML section below
52
+ gem 'rubiks'
39
53
 
40
- puts md.to_xml # see the XML section below
41
- ```
42
54
 
43
- The [example YAML file](examples/mondrian_docs.yml) contents are:
44
-
45
- ```yaml
46
- cubes:
47
- - name: sales
48
- dimensions:
49
- - name: date
50
- hierarchies:
51
- - name: year_quarter_month
52
- levels:
53
- - name: year
54
- column: the_year
55
- data_type: numeric
56
-
57
- - name: quarter
58
- data_type: string
59
-
60
- - name: month
61
- column: month_of_year
62
- data_type: Numeric
63
-
64
- measures:
65
- - name: unit_sales
66
- aggregator: sum
67
- format_string: '#,###'
68
-
69
- - name: store_sales
70
- aggregator: sum
71
- format_string: '#,###'
72
-
73
- - name: store_cost
74
- aggregator: sum
75
- format_string: '#,###'
76
-
77
- calculated_members:
78
- - name: profit
79
- dimension: measures
80
- formula: '[Measures].[Store Sales] / [Measures].[Store Cost]'
81
- format_string: '$#,##0.00'
82
- ```
55
+ ### Schema Example
83
56
 
84
- and the generated XML is:
57
+ After installing the gem, fire up an IRB session with `irb` or `bundle exec irb` if you are using Bundler, and follow this (or even paste it into your session):
85
58
 
59
+ ```ruby
60
+ require 'rubiks'
61
+
62
+ schema = ::Rubiks::Schema.define :banking do
63
+ cube :transactions do
64
+ dimension :date, :type => 'TimeDimension' do
65
+ hierarchy :yqmwd, :caption => 'YQMWD' do
66
+ level :year, :level_type => 'TimeYears', :type => :numeric, :contiguous => true
67
+ level :quarter, :level_type => 'TimeQuarters', :type => :numeric, :contiguous => true, :cardinality => :low
68
+ level :month, :level_type => 'TimeMonths', :type => :numeric, :contiguous => true
69
+ level :week, :level_type => 'TimeWeeks', :type => :numeric, :column => :week_of_month, :contiguous => true, :cardinality => :low
70
+ level :day, :level_type => 'TimeDays', :type => :numeric, :contiguous => true
71
+ end
72
+ end
73
+
74
+ dimension :account do
75
+ hierarchy :account_type do
76
+ level :asset_liability, :cardinality => :low
77
+ level :account_type
78
+ end
79
+ end
80
+
81
+ measure :count, :column => :quantity
82
+ measure :amount, :aggregator => :sum, :format_string => '$#,###'
83
+ end
84
+ end
85
+
86
+ puts schema.to_xml
87
+ ```
88
+ You should see this XML:
86
89
 
87
90
  ```xml
88
91
  <?xml version="1.0" encoding="UTF-8"?>
89
- <schema name="default">
90
- <cube name="Sales">
91
- <table name="view_sales"/>
92
- <dimension name="Date" foreignKey="date_id">
93
- <hierarchy name="Year Quarter Month" primaryKey="id" hasAll="true">
92
+ <schema name="Banking">
93
+ <cube name="Transactions">
94
+ <table name="view_transactions"/>
95
+ <dimension name="Date" foreignKey="date_id" type="TimeDimension">
96
+ <hierarchy name="YQMWD" hasAll="true" primaryKey="id">
94
97
  <table name="view_dates"/>
95
- <level name="Year" column="the_year" type="Numeric"/>
96
- <level name="Quarter" column="quarter" type="String"/>
97
- <level name="Month" column="month_of_year" type="Numeric"/>
98
+ <level name="Year" column="year" levelType="TimeYears" type="Numeric"/>
99
+ <level name="Quarter" column="quarter" levelType="TimeQuarters" type="Numeric"/>
100
+ <level name="Month" column="month" levelType="TimeMonths" type="Numeric"/>
101
+ <level name="Week" column="week_of_month" levelType="TimeWeeks" type="Numeric"/>
102
+ <level name="Day" column="day" levelType="TimeDays" type="Numeric"/>
103
+ </hierarchy>
104
+ </dimension>
105
+ <dimension name="Account" foreignKey="account_id">
106
+ <hierarchy name="Account Type" hasAll="true" primaryKey="id">
107
+ <table name="view_accounts"/>
108
+ <level name="Asset Liability" column="asset_liability"/>
109
+ <level name="Account Type" column="account_type"/>
98
110
  </hierarchy>
99
111
  </dimension>
100
- <measure name="Unit Sales" aggregator="sum" formatString="#,###" column="unit_sales"/>
101
- <measure name="Store Sales" aggregator="sum" formatString="#,###" column="store_sales"/>
102
- <measure name="Store Cost" aggregator="sum" formatString="#,###" column="store_cost"/>
103
- <calculatedMember name="Profit" dimension="Measures" formula="[Measures].[Store Sales] / [Measures].[Store Cost]">
104
- <calculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
105
- </calculatedMember>
112
+ <measure name="Count" column="quantity" aggregator="count"/>
113
+ <measure name="Amount" column="amount" aggregator="sum" formatString="$#,###"/>
106
114
  </cube>
107
115
  </schema>
108
116
  ```
109
117
 
110
- ## Contributing
118
+
119
+ ### Similar projects
120
+
121
+ Check out these projects (which have been super helpful in working on Rubiks):
122
+
123
+ * [Mondrian (git)](https://github.com/pentaho/mondrian) - source code for Mondrian on GitHub
124
+ * [mondrian-olap](https://github.com/rsim/mondrian-olap) - a RubyGem wrapping Mondrian
125
+ * [Saiku](http://analytical-labs.com) ([Saiku on GitHub](https://github.com/OSBI/saiku)) - a modular open-source analysis suite offering lightweight OLAP which remains easily embeddable, extendable and configurable.
126
+
127
+
128
+ ### Contributing
111
129
 
112
130
  1. Fork it
113
131
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -0,0 +1,26 @@
1
+ module ::Rubiks
2
+
3
+ class CalculatedMeasure < NamedObject
4
+ def formula(new_value=nil, options={})
5
+ @formula = new_value.to_s if new_value.present?
6
+ @formula ||= @options[:formula]
7
+ end
8
+
9
+ def format_string(new_value=nil, options={})
10
+ @format_string = new_value.to_s if new_value.present?
11
+ @format_string ||= @options[:format_string]
12
+ end
13
+
14
+ def to_xml(builder = nil)
15
+ builder = builder || new_builder
16
+
17
+ xml_attrs = default_xml_attributes
18
+ xml_attrs[:dimension] = 'Measures'
19
+ xml_attrs[:formula] = formula if formula.present?
20
+ xml_attrs[:formatString] = format_string if format_string.present?
21
+
22
+ builder.calculatedMember(xml_attrs)
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,80 @@
1
+ module ::Rubiks
2
+
3
+ class Cube < NamedObject
4
+ def time_dimension(new_value=nil)
5
+ @time_dimension = new_value.to_s if new_value.present?
6
+ @time_dimension ||= @options[:time_dimension]
7
+ end
8
+
9
+ def person_dimension(new_value=nil)
10
+ @person_dimension = new_value.to_s if new_value.present?
11
+ @person_dimension ||= @options[:person_dimension]
12
+ end
13
+
14
+ def count_measure(new_value=nil)
15
+ @count_measure = new_value.to_s if new_value.present?
16
+ @count_measure ||= @options[:count_measure]
17
+ end
18
+
19
+ def person_count_measure(new_value=nil)
20
+ @person_count_measure = new_value.to_s if new_value.present?
21
+ @person_count_measure ||= @options[:person_count_measure]
22
+ end
23
+
24
+ def dimensions
25
+ @dimensions ||= []
26
+ end
27
+
28
+ def dimension(dimension_name, options={}, &block)
29
+ dimensions.push ::Rubiks::Dimension.find_or_create(dimension_name, options, &block)
30
+ end
31
+
32
+ def measures
33
+ @measures ||= []
34
+ end
35
+
36
+ def measure(measure_name, options={}, &block)
37
+ measures.push ::Rubiks::Measure.find_or_create(measure_name, options, &block)
38
+ end
39
+
40
+ def calculated_measures
41
+ @calculated_measures ||= []
42
+ end
43
+
44
+ def calculated_measure(calculated_measure_name, options={}, &block)
45
+ calculated_measures.push ::Rubiks::CalculatedMeasure.find_or_create(calculated_measure_name, options, &block)
46
+ end
47
+
48
+ def json_hash
49
+ hash = default_json_attributes.merge(
50
+ :time_dimension => time_dimension.to_s,
51
+ :person_dimension => person_dimension.to_s,
52
+ :count_measure => count_measure.to_s,
53
+ :person_count_measure => person_count_measure.to_s,
54
+ :dimensions => dimensions.map{ |dim| dim.json_hash },
55
+ :measures => json_measures
56
+ )
57
+ hash.delete_if { |key,value| value.nil? || value.blank? }
58
+ hash.stringify_keys!
59
+ end
60
+
61
+ def to_xml(builder = nil)
62
+ builder = builder || new_builder
63
+
64
+ builder.cube(default_xml_attributes) do
65
+ builder.table(:name => table)
66
+ dimensions.each{ |dimension| dimension.to_xml(builder) }
67
+ measures.each{ |measure| measure.to_xml(builder) }
68
+ calculated_measures.each{ |measure| measure.to_xml(builder) }
69
+ end
70
+ end
71
+
72
+ def json_measures
73
+ json_measures = []
74
+ json_measures.push(*measures.map{ |m| m.json_hash })
75
+ json_measures.push(*calculated_measures.map{ |cm| cm.json_hash })
76
+ json_measures
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,48 @@
1
+ module ::Rubiks
2
+
3
+ class Dimension < NamedObject
4
+ def degenerate(new_value=nil)
5
+ @degenerate = new_value.to_s if new_value.present?
6
+ @degenerate ||= @options[:degenerate]
7
+ end
8
+
9
+ def type(new_value=nil)
10
+ @type = new_value.to_s if new_value.present?
11
+ @type ||= @options[:type]
12
+ end
13
+
14
+ def hierarchies
15
+ @hierarchies ||= []
16
+ end
17
+
18
+ def hierarchy(hierarchy_name, options={}, &block)
19
+ options.merge!(:table => degenerate ? 'degenerate' : self.table)
20
+ hierarchies.push ::Rubiks::Hierarchy.find_or_create(hierarchy_name, options, &block)
21
+ end
22
+
23
+ def json_hash
24
+ hash = default_json_attributes.merge(
25
+ :hierarchies => hierarchies.map{ |hier| hier.json_hash }
26
+ )
27
+ hash[:type] = type.to_s if type.present?
28
+ hash.delete_if { |key,value| value.nil? }
29
+ hash.stringify_keys!
30
+ end
31
+
32
+ def to_xml(builder = nil)
33
+ builder = builder || new_builder
34
+
35
+ xml_attrs = default_xml_attributes
36
+ if self.degenerate
37
+ xml_attrs.delete(:table)
38
+ else
39
+ xml_attrs[:foreignKey] = "#{name}_id"
40
+ end
41
+ xml_attrs[:type] = type if type.present?
42
+ builder.dimension(xml_attrs) do
43
+ hierarchies.each{ |hierarchy| hierarchy.to_xml(builder) }
44
+ end
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,46 @@
1
+ module ::Rubiks
2
+
3
+ class Hierarchy < ::Rubiks::NamedObject
4
+ def levels
5
+ @levels ||= []
6
+ end
7
+
8
+ def level(level_name, options={}, &block)
9
+ levels.push ::Rubiks::Level.find_or_create(level_name, options, &block)
10
+ end
11
+
12
+ def all_member_name(new_value=nil)
13
+ @all_member_name = new_value.to_s if new_value.present?
14
+ @all_member_name ||= true
15
+ end
16
+
17
+ def has_all(new_value=nil)
18
+ @has_all = new_value.to_s if new_value.present?
19
+ @has_all ||= true
20
+ end
21
+
22
+ def json_hash
23
+ hash = default_json_attributes.merge(
24
+ :levels => levels.map{ |lvl| lvl.json_hash }
25
+ )
26
+ hash.delete_if { |key,value| value.nil? }
27
+ hash.stringify_keys!
28
+ end
29
+
30
+ def to_xml(builder = nil)
31
+ builder = builder || new_builder
32
+
33
+ xml_attrs = default_xml_attributes.merge(:hasAll => has_all.to_s)
34
+ xml_attrs[:primaryKey] = 'id' unless degenerate?
35
+ builder.hierarchy(xml_attrs) do
36
+ builder.table(:name => table) unless degenerate?
37
+ levels.each{ |level| level.to_xml(builder) }
38
+ end
39
+ end
40
+
41
+ def degenerate?
42
+ table == 'degenerate'
43
+ end
44
+ end
45
+
46
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,57 @@
1
+ module ::Rubiks
2
+
3
+ class Level < ::Rubiks::NamedObject
4
+ def cardinality(new_value=nil)
5
+ @cardinality = new_value.to_s if new_value.present?
6
+ @cardinality ||= @options[:cardinality]
7
+ end
8
+
9
+ def contiguous(new_value=nil)
10
+ @contiguous = new_value.to_s if new_value.present?
11
+ @contiguous ||= @options.key?(:contiguous) ? @options[:contiguous].to_s : nil
12
+ end
13
+
14
+ def column(new_value=nil)
15
+ @column = new_value.to_s if new_value.present?
16
+ @column ||= @options[:column] || name
17
+ end
18
+
19
+ def name_column(new_value=nil)
20
+ @name_column = new_value.to_s if new_value.present?
21
+ @name_column ||= @options[:name_column]
22
+ end
23
+
24
+ def ordinal_column(new_value=nil)
25
+ @ordinal_column = new_value.to_s if new_value.present?
26
+ @ordinal_column ||= @options[:ordinal_column]
27
+ end
28
+
29
+ def level_type(new_value=nil)
30
+ @level_type = new_value.to_s if new_value.present?
31
+ @level_type ||= @options[:level_type]
32
+ end
33
+
34
+ def type(new_value=nil)
35
+ @type = new_value if new_value.present?
36
+ @type ||= @options[:type]
37
+ end
38
+
39
+ def json_hash
40
+ hash = default_json_attributes
41
+ hash[:cardinality] = cardinality.to_s if cardinality.present?
42
+ hash[:visible] = visible if visible.present? && visible == 'false'
43
+ hash[:contiguous] = contiguous if contiguous.present? && contiguous == 'true'
44
+ hash.stringify_keys!
45
+ end
46
+
47
+ def to_xml(builder = nil)
48
+ builder = builder || new_builder
49
+
50
+ xml_attrs = default_xml_attributes.merge(:column => column)
51
+ xml_attrs[:levelType] = level_type if level_type.present?
52
+ xml_attrs[:type] = type.to_s.capitalize if type.present?
53
+ builder.level(xml_attrs)
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,28 @@
1
+ module ::Rubiks
2
+
3
+ class Measure < ::Rubiks::NamedObject
4
+ def column(new_name=nil, options={})
5
+ @column = new_name.to_s if new_name.present?
6
+ @column ||= @options[:column] || name
7
+ end
8
+
9
+ def aggregator(new_name=nil, options={})
10
+ @aggregator = new_name.to_s if new_name.present?
11
+ @aggregator ||= @options[:aggregator] || 'count'
12
+ end
13
+
14
+ def format_string(new_value=nil, options={})
15
+ @format_string = new_value.to_s if new_value.present?
16
+ @format_string ||= @options[:format_string]
17
+ end
18
+
19
+ def to_xml(builder = nil)
20
+ builder = builder || new_builder
21
+
22
+ xml_attrs = {:name => caption, :column => column, :aggregator => aggregator}
23
+ xml_attrs[:formatString] = format_string if format_string.present?
24
+ builder.measure(xml_attrs)
25
+ end
26
+ end
27
+
28
+ end