<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>OnRails.org: Analyzing the Subversion logs from the Rails project with mx:OLAPCube</title>
    <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <item>
      <title>Analyzing the Subversion logs from the Rails project with mx:OLAPCube</title>
      <description>&lt;p&gt;I started playing with &lt;a href="http://anthonyeden.com"&gt;Anthony Eden&amp;#8217;s&lt;/a&gt; &lt;a href="http://activewarehouse.rubyforge.org/"&gt;ActiveWarehouse&lt;/a&gt; and followed his &lt;a href="http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs"&gt;excellent tutorial&lt;/a&gt; on how to analyze the Ruby On Rails Svn Commit Log with the ActiveWarehouse framework. Of course this made me want to try to do the same with the new mx:OLAPCube and mx:OLAPDataGrid provided by Flex 3 as part of the DataVisualization components. Let me just say this&amp;#8230;I am not done playing with either the Flex OLAPCube nor the Rails ActiveWarehouse framework as these are pretty complex beasts. Both of these frameworks are overlapping and complementary. There are overlapping as both can digest raw data and perform aggregation of that data. They are complementary in the sense that a server side warehouse needs a good visualization front-end. Maybe the OLAPCube and OLAPDataGrid can be this front-end. In my initial trials I haven&amp;#8217;t come up with a compelling way to integrate both, but by using some simple &lt;span class="caps"&gt;SQL I&lt;/span&gt; could extract the data from the ActiveWarehouse and pass it to the OLAPCube.&lt;/p&gt;


	&lt;p&gt;Before going on you may want to read Anthony&amp;#8217;s &lt;a href="http://anthonyeden.com"&gt;blog&lt;/a&gt; and check his presentation  on &lt;a href="anthonyeden.com/assets/2007/5/20/activewarehouse.pdf"&gt;Data Warehouses with ActiveWarehouse&lt;/a&gt;. I didn&amp;#8217;t find much information on the Flex OLAPCube besides these: &lt;a href="http://labs.adobe.com/wiki/index.php/Flex_3:Feature_Introductions:_OLAPDataGrid"&gt;Feature_Introductions:_OLAPDataGrid on Adobe&amp;#8217;s labs&lt;/a&gt;,  &lt;a href="http://labs.adobe.com/technologies/flex/videos/olap/"&gt;Flex 3: Feature Introduction Video for &lt;span class="caps"&gt;OLAP&lt;/span&gt; Support&lt;/a&gt;, and these &lt;a href="http://download.macromedia.com/pub/labs/flex/3/featuresamples/olapsamples_beta2.zip"&gt;Flex examples&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;So I create the following sample application. You can try it out &lt;a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank"&gt;here&lt;/a&gt;. Note it&amp;#8217;s pretty slow, it takes up to a minute to aggregate 10000 values. The Flex team mentioned they didn&amp;#8217;t optimize this component yet. I can confirm this. But I may also have messed something up as these are only my initial steps with that component. The application displays the Author dimension with the Author Name as rows and the Time dimension with the Year and Quarter as columns. The facts is the File Change count during that period. Flex calls the &amp;#8220;facts&amp;#8221; a measure. 
&lt;br/&gt;
&lt;img src="http://onrails.org/files/20071128_OLAPCube.jpg" alt="20071128_OLAPCube.jpg" border="0" width="495" /&gt;
&lt;br/&gt;
&lt;a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank"&gt;Run the applicaiton&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;To extract the data from the ActiveWarehouse I created this &lt;span class="caps"&gt;SQL&lt;/span&gt; to join the facts table with all the dimensions table. I need to find out if the ActiveWarehouse doesn&amp;#8217;t just return this data in xml format by using it&amp;#8217;s build-in classes.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;report_as_xml&lt;/span&gt;
    &lt;span class="ident"&gt;sql&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="constant"&gt;EOSQL&lt;/span&gt;&lt;span class="string"&gt;
    SELECT
     date.calendar_year,
     date.calendar_quarter,
     date.calendar_month_name,
     author.name,
     file_revision_facts.file_changed AS `file_changed`
    FROM
     file_revision_facts
    JOIN date_dimension as date
     ON file_revision_facts.date_id = date.id
    JOIN author_dimension as author
     ON file_revision_facts.author_id = author.id
    WHERE 
      date.calendar_year &amp;gt; '2005'
