rubiks 0.0.6 → 0.1.0

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 (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