You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2016/12/16 08:07:02 UTC

[01/14] kylin git commit: KYLIN 1875 minor, data model designer [Forced Update!]

Repository: kylin
Updated Branches:
  refs/heads/KYLIN-2283 aab00c0d1 -> e79626e7c (forced update)


KYLIN 1875 minor,data model designer

Signed-off-by: Li Yang <li...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/1c2c43cb
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/1c2c43cb
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/1c2c43cb

Branch: refs/heads/KYLIN-2283
Commit: 1c2c43cb88d2abc5a1ea1cbf18cbede02fe8c4f5
Parents: f55cc5c
Author: chenzhx <34...@qq.com>
Authored: Thu Dec 15 17:45:13 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeAdvanceSetting.js |  2 -
 webapp/app/js/controllers/cubeEdit.js           | 12 +++++
 webapp/app/js/controllers/modelDataModel.js     | 47 ++++++--------------
 webapp/app/js/controllers/modelEdit.js          | 22 ++++++++-
 .../modelDesigner/conditions_settings.html      |  4 +-
 .../app/partials/modelDesigner/data_model.html  | 24 +++++-----
 6 files changed, 63 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/js/controllers/cubeAdvanceSetting.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeAdvanceSetting.js b/webapp/app/js/controllers/cubeAdvanceSetting.js
index e557afa..20af908 100644
--- a/webapp/app/js/controllers/cubeAdvanceSetting.js
+++ b/webapp/app/js/controllers/cubeAdvanceSetting.js
@@ -160,7 +160,6 @@ KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfi
     if (aggregation_group) {
       list[index] = aggregation_group;
     }
-    console.log($scope.cubeMetaFrame.aggregation_groups);
   };
 
   $scope.refreshAggregationJoint = function (list, index, aggregation_group,joinIndex,jointDim){
@@ -170,7 +169,6 @@ KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfi
     if (aggregation_group) {
       list[index] = aggregation_group;
     }
-    console.log($scope.cubeMetaFrame.aggregation_groups);
   };
 
   $scope.refreshIncludes = function (list, index, aggregation_groups) {

http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index d58f08f..a2b38f9 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -328,6 +328,18 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         if (!modelsManager.getModels().length) {
           ModelDescService.query({model_name: $scope.cubeMetaFrame.model_name}, function (_model) {
             $scope.metaModel.model = _model;
+            var rootFactTable = VdmUtil.removeNameSpace($scope.metaModel.model.fact_table);
+            $scope.aliasName.push(rootFactTable);
+            $scope.aliasTableMap[rootFactTable]=$scope.metaModel.model.fact_table;
+            $scope.tableAliasMap[$scope.metaModel.model.fact_table]=rootFactTable;
+            angular.forEach($scope.metaModel.model.lookups,function(joinTable){
+              if(!joinTable.alias){
+                joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
+              }
+              $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+              $scope.tableAliasMap[joinTable.table]=joinTable.alias;
+              $scope.aliasName.push(joinTable.alias);
+            });
           });
         }
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);

http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/js/controllers/modelDataModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDataModel.js b/webapp/app/js/controllers/modelDataModel.js
index b6edd43..3834e06 100644
--- a/webapp/app/js/controllers/modelDataModel.js
+++ b/webapp/app/js/controllers/modelDataModel.js
@@ -20,26 +20,13 @@
 
 KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager,VdmUtil) {
     $scope.modelsManager = modelsManager;
+    $scope.VdmUtil = VdmUtil;
     angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
       if(!joinTable.alias){
         joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
       }
     });
-    $scope.init = function (){
-      $scope.FactTable={root:$scope.modelsManager.selectedModel.fact_table};
-      $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
-      $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table]=VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table);
-      $scope.aliasName.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
-      angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
-        $scope.aliasTableMap[joinTable.alias]=joinTable.table;
-        $scope.tableAliasMap[joinTable.table]=joinTable.alias;
-        $scope.aliasName.push(joinTable.alias);
-      });
-    }
-    if($scope.state.mode=='edit'){
-      $scope.init();
-    }
-
+    $scope.FactTable={root:$scope.modelsManager.selectedModel.fact_table};
     $scope.cubeConfig = cubeConfig;
     var DataModel = function () {
         return {
@@ -134,13 +121,11 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
         $scope.tableAliasMap[$scope.newLookup.table]=$scope.newLookup.alias;
         $scope.aliasName.push($scope.newLookup.alias);
         lookupList.push(angular.copy($scope.newLookup));
-
         $scope.resetParams();
     };
 
     $scope.doneEditLookup = function () {
         // Copy edited model to destination model.
-        angular.copy($scope.newLookup, lookupList[$scope.lookupState.editingIndex]);
         var oldAlias=$scope.aliasName[$scope.lookupState.editingIndex+1];
         var newAlias=$scope.newLookup.alias;
         if(oldAlias!=newAlias){
@@ -168,7 +153,9 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
             for(var i=0;i< modelsManager.selectedModel.metrics.length;i++){
                modelsManager.selectedModel.metrics[i]= modelsManager.selectedModel.metrics[i].replace(oldAlias+'.',newAlias+'.');
             }
-            modelsManager.selectedModel.partition_desc.partition_date_column = modelsManager.selectedModel.partition_desc.partition_date_column.replace(oldAlias+'.',newAlias+'.');
+            if(modelsManager.selectedModel.partition_desc.partition_date_column){
+              modelsManager.selectedModel.partition_desc.partition_date_column = modelsManager.selectedModel.partition_desc.partition_date_column.replace(oldAlias+'.',newAlias+'.');
+            }
           }
         }
         angular.copy($scope.newLookup,lookupList[$scope.lookupState.editingIndex]);
@@ -176,19 +163,21 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
         $scope.resetParams();
     };
     $scope.changeFactTable = function () {
-        $scope.aliasTableMap={};
+        if(!$scope.FactTable){
+         return;
+        }
         $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.FactTable.root)]=$scope.FactTable.root;
-        $scope.tableAliasMap={};
         $scope.tableAliasMap[$scope.FactTable.root]=VdmUtil.removeNameSpace($scope.FactTable.root);
-        $scope.aliasName=[VdmUtil.removeNameSpace($scope.FactTable.root)];
-        modelsManager.selectedModel.lookups = [];
-        modelsManager.selectedModel.dimensions = [];
-        modelsManager.selectedModel.metrics= [];
+        $scope.aliasName.splice(0,$scope.aliasName.length);
+        $scope.aliasName.push(VdmUtil.removeNameSpace($scope.FactTable.root));
+        modelsManager.selectedModel.lookups.splice(0,modelsManager.selectedModel.lookups.length);
+        modelsManager.selectedModel.dimensions.splice(0,modelsManager.selectedModel.dimensions.length);
+        modelsManager.selectedModel.metrics.splice(0,modelsManager.selectedModel.metrics.length);
         modelsManager.selectedModel.partition_desc.partition_date_column = null;
         $scope.modelsManager.selectedModel.fact_table=$scope.FactTable.root;
     }
     $scope.changeJoinTable = function () {
-        $scope.newLookup.alias=$scope.newLookup.table;
+        $scope.newLookup.alias=VdmUtil.removeNameSpace($scope.newLookup.table);
     }
     $scope.cancelLookup = function () {
         $scope.resetParams();
@@ -221,8 +210,6 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
             lookupList.splice(lookupList.indexOf(lookup), 1);
         }
     };
-    $scope.changeAlias = function (){
-    }
 
     $scope.changeKey = function(index){
          var join_table = $scope.newLookup.joinTable;
@@ -297,10 +284,4 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     $scope.filterNotRoot = function (item) {
       return item.name!==modelsManager.selectedModel.fact_table;
     };
-/*    $scope.$watch('$scope.newLookup.alias', function (newValue, oldValue) {
-      if (newValue&&$scope.lookupState.editing ) {
-        console.log(newValue);
-        console.log(oldValue);
-      }
-    });*/
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index fd78d03..c504b52 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -25,6 +25,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     $scope.tableAliasMap={};
     $scope.aliasTableMap={};
     $scope.aliasName=[];
+    $scope.selectedAliasCubeMap={};
     $scope.route={params:$routeParams.modelName};
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
 
@@ -93,8 +94,27 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
       ModelDescService.query({model_name: modelName}, function (model) {
         if (model) {
           modelsManager.selectedModel = model;
+          $scope.FactTable={root:$scope.modelsManager.selectedModel.fact_table};
+          $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
+          $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table]=VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table);
+          $scope.aliasName.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
+          angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
+            $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+            $scope.tableAliasMap[joinTable.table]=joinTable.alias;
+            $scope.aliasName.push(joinTable.alias);
+          });
           CubeService.list({modelName:model.name}, function (_cubes) {
-              $scope.cubesLength = _cubes.length;
+            $scope.cubesLength = _cubes.length;
+            angular.forEach(_cubes,function(cube){
+              CubeDescService.query({cube_name:cube.name},{},function(each){
+                angular.forEach(each[0].dimensions,function(dimension){
+                  $scope.selectedAliasCubeMap[dimension.table]=true;
+                });
+                angular.forEach(each[0].measures,function(measure){
+                  $scope.selectedAliasCubeMap[VdmUtil.getNameSpaceAliasName(measure.function.parameter.value)]=true;
+                });
+              })
+            });
           });
           modelsManager.selectedModel.project = ProjectModel.getProjectByCubeModel(modelName);
           if(!ProjectModel.getSelectedProject()){

http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/partials/modelDesigner/conditions_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/conditions_settings.html b/webapp/app/partials/modelDesigner/conditions_settings.html
index 6820b60..30fcb67 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -27,14 +27,14 @@
               <div class="row middle-popover">
                   <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b> <i kylinpopover placement="right" title="Partition Date Column" template="partitionTip.html" class="fa fa-info-circle"></i></label>
                   <div class="col-xs-12 col-sm-6" ng-if="state.mode=='edit'">
-                      <select style="width: 45%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
+                      <select style="width: 49%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
                               ng-model="selectedTables.fact"
                               data-placement=""
                               ng-options="alias as alias for alias in availableFactTables" >
                           <option value="">--Select Partition Table--</option>
                       </select>
 
-                      <select style="width: 45%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
+                      <select style="width: 49%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
                             ng-model="modelsManager.selectedModel.partition_desc.partition_date_column"
                             ng-change="partitionChange(modelsManager.selectedModel.partition_desc.partition_date_column)"
                             data-placement=""

http://git-wip-us.apache.org/repos/asf/kylin/blob/1c2c43cb/webapp/app/partials/modelDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/data_model.html b/webapp/app/partials/modelDesigner/data_model.html
index e032cf9..97d3c51 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -27,7 +27,7 @@
             </label>
             <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.table_name.$invalid && (forms.data_model_form.table_name.$dirty||forms.data_model_form.$submitted)}">
               <select chosen ng-model="FactTable.root" ng-if="state.mode=='edit'"
-                      ng-options="table.name as table.name for table in tableModel.selectProjectTables"
+                      ng-options="table.name as VdmUtil.removeNameSpace(table.name) for table in tableModel.selectProjectTables"
                       style="width:100%;" ng-change="changeFactTable()"
                       name="table_name"   ng-disabled="cubesLength>0"
                       ng-required="true"
@@ -35,7 +35,7 @@
                       class="chosen-select">
                 <option value=""> -- Select Fact Table -- </option>
               </select>
-              <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.fact_table}}</span>
+              <span ng-if="state.mode=='view'">{{VdmUtil.removeNameSpace(modelsManager.selectedModel.fact_table)}}</span>
             </div>
         </div>
     </div>
@@ -67,7 +67,7 @@
                 <th>Table Kind</th>
                 <th>Join Type</th>
                 <th>Join Condition</th>
-                <th ng-if="state.mode=='edit'">Actions</th>
+                <th ng-if="state.mode=='edit'" class="col-xs-1">Actions</th>
             </tr>
             </thead>
             <tbody>
@@ -98,13 +98,14 @@
                 </td>
                 <td ng-if="state.mode=='edit'">
                     <!-- edit button -->
-                    <button class="btn btn-xs btn-info" ng-disabled="lookupState.editing||cubesLength>0"
+                    <button class="btn btn-xs btn-info" ng-disabled="lookupState.editing||selectedAliasCubeMap[lookup.alias]"
                             ng-click="editLookup(lookup)" ><i class="fa fa-pencil"></i>
                     </button>
                     <!-- remove button -->
-                    <button class="btn btn-xs btn-danger" ng-disabled="lookupState.editing||cubesLength>0"
+                    <button class="btn btn-xs btn-danger" ng-disabled="lookupState.editing||selectedAliasCubeMap[lookup.alias]"
                             ng-click="removeLookup(lookup)" ><i class="fa fa-trash-o"></i>
                     </button>
+                  <i class="fa fa-info-circle" ng-if="selectedAliasCubeMap[lookup.alias]" kylinpopover placement="left" title="Tip" template="tableInUse.html"></i>
                 </td>
             </tr>
             </tbody>
@@ -115,7 +116,7 @@
     <!-- Add Join Table Form -->
     <script type="text/ng-template" id="dataModelLookupTable.html">
         <div class="modal-header">
-            <h4 class="box-title lighter">{{lookupState.editing ? 'Edit' : 'Add'}} Lookup</h4>
+            <h4 class="box-title lighter">{{lookupState.editing ? 'Edit' : 'Add'}} Join Table</h4>
         </div>
         <div class="modal-body">
             <div class="row">
@@ -136,7 +137,7 @@
                               <small class="help-block" ng-show="lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)">Table name required</small>
                               <b>&nbsp;&nbsp;&nbsp;</b>
                               <select chosen ng-model="newLookup.table" style="width: 45%"
-                                      ng-options="table.name as table.name for table in tableModel.selectProjectTables|filter:filterNotRoot"
+                                      ng-options="table.name as VdmUtil.removeNameSpace(table.name) for table in tableModel.selectProjectTables|filter:filterNotRoot"
                                       name="table_name"  ng-disabled="lookupState.editing"
                                       ng-required="true"  ng-change="changeJoinTable()"
                                       data-placeholder="Join Table Name"
@@ -155,7 +156,7 @@
                             <label class="col-sm-3 control-label font-color-default"><b>Alias</b></label>
                             <div class="col-sm-6">
                               <input type="text" class="form-control " name="joinTable_alias" placeholder="Input Table Alias" ng-required="true"
-                                     ng-model="newLookup.alias" ng-change="changeAlias()"  ng-pattern="/^\w+$/">
+                                     ng-model="newLookup.alias"  ng-pattern="/^\w+$/">
                               <small class="help-block red" ng-show="!lookup_form.joinTable_alias.$error.required&&lookup_form.joinTable_alias.$invalid && (lookup_form.joinTable_alias.$dirty||lookup_form.$submitted)"><i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp; Alias is invalid.</small>
                             </div>
                         </div>
@@ -186,13 +187,13 @@
                             <div class="col-xs-9">
                                 <div ng-repeat="joinIndex in [] | range: newLookup.join.primary_key.length">
                                     <div>
-                                        <select style="width: 45%" chosen data-placeholder="Fact Table Column"
+                                        <select style="width: 45%" chosen data-placeholder="JoinTable Column"
                                                 ng-model="newLookup.join.foreign_key[$index]"  ng-change="changeKey($index)"
                                                 ng-options="newLookup.joinTable+'.'+columns.name as columns.name for columns in getColumnsByAlias(newLookup.joinTable)" >
                                             <option value=""></option>
                                         </select>
                                         <b>=</b>
-                                        <select style="width: 45%" chosen data-placeholder="Lookup Table Column"
+                                        <select style="width: 45%" chosen data-placeholder=" JoinTable Column"
                                                 ng-model="newLookup.join.primary_key[$index]"  ng-change="changeKey($index)"
                                                 ng-options="newLookup.alias+'.'+columns.name as columns.name for columns in getColumnsByTable(newLookup.table)" >
                                             <option value=""></option>
@@ -249,3 +250,6 @@
         </div>
     </script>
 </div>
+<script type="text/ng-template" id="tableInUse.html">
+  <p>This table is in use in Cube.</p>
+</script>


[09/14] kylin git commit: KYLIN 1875 update cube designer

Posted by li...@apache.org.
KYLIN 1875 update cube designer

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/a9230473
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/a9230473
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/a9230473

Branch: refs/heads/KYLIN-2283
Commit: a9230473e3c3bad774f930ad90f4479dcbe34fa0
Parents: 076fbcf
Author: chenzhx <34...@qq.com>
Authored: Tue Dec 13 15:32:54 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeAdvanceSetting.js |  5 --
 webapp/app/js/controllers/cubeDimensions.js     | 75 ++++++++++----------
 webapp/app/js/controllers/cubeEdit.js           | 60 +++++++++-------
 webapp/app/js/controllers/cubeMeasures.js       | 21 +-----
 webapp/app/js/controllers/modelDataModel.js     | 11 ++-
 .../cubeDesigner/advanced_settings.html         |  3 +-
 .../app/partials/cubeDesigner/dimensions.html   | 46 ++++--------
 webapp/app/partials/cubeDesigner/measures.html  |  7 +-
 8 files changed, 104 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/js/controllers/cubeAdvanceSetting.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeAdvanceSetting.js b/webapp/app/js/controllers/cubeAdvanceSetting.js