&lt;/span&gt;&lt;span class="constant"&gt;    EOSQL&lt;/span&gt;

    &lt;span class="attribute"&gt;@@xml&lt;/span&gt; &lt;span class="punct"&gt;||=&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connection&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select_all&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sql&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_xml&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:dasherize&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="symbol"&gt;:text&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@@xml&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In Flex the OLAPCube can be loaded with the &lt;span class="caps"&gt;XML&lt;/span&gt;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    var data:ICollectionView = new ArrayCollection(result.records.record); // is Array
    cube.dataProvider = data;
    cube.addEventListener(CubeEvent.CUBE_COMPLETE, creationCompleteHandler);
    cube.refresh();        &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Once the cube is loaded you can slice and dice it in many ways by using an OLAPQuery. I still need to figure out all the possibilities which are offered.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    [Bindable]
    private var cubeResult:IOLAPResult;

    private function creationCompleteHandler(event:CubeEvent):void
    {
        //Cube was created, let's query it
        var query:OLAPQuery = new OLAPQuery;

        // TIME DIMENSION            
        var yearSet:IOLAPSet = new OLAPSet;
        yearSet.addElements(cube.findDimension(&amp;quot;Time&amp;quot;).findAttribute(&amp;quot;Year&amp;quot;).members);

        var quarterSet:IOLAPSet = new OLAPSet;
        quarterSet.addElements(cube.findDimension(&amp;quot;Time&amp;quot;).findAttribute(&amp;quot;Quarter&amp;quot;).members);

        //year-quarter
        var newTimeSet:IOLAPSet = yearSet.crossJoin(quarterSet);

        // AUTHOR    DIMENSION    
        var authorSet:IOLAPSet = new OLAPSet;
        authorSet.addElements(cube.findDimension(&amp;quot;Author&amp;quot;).findAttribute(&amp;quot;Name&amp;quot;).members);

        // ROW/COLUMNS        
        var rowAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.ROW_AXIS);
        rowAxis.addSet(authorSet.hierarchize(true));
        var colAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.COLUMN_AXIS);
        colAxis.addSet(newTimeSet.hierarchize(true));

        // QUERY CUBE
        var token:AsyncToken = cube.execute(query);
       token.addResponder(new AsyncResponder(displayResult, olapFaultHandler));
    }
    private function displayResult(result:Object, token:Object=null):void
    {
        cubeResult = result as IOLAPResult;
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The cube result is the dataProvider of the Cube which in it&amp;#8217;s simplests form can be defined as follows:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;mx:OLAPDataGrid id=&amp;quot;olapGrid&amp;quot; dataProvider=&amp;quot;{cubeResult}&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;ve then added a change listener for the grid to create the dataProvider for the ColumnChart.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    [Bindable]
    private var chartData:Array;

    private function gridSelectionChanged():void {
        if (!(olapGrid.selectedItem is OLAPAxisPosition)) return;
        var rowIndex:Number = olapGrid.selectedIndex;
        var axis:IOLAPQueryAxis = cubeResult.query.getAxis(OLAPQuery.COLUMN_AXIS);
        var columnLength:Number = cubeResult.getAxis(OLAPQuery.COLUMN_AXIS).positions.length;
        var newChartData:Array = [];
        for (var i:int=0;i&amp;lt;columnLength;i++) {
            var tuple:OLAPTuple = axis.tuples[i];
            var key:String = tuple.explicitMembers.toArray().join(&amp;quot;,&amp;quot;);
            if (key.indexOf(&amp;quot;(All)&amp;quot;) &amp;gt; -1) continue;            newChartData.push({key:key, value:cubeResult.getCell(rowIndex, i).value});
        }
        chartData = newChartData;
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

This code to extract a time serie for the chart is a little &amp;#8220;hairy&amp;#8221;. I hope the Flex team has some OLAPCharts on their todo list ;-)&lt;br/&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;mx:ColumnChart id=&amp;quot;chart&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;30%&amp;quot; dataProvider=&amp;quot;{chartData}&amp;quot;&amp;gt;
        &amp;lt;mx:series&amp;gt;
            &amp;lt;mx:ColumnSeries yField=&amp;quot;value&amp;quot; /&amp;gt;
        &amp;lt;/mx:series&amp;gt;
        &amp;lt;mx:horizontalAxis&amp;gt;
            &amp;lt;mx:CategoryAxis categoryField=&amp;quot;key&amp;quot; /&amp;gt;
        &amp;lt;/mx:horizontalAxis&amp;gt;
&amp;lt;/mx:ColumnChart&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;This are my first tribulations with both frameworks. Over the next few month I will have to dive more deeply into the possibilities which are offered. Thanks to both teams as this is pretty cool.&lt;/p&gt;


	&lt;p&gt;Enjoy!
Daniel.&lt;/p&gt;</description>
      <pubDate>Thu, 29 Nov 2007 05:23:34 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e8079876-729e-419c-93c8-50194b7026d5</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube</link>
      <category>Flex</category>
    </item>
    <item>
      <title>"Analyzing the Subversion logs from the Rails project with mx:OLAPCube" by Daniel Wanja</title>
      <description>&lt;p&gt;Ideally there would be an OLAPChart or OLAPChartDataProvider to feed the same data to the OLAPGrid and chart, but right now you need to do some marshaling.&lt;/p&gt;</description>
      <pubDate>Mon, 21 Jul 2008 14:17:02 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:71f83747-a078-4737-a76c-b11719ec7c87</guid>
      <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube#comment-3861</link>
    </item>
    <item>
      <title>"Analyzing the Subversion logs from the Rails project with mx:OLAPCube" by Daniel Wanja</title>
      <description>&lt;p&gt;Hi Ram,&lt;/p&gt;


	&lt;p&gt;Shoot me an email to daniel[at]onrails.org I&amp;#8217;ll send you the source code. I mostly use FlexBuilder so if you have a later beta version than 2, I can try that out. Now my question is&amp;#8230;what bug do you want me to file? Missing facilities to bind grid to chart? I could add a couple of more issues, like selecting rows, columns, and cells. Selecting using a tuple or parital tuple..many more use cases. But the Cube is pretty cool&amp;#8230;looking forward for the next version.&lt;/p&gt;</description>
      <pubDate>Fri, 30 Nov 2007 02:09:37 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:5bc4bae9-8ac2-4a60-9ed8-b8c72b7b2e27</guid>
      <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube#comment-2923</link>
    </item>
    <item>
      <title>"Analyzing the Subversion logs from the Rails project with mx:OLAPCube" by Ram</title>
      <description>&lt;p&gt;Hi,
This is a very interesting use case indeed! Flexteam has been building working on a few samples that should make it much more easier for you to consume OLAP data in charts which we hope to post some time in the near future. We have also improved the query performance since the last beta and would like to run your sample to see the current performance. Could you log a bug here for us to track?
&lt;a href="http://bugs.adobe/flex/"&gt;http://bugs.adobe/flex/&lt;/a&gt;
(Flex Data visualization components project)&lt;/p&gt;


	&lt;p&gt;Cheers
Ram&lt;/p&gt;</description>
      <pubDate>Fri, 30 Nov 2007 01:58:52 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:dee68151-0726-41b4-a171-e6dc3d5014e5</guid>
      <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube#comment-2921</link>
    </item>
  </channel>
</rss>