index 8192419..e557afa 100644
--- a/webapp/app/js/controllers/cubeAdvanceSetting.js
+++ b/webapp/app/js/controllers/cubeAdvanceSetting.js
@@ -38,12 +38,7 @@ KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfi
   //rowkey
   $scope.convertedRowkeys = [];
   angular.forEach($scope.cubeMetaFrame.rowkey.rowkey_columns,function(item){
-    //var _isDictionaries = item.encoding === "dict"?"true":"false";
-    //var version=$scope.getTypeVersion(encoding);
     item.encoding=$scope.removeVersion(item.encoding);
-    //var _isFixedLength = item.encoding.substring(0,12) === "fixed_length"?"true":"false";//fixed_length:12
-    //var _isIntegerLength = item.encoding.substring(0,7) === "integer"?"true":"false";
-    //var _isIntLength = item.encoding.substring(0,3) === "int"?"true":"false";
     var _encoding = item.encoding;
     var _valueLength ;
     var baseKey=item.encoding.replace(/:\d+/,'');

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index 7cb850b..e2787a5 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cubesManager,SweetAlert) {
+KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cubesManager,SweetAlert, VdmUtil) {
 
     $scope.cubeManager = cubesManager;
     // Available columns list derived from cube data model.
@@ -27,10 +27,6 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
     // Columns selected and disabled status bound to UI, group by table.
     $scope.selectedColumns = {};
 
-    // Available tables cache: 1st is the fact table, next are lookup tables.
-    $scope.availableTables = [];
-
-
     /**
      * Helper func to get columns that dimensions based on, three cases:
      * 1. normal dimension: column array.
@@ -40,17 +36,10 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
     var dimCols = function (dim) {
         var referredCols = [];
 
-        // Case 3.
         if (dim.derived && dim.derived.length) {
             referredCols = referredCols.concat(dim.derived);
         }
 
-        // Case 2.
-        //if (dim.hierarchy && dim.column.length) {
-        //    referredCols = referredCols.concat(dim.column);
-        //}
-
-        // Case 1.
         if (!dim.derived && dim.column) {
             referredCols.push(dim.column);
         }
@@ -60,52 +49,66 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
 
     // Dump available columns plus column table name, whether is from lookup table.
     $scope.initColumns = function () {
-        var factTable = $scope.metaModel.model.fact_table;
 
+        var rootFactTable = VdmUtil.removeNameSpace($scope.metaModel.model.fact_table);
+
+        if($scope.aliasName.length==0){
+          $scope.aliasName.push(rootFactTable);
+          $scope.aliasTableMap[rootFactTable]=$scope.metaModel.model.fact_table;
+          $scope.tableAliasMap[$scope.metaModel.model.fact_table]=rootFactTable;
+          angular.forEach($scope.metaModel.model.lookups,function(joinTable){
+            if(!joinTable.alias){
+              joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
+            }
+            $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+            $scope.tableAliasMap[joinTable.table]=joinTable.alias;
+            $scope.aliasName.push(joinTable.alias);
+          });
+        }
         // At first dump the columns of fact table.
-//        var cols = $scope.getColumnsByTable(factTable);
-        var cols = $scope.getDimColumnsByTable(factTable);
+
+        var cols = $scope.getDimColumnsByAlias(rootFactTable);
 
         // Initialize selected available.
         var factSelectAvailable = {};
 
         for (var i = 0; i < cols.length; i++) {
-            cols[i].table = factTable;
-            cols[i].isLookup = false;
+            cols[i].table = rootFactTable;
 
             // Default not selected and not disabled.
             factSelectAvailable[cols[i].name] = {name:cols[i].name ,selected: false};
 
         }
 
-        $scope.availableColumns[factTable] = cols;
+        $scope.availableColumns[rootFactTable] = cols;
         factSelectAvailable.all=false;
-        $scope.selectedColumns[factTable] = factSelectAvailable;
-        $scope.availableTables.push(factTable);
-
+        $scope.selectedColumns[rootFactTable] = factSelectAvailable;
+//        $scope.availableTables.push(rootFactTable);
+        $scope.availableFactTables.push(rootFactTable);
         // Then dump each lookup tables.
         var lookups = $scope.metaModel.model.lookups;
 
         for (var j = 0; j < lookups.length; j++) {
-            var cols2 = $scope.getDimColumnsByTable(lookups[j].table);
+            if(lookups[j].kind=="FACT"){
+                $scope.availableFactTables.push(lookups[j].alias);
+            }else{
+                $scope.availableLookupTables.push(lookups[j].alias);
+            }
+            var cols2 = $scope.getDimColumnsByAlias(lookups[j].alias);
 
             // Initialize selected available.
             var lookupSelectAvailable = {};
 
             for (var k = 0; k < cols2.length; k++) {
-                cols2[k].table = lookups[j].table;
-                cols2[k].isLookup = true;
+                cols2[k].table = lookups[j].alias;
 
                 // Default not selected and not disabled.
                 lookupSelectAvailable[cols2[k].name] = {name:cols2[k].name,selected: false};
             }
 
-            $scope.availableColumns[lookups[j].table] = cols2;
+            $scope.availableColumns[lookups[j].alias] = cols2;
             lookupSelectAvailable.all=false;
-            $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
-            if($scope.availableTables.indexOf(lookups[j].table)==-1){
-                $scope.availableTables.push(lookups[j].table);
-            }
+            $scope.selectedColumns[lookups[j].alias] = lookupSelectAvailable;
         }
     };
 
@@ -178,10 +181,6 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
             types.push('derived');
         }
 
-        //if (dim.hierarchy && dim.column.length) {
-        //    types.push('hierarchy');
-        //}
-
         if (!types.length) {
             types.push('normal');
         }
@@ -259,7 +258,6 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
                 errorInfo+="\n"+item;
             });
             if(errors.length){
-//                SweetAlert.swal('Warning!', errorInfo, '');
                 SweetAlert.swal('', errorInfo, 'warning');
                 return false;
             }else{
@@ -384,7 +382,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
         var selectedCols = $scope.getSelectedCols();
         dimList=[];
         angular.forEach(selectedCols, function (cols, table) {
-            if ($scope.metaModel.model.fact_table == table) {
+            if ($scope.availableFactTables.indexOf(table)!=-1) {
                 // Fact table: for each selected column, create one normal dimension.
                 for (var i = 0; i < cols.length; i++) {
                     dimList.push(Dimension(cols[i].name, table, [cols[i].col], 'normal'));
@@ -404,8 +402,8 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
 
     };
 
-    $scope.autoChange= function(table,name){
-         if($scope.metaModel.model.fact_table==table){
+    $scope.autoChange = function(table,name){
+         if($scope.availableFactTables.indexOf(table)!=-1){
                if($scope.selectedColumns[table][name].selected==false){
                     $scope.selectedColumns[table].all=false;
                }else{
@@ -437,8 +435,9 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cub
               }
          }
     }
+
     $scope.autoChangeAll= function(table){
-         if($scope.metaModel.model.fact_table==table){
+         if($scope.availableFactTables.indexOf(table)!=-1){
               if($scope.selectedColumns[table].all==true){
                    angular.forEach($scope.selectedColumns[table],function(col){
                         if(typeof col==="object"){

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index b901e48..d58f08f 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -22,6 +22,11 @@
 KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert, $log, cubeConfig, CubeDescModel, MetaModel, TableModel, ModelDescService, modelsManager, cubesManager, ProjectModel, StreamingModel, StreamingService,VdmUtil) {
   $scope.cubeConfig = cubeConfig;
   $scope.metaModel = {};
+  $scope.tableAliasMap={};
+  $scope.aliasTableMap={};
+  $scope.aliasName=[];
+  $scope.availableFactTables = [];
+  $scope.availableLookupTables = [];
   $scope.modelsManager = modelsManager;
 
   //add or edit ?
@@ -112,7 +117,15 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     }
     return filterEncoding;
   }
-
+  $scope.getColumnsByAlias = function (alias) {
+    var temp = [];
+    angular.forEach(TableModel.selectProjectTables, function (table) {
+      if (table.name == $scope.aliasTableMap[alias]) {
+        temp = table.columns;
+      }
+    });
+    return temp;
+  };
   $scope.getColumnsByTable = function (tableName) {
     var temp = [];
     angular.forEach(TableModel.selectProjectTables, function (table) {
@@ -124,13 +137,13 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
   };
 
   //get columns from model
-  $scope.getDimColumnsByTable = function (tableName) {
-    if (!tableName) {
+  $scope.getDimColumnsByAlias = function (alias) {
+    if (!alias) {
       return [];
     }
-    var tableColumns = $scope.getColumnsByTable(tableName);
+    var tableColumns = $scope.getColumnsByAlias(alias);
     var tableDim = _.find($scope.metaModel.model.dimensions, function (dimension) {
-      return dimension.table == tableName
+      return dimension.table == alias
     });
     if(!tableDim){
       return [];
@@ -169,17 +182,18 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
   $scope.getAllModelDimMeasureColumns = function () {
     var me_columns = [];
     if($scope.metaModel.model.metrics){
-      angular.forEach($scope.metaModel.model.metrics,function(metric,index){
+      angular.forEach($scope.metaModel.model.metrics,function(metric){
         me_columns.push(metric);
       })
     }
 
-    angular.forEach($scope.metaModel.model.dimensions,function(dimension,index){
+    angular.forEach($scope.metaModel.model.dimensions,function(dimension){
       if(dimension.columns){
-        me_columns = me_columns.concat(dimension.columns);
+        angular.forEach(dimension.columns,function(column){
+          me_columns = me_columns.concat(dimension.table+"."+column);
+        });
       }
-    })
-
+    });
     return distinct_array(me_columns);
   };
 
@@ -187,7 +201,9 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     var me_columns = [];
     angular.forEach($scope.metaModel.model.dimensions,function(dimension,index){
       if(dimension.columns){
-        me_columns = me_columns.concat(dimension.columns);
+        angular.forEach(dimension.columns,function(column){
+          me_columns = me_columns.concat(dimension.table+"."+column);
+        });
       }
     })
 
@@ -209,11 +225,11 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     var me_columns = [];
     //add cube dimension column for specific measure
     angular.forEach($scope.cubeMetaFrame.dimensions,function(dimension,index){
-      if($scope.metaModel.model.fact_table !== dimension.table){
+      if($scope.availableFactTables.indexOf(dimension.table)==-1){
         return;
       }
       if(dimension.column && dimension.derived == null){
-        me_columns.push(dimension.column);
+        me_columns.push(dimension.table+"."+dimension.column);
       }
     });
     return me_columns;
@@ -224,12 +240,12 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     var me_columns = [];
     angular.forEach($scope.cubeMetaFrame.dimensions,function(dimension,index){
       if(dimension.column && dimension.derived == null){
-        me_columns.push(dimension.column);
+        me_columns.push(dimension.table+"."+dimension.column);
 
       }
       else{
         angular.forEach(dimension.derived,function(derived){
-          me_columns.push(derived);
+          me_columns.push(dimension.table+"."+derived);
         });
 
       }
@@ -256,8 +272,8 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
 
 
-  $scope.getColumnType = function (_column, table) {
-    var columns = $scope.getColumnsByTable(table);
+  $scope.getColumnType = function (_column, alias) {
+    var columns = $scope.getColumnsByAlias(alias);
     var type;
     angular.forEach(columns, function (column) {
       if (_column === column.name) {
@@ -314,10 +330,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             $scope.metaModel.model = _model;
           });
         }
-
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
-
-
       }
     });
 
@@ -520,7 +533,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
   }
 
   function reGenerateRowKey() {
-    $log.log("reGen rowkey & agg group");
     //var fk_pk = {};
     var tmpRowKeyColumns = [];
     var tmpAggregationItems = [];//put all aggregation item
@@ -530,7 +542,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     for( var i=0;i<$scope.metaModel.model.lookups.length;i++){
       var lookup = $scope.metaModel.model.lookups[i];
-      var table = lookup.table;
+      var table = lookup.alias;
       pfkMap[table] = {};
       for(var j=0;j<lookup.join.primary_key.length;j++){
         var pk = lookup.join.primary_key[j];
@@ -543,7 +555,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
       //derived column
       if (dimension.derived && dimension.derived.length) {
         var lookup = _.find($scope.metaModel.model.lookups, function (lookup) {
-          return lookup.table == dimension.table
+          return lookup.alias == dimension.table
         });
         angular.forEach(lookup.join.foreign_key, function (fk, index) {
           for (var i = 0; i < tmpRowKeyColumns.length; i++) {
@@ -568,7 +580,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
         var tableName = dimension.table;
         var columnName = dimension.column;
-        var rowkeyColumn = dimension.column;
+        var rowkeyColumn = dimension.table+"."+dimension.column;
         if(pfkMap[tableName]&&pfkMap[tableName][columnName]){
           //lookup table primary key column as dimension
           rowkeyColumn = pfkMap[tableName][columnName];

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/js/controllers/cubeMeasures.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeMeasures.js b/webapp/app/js/controllers/cubeMeasures.js
index 18f53c2..67a107b 100644
--- a/webapp/app/js/controllers/cubeMeasures.js
+++ b/webapp/app/js/controllers/cubeMeasures.js
@@ -98,24 +98,8 @@ KylinApp.controller('CubeMeasuresCtrl', function ($scope, $modal,MetaModel,cubes
           if(/topn\.encoding\./.test(configuration)){
             var _name=configuration.slice(14);
             var item=$scope.newMeasure.function.configuration[configuration];
-            //var _isFixedLength = item.substring(0,12) === "fixed_length"?"true":"false";//fixed_length:12
-            //var _isIntegerLength = item.substring(0,7) === "integer"?"true":"false";
-            //var _isIntLength = item.substring(0,3) === "int"?"true":"false";
             var _encoding = item;
             var _valueLength = 0 ;
-            //if(_isFixedLength !=="false"){
-            //  _valueLength = item.substring(13,item.length);
-            //  _encoding = "fixed_length";
-            //}
-            //if(_isIntLength!="false" && _isIntegerLength=="false" ){
-            //  _valueLength = item.substring(4,item.length);
-            //  _encoding = "int";
-            //}
-            //
-            //if(_isIntegerLength!="false" ){
-            //  _valueLength = item.substring(8,item.length);
-            //  _encoding = "integer";
-            //}
             var version=$scope.newMeasure.function.configuration['topn.encoding_version.'+_name]||1;
             item=$scope.removeVersion(item);
             var baseKey=item.replace(/:\d+/,'');
@@ -369,8 +353,9 @@ KylinApp.controller('CubeMeasuresCtrl', function ($scope, $modal,MetaModel,cubes
     if($scope.newMeasure.function.parameter.type=="column"&&$scope.newMeasure.function.expression!=="COUNT_DISTINCT"){
 
       var column = $scope.newMeasure.function.parameter.value;
-      var colType = $scope.getColumnType(column, $scope.metaModel.model.fact_table); // $scope.getColumnType defined in cubeEdit.js
-
+      if(column){
+        var colType = $scope.getColumnType(VdmUtil.removeNameSpace(column), VdmUtil.getNameSpaceAliasName(column)); // $scope.getColumnType defined in cubeEdit.js
+      }
       if(colType==""||!colType){
         $scope.newMeasure.function.returntype = "";
         return;

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/js/controllers/modelDataModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDataModel.js b/webapp/app/js/controllers/modelDataModel.js
index 95a4c70..a09101b 100644
--- a/webapp/app/js/controllers/modelDataModel.js
+++ b/webapp/app/js/controllers/modelDataModel.js
@@ -20,15 +20,20 @@
 
 KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager,VdmUtil) {
     $scope.modelsManager = modelsManager;
+    angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
+      if(!joinTable.alias){
+           joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
+      }
+    });
     $scope.init = function (){
       $scope.FactTable={root:$scope.modelsManager.selectedModel.fact_table};
       $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
       $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table]=VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table);
       $scope.aliasName.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
       angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
-         $scope.aliasTableMap[joinTable.alias]=joinTable.table;
-         $scope.tableAliasMap[joinTable.table]=joinTable.alias;
-         $scope.aliasName.push(joinTable.alias);
+        $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+        $scope.tableAliasMap[joinTable.table]=joinTable.alias;
+        $scope.aliasName.push(joinTable.alias);
       });
     }
     if($scope.state.mode=='edit'){

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/partials/cubeDesigner/advanced_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/advanced_settings.html b/webapp/app/partials/cubeDesigner/advanced_settings.html
index 2728240..438eb1f 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -63,7 +63,6 @@
                           {{rowkey_column.column}}
                         </ui-select-choices>
                       </ui-select>
-
                       <p ng-if="state.mode=='view'">
                         {{aggregation_group.includes}}</p>
                     </td>
@@ -203,7 +202,7 @@
                   <thead>
                   <tr>
                     <th>ID</th>
-                    <th style="width:200px;">Column</th>
+                    <th class="col-xs-4">Column</th>
                     <th>Encoding</th>
                     <th>Length</th>
                     <th>Shard By</th>

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index ed265c4..8c1cdab 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -22,16 +22,6 @@
     <div class="dataTables_wrapper form-inline no-footer">
         <div class="row">
             <div class="col-xs-6" ng-if="state.mode=='edit'">
-                <div class="btn-group">
-                    <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" ng-disabled="instance.status=='READY'">
-                        <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
-                    </button>
-                    <ul class="dropdown-menu" role="menu">
-                        <li><a ng-click="addDim('normal')">Normal</a></li>
-                        <!--<li><a ng-click="addDim('hierarchy')">Hierarchy</a></li>-->
-                        <li><a ng-click="addDim('derived')">Derived</a></li>
-                    </ul>
-                </div>
                 <button type="button" class="btn btn-default" ng-disabled="!metaModel.model.fact_table.length||instance.status=='READY'"
                         ng-click="openAutoGenModal()" >
                     <i class="fa fa-building-o"></i> Auto Generator
@@ -51,7 +41,7 @@
                     <th>Name</th>
                     <th>Table Name</th>
                     <th>Type</th>
-                    <th></th>
+                    <th>Column</th>
                     <th ng-if="state.mode=='edit'">Actions</th>
                 </tr>
             </thead>
@@ -67,7 +57,7 @@
                     </td>
                     <!--Table Name -->
                     <td>
-                        <span tooltip="{{dimension.table == metaModel.model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                        <span>{{dimension.table}}</span>
                     </td>
                     <!--Type-->
                     <td>
@@ -77,18 +67,12 @@
                     <td>
                         <div ng-repeat="t in getDimType(dimension)">
                             <div ng-switch="t">
-                                <!--<dl class="dl-horizontal" ng-switch-when="hierarchy">-->
-                                    <!--<dt>Hierarchy</dt>-->
-                                    <!--<dd>{{dimension.column}}</dd>-->
-                                <!--</dl>-->
-                                <dl class="dl-horizontal" ng-switch-when="derived">
-                                    <dt>Derived</dt>
-                                    <dd>{{dimension.derived}}</dd>
-                                </dl>
-                                <dl class="dl-horizontal" ng-switch-when="normal">
-                                    <dt>Column</dt>
-                                    <dd>{{dimension.column}}</dd>
-                                </dl>
+                                <span  ng-switch-when="derived">
+                                    {{dimension.derived}}
+                                </span>
+                                <span ng-switch-when="normal">
+                                    {{dimension.column}}
+                                </span>
                             </div>
                         </div>
                     </td>
@@ -156,13 +140,13 @@
                             <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Table Name</b></label>
                             <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') >= 0">
                                 <select class="form-control" required="true" chosen data-placeholder="Select a lookup table"
-                                        ng-model="newDimension.table" ng-options="table for table in availableTables.slice(1)">
+                                        ng-model="newDimension.table" ng-options="table for table in availableLookupTables">
                                     <option value=""></option>
                                 </select>
                             </div>
                             <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') == -1">
                                 <select class="form-control" required="true" chosen data-placeholder="Select a table"
-                                        ng-model="newDimension.table" ng-options="table for table in availableTables">
+                                        ng-model="newDimension.table" ng-options="table for table in availableFactTables">
                                     <option value=""></option>
                                 </select>
                             </div>
@@ -180,7 +164,7 @@
                             <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Column Name</b></label>
                             <div class="col-xs-12 col-sm-6">
                                 <select class="form-control" required="true" chosen data-placeholder="Select a column"
-                                        ng-model="newDimension.column" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
+                                        ng-model="newDimension.column" ng-options="column.name as column.name for column in getDimColumnsByAlias(newDimension.table)">
                                     <option value=""></option>
                                 </select>
                             </div>
@@ -195,7 +179,7 @@
                                         <div>
                                             <select chosen style="width: 80%;" data-placeholder="Derived Columns.."
                                                     ng-model="newDimension.derived[$index]"
-                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
+                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByAlias(newDimension.table)" >
                                                 <option value=""></option>
                                             </select>
                                             <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
@@ -236,9 +220,9 @@
                         <div class="box-body">
                           <ul class="list-unstyled columns-region">
                               <!--FactTable-->
-                              <div ng-repeat="table in availableTables track by $index" ng-if="$index == 0"  class="panel-default " >
+                              <div ng-repeat="table in availableFactTables track by $index"   class="panel-default " >
                                 <h4>{{table}}[FactTable]</h4>
-                                <table class="table table-striped table-hover ng-scope"    >
+                                <table class="table table-striped table-hover ng-scope">
                                   <tr >
                                     <td class="col-xs-2"><label><input type="checkbox" ng-model="selectedColumns[table].all" ng-change="autoChangeAll(table)">Select All</label></td>
                                     <td class="col-xs-4"><label>Name</label></td>
@@ -262,7 +246,7 @@
                                 </table>
                               </div>
                               <!--LookUp Table-->
-                              <div ng-repeat="table in availableTables track by $index" ng-if="$index > 0"  class="panel-default" >
+                              <div ng-repeat="table in availableLookupTables track by $index"  class="panel-default" >
                                 <h4>{{table}}[LookupTable]</h4>
                                 <table class="table table-striped table-hover ng-scope">
                                   <tr class="row" >

http://git-wip-us.apache.org/repos/asf/kylin/blob/a9230473/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index 8961cc6..492220c 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -148,6 +148,7 @@
                                       ng-if="newMeasure.function.parameter.type == 'constant'"
                                       ng-init="newMeasure.function.parameter.value = 1"><b>&nbsp;&nbsp;1</b></span>
                                 <!--!COUNT_DISTINCT-->
+
                                 <select class="form-control" chosen
                                         ng-if="newMeasure.function.parameter.type == 'column' && (newMeasure.function.expression == 'COUNT_DISTINCT'||newMeasure.function.expression == 'RAW')"
                                         ng-model="newMeasure.function.parameter.value" required
@@ -239,7 +240,7 @@
                                   <thead>
                                   <tr>
                                     <th>ID</th>
-                                    <th>Column</th>
+                                    <th class="col-xs-5" >Column</th>
                                     <th>Encoding</th>
                                     <th>Length</th>
                                     <th ng-if="state.mode=='edit'"></th>
@@ -257,9 +258,9 @@
                                     </td>
                                     <!--Column Name -->
                                     <td>
-                                      <select class="form-control" chosen ng-if="nextPara.type !== 'constant'" required
+                                      <select class="form-control col-xs-12" chosen ng-if="nextPara.type !== 'constant'" required
                                               ng-model="groupby_column.name"
-                                              ng-options="column as column for column in getAllModelDimColumns()" style="width:200px;">
+                                              ng-options="column as column for column in getAllModelDimColumns()" >
                                         <option value="">--Select A Column--</option>
                                       </select>
                                     </td>


[03/14] kylin git commit: minor, test query of group by pushdown

Posted by li...@apache.org.
minor, test query of group by pushdown


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/520b05f7
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/520b05f7
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/520b05f7

Branch: refs/heads/KYLIN-2283
Commit: 520b05f744b13ad4cbd37372ae70272099ea48a1
Parents: 8d0b504
Author: Yang Li <li...@apache.org>
Authored: Sat Dec 3 12:33:14 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 .../src/test/resources/query/sql_subquery/query02.sql    | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/520b05f7/kylin-it/src/test/resources/query/sql_subquery/query02.sql
----------------------------------------------------------------------
diff --git a/kylin-it/src/test/resources/query/sql_subquery/query02.sql b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
index 3ecfb1b..81b4887 100644
--- a/kylin-it/src/test/resources/query/sql_subquery/query02.sql
+++ b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
@@ -18,19 +18,14 @@
 
 SELECT
   week_beg_dt
-  ,sum(price) as sum_price
+  ,sum(price)
 FROM
 ( 
   select
     test_cal_dt.week_beg_dt
     ,test_kylin_fact.price
   from test_kylin_fact 
-    inner JOIN edw.test_cal_dt as test_cal_dt
-      ON test_kylin_fact.cal_dt = test_cal_dt.cal_dt
-    inner JOIN test_category_groupings
-      ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id AND test_kylin_fact.lstg_site_id = test_category_groupings.site_id
-    inner JOIN edw.test_sites as test_sites
-      ON test_kylin_fact.lstg_site_id = test_sites.site_id
+  inner join edw.test_cal_dt as test_cal_dt
+    on test_kylin_fact.cal_dt = test_cal_dt.cal_dt
 ) t
 group by week_beg_dt 
-order by week_beg_dt 
\ No newline at end of file


[07/14] kylin git commit: KYLIN 1875 update tooltip

Posted by li...@apache.org.
KYLIN 1875 update tooltip

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/e7cc152e
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/e7cc152e
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/e7cc152e

Branch: refs/heads/KYLIN-2283
Commit: e7cc152e69ce98cba7fd3be5251d334314f25828
Parents: a923047
Author: chenzhx <34...@qq.com>
Authored: Tue Dec 13 15:57:34 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/partials/cubeDesigner/dimensions.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/e7cc152e/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 8c1cdab..7fedeb6 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -57,7 +57,7 @@
                     </td>
                     <!--Table Name -->
                     <td>
-                        <span>{{dimension.table}}</span>
+                        <span tooltip="{{availableFactTables.indexOf(dimension.table)==-1? 'Lookup Table':'Fact Table'}}">{{dimension.table}}</span>
                     </td>
                     <!--Type-->
                     <td>


[06/14] kylin git commit: KYLIN 1875 model visualization

Posted by li...@apache.org.
KYLIN 1875 model visualization

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/36a42d86
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/36a42d86
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/36a42d86

Branch: refs/heads/KYLIN-2283
Commit: 36a42d86f84e0b0ba69b44e809e68fcee5437d65
Parents: d5b8c7f
Author: chenzhx <34...@qq.com>
Authored: Mon Dec 12 10:56:17 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/modelDataModel.js     | 10 ++--
 webapp/app/js/controllers/models.js             |  1 +
 webapp/app/js/services/tree.js                  | 60 ++++++--------------
 .../app/partials/modelDesigner/data_model.html  |  8 +--
 webapp/app/partials/models/model_detail.html    | 18 +-----
 5 files changed, 26 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/36a42d86/webapp/app/js/controllers/modelDataModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDataModel.js b/webapp/app/js/controllers/modelDataModel.js
index d17af91..95a4c70 100644
--- a/webapp/app/js/controllers/modelDataModel.js
+++ b/webapp/app/js/controllers/modelDataModel.js
@@ -21,7 +21,7 @@
 KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager,VdmUtil) {
     $scope.modelsManager = modelsManager;
     $scope.init = function (){
-      $scope.rootFactTable=$scope.modelsManager.selectedModel.fact_table;
+      $scope.FactTable={root:$scope.modelsManager.selectedModel.fact_table};
       $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
       $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table]=VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table);
       $scope.aliasName.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
@@ -137,12 +137,12 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     };
     $scope.changeFactTable = function () {
         delete $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)];
-        $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.rootFactTable)]=$scope.rootFactTable;
+        $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.FactTable.root)]=$scope.FactTable.root;
         delete $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table];
-        $scope.tableAliasMap[$scope.rootFactTable]=VdmUtil.removeNameSpace($scope.rootFactTable);
+        $scope.tableAliasMap[$scope.FactTable.root]=VdmUtil.removeNameSpace($scope.FactTable.root);
         $scope.aliasName.splice($scope.aliasName.indexOf(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)),1);
-        $scope.aliasName.push(VdmUtil.removeNameSpace($scope.rootFactTable));
-        $scope.modelsManager.selectedModel.fact_table=$scope.rootFactTable;
+        $scope.aliasName.push(VdmUtil.removeNameSpace($scope.FactTable.root));
+        $scope.modelsManager.selectedModel.fact_table=$scope.FactTable.root;
     }
     $scope.changeJoinTable = function () {
         $scope.newLookup.alias=$scope.newLookup.table;

http://git-wip-us.apache.org/repos/asf/kylin/blob/36a42d86/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 6fe2598..fb2c6d1 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -177,6 +177,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
   };
 
   var ModelDetailModalCtrl = function ($scope, $location, $modalInstance, scope) {
+    modelsManager.selectedModel.visiblePage='metadata';
     $scope.cancel = function () {
       $modalInstance.dismiss('cancel');
     };

http://git-wip-us.apache.org/repos/asf/kylin/blob/36a42d86/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index 3b444c6..08e290b 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -17,8 +17,8 @@
 */
 
 KylinApp.service('ModelGraphService', function (VdmUtil) {
-    var tablesNodeList=[];
-    var aliasList=[];
+    var tablesNodeList={};
+  //  var aliasList=[];
     var margin = {top: 20, right: 100, bottom: 20, left: 100},
         width = 1100 - margin.right - margin.left,
         height = 600;
@@ -42,12 +42,12 @@ KylinApp.service('ModelGraphService', function (VdmUtil) {
             "name": VdmUtil.removeNameSpace(model.fact_table),
             "children": []
         };
-        tablesNodeList.push(graphData);
-        aliasList.push(graphData.name);
+        tablesNodeList[graphData.name]=graphData;
+      //   aliasList.push(graphData.name);
         model.graph = (!!model.graph) ? model.graph : {};
 
-        angular.forEach(model.lookups, function (lookup, index) {
-          if (lookup.join && aliasList.indexOf(lookup.alias)==-1) {
+        angular.forEach(model.lookups,function (lookup, index) {
+          if (lookup.join && lookup.join.primary_key.length > 0) {
             var  dimensionNode={
                 "type": lookup.kind,
                 "name": lookup.alias,
@@ -55,49 +55,21 @@ KylinApp.service('ModelGraphService', function (VdmUtil) {
                 "children": [],
                 "_children": []
               }
-              aliasList.push(dimensionNode.name);
-              tablesNodeList.push(dimensionNode);
+        //      aliasList.push(dimensionNode.name);
+              tablesNodeList[dimensionNode.name]=dimensionNode;
             }
 
         });
-        angular.forEach(model.lookups, function (lookup) {
-           if (lookup.join && lookup.join.primary_key.length > 0) {
-                  VdmUtil.getNameSpaceAliasName(lookup.join.primary_key[0]);
-                  VdmUtil.getNameSpaceAliasName(lookup.join.foreign_key[0]);
-           }
-        });
-
-
-/* Loop through the graphData.children array to find out: If the LKP table is already existed *//*
-
-          for(var j = 0; j < graphData.children.length; j++ ) {
-            if(graphData.children[j].name == lookup.alias){
-              dimensionNode = graphData.children[j];
-              break;
-            }
-          }
 
-          */
-/* If not existed, create dimensionNode and push it *//*
-
-          if(j == graphData.children.length) {
-            dimensionNode = {
-              "type": "dimension",
-              "name": lookup.alias,
-              "join": lookup.join,
-              "children": [],
-              "_children": []
-            };
+        angular.forEach(model.lookups,function(joinTable){
+          if (joinTable.join && joinTable.join.primary_key.length > 0) {
+            var fkAliasName=VdmUtil.getNameSpaceAliasName(joinTable.join.foreign_key[0]);
+            var pkAliasName=VdmUtil.getNameSpaceAliasName(joinTable.join.primary_key[0]);
+            tablesNodeList[fkAliasName].children.push(tablesNodeList[pkAliasName]);
           }
+        });
 
-          if(j == graphData.children.length) {
-            graphData.children.push(dimensionNode);
-          }
-
-        }
-*/
-
-      angular.forEach(model.dimensions, function (dimension, index) {
+/*      angular.forEach(model.dimensions, function (dimension, index) {
         // for dimension on lookup table
         if(model.fact_table!==dimension.table){
             var lookup = _.find(graphData.children,function(item){
@@ -117,7 +89,7 @@ KylinApp.service('ModelGraphService', function (VdmUtil) {
                   }
           });
         };
-      });
+      });*/
         model.graph.columnsCount = 0;
         model.graph.tree = tree;
         model.graph.root = graphData;

http://git-wip-us.apache.org/repos/asf/kylin/blob/36a42d86/webapp/app/partials/modelDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/data_model.html b/webapp/app/partials/modelDesigner/data_model.html
index 82be964..f1192f4 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -23,10 +23,10 @@
     <div class="form-group" ng-class="{'required':state.mode=='edit'}">
         <div class="row">
             <label class="col-xs-12 col-sm-2 control-label concube.detailtrol-label no-padding-right font-color-default">
-                <b>Fact Table</b>
+                <b>Root Fact Table</b>
             </label>
             <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.table_name.$invalid && (forms.data_model_form.table_name.$dirty||forms.data_model_form.$submitted)}">
-              <select chosen ng-model="$parent.rootFactTable" ng-if="state.mode=='edit'"
+              <select chosen ng-model="FactTable.root" ng-if="state.mode=='edit'"
                       ng-options="table.name as table.name for table in tableModel.selectProjectTables"
                       style="width:100%;" ng-change="changeFactTable()"
                       name="table_name"
@@ -35,9 +35,7 @@
                       class="chosen-select">
                 <option value=""> -- Select Fact Table -- </option>
               </select>
-
-                <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$submitted)">The fact table is required</small>
-                <span ng-if="state.mode=='view'">{{$parent.rootFactTable}}</span>
+              <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.fact_table}}</span>
             </div>
         </div>
     </div>

http://git-wip-us.apache.org/repos/asf/kylin/blob/36a42d86/webapp/app/partials/models/model_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_detail.html b/webapp/app/partials/models/model_detail.html
index dcf782a..2549da2 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -32,23 +32,7 @@
       <li class="{{modelsManager.selectedModel.visiblePage=='json_model'? 'active':''}}">
         <a href="" ng-click="modelsManager.selectedModel.visiblePage='json_model';">JSON</a>
       </li>
-        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(modelsManager.selectedModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-            <a class="dropdown-toggle highlight-bule" data-toggle="dropdown" href="#" aria-expanded="true">
-                <i class="fa fa-star"> Action </i> <span class="caret"></span>
-            </a>
-            <ul class="dropdown-menu">
-                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(modelsManager.selectedModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <a href="models/edit/{{modelsManager.selectedModel.name}}" data-widget="collapse">Edit</a>
-                </li>
-                <li ng-if="userService.hasRole('ROLE_ADMIN')">
-                    <a ng-click="dropModel(modelsManager.selectedModel)">Drop</a>
-                </li>
-                <li role="presentation" class="divider"></li>
-                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(modelsManager.selectedModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <a href="cubes/add/{{modelsManager.selectedModel.name}}" data-widget="collapse">Create Cube</a>
-                </li>
-            </ul>
-        </li>
+
     </ul>
 
     <div class="model-detail" ng-if="!modelsManager.selectedModel.visiblePage || modelsManager.selectedModel.visiblePage=='metadata'">


[13/14] kylin git commit: halfway

Posted by li...@apache.org.
halfway


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/f6208f8a
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/f6208f8a
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/f6208f8a

Branch: refs/heads/KYLIN-2283
Commit: f6208f8ae330cf8260de63909c43a4ea5760c184
Parents: f2377db
Author: Li Yang <li...@apache.org>
Authored: Thu Dec 15 18:51:00 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Fri Dec 16 16:06:48 2016 +0800

----------------------------------------------------------------------
 .../apache/kylin/metadata/model/ColumnDesc.java |   8 ++
 .../apache/kylin/metadata/model/TableDesc.java  |   9 ++
 .../kylin/source/datagen/ColumnGenConfig.java   |  86 ++++++++++++
 .../kylin/source/datagen/ColumnGenerator.java   |  41 ++++++
 .../source/datagen/ModelDataGenerator.java      | 130 +++++++++++++++++++
 .../kylin/source/datagen/TableGenConfig.java    |  41 ++++++
 .../org/apache/kylin/source/datagen/Util.java   |  68 ++++++++++
 7 files changed, 383 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java
index 2da1f5e..7105ede 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ColumnDesc.java
@@ -45,6 +45,10 @@ public class ColumnDesc implements Serializable {
     @JsonInclude(JsonInclude.Include.NON_NULL)
     private String comment;
 
+    @JsonProperty("data_gen")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String dataGen;
+
     // parsed from data type
     private DataType type;
     private DataType upgradedType;
@@ -148,6 +152,10 @@ public class ColumnDesc implements Serializable {
     public void setNullable(boolean nullable) {
         this.isNullable = nullable;
     }
+    
+    public String getDataGen() {
+        return dataGen;
+    }
 
     public void init(TableDesc table) {
         this.table = table;

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
index ab8c465..e845da1 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
@@ -26,6 +26,7 @@ import org.apache.kylin.common.persistence.RootPersistentEntity;
 import org.apache.kylin.common.util.StringSplitter;
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -47,6 +48,10 @@ public class TableDesc extends RootPersistentEntity implements ISourceAware {
     private int sourceType = ISourceAware.ID_HIVE;
     @JsonProperty("table_type")
     private String tableType;
+    
+    @JsonProperty("data_gen")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String dataGen;
 
     private DatabaseDesc database = new DatabaseDesc();
 
@@ -160,6 +165,10 @@ public class TableDesc extends RootPersistentEntity implements ISourceAware {
         return getMaxColumnIndex() + 1;
     }
 
+    public String getDataGen() {
+        return dataGen;
+    }
+
     public void init() {
         if (name != null)
             name = name.toUpperCase();

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
new file mode 100644
index 0000000..91f5366
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.source.datagen;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.kylin.metadata.model.ColumnDesc;
+
+public class ColumnGenConfig {
+
+    // discrete values
+    List<String> values;
+    
+    // random
+    boolean isRandom;
+    int randCardinality;
+    
+    // ID
+    boolean isID;
+    int idStart;
+    
+    // null handling
+    boolean genNull;
+    double genNullPct;
+    
+    public ColumnGenConfig(ColumnDesc col) {
+        init(col.getName(), col.getDataGen());
+    }
+
+    private void init(String col, String dataGen) {
+        
+        Map<String, String> config = Util.parseEqualCommaPairs(dataGen, "values");
+        
+        values = Arrays.asList(Util.parseString(config, "values", "").split("|"));
+        
+        if ("ID".equals(values.get(0))) {
+            isID = true;
+            idStart = (values.size() > 1) ? Integer.parseInt(values.get(1)) : 0;
+        } else {
+            isRandom = true;
+            randCardinality = Util.parseInt(config, "cardinality", guessCardinality(col));
+        }
+        
+        genNull = Util.parseBoolean(config, "genNull", guessGenNull(col));
+        genNullPct = Util.parseDouble(config, "genNullPct", 0.01);
+    }
+
+    private int guessCardinality(String col) {
+        for (String s : col.split("_")) {
+            if (s.startsWith("C")) {
+                try {
+                    return Integer.parseInt(s.substring(1));
+                } catch (Exception ex) {
+                    // ok
+                }
+            }
+        }
+        return 0;
+    }
+
+    private boolean guessGenNull(String col) {
+        return col.contains("_NULL");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
new file mode 100644
index 0000000..c4c4fe7
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.source.datagen;
+
+import java.util.Iterator;
+
+import org.apache.kylin.metadata.model.ColumnDesc;
+
+public class ColumnGenerator {
+
+    final private ColumnDesc targetCol;
+    final private int targetRows;
+    final private ModelDataGenerator modelGen;
+
+    public ColumnGenerator(ColumnDesc col, int nRows, ModelDataGenerator modelGen) {
+        this.targetCol = col;
+        this.targetRows = nRows;
+        this.modelGen = modelGen;
+    }
+    
+    public Iterator<String> generate() {
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ModelDataGenerator.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ModelDataGenerator.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ModelDataGenerator.java
new file mode 100644
index 0000000..0f67377
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ModelDataGenerator.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.source.datagen;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.metadata.model.ColumnDesc;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.model.JoinTableDesc;
+import org.apache.kylin.metadata.model.TableDesc;
+
+import com.google.common.base.Preconditions;
+
+public class ModelDataGenerator {
+
+    final private DataModelDesc model;
+    final private int targetRows;
+    final private ResourceStore outputStore;
+    final private String outputPath;
+    
+    public ModelDataGenerator(DataModelDesc model, int nRows) {
+        this(model, nRows, ResourceStore.getStore(model.getConfig()), "/data");
+    }
+    
+    public ModelDataGenerator(DataModelDesc model, int nRows, ResourceStore outputStore, String outputPath) {
+        this.model = model;
+        this.targetRows = nRows;
+        this.outputStore = outputStore;
+        this.outputPath = outputPath;
+    }
+    
+    public void generate() throws IOException {
+        Set<TableDesc> generated = new HashSet<>();
+        
+        JoinTableDesc[] allTables = model.getJoinTables();
+        for (int i = allTables.length - 1; i >= 0; i--) {
+            TableDesc table = allTables[i].getTableRef().getTableDesc();
+            if (generated.contains(table))
+                continue;
+            
+            boolean gen = generateTable(table);
+            
+            if (gen)
+                generated.add(table);
+        }
+        
+        generateDDL(generated);
+    }
+
+    private boolean generateTable(TableDesc table) throws IOException {
+        TableGenConfig config = new TableGenConfig(table);
+        if (!config.needGen)
+            return false;
+        
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        PrintWriter pout = new PrintWriter(new OutputStreamWriter(bout, "UTF-8"));
+        
+        generateTableInternal(table, config, pout);
+        
+        pout.close();
+        bout.close();
+        
+        outputStore.putResource(path(table), new ByteArrayInputStream(bout.toByteArray()), System.currentTimeMillis());
+        return true;
+    }
+
+    private void generateTableInternal(TableDesc table, TableGenConfig config, PrintWriter out) {
+        ColumnDesc[] columns = table.getColumns();
+        ColumnGenerator[] colGens = new ColumnGenerator[columns.length];
+        Iterator<String>[] colIters = new Iterator[columns.length];
+        
+        int tableRows = (int) (targetRows * config.scaleFactor);
+        tableRows = Math.max(1, tableRows);
+        
+        for (int i = 0; i < columns.length; i++) {
+            colGens[i] = new ColumnGenerator(columns[i], tableRows, this);
+            colIters[i] = colGens[i].generate();
+        }
+        
+        for (int i = 0; i < tableRows; i++) {
+            for (int c = 0; c < columns.length; c++) {
+                if (c > 0)
+                    out.print(",");
+                
+                String v = colIters[c].next();
+                Preconditions.checkState(v.contains(",") == false);
+                
+                out.print(v);
+            }
+            out.print("\n");
+        }
+    }
+
+    private void generateDDL(Set<TableDesc> generated) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    private String path(TableDesc table) {
+        return outputPath + "/" + table.getIdentity() + ".csv";
+    }
+    
+    public DataModelDesc getModle() {
+        return model;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/source/datagen/TableGenConfig.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/TableGenConfig.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/TableGenConfig.java
new file mode 100644
index 0000000..9e6fa73
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/TableGenConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.source.datagen;
+
+import java.util.Map;
+
+import org.apache.kylin.metadata.model.TableDesc;
+
+public class TableGenConfig {
+    
+    boolean needGen;
+    double scaleFactor;
+    
+    public TableGenConfig(TableDesc table) {
+        init(table.getDataGen());
+    }
+
+    private void init(String dataGen) {
+        needGen = !dataGen.isEmpty();
+        
+        Map<String, String> config = Util.parseEqualCommaPairs(dataGen, "scaleFactor");
+        scaleFactor = Util.parseDouble(config, "scaleFactor", 1.0);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/f6208f8a/core-metadata/src/main/java/org/apache/kylin/source/datagen/Util.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/Util.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/Util.java
new file mode 100644
index 0000000..4b87ee2
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/Util.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.source.datagen;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Util {
+
+    static Map<String, String> parseEqualCommaPairs(String equalCommaPairs, String defaultKey) {
+        Map<String, String> r = new LinkedHashMap<>();
+        for (String s : equalCommaPairs.split(",")) {
+            int equal = s.indexOf("=");
+            if (equal < 0) {
+                if (r.containsKey(defaultKey))
+                    throw new IllegalStateException();
+                r.put(defaultKey, s.trim());
+            } else {
+                r.put(s.substring(0, equal).trim(), s.substring(equal + 1).trim());
+            }
+        }
+        return r;
+    }
+
+    static double parseDouble(Map<String, String> config, String key, double dft) {
+        if (config.containsKey(key))
+            return Double.parseDouble(config.get(key));
+        else
+            return dft;
+    }
+
+    static boolean parseBoolean(Map<String, String> config, String key, boolean dft) {
+        if (config.containsKey(key))
+            return Boolean.parseBoolean(config.get(key));
+        else
+            return dft;
+    }
+
+    public static int parseInt(Map<String, String> config, String key, int dft) {
+        if (config.containsKey(key))
+            return Integer.parseInt(config.get(key));
+        else
+            return dft;
+    }
+
+    public static String parseString(Map<String, String> config, String key, String dft) {
+        if (config.containsKey(key))
+            return config.get(key);
+        else
+            return dft;
+    }
+}


[04/14] kylin git commit: KYLIN 1875 update model designer

Posted by li...@apache.org.
KYLIN 1875 update model designer

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/d5b8c7f2
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/d5b8c7f2
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/d5b8c7f2

Branch: refs/heads/KYLIN-2283
Commit: d5b8c7f27820196400f43cdcd88b94206b581484
Parents: 91cf788
Author: chenzhx <34...@qq.com>
Authored: Fri Dec 9 11:44:35 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/index.html                           |   3 +
 webapp/app/js/controllers/cubeModel.js          | 191 +-------------
 .../js/controllers/modelConditionsSettings.js   |  84 ++++++
 webapp/app/js/controllers/modelDataModel.js     | 254 +++++++++++++++++++
 webapp/app/js/controllers/modelDimensions.js    |   6 +-
 webapp/app/js/controllers/modelEdit.js          | 100 +++-----
 webapp/app/js/controllers/modelMeasures.js      |  29 ++-
 webapp/app/js/services/tree.js                  |  48 +++-
 webapp/app/js/utils/utils.js                    |  24 +-
 .../modelDesigner/conditions_settings.html      |  57 ++---
 .../app/partials/modelDesigner/data_model.html  |  89 ++++---
 .../modelDesigner/model_dimensions.html         |   4 +-
 .../partials/modelDesigner/model_measures.html  |  59 +++--
 13 files changed, 585 insertions(+), 363 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index ad881d5..13b54c8 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -187,6 +187,9 @@
 <!--New GUI-->
 <script src="js/controllers/modelSchema.js"></script>
 <script src="js/controllers/modelDimensions.js"></script>
+<script src="js/controllers/modelDataModel.js"></script>
+<script src="js/controllers/modelMeasures.js"></script>
+<script src="js/controllers/modelConditionsSettings.js"></script>
 <script src="js/controllers/modelRefresh.js"></script>
 <script src="js/controllers/modelEdit.js"></script>
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index b20a829..2c7de2c 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,8 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager) {
-
+KylinApp.controller('CubeModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager,VdmUtil) {
     $scope.modelsManager = modelsManager;
 
     $scope.buildGraph = function (model) {
@@ -45,193 +44,5 @@ KylinApp.controller('CubeModelCtrl', function ($location,$scope, $modal,cubeConf
     };
 
     $scope.cubeConfig = cubeConfig;
-    var DataModel = function () {
-        return {
-            name: '',
-            fact_table: '',
-            lookups: []
-        };
-    };
-
-    var Lookup = function () {
-        return {
-            table: '',
-            join: {
-                type: '',
-                primary_key: [],
-                foreign_key: [],
-                isCompatible:[],
-                pk_type:[],
-                fk_type:[]
-            }
-        };
-    };
-
-    // Initialize params.
-    $scope.lookupState = {
-        editing: false,
-        editingIndex: -1,
-        filter: ''
-    };
-
-    $scope.newLookup = Lookup();
-
-    var lookupList = modelsManager.selectedModel.lookups;
-
-    $scope.openLookupModal = function () {
-        var modalInstance = $modal.open({
-            templateUrl: 'dataModelLookupTable.html',
-            controller: cubeModelLookupModalCtrl,
-            backdrop: 'static',
-            scope: $scope
-        });
-        modalInstance.result.then(function () {
-            if (!$scope.lookupState.editing) {
-                $scope.doneAddLookup();
-            } else {
-                $scope.doneEditLookup();
-            }
-
-        }, function () {
-            $scope.cancelLookup();
-        });
-    };
-
-    // Controller for cube model lookup modal.
-    var cubeModelLookupModalCtrl = function ($scope, $modalInstance) {
-        $scope.ok = function () {
-            $modalInstance.close();
-        };
-
-        $scope.cancel = function () {
-            $modalInstance.dismiss('cancel');
-        };
-    };
-
-    $scope.editLookup = function (lookup) {
-        $scope.lookupState.editingIndex = lookupList.indexOf(lookup);
-        $scope.lookupState.editing = true;
-
-        // Make a copy of model will be editing.
-        $scope.newLookup = angular.copy(lookup);
-
-        $scope.openLookupModal();
-    };
-
-    $scope.doneAddLookup = function () {
-        // Push newLookup which bound user input data.
-        lookupList.push(angular.copy($scope.newLookup));
-
-        $scope.resetParams();
-    };
-
-    $scope.doneEditLookup = function () {
-        // Copy edited model to destination model.
-        angular.copy($scope.newLookup, lookupList[$scope.lookupState.editingIndex]);
-
-        $scope.resetParams();
-    };
-
-    $scope.cancelLookup = function () {
-        $scope.resetParams();
-    };
-
-        $scope.removeLookup = function (lookup) {
-            var dimExist = _.some(modelsManager.selectedModel.dimensions,function(item,index){
-                return item.table===lookup.table;
-            });
-            if(dimExist) {
-                SweetAlert.swal({
-                    title: '',
-                    text: "Once it's removed, all relative dimensions will be removed. Are you sure to remove the lookup table?",
-                    type: '',
-                    showCancelButton: true,
-                    confirmButtonColor: '#DD6B55',
-                    confirmButtonText: "Yes",
-                    closeOnConfirm: true
-                }, function (isConfirm) {
-                    if (isConfirm) {
-                        for (var i = modelsManager.selectedModel.dimensions.length - 1; i >= 0; i--) {
-                            if (modelsManager.selectedModel.dimensions[i].table === lookup.table) {
-                                modelsManager.selectedModel.dimensions.splice(i, 1);
-                            }
-                        }
-                        lookupList.splice(lookupList.indexOf(lookup), 1);
-                    }
-                });
-            }else{
-                lookupList.splice(lookupList.indexOf(lookup), 1);
-            }
-        };
-
-
-    $scope.changeKey = function(index){
-         var fact_table = modelsManager.selectedModel.fact_table;
-         var lookup_table = $scope.newLookup.table;
-         var pk_column = $scope.newLookup.join.primary_key[index];
-         var fk_column = $scope.newLookup.join.foreign_key[index];
-         if(pk_column!=='null'&&fk_column!=='null'){
-             $scope.newLookup.join.pk_type[index] = TableModel.getColumnType(pk_column,lookup_table);
-             $scope.newLookup.join.fk_type[index] = TableModel.getColumnType(fk_column,fact_table);
-            if($scope.newLookup.join.pk_type[index]!==$scope.newLookup.join.fk_type[index]){
-               $scope.newLookup.join.isCompatible[index]=false;
-            }else{
-               $scope.newLookup.join.isCompatible[index]=true;
-            }
-
-         }
-    }
-
-    $scope.addNewJoin = function(){
-        $scope.newLookup.join.primary_key.push("null");
-        $scope.newLookup.join.foreign_key.push("null");
-        $scope.newLookup.join.fk_type.push("null");
-        $scope.newLookup.join.pk_type.push("null");
-        $scope.newLookup.join.isCompatible.push(true);
-    };
-
-    $scope.removeJoin = function($index){
-        $scope.newLookup.join.primary_key.splice($index,1);
-        $scope.newLookup.join.foreign_key.splice($index,1);
-        $scope.newLookup.join.fk_type.splice($index,1);
-        $scope.newLookup.join.pk_type.splice($index,1);
-        $scope.newLookup.join.isCompatible.splice($index,1);
-    };
-
-    $scope.resetParams = function () {
-        $scope.lookupState.editing = false;
-        $scope.lookupState.editingIndex = -1;
-        $scope.newLookup = Lookup();
-    };
-
-    $scope.checkLookupForm = function(){
-            var errors = [];
-            // null validate
-            for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){
-                if($scope.newLookup.join.primary_key[i]==='null'){
-                    errors.push("Primary Key can't be null.");
-                    break;
-                }
-            }
-            for(var i = 0;i<$scope.newLookup.join.foreign_key.length;i++){
-                if($scope.newLookup.join.foreign_key[i]==='null'){
-                    errors.push("Foreign Key can't be null.");
-                    break;
-                }
-            }
-
-            var errorInfo = "";
-            angular.forEach(errors,function(item){
-                errorInfo+="\n"+item;
-            });
-            if(errors.length){
-//                SweetAlert.swal('Warning!', errorInfo, '');
-                SweetAlert.swal('', errorInfo, 'warning');
-                return false;
-            }else{
-                return true;
-            }
-
-    };
 
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/modelConditionsSettings.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelConditionsSettings.js b/webapp/app/js/controllers/modelConditionsSettings.js
new file mode 100644
index 0000000..b3e4998
--- /dev/null
+++ b/webapp/app/js/controllers/modelConditionsSettings.js
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Created by jiazhong on 2015/3/13.
+ */
+
+'use strict';
+
+KylinApp.controller('ModelConditionsSettingsCtrl', function ($scope, $modal,MetaModel,modelsManager,VdmUtil) {
+  $scope.modelsManager = modelsManager;
+  $scope.availableFactTables = [];
+  $scope.selectedTables={fact:VdmUtil.getNameSpaceAliasName($scope.modelsManager.selectedModel.partition_desc.partition_date_column)}
+  $scope.availableFactTables.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
+  var joinTable = $scope.modelsManager.selectedModel.lookups;
+  for (var j = 0; j < joinTable.length; j++) {
+    if(joinTable[j].kind=='FACT'){
+      $scope.availableFactTables.push(joinTable[j].alias);
+    }
+  }
+  $scope.isFormatEdit = {editable:false};
+  var judgeFormatEditable = function(dateColumn){
+    if(dateColumn == null){
+      $scope.isFormatEdit.editable = false;
+      return;
+    }
+    var column = _.filter($scope.getColumnsByAlias(VdmUtil.getNameSpaceAliasName(dateColumn)),function(_column){
+      var columnName=VdmUtil.getNameSpaceAliasName(dateColumn)+"."+_column.name;
+      if(dateColumn == columnName){
+        return _column;
+      }
+    });
+
+    var data_type = column[0].datatype;
+    if(data_type ==="bigint" ||data_type ==="int" ||data_type ==="integer"){
+      $scope.isFormatEdit.editable = false;
+      $scope.modelsManager.selectedModel.partition_desc.partition_date_format='yyyyMMdd';
+      $scope.partitionColumn.hasSeparateTimeColumn=false;
+      $scope.modelsManager.selectedModel.partition_desc.partition_time_column=null;
+      $scope.modelsManager.selectedModel.partition_desc.partition_time_format=null;
+
+      return;
+    }
+
+    $scope.isFormatEdit.editable = true;
+    return;
+
+  };
+  $scope.partitionChange = function (dateColumn) {
+    judgeFormatEditable(dateColumn);
+  };
+  $scope.partitionColumn ={
+      "hasSeparateTimeColumn" : false
+  }
+
+  if (($scope.state.mode=='edit')&&($scope.isEdit = !!$scope.route.params)) {
+    if($scope.modelsManager.selectedModel.partition_desc.partition_time_column){
+      $scope.partitionColumn.hasSeparateTimeColumn = true;
+    }
+    judgeFormatEditable($scope.modelsManager.selectedModel.partition_desc.partition_date_column);
+  }
+
+
+  $scope.toggleHasSeparateColumn = function(){
+    if($scope.partitionColumn.hasSeparateTimeColumn == false){
+      $scope.modelsManager.selectedModel.partition_desc.partition_time_column = null;
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/modelDataModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDataModel.js b/webapp/app/js/controllers/modelDataModel.js
new file mode 100644
index 0000000..d17af91
--- /dev/null
+++ b/webapp/app/js/controllers/modelDataModel.js
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+'use strict';
+
+KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager,VdmUtil) {
+    $scope.modelsManager = modelsManager;
+    $scope.init = function (){
+      $scope.rootFactTable=$scope.modelsManager.selectedModel.fact_table;
+      $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
+      $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table]=VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table);
+      $scope.aliasName.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
+      angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
+         $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+         $scope.tableAliasMap[joinTable.table]=joinTable.alias;
+         $scope.aliasName.push(joinTable.alias);
+      });
+    }
+    if($scope.state.mode=='edit'){
+      $scope.init();
+    }
+
+    $scope.cubeConfig = cubeConfig;
+    var DataModel = function () {
+        return {
+            name: '',
+            fact_table: '',
+            lookups: []
+        };
+    };
+
+    var Lookup = function () {
+        return {
+            table: '',
+            alias: '',
+            joinTable:'',
+            kind:'LOOKUP',
+            join: {
+                type: '',
+                primary_key: [],
+                foreign_key: [],
+                isCompatible:[],
+                pk_type:[],
+                fk_type:[]
+            }
+        };
+    };
+
+    // Initialize params.
+    $scope.lookupState = {
+        editing: false,
+        editingIndex: -1,
+        filter: ''
+    };
+
+    $scope.newLookup = Lookup();
+
+    var lookupList = modelsManager.selectedModel.lookups;
+
+    $scope.openLookupModal = function () {
+        var modalInstance = $modal.open({
+            templateUrl: 'dataModelLookupTable.html',
+            controller: cubeModelLookupModalCtrl,
+            backdrop: 'static',
+            scope: $scope
+        });
+        modalInstance.result.then(function () {
+            if (!$scope.lookupState.editing) {
+                $scope.doneAddLookup();
+            } else {
+                $scope.doneEditLookup();
+            }
+
+        }, function () {
+            $scope.cancelLookup();
+        });
+    };
+
+    // Controller for cube model lookup modal.
+    var cubeModelLookupModalCtrl = function ($scope, $modalInstance) {
+        $scope.ok = function () {
+            $modalInstance.close();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+        };
+    };
+
+    $scope.editLookup = function (lookup) {
+        $scope.lookupState.editingIndex = lookupList.indexOf(lookup);
+        $scope.lookupState.editing = true;
+
+        // Make a copy of model will be editing.
+        $scope.newLookup = angular.copy(lookup);
+        $scope.newLookup.joinTable=VdmUtil.getNameSpaceTopName($scope.newLookup.join.foreign_key[0]);
+        $scope.openLookupModal();
+    };
+
+    $scope.doneAddLookup = function () {
+        // Push newLookup which bound user input data.
+        $scope.aliasTableMap[$scope.newLookup.alias]=$scope.newLookup.table;
+        $scope.tableAliasMap[$scope.newLookup.table]=$scope.newLookup.alias;
+        $scope.aliasName.push($scope.newLookup.alias);
+        lookupList.push(angular.copy($scope.newLookup));
+
+        $scope.resetParams();
+    };
+
+    $scope.doneEditLookup = function () {
+        // Copy edited model to destination model.
+        $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
+        $scope.aliasName=[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)];
+        angular.copy($scope.newLookup, lookupList[$scope.lookupState.editingIndex]);
+        angular.forEach(lookupList,function(joinTable){
+          $scope.aliasName.push(joinTable.alias);
+          $scope.aliasTableMap[joinTable.alias]=joinTable.table;
+         // $scope.tableAliasMap[joinTable.alias]=joinTable.table;
+        });
+
+        $scope.resetParams();
+    };
+    $scope.changeFactTable = function () {
+        delete $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)];
+        $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.rootFactTable)]=$scope.rootFactTable;
+        delete $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table];
+        $scope.tableAliasMap[$scope.rootFactTable]=VdmUtil.removeNameSpace($scope.rootFactTable);
+        $scope.aliasName.splice($scope.aliasName.indexOf(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)),1);
+        $scope.aliasName.push(VdmUtil.removeNameSpace($scope.rootFactTable));
+        $scope.modelsManager.selectedModel.fact_table=$scope.rootFactTable;
+    }
+    $scope.changeJoinTable = function () {
+        $scope.newLookup.alias=$scope.newLookup.table;
+    }
+    $scope.cancelLookup = function () {
+        $scope.resetParams();
+    };
+
+    $scope.removeLookup = function (lookup) {
+        var dimExist = _.some(modelsManager.selectedModel.dimensions,function(item,index){
+            return item.alias===lookup.alias;
+        });
+        if(dimExist) {
+            SweetAlert.swal({
+                 title: '',
+                 text: "Once it's removed, all relative dimensions will be removed. Are you sure to remove the lookup table?",
+                 type: '',
+                 showCancelButton: true,
+                 confirmButtonColor: '#DD6B55',
+                 confirmButtonText: "Yes",
+                 closeOnConfirm: true
+            }, function (isConfirm) {
+                if (isConfirm) {
+                    for (var i = modelsManager.selectedModel.dimensions.length - 1; i >= 0; i--) {
+                        if (modelsManager.selectedModel.dimensions[i].alias === lookup.alias) {
+                            modelsManager.selectedModel.dimensions.splice(i, 1);
+                        }
+                    }
+                    lookupList.splice(lookupList.indexOf(lookup), 1);
+                }
+            });
+        }else{
+            lookupList.splice(lookupList.indexOf(lookup), 1);
+        }
+    };
+    $scope.changeAlias = function (){
+    }
+
+    $scope.changeKey = function(index){
+         var join_table = $scope.newLookup.jointable;
+         var lookup_table = $scope.newLookup.table;
+         var pk_column = $scope.newLookup.join.primary_key[index];
+         var fk_column = $scope.newLookup.join.foreign_key[index];
+         if(pk_column!=='null'&&fk_column!=='null'){
+             $scope.newLookup.join.pk_type[index] = TableModel.getColumnType(pk_column,lookup_table);
+             $scope.newLookup.join.fk_type[index] = TableModel.getColumnType(fk_column,join_table);
+            if($scope.newLookup.join.pk_type[index]!==$scope.newLookup.join.fk_type[index]){
+               $scope.newLookup.join.isCompatible[index]=false;
+            }else{
+               $scope.newLookup.join.isCompatible[index]=true;
+            }
+
+         }
+    }
+
+    $scope.addNewJoin = function(){
+        $scope.newLookup.join.primary_key.push("null");
+        $scope.newLookup.join.foreign_key.push("null");
+        $scope.newLookup.join.fk_type.push("null");
+        $scope.newLookup.join.pk_type.push("null");
+        $scope.newLookup.join.isCompatible.push(true);
+    };
+
+    $scope.removeJoin = function($index){
+        $scope.newLookup.join.primary_key.splice($index,1);
+        $scope.newLookup.join.foreign_key.splice($index,1);
+        $scope.newLookup.join.fk_type.splice($index,1);
+        $scope.newLookup.join.pk_type.splice($index,1);
+        $scope.newLookup.join.isCompatible.splice($index,1);
+    };
+
+    $scope.resetParams = function () {
+        $scope.lookupState.editing = false;
+        $scope.lookupState.editingIndex = -1;
+        $scope.newLookup = Lookup();
+    };
+
+    $scope.checkLookupForm = function(){
+            var errors = [];
+            // null validate
+            for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){
+                if($scope.newLookup.join.primary_key[i]==='null'){
+                    errors.push("Primary Key can't be null.");
+                    break;
+                }
+            }
+            for(var i = 0;i<$scope.newLookup.join.foreign_key.length;i++){
+                if($scope.newLookup.join.foreign_key[i]==='null'){
+                    errors.push("Foreign Key can't be null.");
+                    break;
+                }
+            }
+
+            var errorInfo = "";
+            angular.forEach(errors,function(item){
+                errorInfo+="\n"+item;
+            });
+            if(errors.length){
+//                SweetAlert.swal('Warning!', errorInfo, '');
+                SweetAlert.swal('', errorInfo, 'warning');
+                return false;
+            }else{
+                return true;
+            }
+
+    };
+
+
+});

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/modelDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDimensions.js b/webapp/app/js/controllers/modelDimensions.js
index 1b0e889..3f8a55b 100644
--- a/webapp/app/js/controllers/modelDimensions.js
+++ b/webapp/app/js/controllers/modelDimensions.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel,modelsManager) {
+KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel,modelsManager,VdmUtil) {
     $scope.modelsManager = modelsManager;
 
     // Available columns list derived from cube data model.
@@ -34,10 +34,10 @@ KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel,mo
     // Dump available columns plus column table name, whether is from lookup table.
     $scope.initColumns = function () {
 
-        $scope.availableTables.push(modelsManager.selectedModel.fact_table);
+        $scope.availableTables.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
         var lookups = modelsManager.selectedModel.lookups;
         for (var j = 0; j < lookups.length; j++) {
-            $scope.availableTables.push(lookups[j].table);
+            $scope.availableTables.push(lookups[j].alias);
         }
 
         for(var i = 0;i<$scope.availableTables.length;i++){

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 2f1b35e..4d1e12c 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -22,6 +22,10 @@
 KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, ModelService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel,ProjectService,ProjectModel,modelsManager,VdmUtil) {
     //add or edit ?
     var absUrl = $location.absUrl();
+    $scope.tableAliasMap={};
+    $scope.aliasTableMap={};
+    $scope.aliasName=[];
+    $scope.route={params:$routeParams.modelName};
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
 
     if($scope.modelMode=="addNewModel"&&ProjectModel.selectedProject==null){
@@ -30,11 +34,10 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     }
 
     $scope.modelsManager = modelsManager;
-
     $scope.cubeConfig = cubeConfig;
 
-    $scope.getPartitonColumns = function(tableName){
-        var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
+    $scope.getPartitonColumns = function(alias){
+        var columns = _.filter($scope.getColumnsByAlias(alias),function(column){
             return column.datatype==="date"||column.datatype==="timestamp"||column.datatype==="string"||column.datatype.startsWith("varchar")||column.datatype==="bigint"||column.datatype==="int"||column.datatype==="integer";
         });
         return columns;
@@ -56,9 +59,17 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         });
         return temp;
     };
-
-    $scope.getColumnType = function (_column,table){
-        var columns = $scope.getColumnsByTable(table);
+    $scope.getColumnsByAlias = function (aliasName) {
+        var temp = [];
+        angular.forEach(TableModel.selectProjectTables, function (table) {
+            if (table.name == $scope.aliasTableMap[aliasName]) {
+                temp = table.columns;
+            }
+        });
+        return temp;
+    };
+    $scope.getColumnType = function (_column,alias){
+        var columns = $scope.getColumnsByAlias(alias);
         var type;
         angular.forEach(columns,function(column){
             if(_column === column.name){
@@ -69,38 +80,6 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         return type;
     };
 
-  $scope.isFormatEditable = false;
-  var judgeFormatEditable = function(dateColumn){
-
-    if(dateColumn == null){
-      $scope.isFormatEditable = false;
-      return;
-    }
-    var column = _.filter($scope.getColumnsByTable($scope.modelsManager.selectedModel.fact_table),function(_column){
-      var columnName=$scope.modelsManager.selectedModel.fact_table+"."+_column.name;
-      if(dateColumn == columnName)
-        return _column;
-    });
-
-    var data_type = column[0].datatype;
-    if(data_type ==="bigint" ||data_type ==="int" ||data_type ==="integer"){
-      $scope.isFormatEditable = false;
-      $scope.modelsManager.selectedModel.partition_desc.partition_date_format='yyyyMMdd';
-      $scope.partitionColumn.hasSeparateTimeColumn=false;
-      $scope.modelsManager.selectedModel.partition_desc.partition_time_column=null;
-      $scope.modelsManager.selectedModel.partition_desc.partition_time_format=null;
-
-      return;
-    }
-
-    $scope.isFormatEditable = true;
-    return;
-
-  };
-  $scope.partitionChange = function (dateColumn) {
-    judgeFormatEditable(dateColumn);
-  };
-
     // ~ Define data
     $scope.state = {
         "modelSchema": "",
@@ -109,46 +88,27 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         project:$scope.projectModel.selectedProject
     };
 
-    $scope.partitionColumn ={
-      "hasSeparateTimeColumn" : false
-    }
-    // ~ init
     if ($scope.isEdit = !!$routeParams.modelName) {
-
-        var modelName = $routeParams.modelName;
-        ModelDescService.query({model_name: modelName}, function (model) {
-                    if (model) {
-                        modelsManager.selectedModel = model;
-
-                        if($scope.modelsManager.selectedModel.partition_desc.partition_time_column){
-                          $scope.partitionColumn.hasSeparateTimeColumn = true;
-                        }
-                        modelsManager.selectedModel.project = ProjectModel.getProjectByCubeModel(modelName);
-
-                        if(!ProjectModel.getSelectedProject()){
-                            ProjectModel.setSelectedProject(modelsManager.selectedModel.project);
-                        }
-
-                        TableModel.aceSrcTbLoaded().then(function(){
-                          judgeFormatEditable($scope.modelsManager.selectedModel.partition_desc.partition_date_column);
-                        });
-                    }
-                });
+      var modelName = $routeParams.modelName;
+      ModelDescService.query({model_name: modelName}, function (model) {
+        if (model) {
+          modelsManager.selectedModel = model;
+          if($scope.modelsManager.selectedModel.partition_desc.partition_time_column){
+            $scope.partitionColumn.hasSeparateTimeColumn = true;
+          }
+          modelsManager.selectedModel.project = ProjectModel.getProjectByCubeModel(modelName);
+          if(!ProjectModel.getSelectedProject()){
+            ProjectModel.setSelectedProject(modelsManager.selectedModel.project);
+          }
+        }
+      });
         //init project
-
     } else {
         MetaModel.initModel();
         modelsManager.selectedModel = MetaModel.getMetaModel();
         modelsManager.selectedModel.project = ProjectModel.getSelectedProject();
     }
 
-
-    $scope.toggleHasSeparateColumn = function(){
-      if($scope.partitionColumn.hasSeparateTimeColumn == false){
-        $scope.modelsManager.selectedModel.partition_desc.partition_time_column = null;
-      }
-    }
-
     $scope.prepareModel = function () {
         // generate column family
         $scope.state.project = modelsManager.selectedModel.project;

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/controllers/modelMeasures.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelMeasures.js b/webapp/app/js/controllers/modelMeasures.js
index 01cd35a..342f341 100644
--- a/webapp/app/js/controllers/modelMeasures.js
+++ b/webapp/app/js/controllers/modelMeasures.js
@@ -22,6 +22,31 @@
 
 'use strict';
 
-KylinApp.controller('ModelMeasuresCtrl', function ($scope) {
-
+KylinApp.controller('ModelMeasuresCtrl', function ($scope, $modal,MetaModel,modelsManager,VdmUtil) {
+    $scope.modelsManager = modelsManager;
+    $scope.availableFactTables = [];
+    $scope.selectedFactTables = {};
+    $scope.availableFactTables.push(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table));
+    var joinTable = $scope.modelsManager.selectedModel.lookups;
+    for (var j = 0; j < joinTable.length; j++) {
+        if(joinTable[j].kind=='FACT'){
+          $scope.availableFactTables.push(joinTable[j].alias);
+        }
+    }
+    angular.forEach($scope.modelsManager.selectedModel.metrics,function(metric){
+       $scope.selectedFactTables[VdmUtil.getNameSpaceAliasName(metric)]=$scope.selectedFactTables[VdmUtil.getNameSpaceAliasName(metric)]||[];
+       $scope.selectedFactTables[VdmUtil.getNameSpaceAliasName(metric)].push(metric);
+    });
+    $scope.changeColumns = function (table){
+       angular.forEach($scope.selectedFactTables[table],function(column){
+          if($scope.modelsManager.selectedModel.metrics.indexOf(column)==-1){
+             $scope.modelsManager.selectedModel.metrics.push(column);
+          }
+       });
+       angular.forEach($scope.modelsManager.selectedModel.metrics,function(metric){
+          if($scope.selectedFactTables[VdmUtil.getNameSpaceAliasName(metric)].indexOf(metric)==-1){
+            $scope.modelsManager.selectedModel.metrics.splice($scope.modelsManager.selectedModel.metrics.indexOf(metric),1);
+          }
+       });
+    }
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index acc4626..3b444c6 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -16,8 +16,9 @@
  * limitations under the License.
 */
 
-KylinApp.service('ModelGraphService', function () {
-
+KylinApp.service('ModelGraphService', function (VdmUtil) {
+    var tablesNodeList=[];
+    var aliasList=[];
     var margin = {top: 20, right: 100, bottom: 20, left: 100},
         width = 1100 - margin.right - margin.left,
         height = 600;
@@ -37,31 +38,52 @@ KylinApp.service('ModelGraphService', function () {
             .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
         var graphData = {
-            "type": "fact",
-            "name": model.fact_table,
+            "type": "FACT",
+            "name": VdmUtil.removeNameSpace(model.fact_table),
             "children": []
         };
-
+        tablesNodeList.push(graphData);
+        aliasList.push(graphData.name);
         model.graph = (!!model.graph) ? model.graph : {};
 
-      angular.forEach(model.lookups, function (lookup, index) {
-        if (lookup.join && lookup.join.primary_key.length > 0) {
+        angular.forEach(model.lookups, function (lookup, index) {
+          if (lookup.join && aliasList.indexOf(lookup.alias)==-1) {
+            var  dimensionNode={
+                "type": lookup.kind,
+                "name": lookup.alias,
+                "join": lookup.join,
+                "children": [],
+                "_children": []
+              }
+              aliasList.push(dimensionNode.name);
+              tablesNodeList.push(dimensionNode);
+            }
+
+        });
+        angular.forEach(model.lookups, function (lookup) {
+           if (lookup.join && lookup.join.primary_key.length > 0) {
+                  VdmUtil.getNameSpaceAliasName(lookup.join.primary_key[0]);
+                  VdmUtil.getNameSpaceAliasName(lookup.join.foreign_key[0]);
+           }
+        });
+
 
-          var dimensionNode;
+/* Loop through the graphData.children array to find out: If the LKP table is already existed *//*
 
-          /* Loop through the graphData.children array to find out: If the LKP table is already existed */
           for(var j = 0; j < graphData.children.length; j++ ) {
-            if(graphData.children[j].name == lookup.table){
+            if(graphData.children[j].name == lookup.alias){
               dimensionNode = graphData.children[j];
               break;
             }
           }
 
-          /* If not existed, create dimensionNode and push it */
+          */
+/* If not existed, create dimensionNode and push it *//*
+
           if(j == graphData.children.length) {
             dimensionNode = {
               "type": "dimension",
-              "name": lookup.table,
+              "name": lookup.alias,
               "join": lookup.join,
               "children": [],
               "_children": []
@@ -73,7 +95,7 @@ KylinApp.service('ModelGraphService', function () {
           }
 
         }
-      });
+*/
 
       angular.forEach(model.dimensions, function (dimension, index) {
         // for dimension on lookup table

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/js/utils/utils.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/utils/utils.js b/webapp/app/js/utils/utils.js
index 0875e52..1da840e 100644
--- a/webapp/app/js/utils/utils.js
+++ b/webapp/app/js/utils/utils.js
@@ -140,7 +140,27 @@ KylinApp.factory('VdmUtil', function ($modal, $timeout, $location, $anchorScroll
         return obj;
       }
       return angular.toJson(filterData(newObj),true);
-    }
-
+    },
+    removeNameSpace:function(str){
+      if(str){
+         return str.replace(/([^.\s]+\.)+/,'');
+      }else{
+        return '';
+      }
+    },
+    getNameSpaceTopName:function(str){
+      if(str){
+         return str.replace(/(\.[^.]+)/,'');
+      }else{
+        return '';
+      }
+    },
+    getNameSpaceAliasName:function(str){
+      if(str){
+         return str.replace(/\.[^.]+$/,'');
+      }else{
+        return '';
+      }
+    },
   }
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/partials/modelDesigner/conditions_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/conditions_settings.html b/webapp/app/partials/modelDesigner/conditions_settings.html
index 6e7a883..6820b60 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -15,52 +15,44 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-
-<div class="row">
+<div ng-controller="ModelConditionsSettingsCtrl">
+  <div class="row">
     <div class="col-xs-12">
       <ng-form name="forms.model_setting_form" novalidate>
 
         <h3>Partition</h3>
         <div class="box-body">
-        <!--Cube Partition Type-->
-          <div class="form-group" ng-hide="true">
-              <div class="row">
-                  <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Type</b></label>
-                  <div class="col-xs-12 col-sm-6">
-                      <select class="form-control"
-                          ng-if="state.mode=='edit'"
-                          chosen ng-model="modelsManager.selectedModel.partition_desc.partition_type"
-                          ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
-                          <option value=""></option>
-                      </select>
-                      <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.partition_desc.partition_type}}</span>
-                  </div>
-              </div>
-          </div>
-
           <!--Partition Column-->
           <div class="form-group">
               <div class="row middle-popover">
                   <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b> <i kylinpopover placement="right" title="Partition Date Column" template="partitionTip.html" class="fa fa-info-circle"></i></label>
-                  <div class="col-xs-12 col-sm-6">
-
-                      <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
-                              ng-model="modelsManager.selectedModel.partition_desc.partition_date_column"
-                              ng-if="state.mode=='edit'" ng-change="partitionChange(modelsManager.selectedModel.partition_desc.partition_date_column)"
+                  <div class="col-xs-12 col-sm-6" ng-if="state.mode=='edit'">
+                      <select style="width: 45%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
+                              ng-model="selectedTables.fact"
                               data-placement=""
-                              ng-options="modelsManager.selectedModel.fact_table+'.'+columns.name as modelsManager.selectedModel.fact_table+'.'+columns.name for columns in getPartitonColumns(modelsManager.selectedModel.fact_table)" >
-                          <option value="">--Select Partition Column--</option>
+                              ng-options="alias as alias for alias in availableFactTables" >
+                          <option value="">--Select Partition Table--</option>
                       </select>
-                      <!--<small class="text-info" ng-show="state.mode=='edit'">(Column Type should be DATE or TIMESTAMP Type)</small>-->
 
-                      <span ng-if="state.mode=='view'">
-                          {{!!(modelsManager.selectedModel.partition_desc.partition_date_column)?modelsManager.selectedModel.partition_desc.partition_date_column: ''}}</span>
+                      <select style="width: 45%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
+                            ng-model="modelsManager.selectedModel.partition_desc.partition_date_column"
+                            ng-change="partitionChange(modelsManager.selectedModel.partition_desc.partition_date_column)"
+                            data-placement=""
+                            ng-options="selectedTables.fact+'.'+columns.name as columns.name for columns in getPartitonColumns(selectedTables.fact)" >
+                      <option value="">--Select Partition Column--</option>
+                    </select>
+                      <!--<small class="text-info" ng-show="state.mode=='edit'">(Column Type should be DATE or TIMESTAMP Type)</small>-->
+                  </div>
+                  <div class="col-xs-12 col-sm-6" ng-if="state.mode=='view'">
+                     <span >
+                          {{!!(modelsManager.selectedModel.partition_desc.partition_date_column)?modelsManager.selectedModel.partition_desc.partition_date_column: ''}}
+                     </span>
                   </div>
               </div>
           </div>
 
           <!--Date Format-->
-          <div class="form-group"  ng-if="(state.mode=='edit') || (state.mode=='view')">
+          <div class="form-group" >
             <div class="row">
               <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Date Format</b></label>
               <div class="col-xs-12 col-sm-6">
@@ -68,7 +60,7 @@
                         ng-required="modelsManager.selectedModel.partition_desc.partition_date_format"
                         ng-model="modelsManager.selectedModel.partition_desc.partition_date_format"
                         ng-if="state.mode=='edit'"
-                        ng-disabled="isFormatEditable!==true"
+                        ng-disabled="$parent.isFormatEdit.editable!==true"
                         data-placement=""
                         ng-options="ddt as ddt for ddt in cubeConfig.partitionDateFormatOpt">
                   <option value="">--Select Date Format--</option>
@@ -79,7 +71,7 @@
           </div>
 
           <!--Date Format-->
-          <div class="form-group middle-popover" ng-if="isFormatEditable==true">
+          <div class="form-group middle-popover" ng-if="isFormatEdit.editable==true">
             <div class="row">
               <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Has a separate "time of the day" column ?</b>  <i kylinpopover placement="right" title="Separate Time Column" template="separateTimeColumnTip.html" class="fa fa-info-circle"></i></label>
               <div class="col-xs-12 col-sm-6">
@@ -160,8 +152,8 @@
         </div>
        </ng-form>
     </div>
+  </div>
 </div>
-
 <script type="text/ng-template" id="partitionTip.html">
     <ol>
       <li>Partition date column not required,leave as default if cube always need full build</Li>
@@ -183,3 +175,4 @@
 <script type="text/ng-template" id="separateTimeColumnTip.html">
   <p>For cases where fact table saves date and hour at two columns (KYLIN-1427)</p>
 </script>
+

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/partials/modelDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/data_model.html b/webapp/app/partials/modelDesigner/data_model.html
index ace977f..82be964 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -16,7 +16,7 @@
 * limitations under the License.
 -->
 
-<div ng-controller="CubeModelCtrl">
+<div ng-controller="ModelDataModelCtrl">
     <ng-form name="forms.data_model_form">
 
     <!-- Fact Table Name -->
@@ -26,9 +26,9 @@
                 <b>Fact Table</b>
             </label>
             <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.table_name.$invalid && (forms.data_model_form.table_name.$dirty||forms.data_model_form.$submitted)}">
-              <select chosen ng-model="modelsManager.selectedModel.fact_table" ng-if="state.mode=='edit'"
+              <select chosen ng-model="$parent.rootFactTable" ng-if="state.mode=='edit'"
                       ng-options="table.name as table.name for table in tableModel.selectProjectTables"
-                      style="width:100%;"
+                      style="width:100%;" ng-change="changeFactTable()"
                       name="table_name"
                       ng-required="true"
                       data-placeholder="Fact Table Name"
@@ -37,7 +37,7 @@
               </select>
 
                 <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$submitted)">The fact table is required</small>
-                <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.fact_table}}</span>
+                <span ng-if="state.mode=='view'">{{$parent.rootFactTable}}</span>
             </div>
         </div>
     </div>
@@ -48,11 +48,11 @@
             <div class="col-xs-6" ng-if="state.mode=='edit'">
                 <button type="button" class="btn btn-primary" ng-disabled="!modelsManager.selectedModel.fact_table.length"
                         ng-click="openLookupModal()">
-                    <i class="fa fa-plus"></i> Add Lookup Table
+                    <i class="fa fa-plus"></i> Add Join Table
                 </button>
             </div>
             <div class="col-xs-6" ng-if="state.mode!='edit'">
-                <b>{{modelsManager.selectedModel.lookups.length ? 'Lookup Tables' : 'No Lookup Tables'}}</b>
+                <b>{{modelsManager.selectedModel.lookups.length ? 'Join Tables' : 'No Join Tables'}}</b>
             </div>
             <div class="col-xs-6">
                 <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;" ng-if="modelsManager.selectedModel.lookups.length">
@@ -66,19 +66,24 @@
             <tr>
                 <th>ID</th>
                 <th>Table Name</th>
+                <th>Table Kind</th>
                 <th>Join Type</th>
                 <th>Join Condition</th>
                 <th ng-if="state.mode=='edit'">Actions</th>
             </tr>
             </thead>
             <tbody>
-            <tr ng-repeat="lookup in modelsManager.selectedModel.lookups | filter:lookupState.filter track by $index">
+            <tr ng-repeat="lookup in modelsManager.selectedModel.lookups | filter:lookupState.filter">
                 <td>
                     <b>{{$index + 1}}</b>
                 </td>
                 <!-- Table Name -->
                 <td>
-                    <span tooltip="Lookup Table Name">{{lookup.table}}</span>
+                    <span>{{lookup.alias}}</span>
+                </td>
+                <!-- Table Kind -->
+                <td>
+                    <span>{{lookup.kind}}</span>
                 </td>
                 <!-- Join Type -->
                 <td>
@@ -88,7 +93,7 @@
                 <td>
                     <ul class="list-unstyled">
                         <li ng-repeat="pk in lookup.join.primary_key track by $index">
-                            <code>{{modelsManager.selectedModel.fact_table + '.' + lookup.join.foreign_key[$index]}} = {{lookup.table + '.' + pk}}</code>
+                            <code>{{lookup.join.foreign_key[$index]}} = {{pk}}</code>
                         </li>
                     </ul>
                 </td>
@@ -108,7 +113,7 @@
     </div>
     </ng-form>
 
-    <!-- Add Lookup Table Form -->
+    <!-- Add Join Table Form -->
     <script type="text/ng-template" id="dataModelLookupTable.html">
         <div class="modal-header">
             <h4 class="box-title lighter">{{lookupState.editing ? 'Edit' : 'Add'}} Lookup</h4>
@@ -117,28 +122,45 @@
             <div class="row">
                 <div class="col-xs-8">
                     <ng-form name="lookup_form">
-                    <!--Table Name-->
-                    <div class="form-group">
+                      <div class="form-group">
                         <div class="row">
-                            <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Lookup Table Name</b></label>
-                            <div ng-class="{'has-error':lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)}">
-                                <div class="col-xs-12 col-sm-6">
-                                  <select chosen ng-model="newLookup.table"
-                                          ng-options="table.name as table.name for table in tableModel.selectProjectTables"
-                                          style="width:100%;"
-                                          name="table_name"
-                                          ng-required="true"
-                                          data-placeholder="Lookup Table Name"
-                                          class="chosen-select">
-                                    <option value=""> -- Select Lookup Table -- </option>
-                                  </select>
+                          <div class="col-xs-9">
+                            <div>
+                              <select chosen ng-model="newLookup.joinTable" style="width: 45%"
+                                      ng-options="table as table for table in aliasName"
+                                      name="table_name"
+                                      ng-required="true"
+                                      data-placeholder="Join Table Name"
+                                      class="chosen-select">
+                                <option value=""> &#45;&#45; Select Join Table &#45;&#45; </option>
+                              </select>
+                              <small class="help-block" ng-show="lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)">Table name required</small>
+                              <b>&nbsp;</b>
+                              <select chosen ng-model="newLookup.table" style="width: 45%"
+                                      ng-options="table.name as table.name for table in tableModel.selectProjectTables"
+                                      name="table_name"
+                                      ng-required="true"  ng-change="changeJoinTable()"
+                                      data-placeholder="Join Table Name"
+                                      class="chosen-select">
+                                <option value=""> &#45;&#45; Select Join Table &#45;&#45; </option>
+                              </select>
+                              <small class="help-block" ng-show="lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)">Table name required</small>
 
-                                    <small class="help-block" ng-show="lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)">Table name required</small>
-                                </div>
+                            </div>
+                            <div class="space-4"></div>
+                            <small class="help-block red" ng-show="newLookup.join.isCompatible[$index]==false"><i class="fa fa-exclamation-triangle"></i> <b>Column Type incompatible {{newLookup.join.foreign_key[$index]}}[{{newLookup.join.fk_type[$index]}}], {{newLookup.join.primary_key[$index]}} [{{newLookup.join.pk_type[$index]}}]</b></small>
+                          </div>
+                        </div>
+                      </div>
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-sm-3 control-label font-color-default"><b>Alias</b></label>
+                            <div class="col-sm-6">
+                              <input type="text" class="form-control " placeholder="Input Table Alias" ng-required="true"
+                                     ng-model="newLookup.alias" ng-change="changeAlias()" ng-disabled="">
                             </div>
                         </div>
                     </div>
-
                     <!--Join Type and Columns-->
                     <div class="form-group">
                         <div class="row">
@@ -153,18 +175,27 @@
                     </div>
                     <div class="form-group">
                         <div class="row">
+                          <label class="col-sm-3 control-label font-color-default"><b>Table Type</b></label>
+                          <div class="col-sm-6">
+                            <label> <input type="radio" ng-model="newLookup.kind" value="FACT" > Fact Table </label>
+                            <label> <input type="radio" ng-model="newLookup.kind" value="LOOKUP"> Lookup Table </label>
+                          </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="row">
                             <div class="col-xs-9">
                                 <div ng-repeat="joinIndex in [] | range: newLookup.join.primary_key.length">
                                     <div>
                                         <select style="width: 45%" chosen data-placeholder="Fact Table Column"
                                                 ng-model="newLookup.join.foreign_key[$index]"  ng-change="changeKey($index)"
-                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(modelsManager.selectedModel.fact_table)" >
+                                                ng-options="newLookup.joinTable+'.'+columns.name as columns.name for columns in getColumnsByAlias(newLookup.joinTable)" >
                                             <option value=""></option>
                                         </select>
                                         <b>=</b>
                                         <select style="width: 45%" chosen data-placeholder="Lookup Table Column"
                                                 ng-model="newLookup.join.primary_key[$index]"  ng-change="changeKey($index)"
-                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(newLookup.table)" >
+                                                ng-options="newLookup.alias+'.'+columns.name as columns.name for columns in getColumnsByTable(newLookup.table)" >
                                             <option value=""></option>
                                         </select>
                                         <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer" tooltip="Delete"

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/partials/modelDesigner/model_dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_dimensions.html b/webapp/app/partials/modelDesigner/model_dimensions.html
index f767b9d..6249521 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -70,13 +70,13 @@
                     </td>
                     <td class="col-xs-9">
                       <ui-select
-                        ng-if="state.mode=='edit'" style="width: 100%"
+                        style="width: 100%"
                         autofocus="true"
                         close-on-select="false"
                         ng-model="modelsManager.selectedModel.dimensions[$index].columns" multiple>
                         <ui-select-match placeholder="Select Column...">{{$item.name}}</ui-select-match>
                         <ui-select-choices
-                          repeat="column.name as column in getColumnsByTable(dimension.table) | filter:$select.search">
+                          repeat="column.name as column in getColumnsByAlias(dimension.table) | filter:$select.search">
                           {{column.name}}
                         </ui-select-choices>
                       </ui-select>

http://git-wip-us.apache.org/repos/asf/kylin/blob/d5b8c7f2/webapp/app/partials/modelDesigner/model_measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_measures.html b/webapp/app/partials/modelDesigner/model_measures.html
index 20c73c3..f34e3fb 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -17,10 +17,10 @@
 -->
 
 <!-- Measures Summary -->
-<ng-form name="forms.model_measure_form" novalidate>
-<div class="dataTables_wrapper form-inline no-footer">
-
-    <table ng-if="state.mode=='view'&&modelsManager.selectedModel.metrics.length > 0" class="table table-striped table-hover">
+<div ng-controller="ModelMeasuresCtrl">
+  <ng-form name="forms.model_measure_form" novalidate>
+    <div class="dataTables_wrapper form-inline no-footer">
+      <table ng-if="state.mode=='view'&&modelsManager.selectedModel.metrics.length > 0" class="table table-striped table-hover">
         <thead>
             <tr>
                 <th>ID</th>
@@ -39,23 +39,42 @@
                 </td>
             </tr>
         </tbody>
-    </table>
-    <div  ng-if="state.mode=='edit'" class="form-group" style="width: 100%">
+      </table>
+      <div  ng-if="state.mode=='edit'" class="form-group" style="width: 100%">
         <h4 style="margin-left:42px">Select measure columns</h4>
-      <ui-select
-        close-on-select="false"
-        ng-if="state.mode=='edit'"
-        style="width: 100%"
-        autofocus="true"
-        ng-model="modelsManager.selectedModel.metrics" multiple>
-        <ui-select-match placeholder="Select Column...">{{$item.name}}</ui-select-match>
-          <ui-select-choices
-            repeat="measure.name as measure in getColumnsByTable(modelsManager.selectedModel.fact_table) | filter:$select.search">
-            {{measure.name}}
-          </ui-select-choices>
-      </ui-select>
+        <table style="margin-left:42px; width:92%"
+               class="table table-hover list">
+          <tr class="row">
+            <th class="col-xs-1">ID</th>
+            <th class="col-xs-2">Table Name</th>
+            <th class="col-xs-9">Columns</th>
+          </tr>
 
+          <tr  class="row" ng-repeat="table in availableFactTables ">
+            <td class="col-xs-1">
+              <!-- ID -->
+              <b>{{($index + 1)}}</b>
+            </td>
+            <td class="col-xs-2">
+              {{table}}
+            </td>
+            <td class="col-xs-9">
+              <ui-select
+                close-on-select="false"
+                ng-if="state.mode=='edit'"
+                style="width: 100%" ng-change="changeColumns(table)"
+                autofocus="true"
+                ng-model="selectedFactTables[table]" multiple>
+                <ui-select-match placeholder="Select Column...">{{$item.name}}</ui-select-match>
+                <ui-select-choices
+                  repeat="table+'.'+measure.name as measure in getColumnsByAlias(table) | filter:$select.search">
+                  {{measure.name}}
+                </ui-select-choices>
+              </ui-select>
+            </td>
+          </tr>
+        </table>
+      </div>
     </div>
+  </ng-form>
 </div>
-
-</ng-form>


[11/14] kylin git commit: KYLIN-2180: refactor ProjectRequest

Posted by li...@apache.org.
KYLIN-2180: refactor ProjectRequest

Signed-off-by: Li Yang <li...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/911bdd00
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/911bdd00
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/911bdd00

Branch: refs/heads/KYLIN-2283
Commit: 911bdd00afb9176af594fe97cbc0a639f376da2d
Parents: 3003d9f
Author: kangkaisen <ka...@live.com>
Authored: Sun Dec 11 17:17:40 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Fri Dec 16 11:18:15 2016 +0800

----------------------------------------------------------------------
 .../rest/controller/ProjectController.java      | 48 ++++++++++----
 .../rest/request/CreateProjectRequest.java      | 57 ----------------
 .../kylin/rest/request/ProjectRequest.java      | 47 +++++++++++++
 .../rest/request/UpdateProjectRequest.java      | 66 -------------------
 .../kylin/rest/service/ProjectService.java      | 23 +++----
 .../rest/controller/ProjectControllerTest.java  | 69 ++++++++++++--------
 webapp/app/js/controllers/page.js               | 27 +++-----
 7 files changed, 143 insertions(+), 194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
index 05af82c..a6edece 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
@@ -24,13 +24,13 @@ import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.constant.Constant;
 import org.apache.kylin.rest.exception.BadRequestException;
 import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CreateProjectRequest;
-import org.apache.kylin.rest.request.UpdateProjectRequest;
+import org.apache.kylin.rest.request.ProjectRequest;
 import org.apache.kylin.rest.service.AccessService;
 import org.apache.kylin.rest.service.CubeService;
 import org.apache.kylin.rest.service.ProjectService;
@@ -198,19 +198,22 @@ public class ProjectController extends BasicController {
 
     @RequestMapping(value = "", method = { RequestMethod.POST })
     @ResponseBody
-    public ProjectInstance saveProject(@RequestBody CreateProjectRequest projectRequest) {
-        if (StringUtils.isEmpty(projectRequest.getName())) {
-            logger.info("Project name should not be empty.");
-            throw new BadRequestException("Project name should not be empty.");
+
+    public ProjectInstance saveProject(@RequestBody ProjectRequest projectRequest) {
+        ProjectInstance projectDesc = deserializeProjectDesc(projectRequest);
+
+        if (StringUtils.isEmpty(projectDesc.getName())) {
+            throw new InternalErrorException("A project name must be given to create a project");
         }
-        if (!StringUtils.containsOnly(projectRequest.getName(), VALID_PROJECTNAME)) {
-            logger.info("Invalid Project name {}, only letters, numbers and underline supported.", projectRequest.getName());
+
+        if (!StringUtils.containsOnly(projectDesc.getName(), VALID_PROJECTNAME)) {
+            logger.info("Invalid Project name {}, only letters, numbers and underline supported.", projectDesc.getName());
             throw new BadRequestException("Invalid Project name, only letters, numbers and underline supported.");
         }
 
         ProjectInstance createdProj = null;
         try {
-            createdProj = projectService.createProject(projectRequest);
+            createdProj = projectService.createProject(projectDesc);
         } catch (Exception e) {
             logger.error("Failed to deal with the request.", e);
             throw new InternalErrorException(e.getLocalizedMessage());
@@ -221,15 +224,22 @@ public class ProjectController extends BasicController {
 
     @RequestMapping(value = "", method = { RequestMethod.PUT })
     @ResponseBody
-    public ProjectInstance updateProject(@RequestBody UpdateProjectRequest projectRequest) {
-        if (StringUtils.isEmpty(projectRequest.getFormerProjectName())) {
+    public ProjectInstance updateProject(@RequestBody ProjectRequest projectRequest) {
+        String formerProjectName = projectRequest.getFormerProjectName();
+        if (StringUtils.isEmpty(formerProjectName)) {
             throw new InternalErrorException("A project name must be given to update a project");
         }
 
+        ProjectInstance projectDesc = deserializeProjectDesc(projectRequest);
+
         ProjectInstance updatedProj = null;
         try {
-            ProjectInstance currentProject = projectService.getProjectManager().getProject(projectRequest.getFormerProjectName());
-            updatedProj = projectService.updateProject(projectRequest, currentProject);
+            ProjectInstance currentProject = projectService.getProjectManager().getProject(formerProjectName);
+            if (currentProject == null) {
+                throw new InternalErrorException("The project named " + formerProjectName + " does not exists");
+            }
+
+            updatedProj = projectService.updateProject(projectDesc, currentProject);
         } catch (Exception e) {
             logger.error("Failed to deal with the request.", e);
             throw new InternalErrorException(e.getLocalizedMessage());
@@ -238,6 +248,18 @@ public class ProjectController extends BasicController {
         return updatedProj;
     }
 
+    private ProjectInstance deserializeProjectDesc(ProjectRequest projectRequest) {
+        ProjectInstance projectDesc = null;
+        try {
+            logger.debug("Saving project " + projectRequest.getProjectDescData());
+            projectDesc = JsonUtil.readValue(projectRequest.getProjectDescData(), ProjectInstance.class);
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return projectDesc;
+    }
+
     @RequestMapping(value = "/{projectName}", method = { RequestMethod.DELETE })
     @ResponseBody
     public void deleteProject(@PathVariable String projectName) {

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
deleted file mode 100644
index 00fe1eb..0000000
--- a/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-package org.apache.kylin.rest.request;
-
-import java.util.LinkedHashMap;
-
-/**
- */
-public class CreateProjectRequest {
-    private String name;
-    private String description;
-    private LinkedHashMap<String, String> overrideKylinProps;
-
-    public CreateProjectRequest() {
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public LinkedHashMap<String, String> getOverrideKylinProps() {
-        return overrideKylinProps;
-    }
-
-    public void setOverrideKylinProps(LinkedHashMap<String, String> overrideKylinProps) {
-        this.overrideKylinProps = overrideKylinProps;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server-base/src/main/java/org/apache/kylin/rest/request/ProjectRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/ProjectRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/ProjectRequest.java
new file mode 100644
index 0000000..da6e190
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/ProjectRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.rest.request;
+
+/**
+ */
+public class ProjectRequest {
+    private String formerProjectName;
+
+    private String projectDescData;
+
+    public ProjectRequest() {
+    }
+
+    public String getProjectDescData() {
+        return projectDescData;
+    }
+
+    public void setProjectDescData(String projectDescData) {
+        this.projectDescData = projectDescData;
+    }
+
+    public String getFormerProjectName() {
+        return formerProjectName;
+    }
+
+    public void setFormerProjectName(String formerProjectName) {
+        this.formerProjectName = formerProjectName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
deleted file mode 100644
index f253c9c..0000000
--- a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-package org.apache.kylin.rest.request;
-
-import java.util.LinkedHashMap;
-
-/**
- */
-public class UpdateProjectRequest {
-    private String formerProjectName;
-    private String newProjectName;
-    private String newDescription;
-    private LinkedHashMap<String, String> overrideKylinProps;
-
-    public UpdateProjectRequest() {
-    }
-
-    public String getFormerProjectName() {
-        return formerProjectName;
-    }
-
-    public void setFormerProjectName(String formerProjectName) {
-
-        this.formerProjectName = formerProjectName;
-    }
-
-    public String getNewDescription() {
-        return newDescription;
-    }
-
-    public void setNewDescription(String newDescription) {
-        this.newDescription = newDescription;
-    }
-
-    public String getNewProjectName() {
-        return newProjectName;
-    }
-
-    public void setNewProjectName(String newProjectName) {
-        this.newProjectName = newProjectName;
-    }
-
-    public LinkedHashMap<String, String> getOverrideKylinProps() {
-        return overrideKylinProps;
-    }
-
-    public void setOverrideKylinProps(LinkedHashMap<String, String> overrideKylinProps) {
-        this.overrideKylinProps = overrideKylinProps;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
index 283cf4a..e6f546c 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
@@ -27,8 +27,6 @@ import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.rest.constant.Constant;
 import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CreateProjectRequest;
-import org.apache.kylin.rest.request.UpdateProjectRequest;
 import org.apache.kylin.rest.security.AclPermission;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,10 +49,10 @@ public class ProjectService extends BasicService {
     private AccessService accessService;
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public ProjectInstance createProject(CreateProjectRequest projectRequest) throws IOException {
-        String projectName = projectRequest.getName();
-        String description = projectRequest.getDescription();
-        LinkedHashMap<String, String> overrideProps = projectRequest.getOverrideKylinProps();
+    public ProjectInstance createProject(ProjectInstance newProject) throws IOException {
+        String projectName = newProject.getName();
+        String description = newProject.getDescription();
+        LinkedHashMap<String, String> overrideProps = newProject.getOverrideKylinProps();
 
         ProjectInstance currentProject = getProjectManager().getProject(projectName);
 
@@ -70,15 +68,10 @@ public class ProjectService extends BasicService {
     }
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#currentProject, 'ADMINISTRATION') or hasPermission(#currentProject, 'MANAGEMENT')")
-    public ProjectInstance updateProject(UpdateProjectRequest projectRequest, ProjectInstance currentProject) throws IOException {
-        String formerProjectName = projectRequest.getFormerProjectName();
-        String newProjectName = projectRequest.getNewProjectName();
-        String newDescription = projectRequest.getNewDescription();
-        LinkedHashMap<String, String> overrideProps = projectRequest.getOverrideKylinProps();
-
-        if (currentProject == null) {
-            throw new InternalErrorException("The project named " + formerProjectName + " does not exists");
-        }
+    public ProjectInstance updateProject(ProjectInstance newProject, ProjectInstance currentProject) throws IOException {
+        String newProjectName = newProject.getName();
+        String newDescription = newProject.getDescription();
+        LinkedHashMap<String, String> overrideProps = newProject.getOverrideKylinProps();
 
         ProjectInstance updatedProject = getProjectManager().updateProject(currentProject, newProjectName, newDescription, overrideProps);
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
index 9a6dfbe..cd9a524 100644
--- a/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/controller/ProjectControllerTest.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,13 +19,12 @@
 package org.apache.kylin.rest.controller;
 
 import java.io.IOException;
-import java.util.List;
+import java.io.StringWriter;
 
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CreateProjectRequest;
-import org.apache.kylin.rest.request.UpdateProjectRequest;
+import org.apache.kylin.rest.request.ProjectRequest;
 import org.apache.kylin.rest.service.ProjectService;
 import org.apache.kylin.rest.service.ServiceTestBase;
 import org.junit.Assert;
@@ -33,6 +32,8 @@ import org.junit.Before;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 /**
  */
 public class ProjectControllerTest extends ServiceTestBase {
@@ -48,6 +49,7 @@ public class ProjectControllerTest extends ServiceTestBase {
 
         projectController = new ProjectController();
         projectController.setProjectService(projectService);
+
         try {
             projectController.deleteProject("new_project");
         } catch (InternalErrorException e) {
@@ -58,38 +60,34 @@ public class ProjectControllerTest extends ServiceTestBase {
         } catch (InternalErrorException e) {
             //project doesn't exist
         }
-
     }
 
     @Test
     public void testAddUpdateProject() throws IOException {
+        int originalProjectCount = projectController.getProjects(null, null).size();
 
-        List<ProjectInstance> projects = projectController.getProjects(null, null);
-
-        int originalProjectCount = projects.size();
-        CreateProjectRequest request = new CreateProjectRequest();
-        request.setName("new_project");
-        ProjectInstance ret = projectController.saveProject(request);
+        //test add project
+        ProjectInstance project = new ProjectInstance();
+        project.setName("new_project");
+        ProjectInstance ret = projectController.saveProject(getProjectRequest(project, null));
 
         Assert.assertEquals(ret.getOwner(), "ADMIN");
         Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1);
 
-        UpdateProjectRequest updateR = new UpdateProjectRequest();
-        updateR.setFormerProjectName("new_project");
-        updateR.setNewProjectName("new_project_2");
-        projectController.updateProject(updateR);
+        //test update project
+        ProjectInstance newProject = new ProjectInstance();
+        newProject.setName("new_project_2");
+        projectController.updateProject(getProjectRequest(newProject, "new_project"));
 
         Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1);
         Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project"), null);
-
         Assert.assertNotEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project_2"), null);
 
-        // only update desc:
-        updateR = new UpdateProjectRequest();
-        updateR.setFormerProjectName("new_project_2");
-        updateR.setNewProjectName("new_project_2");
-        updateR.setNewDescription("hello world");
-        projectController.updateProject(updateR);
+        //test update project description only
+        ProjectInstance newProject2 = new ProjectInstance();
+        newProject2.setName("new_project_2");
+        newProject2.setDescription("hello world");
+        projectController.updateProject(getProjectRequest(newProject2, "new_project_2"));
 
         Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).listAllProjects().size(), originalProjectCount + 1);
         Assert.assertEquals(ProjectManager.getInstance(getTestConfig()).getProject("new_project"), null);
@@ -99,8 +97,27 @@ public class ProjectControllerTest extends ServiceTestBase {
 
     @Test(expected = InternalErrorException.class)
     public void testAddExistingProject() throws IOException {
-        CreateProjectRequest request = new CreateProjectRequest();
-        request.setName("default");
-        projectController.saveProject(request);
+        ProjectInstance newProject = new ProjectInstance();
+        newProject.setName("default");
+
+        projectController.saveProject(getProjectRequest(newProject, null));
+    }
+
+    private ProjectRequest getProjectRequest(ProjectInstance project, String formerProjectName) throws IOException {
+        ProjectRequest request = new ProjectRequest();
+        request.setProjectDescData(getProjectDescData(project));
+        request.setFormerProjectName(formerProjectName);
+
+        return request;
+    }
+
+    private String getProjectDescData(ProjectInstance project) throws IOException {
+        ObjectMapper projectMapper = new ObjectMapper();
+        StringWriter projectWriter = new StringWriter();
+        projectMapper.writeValue(projectWriter, project);
+
+        System.err.println(projectWriter.toString());
+
+        return projectWriter.toString();
     }
 }

http://git-wip-us.apache.org/repos/asf/kylin/blob/911bdd00/webapp/app/js/controllers/page.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/page.js b/webapp/app/js/controllers/page.js
index 2b6bc64..056cc48 100644
--- a/webapp/app/js/controllers/page.js
+++ b/webapp/app/js/controllers/page.js
@@ -195,7 +195,7 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
     projectIdx: -1
   };
   $scope.isEdit = false;
-  $scope.proj = {name: '', description: '', overrideKylinProps: {}};
+  $scope.proj = {name: '', description: '', override_kylin_properties: {}};
   $scope.convertedProperties = [];
 
   if (project) {
@@ -203,10 +203,10 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
     $scope.state.oldProjName = project.name;
     $scope.proj = project;
 
-    for (var key in $scope.proj.overrideKylinProps) {
+    for (var key in $scope.proj.override_kylin_properties) {
       $scope.convertedProperties.push({
         name: key,
-        value: $scope.proj.overrideKylinProps[key]
+        value: $scope.proj.override_kylin_properties[key]
       });
     }
 
@@ -220,14 +220,7 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
 
   $scope.createOrUpdate = function () {
     if ($scope.state.isEdit) {
-
-      var requestBody = {
-        formerProjectName: $scope.state.oldProjName,
-        newProjectName: $scope.proj.name,
-        newDescription: $scope.proj.description,
-        overrideKylinProps: $scope.proj.overrideKylinProps
-      };
-      ProjectService.update({}, requestBody, function (newProj) {
+      ProjectService.update({}, {formerProjectName: $scope.state.oldProjName, projectDescData: angular.toJson($scope.proj)}, function (newProj) {
         SweetAlert.swal('Success!', 'Project update successfully!', 'success');
 
         //update project in project model
@@ -246,7 +239,7 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
       });
     }
     else {
-      ProjectService.save({}, $scope.proj, function (newProj) {
+      ProjectService.save({}, {projectDescData: angular.toJson($scope.proj)}, function (newProj) {
         SweetAlert.swal('Success!', 'New project created successfully!', 'success');
         $modalInstance.dismiss('cancel');
         $cookieStore.put("project", newProj.name);
@@ -271,10 +264,10 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
   };
 
   $scope.addNewProperty = function () {
-    if ($scope.proj.overrideKylinProps.hasOwnProperty('')) {
+    if ($scope.proj.override_kylin_properties.hasOwnProperty('')) {
       return;
     }
-    $scope.proj.overrideKylinProps[''] = '';
+    $scope.proj.override_kylin_properties[''] = '';
     $scope.convertedProperties.push({
       name: '',
       value: ''
@@ -282,9 +275,9 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
   };
 
   $scope.refreshPropertiesObj = function () {
-    $scope.proj.overrideKylinProps = {};
+    $scope.proj.override_kylin_properties = {};
     angular.forEach($scope.convertedProperties, function (item, index) {
-      $scope.proj.overrideKylinProps[item.name] = item.value;
+      $scope.proj.override_kylin_properties[item.name] = item.value;
     })
   };
 
@@ -299,7 +292,7 @@ var projCtrl = function ($scope, $location, $modalInstance, ProjectService, Mess
     if (index > -1) {
       arr.splice(index, 1);
     }
-    delete $scope.proj.overrideKylinProps[item.name];
+    delete $scope.proj.override_kylin_properties[item.name];
   }
 
 };


[14/14] kylin git commit: halfway

Posted by li...@apache.org.
halfway


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/e79626e7
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/e79626e7
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/e79626e7

Branch: refs/heads/KYLIN-2283
Commit: e79626e7c35a914d011f0425025f03e8fac1fbf9
Parents: f6208f8
Author: Yang Li <li...@apache.org>
Authored: Fri Dec 16 06:24:31 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Fri Dec 16 16:06:48 2016 +0800

----------------------------------------------------------------------
 .../kylin/source/datagen/ColumnGenConfig.java   |  30 ++-
 .../kylin/source/datagen/ColumnGenerator.java   | 202 ++++++++++++++++++-
 2 files changed, 222 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/e79626e7/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
index 91f5366..f174eef 100644
--- a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenConfig.java
@@ -19,30 +19,34 @@
 package org.apache.kylin.source.datagen;
 
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.kylin.metadata.model.ColumnDesc;
 
 public class ColumnGenConfig {
 
+    public static final String $RANDOM = "${RANDOM}";
+    
     // discrete values
+    boolean isDiscrete;
     List<String> values;
     
     // random
     boolean isRandom;
-    int randCardinality;
+    String randFormat;
+    int randStart;
+    int randEnd;
     
     // ID
     boolean isID;
     int idStart;
     
-    // null handling
+    // general
+    int cardinality;
     boolean genNull;
     double genNullPct;
+    boolean order;
     
     public ColumnGenConfig(ColumnDesc col) {
         init(col.getName(), col.getDataGen());
@@ -53,17 +57,25 @@ public class ColumnGenConfig {
         Map<String, String> config = Util.parseEqualCommaPairs(dataGen, "values");
         
         values = Arrays.asList(Util.parseString(config, "values", "").split("|"));
+        if (values.size() == 1 && values.get(0).isEmpty())
+            values.set(0, $RANDOM);
         
         if ("ID".equals(values.get(0))) {
             isID = true;
             idStart = (values.size() > 1) ? Integer.parseInt(values.get(1)) : 0;
-        } else {
+        } else if (values.get(0).contains($RANDOM)) {
             isRandom = true;
-            randCardinality = Util.parseInt(config, "cardinality", guessCardinality(col));
+            randFormat = values.get(0);
+            randStart = (values.size() > 1) ? Integer.parseInt(values.get(1)) : 0;
+            randEnd = (values.size() > 2) ? Integer.parseInt(values.get(2)) : 0;
+        } else {
+            isDiscrete = true;
         }
         
-        genNull = Util.parseBoolean(config, "genNull", guessGenNull(col));
-        genNullPct = Util.parseDouble(config, "genNullPct", 0.01);
+        cardinality = Util.parseInt(config, "card", guessCardinality(col));
+        genNull = Util.parseBoolean(config, "null", guessGenNull(col));
+        genNullPct = Util.parseDouble(config, "nullPct", 0.01);
+        order = Util.parseBoolean(config, "order", false);
     }
 
     private int guessCardinality(String col) {

http://git-wip-us.apache.org/repos/asf/kylin/blob/e79626e7/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
index c4c4fe7..409a1e9 100644
--- a/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
+++ b/core-metadata/src/main/java/org/apache/kylin/source/datagen/ColumnGenerator.java
@@ -18,24 +18,224 @@
 
 package org.apache.kylin.source.datagen;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.TreeSet;
 
+import org.apache.kylin.metadata.datatype.DataType;
 import org.apache.kylin.metadata.model.ColumnDesc;
 
 public class ColumnGenerator {
 
+    final private ColumnGenConfig conf;
     final private ColumnDesc targetCol;
     final private int targetRows;
     final private ModelDataGenerator modelGen;
 
     public ColumnGenerator(ColumnDesc col, int nRows, ModelDataGenerator modelGen) {
+        this.conf = new ColumnGenConfig(col);
         this.targetCol = col;
         this.targetRows = nRows;
         this.modelGen = modelGen;
     }
     
     public Iterator<String> generate() {
-        return null;
+        Iterator<String> result;
+        if (conf.isID) {
+            result = new IDIter(conf.idStart);
+        } else if (conf.isRandom) {
+            result = new RandomIter(targetCol.getType(), conf.randFormat, conf.randStart, Math.max(conf.randEnd, conf.randStart + conf.cardinality));
+        } else {
+            result = new DiscreteIter(conf.values);
+        }
+        
+        if (conf.cardinality > 0) {
+            result = new CardinalityIter(result, conf.cardinality);
+        }
+        
+        if (conf.genNull) {
+            result = new AddNullIter(result, conf.genNullPct);
+        }
+        
+        if (conf.order) {
+            result = new OrderIter(result, targetRows);
+        }
+        
+        return result;
     }
     
+    private static class RandomIter implements Iterator<String> {
+
+        public RandomIter(DataType type, String format, int randStart, int randEnd) {
+            // TODO Auto-generated constructor stub
+        }
+
+        @Override
+        public boolean hasNext() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public String next() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+        
+    }
+    
+    private static class IDIter implements Iterator<String> {
+
+        int next;
+        
+        public IDIter(int start) {
+            next = start;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return true;
+        }
+
+        @Override
+        public String next() {
+            return "" + (next++);
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+    
+    private static class DiscreteIter implements Iterator<String> {
+
+        private List<String> values;
+        private Random rand = new Random();
+
+        public DiscreteIter(List<String> values) {
+            this.values = values;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return true;
+        }
+
+        @Override
+        public String next() {
+            if (values.isEmpty())
+                return null;
+            else
+                return values.get(rand.nextInt(values.size()));
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+    
+    private static class CardinalityIter implements Iterator<String> {
+
+        private Iterator<String> input;
+        private int card;
+        private TreeSet<String> cache;
+
+        public CardinalityIter(Iterator<String> input, int card) {
+            assert card > 0;
+            this.input = input;
+            this.card = card;
+            this.cache = new TreeSet<String>();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return input.hasNext();
+        }
+
+        @Override
+        public String next() {
+            String r = input.next();
+            
+            if (cache.size() < card) {
+                cache.add(r);
+                return r;
+            }
+            
+            r = cache.floor(r);
+            return r == null ? cache.first() : r;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static class AddNullIter implements Iterator<String> {
+
+        private Iterator<String> input;
+        private double nullPct;
+        private Random rand = new Random();
+
+        public AddNullIter(Iterator<String> input, double nullPct) {
+            this.input = input;
+            this.nullPct = nullPct;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return true;
+        }
+
+        @Override
+        public String next() {
+            return rand.nextDouble() < nullPct || !input.hasNext() ? null : input.next();
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+    
+    private static class OrderIter implements Iterator<String> {
+
+        private Iterator<String> iter;
+        
+        public OrderIter(Iterator<String> input, int targetRows) {
+            ArrayList<String> cache = new ArrayList<>(targetRows);
+            for (int i = 0; i < targetRows; i++) {
+                cache.add(input.next());
+            }
+            Collections.sort(cache);
+            
+            iter = cache.iterator();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return iter.hasNext();
+        }
+
+        @Override
+        public String next() {
+            return iter.next();
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }


[10/14] kylin git commit: minor, fix NPE in OLAPTable

Posted by li...@apache.org.
minor, fix NPE in OLAPTable


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/3003d9fb
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/3003d9fb
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/3003d9fb

Branch: refs/heads/KYLIN-2283
Commit: 3003d9fba7c0b20a74785cbc431f9e708e775418
Parents: 1c2c43c
Author: Yang Li <li...@apache.org>
Authored: Fri Dec 16 07:57:33 2016 +0800
Committer: Yang Li <li...@apache.org>
Committed: Fri Dec 16 07:57:33 2016 +0800

----------------------------------------------------------------------
 .../java/org/apache/kylin/query/schema/OLAPTable.java  | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/3003d9fb/query/src/main/java/org/apache/kylin/query/schema/OLAPTable.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/schema/OLAPTable.java b/query/src/main/java/org/apache/kylin/query/schema/OLAPTable.java
index 06ffdba..c33c4ed 100644
--- a/query/src/main/java/org/apache/kylin/query/schema/OLAPTable.java
+++ b/query/src/main/java/org/apache/kylin/query/schema/OLAPTable.java
@@ -43,13 +43,13 @@ import org.apache.calcite.schema.impl.AbstractTableQueryable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.datatype.DataType;
 import org.apache.kylin.metadata.model.ColumnDesc;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.model.FunctionDesc;
 import org.apache.kylin.metadata.model.MeasureDesc;
 import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.RealizationType;
@@ -198,14 +198,13 @@ public class OLAPTable extends AbstractQueryableTable implements TranslatableTab
             }
         }
         //2. All integer measures in non-cube realizations
-        MetadataManager metadataManager = MetadataManager.getInstance(olapSchema.getConfig());
         for (IRealization realization : mgr.listAllRealizations(olapSchema.getProjectName())) {
             if (realization.getType() == RealizationType.INVERTED_INDEX && realization.getModel().isFactTable(sourceTable.getIdentity())) {
-                DataModelDesc dataModelDesc = realization.getModel();
-                for (String metricColumn : dataModelDesc.getMetrics()) {
-                    ColumnDesc columnDesc = metadataManager.getColumnDesc(dataModelDesc.getRootFactTable().getTableIdentity() + "." + metricColumn);
-                    if (columnDesc.getType().isIntegerFamily() && !columnDesc.getType().isBigInt())
-                        updateColumns.add(columnDesc);
+                DataModelDesc model = realization.getModel();
+                for (String metricColumn : model.getMetrics()) {
+                    TblColRef col = model.findColumn(metricColumn);
+                    if (col.getType().isIntegerFamily() && !col.getType().isBigInt())
+                        updateColumns.add(col.getColumnDesc());
                 }
             }
         }


[08/14] kylin git commit: KYLIN-2275, Remove dimensions cause wrong remove in advance settings

Posted by li...@apache.org.
KYLIN-2275,Remove dimensions cause wrong remove in advance settings

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/076fbcfb
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/076fbcfb
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/076fbcfb

Branch: refs/heads/KYLIN-2283
Commit: 076fbcfb616cee4b4696cae20178ad6dc8365b3c
Parents: 36a42d8
Author: luguosheng <55...@qq.com>
Authored: Tue Dec 13 14:41:31 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeEdit.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/076fbcfb/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 85bd4b1..b901e48 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -662,14 +662,18 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             var mandatory = group.select_rule.mandatory_dims;
             if(mandatory && mandatory.length){
               var columnIndex = mandatory.indexOf(deprecatedItem);
-              group.select_rule.mandatory_dims.splice(columnIndex,1);
+              if(columnIndex>=0){
+                group.select_rule.mandatory_dims.splice(columnIndex,1);
+              }
             }
 
             var hierarchys =  group.select_rule.hierarchy_dims;
             if(hierarchys && hierarchys.length){
               for(var i=0;i<hierarchys.length;i++){
                 var hierarchysIndex = hierarchys[i].indexOf(deprecatedItem);
-                group.select_rule.hierarchy_dims[i].splice(hierarchysIndex,1);
+                if(hierarchysIndex>=0) {
+                  group.select_rule.hierarchy_dims[i].splice(hierarchysIndex, 1);
+                }
               }
 
             }
@@ -678,7 +682,9 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             if(joints && joints.length){
               for(var i=0;i<joints.length;i++){
                 var jointIndex = joints[i].indexOf(deprecatedItem);
-                group.select_rule.joint_dims[i].splice(jointIndex,1);
+                if(jointIndex>=0) {
+                  group.select_rule.joint_dims[i].splice(jointIndex, 1);
+                }
               }
 
             }


[05/14] kylin git commit: minor sql fix, CI passed

Posted by li...@apache.org.
minor sql fix, CI passed


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/91cf788c
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/91cf788c
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/91cf788c

Branch: refs/heads/KYLIN-2283
Commit: 91cf788cebd66ffa8b56e37586fa3207c09f2d2e
Parents: 520b05f
Author: Yang Li <li...@apache.org>
Authored: Tue Dec 6 07:22:03 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 kylin-it/src/test/resources/query/sql_subquery/query02.sql | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/91cf788c/kylin-it/src/test/resources/query/sql_subquery/query02.sql
----------------------------------------------------------------------
diff --git a/kylin-it/src/test/resources/query/sql_subquery/query02.sql b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
index 81b4887..e6751b7 100644
--- a/kylin-it/src/test/resources/query/sql_subquery/query02.sql
+++ b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
@@ -18,7 +18,7 @@
 
 SELECT
   week_beg_dt
-  ,sum(price)
+  ,sum(price) as sum_price
 FROM
 ( 
   select


[12/14] kylin git commit: minor, sub_query/query02.sql fix CI

Posted by li...@apache.org.
minor, sub_query/query02.sql fix CI


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/f2377db9
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/f2377db9
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/f2377db9

Branch: refs/heads/KYLIN-2283
Commit: f2377db9ff2687098c0bd8a805449547b7dcd436
Parents: 911bdd0
Author: Li Yang <li...@apache.org>
Authored: Fri Dec 16 15:53:30 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Fri Dec 16 15:53:30 2016 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/dimension/DimensionEncodingFactory.java | 2 +-
 .../java/org/apache/kylin/metadata/model/DataModelDesc.java  | 4 ++--
 kylin-it/src/test/resources/query/sql_subquery/query02.sql   | 8 ++++++--
 3 files changed, 9 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/f2377db9/core-metadata/src/main/java/org/apache/kylin/dimension/DimensionEncodingFactory.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/dimension/DimensionEncodingFactory.java b/core-metadata/src/main/java/org/apache/kylin/dimension/DimensionEncodingFactory.java
index 4954ead..3eddba7 100644
--- a/core-metadata/src/main/java/org/apache/kylin/dimension/DimensionEncodingFactory.java
+++ b/core-metadata/src/main/java/org/apache/kylin/dimension/DimensionEncodingFactory.java
@@ -71,7 +71,7 @@ public abstract class DimensionEncodingFactory {
         if (factoryMap == null)
             initFactoryMap();
 
-        Map<String, Integer> result = Maps.newHashMap();
+        Map<String, Integer> result = Maps.newTreeMap();
         for (Pair<String, Integer> p : factoryMap.keySet()) {
             if (result.containsKey(p.getFirst())) {
                 if (result.get(p.getFirst()) > p.getSecond()) {

http://git-wip-us.apache.org/repos/asf/kylin/blob/f2377db9/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
index 0b494e3..571b196 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -393,7 +393,7 @@ public class DataModelDesc extends RootPersistentEntity {
                     col = findColumn(pks[i]);
                 }
                 if (col == null || col.getTableRef().equals(dimTable) == false) {
-                    throw new IllegalStateException("Can't find column " + pks[i] + " in table " + dimTable.getTableIdentity());
+                    throw new IllegalStateException("Can't find PK column " + pks[i] + " in table " + dimTable);
                 }
                 pks[i] = col.getIdentity();
                 pkCols[i] = col;
@@ -406,7 +406,7 @@ public class DataModelDesc extends RootPersistentEntity {
             for (int i = 0; i < fks.length; i++) {
                 TblColRef col = findColumn(fks[i]);
                 if (col == null) {
-                    throw new IllegalStateException("Can't find column " + fks[i] + " in table " + this.getRootFactTable());
+                    throw new IllegalStateException("Can't find FK column " + fks[i]);
                 }
                 fks[i] = col.getIdentity();
                 fkCols[i] = col;

http://git-wip-us.apache.org/repos/asf/kylin/blob/f2377db9/kylin-it/src/test/resources/query/sql_subquery/query02.sql
----------------------------------------------------------------------
diff --git a/kylin-it/src/test/resources/query/sql_subquery/query02.sql b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
index e6751b7..b0dcf73 100644
--- a/kylin-it/src/test/resources/query/sql_subquery/query02.sql
+++ b/kylin-it/src/test/resources/query/sql_subquery/query02.sql
@@ -25,7 +25,11 @@ FROM
     test_cal_dt.week_beg_dt
     ,test_kylin_fact.price
   from test_kylin_fact 
-  inner join edw.test_cal_dt as test_cal_dt
-    on test_kylin_fact.cal_dt = test_cal_dt.cal_dt
+    inner JOIN edw.test_cal_dt as test_cal_dt
+      ON test_kylin_fact.cal_dt = test_cal_dt.cal_dt
+    inner JOIN test_category_groupings
+      ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id AND test_kylin_fact.lstg_site_id = test_category_groupings.site_id
+    inner JOIN edw.test_sites as test_sites
+      ON test_kylin_fact.lstg_site_id = test_sites.site_id  inner join edw.test_cal_dt as test_cal_dt
 ) t
 group by week_beg_dt 


[02/14] kylin git commit: KYLIN 1875 update modify alias

Posted by li...@apache.org.
KYLIN 1875 update modify alias

Signed-off-by: zhongjian <ji...@163.com>


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/f55cc5c4
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/f55cc5c4
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/f55cc5c4

Branch: refs/heads/KYLIN-2283
Commit: f55cc5c446e8878d059019561894cc70bd0ab89b
Parents: e7cc152
Author: chenzhx <34...@qq.com>
Authored: Wed Dec 14 16:33:31 2016 +0800
Committer: Li Yang <li...@apache.org>
Committed: Thu Dec 15 18:57:36 2016 +0800

----------------------------------------------------------------------
 webapp/app/css/AdminLTE.css                     |   5 +
 webapp/app/js/controllers/modelDataModel.js     | 141 ++++++++++++-------
 webapp/app/js/controllers/modelEdit.js          |   8 +-
 webapp/app/js/services/tree.js                  |   3 +
 .../app/partials/modelDesigner/data_model.html  |  25 ++--
 5 files changed, 119 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/f55cc5c4/webapp/app/css/AdminLTE.css
----------------------------------------------------------------------
diff --git a/webapp/app/css/AdminLTE.css b/webapp/app/css/AdminLTE.css
index 6688457..857dbf7 100644
--- a/webapp/app/css/AdminLTE.css
+++ b/webapp/app/css/AdminLTE.css
@@ -4744,6 +4744,11 @@ Gradient Background colors
   opacity: 1;
   filter: alpha(opacity=100);
 }
+.model_graph svg{
+  width:1100px !important;
+  height:600px !important;
+}
+
 
 /*
  * Misc: print

http://git-wip-us.apache.org/repos/asf/kylin/blob/f55cc5c4/webapp/app/js/controllers/modelDataModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDataModel.js b/webapp/app/js/controllers/modelDataModel.js
index a09101b..b6edd43 100644
--- a/webapp/app/js/controllers/modelDataModel.js
+++ b/webapp/app/js/controllers/modelDataModel.js
@@ -22,7 +22,7 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     $scope.modelsManager = modelsManager;
     angular.forEach($scope.modelsManager.selectedModel.lookups,function(joinTable){
       if(!joinTable.alias){
-           joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
+        joinTable.alias=VdmUtil.removeNameSpace(joinTable.table);
       }
     });
     $scope.init = function (){
@@ -110,10 +110,21 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     $scope.editLookup = function (lookup) {
         $scope.lookupState.editingIndex = lookupList.indexOf(lookup);
         $scope.lookupState.editing = true;
-
         // Make a copy of model will be editing.
         $scope.newLookup = angular.copy(lookup);
+        $scope.newLookup.join.pk_type = [];
+        $scope.newLookup.join.fk_type = [];
+        $scope.newLookup.join.isCompatible=[];
         $scope.newLookup.joinTable=VdmUtil.getNameSpaceTopName($scope.newLookup.join.foreign_key[0]);
+        angular.forEach($scope.newLookup.join.primary_key,function(pk,index){
+            $scope.newLookup.join.pk_type[index] = TableModel.getColumnType(VdmUtil.removeNameSpace(pk),$scope.newLookup.table);
+            $scope.newLookup.join.fk_type[index] = TableModel.getColumnType(VdmUtil.removeNameSpace($scope.newLookup.join.foreign_key[index]),$scope.aliasTableMap[$scope.newLookup.joinTable]);
+            if($scope.newLookup.join.pk_type[index]!==$scope.newLookup.join.fk_type[index]){
+               $scope.newLookup.join.isCompatible[index]=false;
+            }else{
+               $scope.newLookup.join.isCompatible[index]=true;
+            }
+        });
         $scope.openLookupModal();
     };
 
@@ -129,24 +140,51 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
 
     $scope.doneEditLookup = function () {
         // Copy edited model to destination model.
-        $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)]=$scope.modelsManager.selectedModel.fact_table;
-        $scope.aliasName=[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)];
         angular.copy($scope.newLookup, lookupList[$scope.lookupState.editingIndex]);
-        angular.forEach(lookupList,function(joinTable){
-          $scope.aliasName.push(joinTable.alias);
-          $scope.aliasTableMap[joinTable.alias]=joinTable.table;
-         // $scope.tableAliasMap[joinTable.alias]=joinTable.table;
-        });
+        var oldAlias=$scope.aliasName[$scope.lookupState.editingIndex+1];
+        var newAlias=$scope.newLookup.alias;
+        if(oldAlias!=newAlias){
+          $scope.aliasName[$scope.lookupState.editingIndex+1]=newAlias;
+          for(var i=0;i<$scope.newLookup.join.primary_key.length;i++){
+            $scope.newLookup.join.primary_key[i]=$scope.newLookup.join.primary_key[i].replace(oldAlias+'.',newAlias+'.');
+          }
+
+          delete $scope.aliasTableMap[oldAlias];
+          $scope.aliasTableMap[newAlias]=$scope.newLookup.table;
+
+          for(var i=0;i<lookupList.length;i++){
+            for(var j=0;j<lookupList[i].join.foreign_key.length;j++){
+             lookupList[i].join.foreign_key[j]=lookupList[i].join.foreign_key[j].replace(oldAlias+'.',newAlias+'.');
+            }
+          }
+
+          for(var i=0;i<modelsManager.selectedModel.dimensions.length;i++){
+            if(modelsManager.selectedModel.dimensions[i].table==oldAlias){
+              modelsManager.selectedModel.dimensions[i].table=newAlias;
+            }
+          }
+
+          if($scope.newLookup.kind=="FACT"){
+            for(var i=0;i< modelsManager.selectedModel.metrics.length;i++){
+               modelsManager.selectedModel.metrics[i]= modelsManager.selectedModel.metrics[i].replace(oldAlias+'.',newAlias+'.');
+            }
+            modelsManager.selectedModel.partition_desc.partition_date_column = modelsManager.selectedModel.partition_desc.partition_date_column.replace(oldAlias+'.',newAlias+'.');
+          }
+        }
+        angular.copy($scope.newLookup,lookupList[$scope.lookupState.editingIndex]);
 
         $scope.resetParams();
     };
     $scope.changeFactTable = function () {
-        delete $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)];
+        $scope.aliasTableMap={};
         $scope.aliasTableMap[VdmUtil.removeNameSpace($scope.FactTable.root)]=$scope.FactTable.root;
-        delete $scope.tableAliasMap[$scope.modelsManager.selectedModel.fact_table];
+        $scope.tableAliasMap={};
         $scope.tableAliasMap[$scope.FactTable.root]=VdmUtil.removeNameSpace($scope.FactTable.root);
-        $scope.aliasName.splice($scope.aliasName.indexOf(VdmUtil.removeNameSpace($scope.modelsManager.selectedModel.fact_table)),1);
-        $scope.aliasName.push(VdmUtil.removeNameSpace($scope.FactTable.root));
+        $scope.aliasName=[VdmUtil.removeNameSpace($scope.FactTable.root)];
+        modelsManager.selectedModel.lookups = [];
+        modelsManager.selectedModel.dimensions = [];
+        modelsManager.selectedModel.metrics= [];
+        modelsManager.selectedModel.partition_desc.partition_date_column = null;
         $scope.modelsManager.selectedModel.fact_table=$scope.FactTable.root;
     }
     $scope.changeJoinTable = function () {
@@ -158,7 +196,7 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
 
     $scope.removeLookup = function (lookup) {
         var dimExist = _.some(modelsManager.selectedModel.dimensions,function(item,index){
-            return item.alias===lookup.alias;
+            return item.table===lookup.alias;
         });
         if(dimExist) {
             SweetAlert.swal({
@@ -172,7 +210,7 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
             }, function (isConfirm) {
                 if (isConfirm) {
                     for (var i = modelsManager.selectedModel.dimensions.length - 1; i >= 0; i--) {
-                        if (modelsManager.selectedModel.dimensions[i].alias === lookup.alias) {
+                        if (modelsManager.selectedModel.dimensions[i].table === lookup.alias) {
                             modelsManager.selectedModel.dimensions.splice(i, 1);
                         }
                     }
@@ -187,13 +225,13 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     }
 
     $scope.changeKey = function(index){
-         var join_table = $scope.newLookup.jointable;
+         var join_table = $scope.newLookup.joinTable;
          var lookup_table = $scope.newLookup.table;
          var pk_column = $scope.newLookup.join.primary_key[index];
          var fk_column = $scope.newLookup.join.foreign_key[index];
          if(pk_column!=='null'&&fk_column!=='null'){
-             $scope.newLookup.join.pk_type[index] = TableModel.getColumnType(pk_column,lookup_table);
-             $scope.newLookup.join.fk_type[index] = TableModel.getColumnType(fk_column,join_table);
+            $scope.newLookup.join.pk_type[index] = TableModel.getColumnType(VdmUtil.removeNameSpace(pk_column),$scope.newLookup.table);
+            $scope.newLookup.join.fk_type[index] = TableModel.getColumnType(VdmUtil.removeNameSpace(fk_column),$scope.aliasTableMap[$scope.newLookup.joinTable]);
             if($scope.newLookup.join.pk_type[index]!==$scope.newLookup.join.fk_type[index]){
                $scope.newLookup.join.isCompatible[index]=false;
             }else{
@@ -226,34 +264,43 @@ KylinApp.controller('ModelDataModelCtrl', function ($location,$scope, $modal,cub
     };
 
     $scope.checkLookupForm = function(){
-            var errors = [];
-            // null validate
-            for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){
-                if($scope.newLookup.join.primary_key[i]==='null'){
-                    errors.push("Primary Key can't be null.");
-                    break;
-                }
-            }
-            for(var i = 0;i<$scope.newLookup.join.foreign_key.length;i++){
-                if($scope.newLookup.join.foreign_key[i]==='null'){
-                    errors.push("Foreign Key can't be null.");
-                    break;
-                }
-            }
-
-            var errorInfo = "";
-            angular.forEach(errors,function(item){
-                errorInfo+="\n"+item;
-            });
-            if(errors.length){
-//                SweetAlert.swal('Warning!', errorInfo, '');
-                SweetAlert.swal('', errorInfo, 'warning');
-                return false;
-            }else{
-                return true;
-            }
-
+      var errors = [];
+      for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){
+        if($scope.newLookup.join.primary_key[i]==='null'){
+          errors.push("Primary Key can't be null.");
+          break;
+        }
+      }
+      for(var i = 0;i<$scope.newLookup.join.foreign_key.length;i++){
+        if($scope.newLookup.join.foreign_key[i]==='null'){
+          errors.push("Foreign Key can't be null.");
+          break;
+        }
+      }
+      if($scope.aliasName.indexOf($scope.newLookup.alias)!=-1&&$scope.lookupState.editing == false){
+        errors.push("Table Alias ["+$scope.newLookup.alias+"] already exist!");
+      }
+      if($scope.aliasName.indexOf($scope.newLookup.alias)!=-1&&$scope.aliasName[$scope.lookupState.editingIndex+1] != $scope.newLookup.alias){
+        errors.push("Table Alias ["+$scope.newLookup.alias+"] already exist!");
+      }
+      var errorInfo = "";
+      angular.forEach(errors,function(item){
+        errorInfo+="\n"+item;
+      });
+      if(errors.length){
+        SweetAlert.swal('', errorInfo, 'warning');
+        return false;
+      }else{
+        return true;
+      }
     };
-
-
+    $scope.filterNotRoot = function (item) {
+      return item.name!==modelsManager.selectedModel.fact_table;
+    };
+/*    $scope.$watch('$scope.newLookup.alias', function (newValue, oldValue) {
+      if (newValue&&$scope.lookupState.editing ) {
+        console.log(newValue);
+        console.log(oldValue);
+      }
+    });*/
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/f55cc5c4/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 4d1e12c..fd78d03 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -19,7 +19,7 @@
 'use strict';
 
 
-KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, ModelService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel,ProjectService,ProjectModel,modelsManager,VdmUtil) {
+KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, ModelService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel,ProjectService,ProjectModel,modelsManager, CubeService, VdmUtil) {
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.tableAliasMap={};
@@ -93,9 +93,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
       ModelDescService.query({model_name: modelName}, function (model) {
         if (model) {
           modelsManager.selectedModel = model;
-          if($scope.modelsManager.selectedModel.partition_desc.partition_time_column){
-            $scope.partitionColumn.hasSeparateTimeColumn = true;
-          }
+          CubeService.list({modelName:model.name}, function (_cubes) {
+              $scope.cubesLength = _cubes.length;
+          });
           modelsManager.selectedModel.project = ProjectModel.getProjectByCubeModel(modelName);
           if(!ProjectModel.getSelectedProject()){
             ProjectModel.setSelectedProject(modelsManager.selectedModel.project);

http://git-wip-us.apache.org/repos/asf/kylin/blob/f55cc5c4/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index 08e290b..20de19b 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -47,6 +47,9 @@ KylinApp.service('ModelGraphService', function (VdmUtil) {
         model.graph = (!!model.graph) ? model.graph : {};
 
         angular.forEach(model.lookups,function (lookup, index) {
+          if(!lookup.alias){
+            lookup.alias=VdmUtil.removeNameSpace(lookup.table);
+          }
           if (lookup.join && lookup.join.primary_key.length > 0) {
             var  dimensionNode={
                 "type": lookup.kind,

http://git-wip-us.apache.org/repos/asf/kylin/blob/f55cc5c4/webapp/app/partials/modelDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/data_model.html b/webapp/app/partials/modelDesigner/data_model.html
index f1192f4..e032cf9 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -29,7 +29,7 @@
               <select chosen ng-model="FactTable.root" ng-if="state.mode=='edit'"
                       ng-options="table.name as table.name for table in tableModel.selectProjectTables"
                       style="width:100%;" ng-change="changeFactTable()"
-                      name="table_name"
+                      name="table_name"   ng-disabled="cubesLength>0"
                       ng-required="true"
                       data-placeholder="Fact Table Name"
                       class="chosen-select">
@@ -92,17 +92,18 @@
                     <ul class="list-unstyled">
                         <li ng-repeat="pk in lookup.join.primary_key track by $index">
                             <code>{{lookup.join.foreign_key[$index]}} = {{pk}}</code>
+
                         </li>
                     </ul>
                 </td>
                 <td ng-if="state.mode=='edit'">
                     <!-- edit button -->
-                    <button class="btn btn-xs btn-info" ng-disabled="lookupState.editing"
-                            ng-click="editLookup(lookup)" tooltip="Edit Lookup"><i class="fa fa-pencil"></i>
+                    <button class="btn btn-xs btn-info" ng-disabled="lookupState.editing||cubesLength>0"
+                            ng-click="editLookup(lookup)" ><i class="fa fa-pencil"></i>
                     </button>
                     <!-- remove button -->
-                    <button class="btn btn-xs btn-danger" ng-disabled="lookupState.editing"
-                            ng-click="removeLookup(lookup)" tooltip="Remove Lookup"><i class="fa fa-trash-o"></i>
+                    <button class="btn btn-xs btn-danger" ng-disabled="lookupState.editing||cubesLength>0"
+                            ng-click="removeLookup(lookup)" ><i class="fa fa-trash-o"></i>
                     </button>
                 </td>
             </tr>
@@ -126,17 +127,17 @@
                             <div>
                               <select chosen ng-model="newLookup.joinTable" style="width: 45%"
                                       ng-options="table as table for table in aliasName"
-                                      name="table_name"
+                                      name="table_name"  ng-disabled="lookupState.editing"
                                       ng-required="true"
                                       data-placeholder="Join Table Name"
                                       class="chosen-select">
                                 <option value=""> &#45;&#45; Select Join Table &#45;&#45; </option>
                               </select>
                               <small class="help-block" ng-show="lookup_form.table_name.$invalid && (lookup_form.table_name.$dirty||forms.model_info_form.$submitted)">Table name required</small>
-                              <b>&nbsp;</b>
+                              <b>&nbsp;&nbsp;&nbsp;</b>
                               <select chosen ng-model="newLookup.table" style="width: 45%"
-                                      ng-options="table.name as table.name for table in tableModel.selectProjectTables"
-                                      name="table_name"
+                                      ng-options="table.name as table.name for table in tableModel.selectProjectTables|filter:filterNotRoot"
+                                      name="table_name"  ng-disabled="lookupState.editing"
                                       ng-required="true"  ng-change="changeJoinTable()"
                                       data-placeholder="Join Table Name"
                                       class="chosen-select">
@@ -146,7 +147,6 @@
 
                             </div>
                             <div class="space-4"></div>
-                            <small class="help-block red" ng-show="newLookup.join.isCompatible[$index]==false"><i class="fa fa-exclamation-triangle"></i> <b>Column Type incompatible {{newLookup.join.foreign_key[$index]}}[{{newLookup.join.fk_type[$index]}}], {{newLookup.join.primary_key[$index]}} [{{newLookup.join.pk_type[$index]}}]</b></small>
                           </div>
                         </div>
                       </div>
@@ -154,8 +154,9 @@
                         <div class="row">
                             <label class="col-sm-3 control-label font-color-default"><b>Alias</b></label>
                             <div class="col-sm-6">
-                              <input type="text" class="form-control " placeholder="Input Table Alias" ng-required="true"
-                                     ng-model="newLookup.alias" ng-change="changeAlias()" ng-disabled="">
+                              <input type="text" class="form-control " name="joinTable_alias" placeholder="Input Table Alias" ng-required="true"
+                                     ng-model="newLookup.alias" ng-change="changeAlias()"  ng-pattern="/^\w+$/">
+                              <small class="help-block red" ng-show="!lookup_form.joinTable_alias.$error.required&&lookup_form.joinTable_alias.$invalid && (lookup_form.joinTable_alias.$dirty||lookup_form.$submitted)"><i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp; Alias is invalid.</small>
                             </div>
                         </div>
                     </div>