You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ma...@apache.org on 2015/05/15 07:21:30 UTC

[01/52] [abbrv] incubator-kylin git commit: KYLIN-763 remove author information

Repository: incubator-kylin
Updated Branches:
  refs/heads/0.8.0 31da12f82 -> 5092c4843 (forced update)


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/StreamingManagerTest.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/StreamingManagerTest.java b/streaming/src/test/java/org/apache/kylin/streaming/StreamingManagerTest.java
index b58dbfd..ea76a93 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/StreamingManagerTest.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/StreamingManagerTest.java
@@ -45,7 +45,6 @@ import static junit.framework.TestCase.assertNotNull;
 import static org.junit.Assert.fail;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public class StreamingManagerTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/invertedindex/PrintOutStreamBuilder.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/invertedindex/PrintOutStreamBuilder.java b/streaming/src/test/java/org/apache/kylin/streaming/invertedindex/PrintOutStreamBuilder.java
index 3b6ae02..b3d7742 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/invertedindex/PrintOutStreamBuilder.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/invertedindex/PrintOutStreamBuilder.java
@@ -44,7 +44,6 @@ import java.util.List;
 import java.util.concurrent.BlockingQueue;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public class PrintOutStreamBuilder extends StreamBuilder {
 


[32/52] [abbrv] incubator-kylin git commit: new models page update

Posted by ma...@apache.org.
new models page update


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

Branch: refs/heads/0.8.0
Commit: ef5ccb5b0b0c09cbddce4406cae9101897b3d1be
Parents: 336973e
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 25 17:56:41 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 .../kylin/rest/controller/CubeController.java   |  4 +-
 .../kylin/rest/controller/ModelController.java  |  4 +-
 .../apache/kylin/rest/service/CubeService.java  |  9 ++++-
 .../apache/kylin/rest/service/ModelService.java | 16 ++++----
 webapp/app/js/controllers/cubeModel.js          | 21 +++++++++--
 webapp/app/js/controllers/modelEdit.js          |  5 ++-
 webapp/app/js/controllers/models.js             |  8 ++--
 webapp/app/js/model/modelList.js                |  3 +-
 webapp/app/less/component.less                  |  4 ++
 webapp/app/partials/cubes/cube_detail.html      |  2 +-
 webapp/app/partials/models/model_detail.html    | 39 +++++++++++++++++++-
 webapp/app/partials/models/model_schema.html    |  6 +--
 webapp/app/partials/models/models_tree.html     |  6 +--
 13 files changed, 93 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index fb1870b..b1f9b4a 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -89,8 +89,8 @@ public class CubeController extends BasicController {
     @RequestMapping(value = "", method = {RequestMethod.GET})
     @ResponseBody
     @Metered(name = "listCubes")
-    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName,@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam("limit") Integer limit, @RequestParam("offset") Integer offset) {
-        return cubeService.getCubes(cubeName, projectName, modelName,(null == limit) ? 20 : limit, offset);
+    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName,@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value="limit",required = false) Integer limit, @RequestParam(value = "offset" ,required = false) Integer offset) {
+        return cubeService.getCubes(cubeName, projectName, modelName, limit, offset);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 5a18a3b..9b50af6 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -58,8 +58,8 @@ public class ModelController extends BasicController {
     @RequestMapping(value = "", method = {RequestMethod.GET})
     @ResponseBody
     @Metered(name = "listModels")
-    public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam("limit") Integer limit, @RequestParam("offset") Integer offset) {
-        return modelService.getModels(modelName, projectName, (null == limit) ? 20 : limit, offset);
+    public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value="limit",required=false) Integer limit, @RequestParam(value="offset",required=false) Integer offset) {
+        return modelService.getModels(modelName, projectName, limit, offset);
     }
 
     @RequestMapping(value = "/{modelName}", method = {RequestMethod.DELETE})

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index 8dc0345..7f63d34 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -117,12 +117,17 @@ public class CubeService extends BasicService {
     }
 
     public List<CubeInstance> getCubes(final String cubeName, final String projectName,final String modelName ,final Integer limit, final Integer offset) {
-        int climit = (null == limit) ? 30 : limit;
-        int coffset = (null == offset) ? 0 : offset;
 
         List<CubeInstance> cubes;
         cubes = listAllCubes(cubeName, projectName,modelName);
 
+        if(limit==null||offset==null){
+            return cubes;
+        }
+
+        int climit = (null == limit) ? 30 : limit;
+        int coffset = (null == offset) ? 0 : offset;
+
         if (cubes.size() <= coffset) {
             return Collections.emptyList();
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 181ccdf..490de31 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -73,21 +73,23 @@ public class ModelService extends BasicService {
     }
 
     public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) {
-        int climit = (null == limit) ? 30 : limit;
-        int coffset = (null == offset) ? 0 : offset;
 
         List<DataModelDesc> modelDescs;
         modelDescs = listAllModels(modelName, projectName);
 
-        if (modelDescs.size() <= coffset) {
-            return Collections.emptyList();
+        if(limit==null || offset == null){
+            return modelDescs;
         }
 
-        if ((modelDescs.size() - coffset) < climit) {
-            return modelDescs.subList(coffset, modelDescs.size());
+//        if (modelDescs.size() <= limit) {
+//            return Collections.emptyList();
+//        }
+
+        if ((modelDescs.size() - offset) < limit) {
+            return modelDescs.subList(offset, modelDescs.size());
         }
 
-        return modelDescs.subList(coffset, coffset + climit);
+        return modelDescs.subList(offset, offset + limit);
     }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index 47014c9..2987905 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -20,11 +20,26 @@
 
 KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log) {
 
-    //copy model for show Json in model tab list
-    $scope.modelJson = angular.copy($scope.model);
 
     $scope.buildGraph = function (model) {
-        GraphService.buildTree(model);
+//        var newModel = jQuery.extend(true, {}, model);
+        var newModel = angular.copy(model);
+        GraphService.buildTree(newModel);
+    };
+
+    $scope.cleanStatus = function(model){
+
+        if (!model)
+        {
+            return;
+        }
+        var newModel = jQuery.extend(true, {}, model);
+        delete newModel.project;
+        delete  newModel.accessEntities;
+        delete  newModel.visiblePage;
+        delete  newModel.cubes;
+
+        return newModel;
     };
 
     $scope.cubeConfig = cubeConfig;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 364919d..30f4c21 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -111,8 +111,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
         }
         $scope.state.project = $scope.model.project;
-        delete $scope.model.project;
-        $scope.state.modelSchema = angular.toJson($scope.model, true);
+        var _model = angular.copy($scope.model);
+        delete _model.project;
+        $scope.state.modelSchema = angular.toJson(_model, true);
 
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index e16c27a..973ede0 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -47,14 +47,14 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
 
         //  TODO offset&limit
-        $scope.list = function (offset, limit) {
+        $scope.list = function () {
             if(!$scope.projectModel.projects.length){
                 return [];
             }
-            offset = (!!offset) ? offset : 0;
-            limit = (!!limit) ? limit : 70;
+//            offset = (!!offset) ? offset : null;
+//            limit = (!!limit) ? limit : null;
 
-            var queryParam = {offset: offset, limit: limit};
+            var queryParam = {};
             if ($scope.listParams.modelName) {
                 queryParam.modelName = $scope.listParams.modelName;
             }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 9c83c4e..b7dba7b 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -36,7 +36,8 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
                 )
                 $log.info("Add cube info to model ,not detail info");
                 cubeDetail.push(
-                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+//                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+                    CubeService.list({modelName:model.name}, function (_cubes) {
                     model.cubes = _cubes;
                     }).$promise
                 );

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index f14ab07..9e05fcf 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -960,3 +960,7 @@ Angular 1.2.0 Animation
 .box-2px{
   border-top:solid 2px #3c8dbc !important;
 }
+
+treecontrol{
+  font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index f0644cc..91e5afe 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -48,7 +48,7 @@
         </li>
         <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
             <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
-                Action <span class="caret"></span>
+                <i class="fa fa-cubes"> Action </i> <span class="caret"></span>
             </a>
             <ul class="dropdown-menu">
                 <li ng-if="cube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/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 6d43210..b116a0a 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -17,7 +17,42 @@
 -->
 
 <div ng-controller="CubeModelCtrl" class="nav-tabs-custom">
-    <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
-         ng-init="state={mode:'view', modelName:model.name}">
+    <ul ng-show="model.name" class="nav nav-tabs">
+        <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
+        </li>
+        <li class="{{model.visiblePage=='graph'? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);$event.stopPropagation();">Visualization</a>
+        </li>
+        <li class="{{model.visiblePage=='json_model'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
+            <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
+        </li>
+        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+            <a class="dropdown-toggle" 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(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <a href="models/edit/{{model.name}}" data-widget="collapse">Edit Model</a>
+                </li>
+                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <a href="cubes/add/{{model.name}}" data-widget="collapse">Create Cube</a>
+                </li>
+            </ul>
+        </li>
+    </ul>
+
+    <div class="model-detail" ng-if="!model.visiblePage || model.visiblePage=='metadata'">
+        <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
+             ng-init="state={mode:'view', modelName:model.name}">
+        </div>
+    </div>
+    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="model-detail model_graph">
     </div>
+    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
+          <pre ng-if="!state.jsonEdit"
+               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>
+    </div>
+
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 60e73e6..898343a 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -16,13 +16,9 @@
 * limitations under the License.
 -->
 
-<div class="box box-primary model-design" ng-hide="state.mode=='view'&&!model.name">
+<div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
-        <div ng-if="state.mode=='view'" class="box-tools pull-right">
-            <a ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)" class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
-            <a ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)" class="btn btn-box-tool"  tooltip="Add Cube" href="cubes/add/{{model.name}}" data-widget="collapse"><i class="fa fa-cube"></i></a>
-        </div>
     </div>
     <div class="box-body">
         <ng-form name="design_form" ng-submit="">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ef5ccb5b/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 1a8c57a..727c498 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -35,9 +35,9 @@
         <abn-tree
                 tree-data         = "models_treedata"
                 tree-control      = "my_tree"
-                icon-leaf         = "fa fa-cube"
-                icon-expand       = "fa fa-plus"
-                icon-collapse     = "fa fa-minus"
+                icon-leaf         = "fa fa-cubes"
+                icon-expand       = "fa fa-star"
+                icon-collapse     = "fa fa-star-o"
                 expand-level      = "2"
                 initial-selection = "">
             ></abn-tree>


[42/52] [abbrv] incubator-kylin git commit: delete model

Posted by ma...@apache.org.
delete model


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

Branch: refs/heads/0.8.0
Commit: 9f9d49d9c5ea8b1b8a623b2571235ba1e06799b2
Parents: d60f726
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 3 18:18:33 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:32 2015 +0800

----------------------------------------------------------------------
 .../kylin/rest/controller/ModelController.java  | 38 ++++++++------------
 .../apache/kylin/rest/service/ModelService.java |  8 ++---
 webapp/app/index.html                           |  2 +-
 3 files changed, 18 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/9f9d49d9/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index ba45df1..290904d 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -70,13 +70,6 @@ public class ModelController extends BasicController {
         }
     }
 
-    @RequestMapping(value = "/{modelName}", method = {RequestMethod.DELETE})
-    @ResponseBody
-    @Metered(name = "deleteModel")
-    public void deleteModel(@PathVariable String modelName) {
-
-    }
-
     /**
      *
      * create model
@@ -140,22 +133,21 @@ public class ModelController extends BasicController {
         return modelRequest;
     }
 
-//    @RequestMapping(value = "/{cubeName}", method = {RequestMethod.DELETE})
-//    @ResponseBody
-//    @Metered(name = "deleteCube")
-//    public void deleteCube(@PathVariable String cubeName) {
-//        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-//        if (null == cube) {
-//            throw new NotFoundException("Cube with name " + cubeName + " not found..");
-//        }
-//
-//        try {
-//            cubeService.deleteCube(cube);
-//        } catch (Exception e) {
-//            logger.error(e.getLocalizedMessage(), e);
-//            throw new InternalErrorException("Failed to delete cube. " + " Caused by: " + e.getMessage(), e);
-//        }
-//    }
+    @RequestMapping(value = "/{modelName}", method = {RequestMethod.DELETE})
+    @ResponseBody
+    @Metered(name = "deleteModel")
+    public void deleteModel(@PathVariable String modelName) {
+        DataModelDesc desc = modelService.getMetadataManager().getDataModelDesc(modelName);
+        if (null == desc) {
+            throw new NotFoundException("Data Model with name " + modelName + " not found..");
+        }
+        try {
+            modelService.deleteModel(desc);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to delete model. " + " Caused by: " + e.getMessage(), e);
+        }
+    }
 
     private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
         DataModelDesc desc = null;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/9f9d49d9/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 3c349cc..2780f40 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -81,10 +81,6 @@ public class ModelService extends BasicService {
             return modelDescs;
         }
 
-//        if (modelDescs.size() <= limit) {
-//            return Collections.emptyList();
-//        }
-
         if ((modelDescs.size() - offset) < limit) {
             return modelDescs.subList(offset, modelDescs.size());
         }
@@ -116,8 +112,8 @@ public class ModelService extends BasicService {
     }
 
 
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public void deleteCube(DataModelDesc desc) throws IOException {
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public void deleteModel(DataModelDesc desc) throws IOException {
 //        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
 
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/9f9d49d9/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 8901721..19ced08 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -101,7 +101,7 @@
 <script src="components/underscore/underscore.js"></script>
 <script src="components/angular-underscore/angular-underscore.js"></script>
 <script src="components/jquery-ui/jquery-ui.min.js"></script>
-<script src="components/angular-ui-sortable/sortable.min.js"></script>
+<script src="components/angular-ui-sortable/sortable.js"></script>
 
 <script src="js/app.js"></script>
 <script src="js/config.js"></script>


[22/52] [abbrv] incubator-kylin git commit: new header

Posted by ma...@apache.org.
new header


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

Branch: refs/heads/0.8.0
Commit: 6fed6cb462890a0e52b5b86a143dbeb2b3dd12fe
Parents: afac451
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 17 17:54:19 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:50 2015 +0800

----------------------------------------------------------------------
 webapp/app/partials/header.html | 4 ++--
 webapp/app/routes.json          | 8 ++++++++
 2 files changed, 10 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6fed6cb4/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index 9a55034..cfc1aa2 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -49,8 +49,8 @@
                     <li class="{{activeTab=='jobs'?'purple':'green'}}" ng-if="userService.isAuthorized()">
                         <a href="jobs">Monitor</a>
                     </li>
-                    <li class="{{activeTab=='sourceMeta'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="sourceMeta">System</a>
+                    <li class="{{activeTab=='admin'?'purple':'green'}}" ng-if="userService.isAuthorized()">
+                        <a href="admin">System</a>
                     </li>
                 </ul>
                 <ul class="nav navbar-nav navbar-right">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6fed6cb4/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 31071c5..8ee6fc3 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -113,6 +113,14 @@
         }
     },
     {
+        "url": "/models/add",
+        "params": {
+            "templateUrl": "partials/models/model_edit.html",
+            "tab": "models",
+            "controller": "ModelEditCtrl"
+        }
+    },
+    {
         "url": "/models/edit/:modelName",
         "params": {
             "templateUrl": "partials/models/model_edit.html",


[39/52] [abbrv] incubator-kylin git commit: compatible with old meta data

Posted by ma...@apache.org.
compatible with old meta data


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

Branch: refs/heads/0.8.0
Commit: 0aca96b1682efa2b2af5deb800681ebfe5f35e8a
Parents: aebd109
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 3 14:11:44 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:00 2015 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/cube/CubeInstance.java     |   7 +-
 .../apache/kylin/invertedindex/IIInstance.java  |   9 +-
 .../apache/kylin/metadata/MetadataManager.java  |  26 ++-
 .../kylin/metadata/model/DataModelDesc.java     |  36 ++++
 .../kylin/metadata/project/ProjectManager.java  |  11 +-
 .../metadata/realization/IRealization.java      |   3 +
 .../kylin/rest/controller/ModelController.java  |   8 +-
 .../apache/kylin/rest/service/ModelService.java |  13 +-
 .../kylin/storage/hybrid/HybridInstance.java    |  13 +-
 webapp/app/js/controllers/modelEdit.js          |   9 +-
 webapp/app/js/controllers/modelSchema.js        |   5 +-
 webapp/app/js/model/metaModel.js                | 191 ++++++++++---------
 webapp/app/js/services/message.js               |   2 +-
 webapp/app/less/component.less                  |   4 +
 .../modelDesigner/conditions_settings.html      |   5 +-
 .../app/partials/modelDesigner/model_info.html  |  15 ++
 webapp/app/partials/models/model_schema.html    |   4 +-
 webapp/app/partials/models/models_tree.html     |   1 +
 .../app/partials/tables/source_table_tree.html  |   1 +
 webapp/bower.json                               |   4 +-
 20 files changed, 233 insertions(+), 134 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/cube/src/main/java/org/apache/kylin/cube/CubeInstance.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/CubeInstance.java b/cube/src/main/java/org/apache/kylin/cube/CubeInstance.java
index e63f836..c397f98 100644
--- a/cube/src/main/java/org/apache/kylin/cube/CubeInstance.java
+++ b/cube/src/main/java/org/apache/kylin/cube/CubeInstance.java
@@ -25,10 +25,7 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.ResourceStore;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 import org.apache.kylin.cube.model.CubeDesc;
-import org.apache.kylin.metadata.model.LookupDesc;
-import org.apache.kylin.metadata.model.MeasureDesc;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.model.*;
 import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.RealizationStatusEnum;
 import org.apache.kylin.metadata.realization.RealizationType;
@@ -120,6 +117,8 @@ public class CubeInstance extends RootPersistentEntity implements IRealization {
         return CubeDescManager.getInstance(config).getCubeDesc(descName);
     }
 
+    public DataModelDesc getDataModelDesc(){return this.getDescriptor().getModel();}
+
     public boolean isReady() {
         return getStatus() == RealizationStatusEnum.READY;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIInstance.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIInstance.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIInstance.java
index 1d300a8..cdb3fa7 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIInstance.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIInstance.java
@@ -28,10 +28,7 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.ResourceStore;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 import org.apache.kylin.invertedindex.model.IIDesc;
-import org.apache.kylin.metadata.model.LookupDesc;
-import org.apache.kylin.metadata.model.MeasureDesc;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.model.*;
 import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.RealizationStatusEnum;
 import org.apache.kylin.metadata.realization.RealizationType;
@@ -113,6 +110,10 @@ public class IIInstance extends RootPersistentEntity implements IRealization {
         return IIDescManager.getInstance(config).getIIDesc(descName);
     }
 
+    public DataModelDesc getDataModelDesc(){
+        return this.getDescriptor().getModel();
+    }
+
     public boolean isReady() {
         return getStatus() == RealizationStatusEnum.READY;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index 86d33f7..ae64f4c 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -29,6 +29,10 @@ import java.util.concurrent.ConcurrentHashMap;
 import org.apache.kylin.metadata.model.TableDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.project.RealizationEntry;
+import org.apache.kylin.metadata.realization.IRealization;
+import org.apache.kylin.metadata.realization.RealizationRegistry;
+import org.apache.kylin.metadata.realization.RealizationType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -287,9 +291,11 @@ public class MetadataManager {
         return new ArrayList<DataModelDesc>(dataModelDescMap.values());
     }
 
-    public List<DataModelDesc> getModels(String projectName){
+    public List<DataModelDesc> getModels(String projectName) throws IOException{
         ProjectInstance projectInstance =  ProjectManager.getInstance(config).getProject(projectName);
         HashSet<DataModelDesc> ret = new HashSet<>();
+
+
         if (projectInstance != null&&projectInstance.getModels()!=null) {
             for (String modelName : projectInstance.getModels()) {
                 DataModelDesc model = getDataModelDesc(modelName);
@@ -301,6 +307,22 @@ public class MetadataManager {
             }
         }
 
+        //TODO, list model from realization,compatible with old meta data,will remove
+        RealizationRegistry registry = RealizationRegistry.getInstance(config);
+        for (RealizationEntry realization : projectInstance.getRealizationEntries()) {
+            IRealization rel = registry.getRealization(realization.getType(), realization.getRealization());
+            if (rel != null) {
+                DataModelDesc modelDesc = rel.getDataModelDesc();
+                if(!ret.contains(modelDesc)){
+                    ProjectManager.getInstance(config).updateModelToProject(modelDesc.getName(),projectName);
+                    ret.add(modelDesc);
+                }
+            } else {
+                logger.warn("Realization '" + realization + "' defined under project '" + projectInstance + "' is not found");
+            }
+        }
+
+
         return new ArrayList<>(ret);
     }
 
@@ -344,7 +366,7 @@ public class MetadataManager {
         String name = desc.getName();
         if (dataModelDescMap.containsKey(name))
             throw new IllegalArgumentException("DataModelDesc '" + name + "' already exists");
-        ProjectManager.getInstance(config).updateModelToProject(name,projectName,owner);
+        ProjectManager.getInstance(config).updateModelToProject(name,projectName);
         return saveDataModelDesc(desc);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
index 7e888c2..88c3521 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -41,6 +41,9 @@ public class DataModelDesc extends RootPersistentEntity {
     @JsonProperty("name")
     private String name;
 
+    @JsonProperty("description")
+    private String description;
+
     @JsonProperty("fact_table")
     private String factTable;
 
@@ -76,6 +79,14 @@ public class DataModelDesc extends RootPersistentEntity {
         this.name = name;
     }
 
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
     public Collection<String> getAllTables() {
         HashSet<String> ret = Sets.newHashSet();
         ret.add(factTable);
@@ -247,6 +258,31 @@ public class DataModelDesc extends RootPersistentEntity {
     public List<String> getError() {
         return this.errors;
     }
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        DataModelDesc modelDesc = (DataModelDesc) o;
+
+        if (!name.equals(modelDesc.name))
+            return false;
+        if (!getFactTable().equals(modelDesc.getFactTable()))
+            return false;
+
+        return true;
+    }
+
+
+    @Override
+    public int hashCode() {
+        int result = 0;
+        result = 31 * result + name.hashCode();
+        result = 31 * result + getFactTable().hashCode();
+        return result;
+    }
 
     @Override
     public String toString() {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index fb2d298..9538398 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -224,10 +224,9 @@ public class ProjectManager {
         return this.getProject(projectName).containsModel(modelName);
     }
 
-    public ProjectInstance updateModelToProject(String modelName, String newProjectName, String owner) throws IOException {
+    public ProjectInstance updateModelToProject(String modelName, String newProjectName) throws IOException {
         removeModelFromProjects(modelName);
-
-        return addModelToProject(modelName, newProjectName, owner);
+        return addModelToProject(modelName, newProjectName);
     }
 
     public void removeModelFromProjects(String modelName) throws IOException {
@@ -238,11 +237,11 @@ public class ProjectManager {
         }
     }
 
-    private ProjectInstance addModelToProject(String modelName, String project, String user) throws IOException {
+    private ProjectInstance addModelToProject(String modelName, String project) throws IOException {
         String newProjectName = ProjectInstance.getNormalizedProjectName(project);
         ProjectInstance newProject = getProject(newProjectName);
         if (newProject == null) {
-            newProject = this.createProject(newProjectName, user, "This is a project automatically added when adding model " + modelName);
+            throw new IllegalArgumentException("Project "+newProjectName+" does not exist.");
         }
         newProject.addModel(modelName);
         saveResource(newProject);
@@ -259,7 +258,7 @@ public class ProjectManager {
         String newProjectName = norm(project);
         ProjectInstance newProject = getProject(newProjectName);
         if (newProject == null) {
-            newProject = this.createProject(newProjectName, user, "This is a project automatically added when adding realization " + realizationName + "(" + type + ")");
+            throw new IllegalArgumentException("Project "+newProjectName+" does not exist.");
         }
         newProject.addRealizationEntry(type, realizationName);
         saveResource(newProject);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealization.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealization.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealization.java
index fbc26d0..251e794 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealization.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealization.java
@@ -18,6 +18,7 @@
 
 package org.apache.kylin.metadata.realization;
 
+import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.model.MeasureDesc;
 import org.apache.kylin.metadata.model.TblColRef;
 
@@ -47,6 +48,8 @@ public interface IRealization {
      */
     public RealizationType getType();
 
+    public DataModelDesc getDataModelDesc();
+
     public String getFactTable();
 
     public List<TblColRef> getAllColumns();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 9b50af6..3e17be1 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -59,7 +59,13 @@ public class ModelController extends BasicController {
     @ResponseBody
     @Metered(name = "listModels")
     public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value="limit",required=false) Integer limit, @RequestParam(value="offset",required=false) Integer offset) {
-        return modelService.getModels(modelName, projectName, limit, offset);
+        try{
+            return modelService.getModels(modelName, projectName, limit, offset);
+        }
+        catch (IOException e){
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
     }
 
     @RequestMapping(value = "/{modelName}", method = {RequestMethod.DELETE})

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 490de31..d210077 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -49,7 +49,7 @@ public class ModelService extends BasicService {
     private AccessService accessService;
 
     @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<DataModelDesc> listAllModels(final String modelName, final String projectName) {
+    public List<DataModelDesc> listAllModels(final String modelName, final String projectName) throws IOException{
         List<DataModelDesc> models = null;
         ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
 
@@ -72,7 +72,7 @@ public class ModelService extends BasicService {
         return filterModels;
     }
 
-    public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) {
+    public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) throws IOException{
 
         List<DataModelDesc> modelDescs;
         modelDescs = listAllModels(modelName, projectName);
@@ -110,13 +110,8 @@ public class ModelService extends BasicService {
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
     public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
-        DataModelDesc existingModel = getMetadataManager().getDataModelDesc(desc.getName());
-        if (existingModel == null) {
-            String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-            getMetadataManager().createDataModelDesc(desc,newProjectName,owner);
-        } else {
-            getMetadataManager().updateDataModelDesc(desc);
-        }
+
+        getMetadataManager().updateDataModelDesc(desc);
         return desc;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
index beb86c5..1694719 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
@@ -7,6 +7,7 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.invertedindex.IIInstance;
+import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.model.MeasureDesc;
 import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.project.RealizationEntry;
@@ -159,7 +160,17 @@ public class HybridInstance extends RootPersistentEntity implements IRealization
         return Math.max(getHistoryRealizationInstance().getDateRangeEnd(), getRealTimeRealizationInstance().getDateRangeEnd()) +1;
     }
 
-    @Override
+    
+
+    public DataModelDesc getDataModelDesc(){
+        if (getHistoryRealizationInstance() instanceof CubeInstance) {
+            return ((CubeInstance) historyRealizationInstance).getDescriptor().getModel();
+        }
+
+        return ((IIInstance) historyRealizationInstance).getDescriptor().getModel();
+    }
+
+   @Override
     public String getModelName() {
         if (getHistoryRealizationInstance() instanceof CubeInstance) {
             return ((CubeInstance) historyRealizationInstance).getDescriptor().getModelName();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 810242e..5ca95b1 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -117,6 +117,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
             }
 
         }
+        if($scope.model.partition_desc.partition_date_column==null){
+            $scope.model.partition_desc.partition_date_start=null;
+        }
         $scope.state.project = $scope.model.project;
         var _model = angular.copy($scope.model);
         delete _model.project;
@@ -159,7 +162,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                             $scope.state.modelSchema = request.modelSchema;
                             MessageService.sendMsg($scope.modelResultTmpl({'text':'Updated the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
                         } else {
-                            $scope.saveModelRollBack();
+                               $scope.saveModelRollBack();
                                 var message =request.message;
                                 var msg = !!(message) ? message : 'Failed to take action.';
                                 MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
@@ -172,6 +175,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         if(e.data&& e.data.exception){
                             var message =e.data.exception;
                             var msg = !!(message) ? message : 'Failed to take action.';
+                            $log.log($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}));
                             MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         } else {
                             MessageService.sendMsg($scope.modelResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
@@ -217,6 +221,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
 //    reverse the date
     $scope.saveModelRollBack = function (){
+        if($scope.model.partition_desc.partition_date_start==0){
+            $scope.model.partition_desc.partition_date_start = null;
+        }
         if($scope.model&&($scope.model.partition_desc.partition_date_start||$scope.model.partition_desc.partition_date_start==0))
         {
             $scope.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 409582a..81df1df 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -171,7 +171,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
             errorInfo+="\n"+item;
         });
         if(errors.length){
-            SweetAlert.swal('', errorInfo, 'warning');
+            SweetAlert.swal('Oops...', errorInfo, 'warning');
             return false;
         }else{
             return true;
@@ -206,9 +206,6 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         if($scope.model.partition_desc.partition_date_column!=null&& $scope.model.partition_desc.partition_date_start==null){
             errors.push("Please indicate start date when partition date column selected.");
         }
-        if($scope.model.partition_desc.partition_date_column==null&& $scope.model.partition_desc.partition_date_start!=null){
-            errors.push("Please select your partitoin date column.");
-        }
         var errorInfo = "";
         angular.forEach(errors,function(item){
             errorInfo+="\n"+item;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 5366809..3c70822 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -1,94 +1,97 @@
-/*
- * 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.
-*/
-
-/**
- *MetaModel will manage model info of cube
- */
-KylinApp.service('MetaModel',function(){
-
-    //data model when edit model
-    this.model={
-        name: null,
-        fact_table: null,
-        lookups: [],
-        filter_condition:null,
-        capacity:null,
-        dimensions:[],
-        metrics:[],
-        "partition_desc" : {
-            "partition_date_column" : null,
-            "partition_date_start" : null,
-            "partition_type" : 'APPEND'
-        },
-        last_modified:0
-    };
-
-
-    this.setMetaModel =function(model){
-        var _model = {};
-        _model.name = model.name;
-        _model.fact_table = model.fact_table;
-        _model.lookups =model.lookups;
-        _model.filter_condition = model.filter_condition;
-        _model.capacity = model.capacity;
-        _model.dimensions = model.dimensions;
-        _model.metrics = model.metrics;
-        _model.partition_desc = model.partition_desc;
-        _model.last_modified = model.last_modified;
-        this.model = _model;
-    };
-
-    this.initModel = function(){
-        this.model = this.createNew();
-    }
-
-    this.getMetaModel = function(){
-        return this.model;
-    };
-
-    this.setFactTable = function(fact_table) {
-        this.model.fact_table =fact_table;
-    };
-
-
-    this.converDateToGMT = function(){
-        if(this.model.partition_desc&&this.model.partition_desc.partition_date_start){
-            this.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
-        }
-    };
-    //
-    this.createNew = function () {
-        var metaModel = {
-            name: '',
-            fact_table: '',
-            lookups: [],
-            filter_condition:'',
-            capacity:'MEDIUM',
-            dimensions:[],
-            metrics:[],
-            "partition_desc" : {
-                "partition_date_column" : null,
-                "partition_date_start" : null,
-                "partition_type" : 'APPEND'
-            },
-            last_modified:0
-        };
-
-        return metaModel;
-    }
-})
\ No newline at end of file
+/*
+ * 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.
+*/
+
+/**
+ *MetaModel will manage model info of cube
+ */
+KylinApp.service('MetaModel',function(){
+
+    //data model when edit model
+    this.model={
+        name: null,
+        description:null,
+        fact_table: null,
+        lookups: [],
+        filter_condition:null,
+        capacity:null,
+        dimensions:[],
+        metrics:[],
+        "partition_desc" : {
+            "partition_date_column" : null,
+            "partition_date_start" : null,
+            "partition_type" : 'APPEND'
+        },
+        last_modified:0
+    };
+
+
+    this.setMetaModel =function(model){
+        var _model = {};
+        _model.name = model.name;
+        _model.description = model.description;
+        _model.fact_table = model.fact_table;
+        _model.lookups =model.lookups;
+        _model.filter_condition = model.filter_condition;
+        _model.capacity = model.capacity;
+        _model.dimensions = model.dimensions;
+        _model.metrics = model.metrics;
+        _model.partition_desc = model.partition_desc;
+        _model.last_modified = model.last_modified;
+        this.model = _model;
+    };
+
+    this.initModel = function(){
+        this.model = this.createNew();
+    }
+
+    this.getMetaModel = function(){
+        return this.model;
+    };
+
+    this.setFactTable = function(fact_table) {
+        this.model.fact_table =fact_table;
+    };
+
+
+    this.converDateToGMT = function(){
+        if(this.model.partition_desc&&this.model.partition_desc.partition_date_start){
+            this.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+        }
+    };
+    //
+    this.createNew = function () {
+        var metaModel = {
+            name: '',
+            description:'',
+            fact_table: '',
+            lookups: [],
+            filter_condition:'',
+            capacity:'MEDIUM',
+            dimensions:[],
+            metrics:[],
+            "partition_desc" : {
+                "partition_date_column" : null,
+                "partition_date_start" : null,
+                "partition_type" : 'APPEND'
+            },
+            last_modified:0
+        };
+
+        return metaModel;
+    }
+})

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/js/services/message.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/message.js b/webapp/app/js/services/message.js
index a5a6d1c..7c8fabd 100644
--- a/webapp/app/js/services/message.js
+++ b/webapp/app/js/services/message.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('MessageService', ['config_ui_messenger', function (config_ui_messenger) {
+KylinApp.service('MessageService', ['config_ui_messenger', function (config_ui_messenger,$log) {
 
     this.sendMsg = function (msg, type, actions, sticky, position) {
         var options = {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 14a6fe8..ab137d2 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -971,4 +971,8 @@ Angular 1.2.0 Animation
 }
 .highlight-bule{
   color:#428bca !important;
+}
+
+.sweet-alert .lead.text-muted{
+  word-break:break-all;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/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 035c777..b104309 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -40,7 +40,7 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></label>
-                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null?'has-error':''">
+                <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="model.partition_desc.partition_date_column"
@@ -49,8 +49,7 @@
                             ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
                         <option value="">--Select Partition Column--</option>
                     </select>
-                    <small class="help-block" ng-show="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null">Please select your partitoin date column.</small>
-                    <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+                    <small class="help-block text-red" ng-show="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</small>
 
                     <span ng-if="state.mode=='view'">
                         {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index 097739c..d300806 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -43,6 +43,21 @@
                     </div>
                 </div>
             </div>
+
+            <!--Description-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Description</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6">
+                        <textarea ng-if="state.mode=='edit'" class="form-control box-default"
+                                  name="comment" id="comment" ng-model="model.description"></textarea>
+                        <span ng-if="state.mode=='view'">{{model.description}}</span>
+                    </div>
+                </div>
+            </div>
+
         </ng-form>
     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index b2cf20c..b94cecb 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -14,7 +14,7 @@
 * 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.
--->A
+-->
 
 <!--hide when view model and no model selected-->
 <div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
@@ -55,7 +55,7 @@
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="saveModel()"
+                        <button class="btn btn-primary"  ng-click="checkForm()?saveModel():''"
                                 ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 142ef0b..4ed21f6 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -41,5 +41,6 @@
                 expand-level      = "2"
                 initial-selection = "">
             </abn-tree>
+        <div no-result ng-if="models_treedata.length==0"></div>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/app/partials/tables/source_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_table_tree.html b/webapp/app/partials/tables/source_table_tree.html
index c7229a9..2e5de36 100755
--- a/webapp/app/partials/tables/source_table_tree.html
+++ b/webapp/app/partials/tables/source_table_tree.html
@@ -42,5 +42,6 @@
                 icon-collapse     = "fa fa-database"
                 expand-level      = "3">
         </abn-tree>
+        <div no-result ng-if="tableModel.selectedSrcDb.length == 0"></div>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0aca96b1/webapp/bower.json
----------------------------------------------------------------------
diff --git a/webapp/bower.json b/webapp/bower.json
index b3f9a8d..0c385a9 100755
--- a/webapp/bower.json
+++ b/webapp/bower.json
@@ -21,7 +21,6 @@
     "nvd3": "1.1.15-beta",
     "angularjs-nvd3-directives": "0.0.5-beta",
     "angular-sweetalert": "~1.0.3",
-    "bootstrap-sweetalert": "~0.4.3",
     "angular-underscore": "~0.5.0",
     "angular-ui-sortable": "0.13.1",
     "underscore": "~1.7.0",
@@ -29,7 +28,8 @@
     "angular-animate": "1.2",
     "angular-cookies": "1.2",
     "angular-bootstrap-nav-tree": "*",
-    "components-font-awesome": "~4.3.0"
+    "components-font-awesome": "~4.3.0",
+    "bootstrap-sweetalert": "~0.4.3"
   },
   "devDependencies": {
     "less.js": "~1.4.0",



[24/52] [abbrv] incubator-kylin git commit: new model GUI

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/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 88b7baf..74bf9ae 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -17,19 +17,13 @@
 -->
 
 <!-- Measures Summary -->
-<div class="dataTables_wrapper form-inline no-footer" ng-if="model.metrics.length > 0">
-    <div class="row">
-        <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
-            <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
-            <i class="ace-icon fa fa-search nav-search-icon"></i>
-        </span>
-    </div>
-    <table class="table table-striped table-hover">
+<div class="dataTables_wrapper form-inline no-footer">
+
+    <table ng-if="state.mode=='view'" class="table table-striped table-hover">
         <thead>
             <tr>
                 <th>ID</th>
                 <th>Column</th>
-                <th ng-if="state.mode=='edit'">Actions</th>
             </tr>
         </thead>
         <tbody>
@@ -42,144 +36,18 @@
                     <!--Name -->
                     <span tooltip="measure name..">{{measure}}</span>
                 </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--Edit Button -->
-                    <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
-                        <i class="fa fa-pencil"></i>
-                    </button>
-                    <!--Remove Button -->
-                    <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
-                        <i class="fa fa-trash-o"></i>
-                    </button>
-                </td>
             </tr>
         </tbody>
     </table>
-</div>
-
-<!--Add Measures Button-->
-<div class="form-group">
-    <button class="btn btn-sm btn-info" ng-click="addNewMeasure()" ng-show="state.mode=='edit' && !newMeasure">
-        <i class="fa fa-plus"></i> Measure
-    </button>
-</div>
-
-<!--Edit Measure-->
-<ng-form name="edit_mes_form">
-<div class="box box-solid" ng-if="newMeasure">
-    <div class="box-header">
-        <h4 class="box-title text-info">Edit Measure</h4>
-    </div>
-    <div class="box-body">
-        <div class="row">
-            <div class="col-xs-8">
-                    <!--Name-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <input type="text" placeholder="Name.." class="form-control"
-                                    tooltip="measure name.." tooltip-trigger="focus"
-                                    ng-model="newMeasure.name" required />
-                            </div>
-                        </div>
-                    </div>
-                    <!--Expression-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Expression</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <select class="form-control"
-                                    ng-init="newMeasure.function.expression = (!!newMeasure.function.expression)?newMeasure.function.expression:cubeConfig.dftSelections.measureExpression" chosen ng-model="newMeasure.function.expression" required
-                                    ng-change="measureReturnTypeUpdate();"
-                                    ng-options="me as me for me in cubeConfig.measureExpressions">
-                                    <option value=""></option>
-                                </select>
-                            </div>
-                        </div>
-                    </div>
-                    <!--Param Type-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Type</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <select class="form-control" ng-if="newMeasure.function.expression != 'COUNT'"
-                                    ng-init="newMeasure.function.parameter.type=(!!newMeasure.function.parameter.type)?newMeasure.function.parameter.type: 'column' "
-                                    chosen ng-model="newMeasure.function.parameter.type" required
-                                    ng-options="mpt as mpt for mpt in cubeConfig.measureParamType">
-                                    <option value=""></option>
-                                </select>
-                                <span class="font-color-default"
-                                       ng-if="newMeasure.function.expression == 'COUNT'"
-                                       ng-init="newMeasure.function.parameter.type= 'constant' "><b>&nbsp;&nbsp;constant</b>
-                                </span>
-                            </div>
-                        </div>
-                    </div>
-                    <!--Param Value-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Value</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <span class="font-color-default"
-                                    ng-if="newMeasure.function.parameter.type == 'constant'"
-                                    ng-init="newMeasure.function.parameter.value = 1"><b>&nbsp;&nbsp;1</b></span>
-                                <select class="form-control" chosen
-                                    ng-if="newMeasure.function.parameter.type == 'column'"
-                                    ng-model="newMeasure.function.parameter.value"
-                                    ng-change="measureReturnTypeUpdate();"
-                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
-                                    <option value="">-- Select a Fact Table Column --</option>
-                                </select>
-                            </div>
-                        </div>
-                    </div>
-                    <!--Return Type-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Return Type</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <select class="form-control"
-                                    ng-if="newMeasure.function.expression == 'COUNT_DISTINCT'"
-                                    ng-init="newMeasure.function.returntype = (!!newMeasure.function.returntype)?newMeasure.function.returntype:cubeConfig.dftSelections.distinctDataType.value"
-                                    chosen ng-model="newMeasure.function.returntype" required
-                                    ng-options="ddt.value as ddt.name for ddt in cubeConfig.distinctDataTypes">
-                                    <option value=""></option>
-                                </select>
-                                <span class="font-color-default"
-                                      ng-if="newMeasure.function.expression != 'COUNT_DISTINCT'"
-                                     ><b>&nbsp;&nbsp;{{newMeasure.function.returntype | uppercase}}</b>
-                                </span>
-                            </div>
-                        </div>
-                    </div>
-            </div>
-
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Tips</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>All cubes have to contain one measure for Count(1), suggest use "_Count_" as name (Has been generated automatically)</li>
-                                    <li>Only accept single column in param value with "Column" type</li>
-                                    <li>Distinct Count is approximate, please indicate Error Rate, higher accuracy degree accompanied with larger storage size and longer build time</li>
-                                </ol>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div class="box-footer">
-        <button class="btn btn-sm btn-info" ng-disabled="edit_mes_form.$invalid"
-                ng-click="saveNewMeasure()" ng-show="state.mode=='edit'">OK</button>
-        <button class="btn btn-link" ng-click="clearNewMeasure()">Cancel</button>
+    <div  ng-if="state.mode=='edit'" class="form-group" style="width: 100%">
+        <h3 class="box-title">Select your measures</h3>
+        <select style="width: 100%"
+                ng-model="model.metrics"  chosen multiple
+                ng-change=""
+                ng-options="measure.name as measure.name for measure in getColumnsByTable(model.fact_table)">
+            <option value=""></option>
+        </select>
     </div>
 </div>
+
 </ng-form>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/models/model_edit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_edit.html b/webapp/app/partials/models/model_edit.html
index 82d0348..d0c9814 100644
--- a/webapp/app/partials/models/model_edit.html
+++ b/webapp/app/partials/models/model_edit.html
@@ -24,8 +24,7 @@
         <form role="form" name="cube_form" novalidate>
             <!-- This margin in order to align with table tree in left part -->
             <div style="margin-top: 20px;">
-                <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
-                     ng-init="state={mode:'edit', modelName: routeParams.modelName}">
+                <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl">
                 </div>
             </div>
         </form>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index ab9564a..0cd0b5e 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -18,7 +18,7 @@
 
 <div class="box box-primary">
     <div class="box-header widget-header-blue widget-header-flat">
-        <h4 class="box-title text-info">Cube Designer</h4>
+        <h4 class="box-title text-info">Model Designer</h4>
     </div>
     <div class="box-body">
         <ng-form name="design_form" ng-submit="">
@@ -43,21 +43,21 @@
                     <div class="col-xs-8">
                         <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
                         <div>
-                            <a href="cubes" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Cubes</a>
+                            <a href="models" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Models</a>
                         </div>
                     </div>
                     <div class="col-xs-4">
-                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Cube Info'">
+                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Model Info'">
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
                         <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
-                                ng-show="curStep.title!='Overview'">
+                                ng-show="curStep.title!='Settings'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareCube();saveCube(design_form)" ng-disabled="design_form.$invalid"
-                                ng-if="curStep.title=='Overview' && state.mode=='edit'">
+                        <button class="btn btn-primary" ng-click="prepareModel();saveModel(design_form)" ng-disabled="design_form.$invalid"
+                                ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>
                     </div>


[35/52] [abbrv] incubator-kylin git commit: add validation for data model

Posted by ma...@apache.org.
add validation for data model


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

Branch: refs/heads/0.8.0
Commit: 3754d6201a7fd385042d739a5396c53a8f276632
Parents: 725598f
Author: jiazhong <ji...@ebay.com>
Authored: Mon Mar 30 19:46:58 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/css/AdminLTE.css                     |  2 +-
 webapp/app/js/controllers/cubeModel.js          | 51 +++++++++++++++-
 webapp/app/js/controllers/modelSchema.js        | 62 +++++++++++++++++---
 webapp/app/js/model/tableModel.js               | 23 ++++++++
 webapp/app/less/app.less                        | 16 ++---
 webapp/app/less/component.less                  |  3 +
 webapp/app/partials/cubes/cube_detail.html      |  2 +-
 .../app/partials/modelDesigner/data_model.html  | 15 +++--
 .../modelDesigner/model_dimensions.html         | 53 +++++++++--------
 .../app/partials/modelDesigner/model_info.html  | 12 ++--
 webapp/app/partials/models/model_detail.html    |  2 +-
 webapp/app/partials/models/model_schema.html    |  9 ++-
 12 files changed, 185 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/css/AdminLTE.css
----------------------------------------------------------------------
diff --git a/webapp/app/css/AdminLTE.css b/webapp/app/css/AdminLTE.css
index 0b9307d..07b1c88 100644
--- a/webapp/app/css/AdminLTE.css
+++ b/webapp/app/css/AdminLTE.css
@@ -20,7 +20,7 @@ body {
 body {
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-  font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  /*font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;*/
   font-weight: 400;
   overflow-x: hidden;
   overflow-y: auto;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index 2987905..1622370 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel) {
 
 
     $scope.buildGraph = function (model) {
@@ -95,7 +95,8 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
 
     // Controller for cube model lookup modal.
     var cubeModelLookupModalCtrl = function ($scope, $modalInstance) {
-        $scope.ok = function () {
+        $scope.ok = function (lookup_form) {
+            console.log(lookup_form);
             $modalInstance.close();
         };
 
@@ -176,4 +177,50 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
         $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;
+                }
+            }
+
+            //column type validate
+            var fact_table = $scope.model.fact_table;
+            var lookup_table = $scope.newLookup.table;
+
+            for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){
+                var pk_column = $scope.newLookup.join.primary_key[i];
+                var fk_column = $scope.newLookup.join.foreign_key[i];
+                if(pk_column!=='null'&&fk_column!=='null'){
+                    var pk_type = TableModel.getColumnType(pk_column,lookup_table);
+                    var fk_type = TableModel.getColumnType(fk_column,fact_table);
+                    if(pk_type!==fk_type){
+                        errors.push(" Column Type incompatible "+pk_column+"["+pk_type+"]"+","+fk_column+"["+fk_type+"].");
+                    }
+                }
+            }
+
+            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/incubator-kylin/blob/3754d620/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 4d7b6c1..883bb3a 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,$log) {
+KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,$log,SweetAlert) {
 
     $log.info($scope.model);
 
@@ -26,17 +26,17 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     $scope.newDimension = null;
     $scope.newMeasure = null;
 
+    $scope.forms = {};
+
 
     $scope.wizardSteps = [
         {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false,form:'model_info_form'},
-        {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false,form:null},
-        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:null},
+        {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false,form:'data_model_form'},
+        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:'model_dimensions'},
         {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:null},
         {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:null}
     ];
 
-    $scope.formStepMap =[{}]
-
     $scope.curStep = $scope.wizardSteps[0];
 
 
@@ -95,11 +95,55 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         }
     };
 
-    $scope.goToStep = function(stepIndex,form){
-        if(form){
-            console.log($scope[form]);
-            console.log(document.querySelector("form"));
+    $scope.checkForm = function(){
+        if(!$scope.curStep.form){
+            return true;
+        }
+        if($scope.state.mode==='view'){
+            return true;
+        }
+        else{
+            //form validation
+            if($scope.forms[$scope.curStep.form].$invalid){
+                return false;
+            }else{
+                //business rule check
+                switch($scope.curStep.form){
+                    case 'data_model_form':
+                        return $scope.check_data_model();
+                     break;
+                    default:
+                        return true;
+                        break;
+                }
+            }
         }
+    };
+
+    /*
+     * lookups can't be null
+     */
+    $scope.check_data_model = function(){
+        var errors = [];
+        if(!$scope.model.lookups.length){
+            errors.push("No lookup table defined");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+
+    }
+
+
+
+    $scope.goToStep = function(stepIndex){
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/js/model/tableModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/tableModel.js b/webapp/app/js/model/tableModel.js
index f482909..55b4e7b 100755
--- a/webapp/app/js/model/tableModel.js
+++ b/webapp/app/js/model/tableModel.js
@@ -138,6 +138,29 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
 
         return defer.promise;
     };
+
+    this.getColumnType = function(_column,_table){
+        var columns = _this.getColumnsByTable(_table);
+        var type;
+        angular.forEach(columns,function(column){
+            if(_column === column.name){
+                type = column.datatype;
+                return;
+            }
+        });
+        return type;
+    };
+
+    this.getColumnsByTable = function (tableName) {
+        var temp = [];
+        angular.forEach(_this.selectProjectTables, function (table) {
+            if (table.name == tableName) {
+                temp = table.columns;
+            }
+        });
+        return temp;
+    };
+
     this.innerSort =function(a, b) {
         var nameA = a.name.toLowerCase(), nameB = b.name.toLowerCase();
         if (nameA < nameB) //sort string ascending

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index 9c629d0..8763bb7 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -364,14 +364,14 @@ pre {
   background: url("../image/icon_table.png") no-repeat;
 }
 
-input.ng-invalid-required {
-  border: 1px solid #dd4b39;
-}
-
-input.ng-invalid-required:after {
-  content: "*";
-  color: red;
-}
+//input.ng-invalid-required {
+//  border: 1px solid #dd4b39;
+//}
+//
+//input.ng-invalid-required:after {
+//  content: "*";
+//  color: red;
+//}
 
 .nav-pills>li {
 cursor: pointer;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index ee28e84..14a6fe8 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -968,4 +968,7 @@ Angular 1.2.0 Animation
 //form validate
 .has-feedback{
 
+}
+.highlight-bule{
+  color:#428bca !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index f5652eb..93084e3 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -47,7 +47,7 @@
             <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">HBase</a>
         </li>
         <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-            <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
+            <a class="dropdown-toggle highlight-bule" data-toggle="dropdown" href="#" aria-expanded="true">
                 <i class="fa fa-cubes">Action</i> <span class="caret"></span>
             </a>
             <ul class="dropdown-menu">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/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 c8cc5a7..79c6533 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -17,7 +17,7 @@
 -->
 
 <div ng-controller="CubeModelCtrl">
-    <ng-form name="model_form">
+    <ng-form name="forms.data_model_form">
 
     <!-- Fact Table Name -->
     <div class="form-group">
@@ -25,9 +25,11 @@
             <label class="col-xs-12 col-sm-2 concube.detailtrol-label no-padding-right font-color-default">
                 <b>Fact Table</b>
             </label>
-            <div class="col-xs-12 col-sm-6">
+            <div class="col-xs-12 col-sm-6" ng-class="forms.data_model_form.innerform.typeahead.$invalid?'has-error':''">
                 <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
                            title="name" model="model.fact_table" required="true"></typeahead>
+                <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required">The fact table is required</small>
+
                 <span ng-if="state.mode=='view'">{{model.fact_table}}</span>
             </div>
         </div>
@@ -109,12 +111,13 @@
                 <div class="col-xs-8">
                     <ng-form name="lookup_form">
                     <!--Table Name-->
-                    <div class="form-group">
+                    <div class="form-group" ng-class="lookup_form.innerform.typeahead.$invalid?'has-error':''">
                         <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 class="col-xs-12 col-sm-6">
-                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" title="name" model="newLookup.table"></typeahead>
+                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" required="true" title="name" model="newLookup.table"></typeahead>
                             </div>
+                            <small class="help-block" ng-show="lookup_form.innerform.typeahead.$error.required">Table name required</small>
                         </div>
                     </div>
 
@@ -123,7 +126,7 @@
                         <div class="row">
                             <label class="col-sm-3 control-label font-color-default"><b>Join Type</b></label>
                             <div class="col-sm-6">
-                                <select class="form-control" chosen ng-model="newLookup.join.type"
+                                <select class="form-control"  chosen ng-model="newLookup.join.type"
                                         ng-options="joinType.value as joinType.name for joinType in cubeConfig.joinTypes">
                                     <option value=""></option>
                                 </select>
@@ -192,7 +195,7 @@
             </div>
         </div>
         <div class="modal-footer">
-            <button class="btn btn-primary" ng-disabled="lookup_form.$invalid || !newLookup.join.primary_key.length" ng-click="ok()">OK</button>
+            <button class="btn btn-primary" ng-disabled="lookup_form.$invalid || !newLookup.join.primary_key.length" ng-click="checkLookupForm()?ok():''">OK</button>
             <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
         </div>
     </script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/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 62af873..10a8d77 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -32,33 +32,34 @@
         </div>
     </div>
 
+    <ng-form name="model_dimensions" novalidate>
      <!-- VIEW MODE -->
-    <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Table Name</th>
-                <th>Columns</th>
-            </tr>
-        </thead>
-        <tbody class="cube-dimension">
-            <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
-                <!--ID -->
-                <td>
-                    <b>{{dimension.id = ($index + 1)}}</b>
-                </td>
-                <!--Name -->
-                <td>
-                    <span>{{dimension.table}}</span>
-                </td>
-                <!--Table Name -->
-                <td>
-                    <span>{{dimension.columns}}</span>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-
+        <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
+            <thead>
+                <tr>
+                    <th>ID</th>
+                    <th>Table Name</th>
+                    <th>Columns</th>
+                </tr>
+            </thead>
+            <tbody class="cube-dimension">
+                <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                    <!--ID -->
+                    <td>
+                        <b>{{dimension.id = ($index + 1)}}</b>
+                    </td>
+                    <!--Name -->
+                    <td>
+                        <span>{{dimension.table}}</span>
+                    </td>
+                    <!--Table Name -->
+                    <td>
+                        <span>{{dimension.columns}}</span>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </ng-form>
     <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
         <h4 style="margin-left:42px">Dimensions</h4>
         <table style="margin-left:42px; width:92%"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index ca7e231..21a8185 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -19,7 +19,7 @@
 <div class="row">
     <div class="col-xs-8">
         <!--Project-->
-        <ng-form name="model_info_form" novalidate>
+        <ng-form name="forms.model_info_form" novalidate>
             <div class="form-group">
                 <div class="row">
                     <label class="col-xs-3 control-label no-padding-right">
@@ -28,11 +28,11 @@
                         </a>
                         <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
                     </label>
-                    <div class="col-xs-6" ng-class="model_info_form.project_name.$invalid?'has-error':model_info_form.project_name.$dirty?'has-success':''">
+                    <div class="col-xs-6" ng-class="forms.model_info_form.project_name.$invalid?'has-error':''">
                          <!--edit-->
                         <input ng-if="state.mode=='edit'" required name="project_name" type="text" class="form-control"
                                ng-model="model.project"/>
-                        <small class="help-block" ng-show="model_info_form.project_name.$error.required">The project is required</small>
+                        <small class="help-block" ng-show="forms.model_info_form.project_name.$error.required">The project is required</small>
 
                         <!--view-->
                         <span ng-if="state.mode=='view'">
@@ -49,15 +49,15 @@
                         <b>Model Name</b>
                     </label>
 
-                    <div class="col-xs-12 col-sm-6" ng-class="model_info_form.model_name.$invalid?'has-error':model_info_form.model_name.$dirty?'has-success':''">
+                    <div class="col-xs-12 col-sm-6" ng-class="forms.model_info_form.model_name.$invalid?'has-error':''">
 
                         <!-- edit -->
                         <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
                                ng-model="model.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
-                        <small class="help-block" ng-show="model_info_form.model_name.$error.required  && model_info_form.model_name.$dirty">Model name is required.</small>
-                        <small class="help-block" ng-show="model_info_form.model_name.$invalid && model_info_form.model_name.$dirty && !model_info_form.model_name.$error.required"> Model name is invalid.</small>
+                        <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required  && forms.model_info_form.model_name.$dirty">Model name is required.</small>
+                        <small class="help-block" ng-show="forms.model_info_form.model_name.$invalid && forms.model_info_form.model_name.$dirty && !forms.model_info_form.model_name.$error.required"> Model name is invalid.</small>
 
 
                         <span ng-if="state.mode=='view'">{{model.name}}</span>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/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 1808d5e..e26c29f 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -30,7 +30,7 @@
             <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
         </li>
         <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-            <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
+            <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">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/3754d620/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index ac607e6..86a3196 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -28,7 +28,7 @@
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
                         class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
-                        <span style="cursor:pointer;" ng-click="goToStep($index,curStep.form)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span style="cursor:pointer;" ng-click="checkForm()?goToStep($index):''" class="step">{{step.step = ($index + 1)}}</span>
                         <span class="title">{{step.title}}</span>
                      </li>
                 </ul>
@@ -40,18 +40,17 @@
             <hr/>
             <div class="wizard-actions">
                 <div class="row">
-                    <div class="col-xs-8" style="display:none;">
-                        <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
+                    <div class="col-xs-8" style="display:block;">
                         <div>
                             <a href="models" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Models</a>
                         </div>
                     </div>
                     <div class="col-xs-4 pull-right">
-                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Model Info'">
+                        <button class="btn btn-prev" ng-click="checkForm()?preView():''" ng-show="curStep.title!='Model Info'">
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''" ng-disabled="design_form.$invalid"
                                 ng-show="curStep.title!='Settings'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>


[40/52] [abbrv] incubator-kylin git commit: add drop data model feature

Posted by ma...@apache.org.
add drop data model feature


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

Branch: refs/heads/0.8.0
Commit: 97963b8fe3903b856a5f119bf271f9737eac34f6
Parents: 9f9d49d
Author: jiazhong <ji...@ebay.com>
Authored: Tue Apr 7 17:10:09 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:32 2015 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/cube/CubeDescManager.java  |  5 +++
 .../kylin/invertedindex/IIDescManager.java      |  5 +++
 .../apache/kylin/metadata/MetadataManager.java  | 24 +++++++++++-
 .../kylin/metadata/project/ProjectManager.java  |  1 -
 .../kylin/rest/controller/ModelController.java  |  4 +-
 .../apache/kylin/rest/service/ModelService.java | 23 +++++++++--
 webapp/app/js/controllers/cube.js               |  4 +-
 webapp/app/js/controllers/cubeModel.js          | 40 +++++++++++++++++++-
 webapp/app/js/controllers/cubes.js              |  6 ++-
 webapp/app/js/controllers/modelEdit.js          |  4 +-
 webapp/app/js/controllers/models.js             |  4 +-
 webapp/app/partials/models/model_detail.html    |  6 ++-
 12 files changed, 109 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java b/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
index a809d86..ac5fc2b 100644
--- a/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
+++ b/cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java
@@ -19,6 +19,7 @@
 package org.apache.kylin.cube;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -96,6 +97,10 @@ public class CubeDescManager {
         return cubeDescMap.get(name);
     }
 
+    public List<CubeDesc> listAllDesc(){
+        return new ArrayList<CubeDesc>(cubeDescMap.values());
+    }
+
     /**
      * Reload CubeDesc from resource store It will be triggered by an desc
      * update event.

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIDescManager.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIDescManager.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIDescManager.java
index e350764..ae38955 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIDescManager.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IIDescManager.java
@@ -32,6 +32,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -89,6 +90,10 @@ public class IIDescManager {
         reloadAllIIDesc();
     }
 
+    public List<IIDesc> listAllDesc(){
+        return new ArrayList<IIDesc>(iiDescMap.values());
+    }
+
     public IIDesc getIIDesc(String name) {
         return iiDescMap.get(name);
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index 933826b..331bd83 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -32,7 +32,6 @@ import org.apache.kylin.metadata.project.ProjectManager;
 import org.apache.kylin.metadata.project.RealizationEntry;
 import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.RealizationRegistry;
-import org.apache.kylin.metadata.realization.RealizationType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,6 +46,8 @@ import org.apache.kylin.common.restclient.CaseInsensitiveStringCache;
 import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.metadata.model.DataModelDesc;
 
+import javax.xml.crypto.Data;
+
 /**
  * Serves (and caches) metadata for Kylin instance.
  * <p/>
@@ -361,6 +362,27 @@ public class MetadataManager {
         }
     }
 
+    // sync on update
+    public DataModelDesc dropModel(DataModelDesc desc) throws IOException {
+        logger.info("Dropping model '" + desc.getName() + "'");
+        ResourceStore store = getStore();
+        if (desc != null)
+            store.deleteResource(desc.getResourcePath());
+        // delete model from project
+        ProjectManager.getInstance(config).removeModelFromProjects(desc.getName());
+        // clean model cache
+        this.afterModelDropped(desc);
+        return desc;
+    }
+
+    private void afterModelDropped(DataModelDesc desc) {
+        removeModelCache(desc);
+    }
+
+    private void removeModelCache(DataModelDesc desc){
+        dataModelDescMap.remove(desc.getName());
+    }
+
     public DataModelDesc createDataModelDesc(DataModelDesc desc,String projectName,String owner) throws IOException {
         String name = desc.getName();
         if (dataModelDescMap.containsKey(name))

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index 9538398..d6a383c 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -232,7 +232,6 @@ public class ProjectManager {
     public void removeModelFromProjects(String modelName) throws IOException {
         for (ProjectInstance projectInstance : findProjects(modelName)) {
             projectInstance.removeModel(modelName);
-
             saveResource(projectInstance);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 290904d..9eb5a41 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import org.apache.commons.lang.StringUtils;
 import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.exception.BadRequestException;
@@ -142,7 +141,7 @@ public class ModelController extends BasicController {
             throw new NotFoundException("Data Model with name " + modelName + " not found..");
         }
         try {
-            modelService.deleteModel(desc);
+            modelService.dropModel(desc);
         } catch (Exception e) {
             logger.error(e.getLocalizedMessage(), e);
             throw new InternalErrorException("Failed to delete model. " + " Caused by: " + e.getMessage(), e);
@@ -172,6 +171,7 @@ public class ModelController extends BasicController {
         request.setSuccessful(success);
         request.setMessage(message);
     }
+
     public void setModelService(ModelService modelService) {
         this.modelService = modelService;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 2780f40..11f2ca0 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -19,6 +19,8 @@
 package org.apache.kylin.rest.service;
 
 
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.invertedindex.model.IIDesc;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.constant.Constant;
@@ -113,13 +115,26 @@ public class ModelService extends BasicService {
 
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public void deleteModel(DataModelDesc desc) throws IOException {
-//        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
+    public void dropModel(DataModelDesc desc) throws IOException {
 
+        //check cube desc exist
+        List<CubeDesc>  cubeDescs = getCubeDescManager().listAllDesc();
+        for(CubeDesc cubeDesc:cubeDescs){
+            if(cubeDesc.getModelName().equals(desc.getName())){
+                throw new InternalErrorException("Model referenced by cube,drop cubes under model and try again.");
+            }
+        }
 
+        //check II desc exist
+        List<IIDesc> iiDescs = getIIDescManager().listAllDesc();
+        for(IIDesc iidesc:iiDescs){
+            if(iidesc.getModelName().equals(desc.getName())){
+                throw new InternalErrorException("Model referenced by IIDesc.");
+            }
+        }
 
+        getMetadataManager().dropModel(desc);
 
-//        getCubeManager().dropCube(cube.getName(), true);
-//        accessService.clean(cube, true);
+        accessService.clean(desc, true);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index d9e7764..f31742a 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -265,7 +265,7 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
 
                 SweetAlert.swal({
                     title: '',
-                    text: "Are you sure to start the build? ",
+                    text: "Are you sure to start the build ?",
                     type: '',
                     showCancelButton: true,
                     confirmButtonColor: '#DD6B55',
@@ -311,7 +311,7 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
                 controller: jobSubmitCtrl,
                 resolve: {
                     cube: function () {
-                        return cube.detail;
+                        return cube;
                     },
                     metaModel:function(){
                         return $scope.metaModel;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index 1622370..cbd7978 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel,ModelService,loadingRequest) {
 
 
     $scope.buildGraph = function (model) {
@@ -223,4 +223,42 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
             }
 
     };
+
+
+    $scope.dropModel = function (model) {
+
+        SweetAlert.swal({
+            title: '',
+            text: "Are you sure to drop this model?",
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                ModelService.drop({modelId: model.name}, {}, function (result) {
+                    loadingRequest.hide();
+//                    CubeList.removeCube(cube);
+                    SweetAlert.swal('Success!', 'Model drop is done successfully', 'success');
+                    location.reload();
+                },function(e){
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+
+        });
+    };
+
+
+
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/webapp/app/js/controllers/cubes.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js
index fdea880..88dcd51 100755
--- a/webapp/app/js/controllers/cubes.js
+++ b/webapp/app/js/controllers/cubes.js
@@ -86,7 +86,9 @@ KylinApp
                         cube.detail = detail[0];
                         ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
                           cube.model = model;
-                          $scope.metaModel.model= model;
+                          $scope.metaModel ={
+                                model: model
+                            }
                           defer.resolve(cube.detail);
                        });
 
@@ -363,7 +365,7 @@ KylinApp
         }
     });
 
-var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube,MetaModel, buildType,SweetAlert,loadingRequest) {
+var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube, buildType,SweetAlert,loadingRequest) {
     $scope.cube = cube;
     $scope.metaModel={
       model:cube.model

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index a571611..dc9b87a 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -139,8 +139,8 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         }
 
         SweetAlert.swal({
-            title: 'Are you sure to update the model?',
-            text: $scope.isEdit?' Please note: if model schema is changed, all cubes of the model will be affected.':'Are you sure to save the Model ?',
+            title: $scope.isEdit?'Are you sure to update the model?':"Are you sure to save the Model?",
+            text: $scope.isEdit?' Please note: if model schema is changed, all cubes of the model will be affected.':'',
             type: 'warning',
             showCancelButton: true,
             confirmButtonColor: '#DD6B55',

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 20ccffb..557be9c 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -109,7 +109,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                                             $scope.cube.detail = detail[0];
                                             //add model info
                                             $scope.metaModel ={
-                                                model : $scope.model
+                                                model : ModelList.getModelByCube(cube.name)
                                             }
                                         }else{
                                             SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
@@ -124,6 +124,8 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                                         }
                                     });
 
+
+
                                     // set selecte model
                                 }
                             }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/97963b8f/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 e26c29f..bda87c1 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -35,9 +35,13 @@
             </a>
             <ul class="dropdown-menu">
                 <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <a href="models/edit/{{model.name}}" data-widget="collapse">Edit Model</a>
+                    <a href="models/edit/{{model.name}}" data-widget="collapse">Edit</a>
                 </li>
                 <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <a ng-click="dropModel(model)">Drop</a>
+                </li>
+                <li role="presentation" class="divider"></li>
+                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
                     <a href="cubes/add/{{model.name}}" data-widget="collapse">Create Cube</a>
                 </li>
             </ul>


[31/52] [abbrv] incubator-kylin git commit: models page update

Posted by ma...@apache.org.
models page update


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

Branch: refs/heads/0.8.0
Commit: 336973ec311771cc3a8c414caef8e1bef0520b0c
Parents: 2cb6e0a
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 25 15:02:39 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeEdit.js        | 11 +++--------
 webapp/app/js/controllers/cubeSchema.js      | 22 ----------------------
 webapp/app/js/controllers/models.js          | 18 +++++++-----------
 webapp/app/js/model/modelList.js             | 12 ++++++++----
 webapp/app/less/component.less               |  4 ++++
 webapp/app/partials/cubes/cube_detail.html   |  2 +-
 webapp/app/partials/cubes/cube_schema.html   |  2 +-
 webapp/app/partials/models/model_schema.html |  4 ++--
 webapp/app/partials/models/models_tree.html  |  2 +-
 9 files changed, 27 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index afc5efe..6b84e6a 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -109,6 +109,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         "cubeSchema": ""
     };
 
+    //fetch cube info and model info in edit model
     // ~ init
     if ($scope.isEdit = !!$routeParams.cubeName) {
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
@@ -123,8 +124,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     } else {
         $scope.cubeMetaFrame = CubeDescModel.createNew();
-//        MetaModel.initModel();
-//        $scope.metaModel = MetaModel;
         $scope.metaModel ={
             model : ModelList.getModel(modelName)
         }
@@ -132,16 +131,12 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
     }
 
-    // ~ public methods
-    $scope.aceChanged = function () {
-    };
-
-    $scope.aceLoaded = function(){
-    };
 
     $scope.prepareCube = function () {
         // generate column family
         generateColumnFamily();
+        //generate rowkey TODO remove after refactor
+        reGenerateRowKey();
 
 
         if ($scope.metaModel.model.partition_desc.partition_date_column&&($scope.metaModel.model.partition_desc.partition_date_start|$scope.metaModel.model.partition_desc.partition_date_start==0)) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 69bb25e..37aa849 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -43,28 +43,6 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         $scope.state = {mode: "view"};
     }
 
-    $scope.$watch('cube.detail', function (newValue, oldValue) {
-        if(!newValue){
-            return;
-        }
-        if (newValue&&$scope.state.mode==="view") {
-            $scope.cubeMetaFrame = newValue;
-
-            // when viw state,each cubeSchema has its own metaModel
-            $scope.metaModel={
-                model:{}
-            }
-
-            //init model
-            ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
-                if (model) {
-                    $scope.metaModel.model = model;
-                }
-            });
-
-        }
-    });
-
     $scope.$watch('cubeMetaFrame', function (newValue, oldValue) {
         if(!newValue){
             return;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 5e9db87..e16c27a 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -23,7 +23,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
         $scope.model = {};
         //tree data
         $scope.models_treedata=[];
-        $scope.selectedCubes = [];
+
         $scope.cubeSelected = false;
         $scope.cube = {};
 
@@ -83,10 +83,9 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                         noLeaf:true,
                         data:model,
                         onSelect:function(branch){
-                         // set selecte model
+                         // set selected model
                             $scope.model=branch.data;
                             $scope.cubeSelected = false;
-                            $scope.selectedCubes = branch.data.cubes;
                         }
                     };
                     var _children = [];
@@ -96,24 +95,22 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                                 label:cube.name,
                                 data:cube,
                                 onSelect:function(branch){
-                                    console.log("cube selected:"+branch.data);
+                                    $log.info("cube selected:"+branch.data.name);
                                     $scope.cubeSelected = true;
 //                                    $scope.cubeMetaFrame = branch.data;
                                     $scope.cube = branch.data;
+                                    $scope.listAccess(cube, 'CubeInstance');
 
                                     CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
                                         if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
+                                            //cubeMetaFrame for cube view and edit
                                             $scope.cubeMetaFrame = detail[0];
+                                            //for show detail info
                                             $scope.cube.detail = detail[0];
+                                            //add model info
                                             $scope.metaModel ={
                                                 model : $scope.model
                                             }
-//                                            ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
-//                                                cube.model = model;
-//                                                $scope.metaModel.model= $scope.model;
-////                                                defer.resolve(cube.detail);
-//                                            });
-
                                         }else{
                                             SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
                                         }
@@ -146,7 +143,6 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 ModelList.removeAll();
                 //init selected model
                 $scope.model = {};
-                $scope.selectedCubes=[];
                 $scope.init();
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 6652611..9c83c4e 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel){
+KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel,$log){
     var models=[];
     var _this = this;
 
@@ -24,13 +24,17 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
 
         var defer = $q.defer();
         var cubeDetail = [];
+        var modelPermission = [];
         ModelService.list(queryParam, function (_models) {
 
             angular.forEach(_models, function (model, index) {
+                $log.info("Add model permission info");
+                modelPermission.push(
                 AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
                     model.accessEntities = accessEntities;
-                });
-//                add cube info to model
+                }).$promise
+                )
+                $log.info("Add cube info to model ,not detail info");
                 cubeDetail.push(
                     CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
                     model.cubes = _cubes;
@@ -39,7 +43,7 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
 
                 model.project = ProjectModel.getProjectByCubeModel(model.name);
             });
-            $q.all(cubeDetail).then(
+            $q.all(cubeDetail,modelPermission).then(
                 function(result){
                     _models = _.filter(_models,function(models){return models.name!=undefined});
                     _this.models = _this.models.concat(_models);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index e9f1a4c..f14ab07 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -956,3 +956,7 @@ Angular 1.2.0 Animation
 .dropdown-menu a{
   cursor: pointer;
 }
+
+.box-2px{
+  border-top:solid 2px #3c8dbc !important;
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 39c727d..f0644cc 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -46,7 +46,7 @@
             ng-if="userService.hasRole('ROLE_ADMIN')">
             <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">HBase</a>
         </li>
-        <li class="dropdown open">
+        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
             <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
                 Action <span class="caret"></span>
             </a>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/partials/cubes/cube_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_schema.html b/webapp/app/partials/cubes/cube_schema.html
index ab9564a..3fa16e5 100644
--- a/webapp/app/partials/cubes/cube_schema.html
+++ b/webapp/app/partials/cubes/cube_schema.html
@@ -16,7 +16,7 @@
 * limitations under the License.
 -->
 
-<div class="box box-primary">
+<div class="box box-primary box-2px">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Cube Designer</h4>
     </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index f19b9d3..60e73e6 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -20,8 +20,8 @@
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
         <div ng-if="state.mode=='view'" class="box-tools pull-right">
-            <a class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
-            <a class="btn btn-box-tool" tooltip="Add Cube" href="cubes/add/{{model.name}}" data-widget="collapse"><i class="fa fa-cube"></i></a>
+            <a ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)" class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
+            <a ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)" class="btn btn-box-tool"  tooltip="Add Cube" href="cubes/add/{{model.name}}" data-widget="collapse"><i class="fa fa-cube"></i></a>
         </div>
     </div>
     <div class="box-body">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/336973ec/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 58921ae..1a8c57a 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -25,7 +25,7 @@
         <!--button-->
         <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;">
             <div class="pull-right">
-                <a class="btn btn-xs btn-primary" href='models/add' tooltip="Create Model"  ng-if="userService.hasRole('ROLE_ADMIN')"><i class="fa fa-plus"></i></a>
+                <a class="btn btn-xs btn-primary" href='models/add' tooltip="Create Model"  ng-if="userService.hasRole('ROLE_MODELER')"><i class="fa fa-plus"></i></a>
             </div>
         </div>
     </div>


[30/52] [abbrv] incubator-kylin git commit: move cube action from cubes.js to cube.js

Posted by ma...@apache.org.
move cube action from cubes.js to cube.js


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

Branch: refs/heads/0.8.0
Commit: 2cb6e0a20b451b52917ff5979f06f30c20a2ba54
Parents: b998dbc
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 24 20:04:31 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cube.js               | 355 ++++++++++++++++++-
 webapp/app/js/controllers/cubeEdit.js           |  24 +-
 webapp/app/js/controllers/models.js             |  34 ++
 webapp/app/js/model/modelList.js                |  14 +
 webapp/app/less/component.less                  |   9 +-
 .../app/partials/cubeDesigner/dimensions.html   |   2 +-
 webapp/app/partials/cubes/cube_detail.html      |  44 ++-
 webapp/app/partials/cubes/cubes.html            |   1 -
 webapp/app/partials/jobs/job_submit.html        |   1 +
 webapp/app/partials/models/models.html          |  31 +-
 10 files changed, 457 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 2765a45..2585345 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert,loadingRequest,ModelList,$modal) {
     $scope.newAccess = null;
     $scope.state = {jsonEdit: false};
 
@@ -102,4 +102,357 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
             });
         }
     };
+
+//    Cube Action
+    $scope.enable = function (cube) {
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to enable the cube? Please note: if cube schema is changed in the disabled period, all segments of the cube will be discarded due to data and schema mismatch.',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+//                confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.enable({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+                    cube.status = 'READY';
+                    SweetAlert.swal('Success!', 'Enable job was submitted successfully', 'success');
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+        });
+    };
+
+    $scope.purge = function (cube) {
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to purge the cube? ',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.purge({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+//                    CubeList.removeAll();
+//                    $scope.reload();
+                    SweetAlert.swal('Success!', 'Purge job was submitted successfully', 'success');
+                },function(e){
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+        });
+    }
+
+
+    $scope.disable = function (cube) {
+
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to disable the cube? ',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.disable({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+                    cube.status = 'DISABLED';
+                    SweetAlert.swal('Success!', 'Disable job was submitted successfully', 'success');
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+
+        });
+    };
+
+
+    $scope.dropCube = function (cube) {
+
+        SweetAlert.swal({
+            title: '',
+            text: " Once it's dropped, your cube’s metadata and data will be cleaned up and can’t be restored back. ",
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.drop({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+//                    CubeList.removeCube(cube);
+                    SweetAlert.swal('Success!', 'Cube drop is done successfully', 'success');
+
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+
+        });
+    };
+
+    $scope.startJobSubmit = function (cube) {
+        $scope.metaModel.model = ModelList.getModelByCube(cube.name);
+        if ($scope.metaModel.model.name) {
+            if ($scope.metaModel.model.partition_desc.partition_date_column) {
+                $modal.open({
+                    templateUrl: 'jobSubmit.html',
+                    controller: jobSubmitCtrl,
+                    resolve: {
+                        cube: function () {
+                            return cube;
+                        },
+                        metaModel:function(){
+                            return $scope.metaModel;
+                        },
+                        buildType: function () {
+                            return 'BUILD';
+                        }
+                    }
+                });
+            }
+            else {
+
+                SweetAlert.swal({
+                    title: '',
+                    text: "Are you sure to start the build? ",
+                    type: '',
+                    showCancelButton: true,
+                    confirmButtonColor: '#DD6B55',
+                    confirmButtonText: "Yes",
+                    closeOnConfirm: true
+                }, function(isConfirm) {
+                    if(isConfirm){
+
+                        loadingRequest.show();
+                        CubeService.rebuildCube(
+                            {
+                                cubeId: cube.name
+                            },
+                            {
+                                buildType: 'BUILD',
+                                startTime: 0,
+                                endTime: 0
+                            }, function (job) {
+
+                                loadingRequest.hide();
+                                SweetAlert.swal('Success!', 'Rebuild job was submitted successfully', 'success');
+                            },function(e){
+
+                                loadingRequest.hide();
+                                if(e.data&& e.data.exception){
+                                    var message =e.data.exception;
+                                    var msg = !!(message) ? message : 'Failed to take action.';
+                                    SweetAlert.swal('Oops...', msg, 'error');
+                                }else{
+                                    SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                                }
+                            });
+                    }
+
+                });
+            }
+        }
+    };
+
+    $scope.startRefresh = function (cube) {
+            $modal.open({
+                templateUrl: 'jobRefresh.html',
+                controller: jobSubmitCtrl,
+                resolve: {
+                    cube: function () {
+                        return cube.detail;
+                    },
+                    metaModel:function(){
+                        return $scope.metaModel;
+                    },
+                    buildType: function () {
+                        return 'BUILD';
+                    }
+                }
+            });
+
+    };
+
+    $scope.startMerge = function (cube) {
+            $modal.open({
+                templateUrl: 'jobMerge.html',
+                controller: jobSubmitCtrl,
+                resolve: {
+                    cube: function () {
+                        return cube.detail;
+                    },
+                    metaModel:function(){
+                        return $scope.metaModel;
+                    },
+                    buildType: function () {
+                        return 'MERGE';
+                    }
+                }
+            });
+    }
+
+
 });
+
+
+var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube,metaModel, buildType,SweetAlert,loadingRequest) {
+    $scope.cube = cube;
+    $scope.metaModel={
+        model:metaModel.model
+    }
+    $scope.jobBuildRequest = {
+        buildType: buildType,
+        startTime: 0,
+        endTime: 0
+    };
+    $scope.message = "";
+
+    $scope.rebuild = function (jobsubmit) {
+
+        $scope.message = null;
+        $scope.jobBuildRequest.startTime = new Date($scope.jobBuildRequest.startTime).getTime();
+        $scope.jobBuildRequest.endTime = new Date($scope.jobBuildRequest.endTime).getTime();
+
+        if ($scope.jobBuildRequest.startTime >= $scope.jobBuildRequest.endTime) {
+            $scope.message = "WARNING: End time should be later than the start time.";
+
+            //rollback date setting
+            if(jobsubmit){
+                $scope.rebuildRollback();
+            }
+            return;
+        }
+
+        loadingRequest.show();
+        CubeService.rebuildCube({cubeId: cube.name}, $scope.jobBuildRequest, function (job) {
+
+            loadingRequest.hide();
+            $modalInstance.dismiss('cancel');
+            SweetAlert.swal('Success!', 'Rebuild job was submitted successfully', 'success');
+        },function(e){
+
+            //rollback date setting
+            if(jobsubmit){
+                $scope.rebuildRollback();
+            }
+
+            loadingRequest.hide();
+            if(e.data&& e.data.exception){
+                var message =e.data.exception;
+                var msg = !!(message) ? message : 'Failed to take action.';
+                SweetAlert.swal('Oops...', msg, 'error');
+            }else{
+                SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+            }
+        });
+    };
+
+    $scope.rebuildRollback = function(){
+        $scope.jobBuildRequest.endTime+=new Date().getTimezoneOffset()*60000;
+    }
+
+    // used by cube segment refresh
+    $scope.segmentSelected = function (selectedSegment) {
+        $scope.jobBuildRequest.startTime = 0;
+        $scope.jobBuildRequest.endTime = 0;
+
+        if (selectedSegment.date_range_start) {
+            $scope.jobBuildRequest.startTime = selectedSegment.date_range_start;
+        }
+
+        if (selectedSegment.date_range_end) {
+            $scope.jobBuildRequest.endTime = selectedSegment.date_range_end;
+        }
+    };
+
+    // used by cube segments merge
+    $scope.mergeStartSelected = function (mergeStartSeg) {
+        $scope.jobBuildRequest.startTime = 0;
+
+        if (mergeStartSeg.date_range_start) {
+            $scope.jobBuildRequest.startTime = mergeStartSeg.date_range_start;
+        }
+    };
+
+    $scope.mergeEndSelected = function (mergeEndSeg) {
+        $scope.jobBuildRequest.endTime = 0;
+
+        if (mergeEndSeg.date_range_end) {
+            $scope.jobBuildRequest.endTime = mergeEndSeg.date_range_end;
+        }
+    };
+
+    $scope.updateDate = function() {
+
+
+//        if ($scope.cube.detail.partition_desc.cube_partition_type=='UPDATE_INSERT')
+//        {
+//            $scope.jobBuildRequest.startTime=$scope.formatDate($scope.jobBuildRequest.startTime);
+//        }
+        $scope.jobBuildRequest.endTime=$scope.formatDate($scope.jobBuildRequest.endTime);
+    };
+
+    $scope.formatDate = function(timestemp) {
+        var dateStart = new Date(timestemp);
+        dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
+        //switch selected time to utc timestamp
+        return new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
+    };
+    $scope.cancel = function () {
+        $modalInstance.dismiss('cancel');
+    };
+};
+

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 01e1623..afc5efe 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -19,10 +19,10 @@
 'use strict';
 
 
-KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService) {
+KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService,ModelList) {
     $scope.cubeConfig = cubeConfig;
 
-    $log.info("model name:"+$routeParams.modelName);
+    // when add cube will transfer model Name
     var modelName = $routeParams.modelName;
 
     //add or edit ?
@@ -114,6 +114,9 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
+                $scope.metaModel ={
+                    model : ModelList.getModel($scope.cubeMetaFrame.model_name)
+                }
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });
@@ -122,24 +125,13 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         $scope.cubeMetaFrame = CubeDescModel.createNew();
 //        MetaModel.initModel();
 //        $scope.metaModel = MetaModel;
+        $scope.metaModel ={
+            model : ModelList.getModel(modelName)
+        }
         $scope.cubeMetaFrame.model_name = modelName;
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
     }
 
-    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
-        if (model) {
-            MetaModel.setMetaModel(model);
-            $scope.metaModel = MetaModel;
-            //use
-            //convert GMT mills ,to make sure partition date show GMT Date
-            //should run only one time
-            if(model.partition_desc&&model.partition_desc.partition_date_start)
-            {
-                MetaModel.converDateToGMT();
-            }
-        }
-    });
-
     // ~ public methods
     $scope.aceChanged = function () {
     };

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index f40e8ec..5e9db87 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -24,6 +24,8 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
         //tree data
         $scope.models_treedata=[];
         $scope.selectedCubes = [];
+        $scope.cubeSelected = false;
+        $scope.cube = {};
 
         $scope.showModels=true;
 
@@ -83,6 +85,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                         onSelect:function(branch){
                          // set selecte model
                             $scope.model=branch.data;
+                            $scope.cubeSelected = false;
                             $scope.selectedCubes = branch.data.cubes;
                         }
                     };
@@ -94,6 +97,36 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                                 data:cube,
                                 onSelect:function(branch){
                                     console.log("cube selected:"+branch.data);
+                                    $scope.cubeSelected = true;
+//                                    $scope.cubeMetaFrame = branch.data;
+                                    $scope.cube = branch.data;
+
+                                    CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
+                                        if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
+                                            $scope.cubeMetaFrame = detail[0];
+                                            $scope.cube.detail = detail[0];
+                                            $scope.metaModel ={
+                                                model : $scope.model
+                                            }
+//                                            ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
+//                                                cube.model = model;
+//                                                $scope.metaModel.model= $scope.model;
+////                                                defer.resolve(cube.detail);
+//                                            });
+
+                                        }else{
+                                            SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
+                                        }
+                                    }, function (e) {
+                                        if(e.data&& e.data.exception){
+                                            var message =e.data.exception;
+                                            var msg = !!(message) ? message : 'Failed to take action.';
+                                            SweetAlert.swal('Oops...', msg, 'error');
+                                        }else{
+                                            SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                                        }
+                                    });
+
                                     // set selecte model
                                 }
                             }
@@ -113,6 +146,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 ModelList.removeAll();
                 //init selected model
                 $scope.model = {};
+                $scope.selectedCubes=[];
                 $scope.init();
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index e5be622..6652611 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -61,6 +61,20 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
         }
     }
 
+    this.getModel = function(modelName){
+      return  _.find(_this.models,function(unit){
+            return unit.name == modelName;
+        })
+    }
+
+    this.getModelByCube = function(cubeName){
+        return  _.find(_this.models,function(model){
+            return _.some(model.cubes,function(_cube){
+                return _cube.name == cubeName;
+            });
+        })
+    }
+
     this.removeAll = function(){
         _this.models = [];
     };

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index b99c765..e9f1a4c 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -953,9 +953,6 @@ Angular 1.2.0 Animation
 .model-design .btn-box-tool{
   font-size: 13px !important;
 }
-
-.models-main {
-  min-height: 100%;
-  background-color: #ecf0f5;
-  z-index: 800;
-}
\ No newline at end of file
+.dropdown-menu a{
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 1267b3f..5a025f4 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -38,9 +38,9 @@
             </button>
         </div>
         <div class="col-xs-6" ng-if="state.mode!='edit'">
-            <b>Dimensions</b>
         </div>
         <div class="col-xs-6">
+            <b>Dimensions</b>
             <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
                 <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
                 <i class="ace-icon fa fa-search nav-search-icon"></i>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 59f2d69..39c727d 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -21,9 +21,9 @@
         <li class="{{(!cube.visiblePage || cube.visiblePage=='metadata')? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='metadata'">Grid</a>
         </li>
-        <li class="{{cube.visiblePage=='graph'? 'active':''}}">
-            <a href="" ng-click="cube.visiblePage='graph';buildGraph(cube);">Visualization</a>
-        </li>
+        <!--<li class="{{cube.visiblePage=='graph'? 'active':''}}">-->
+            <!--<a href="" ng-click="cube.visiblePage='graph';buildGraph(cube);">Visualization</a>-->
+        <!--</li>-->
         <li class="{{cube.visiblePage=='sql'? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='sql';getCubeSql(cube)">SQL</a>
         </li>
@@ -31,10 +31,10 @@
             ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
             <a href="" ng-click="cube.visiblePage='json';">JSON(Cube)</a>
         </li>
-      <li class="{{cube.visiblePage=='json_model'? 'active':''}}"
-          ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
-        <a href="" ng-click="cube.visiblePage='json_model';">JSON(Model)</a>
-      </li>
+      <!--<li class="{{cube.visiblePage=='json_model'? 'active':''}}"-->
+          <!--ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">-->
+        <!--<a href="" ng-click="cube.visiblePage='json_model';">JSON(Model)</a>-->
+      <!--</li>-->
         <li class="{{cube.visiblePage=='access'? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='access';listAccess(cube, 'CubeInstance');">Access</a>
         </li>
@@ -46,6 +46,24 @@
             ng-if="userService.hasRole('ROLE_ADMIN')">
             <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">HBase</a>
         </li>
+        <li class="dropdown open">
+            <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
+                Action <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+                <li ng-if="cube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">
+                    <a ng-click="dropCube(cube)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li>
+                <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))">
+                    <a href="cubes/edit/{{cube.name}}">Edit</a></li>
+                <li><a ng-click="startJobSubmit(cube);">Build</a></li>
+                <li><a ng-click="startRefresh(cube)">Refresh</a></li>
+                <li><a ng-click="startMerge(cube)">Merge</a></li>
+                <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li>
+                <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li>
+                <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li>
+            </ul>
+        </li>
+
     </ul>
 
     <div class="cube-detail" ng-if="!cube.visiblePage || cube.visiblePage=='metadata'">
@@ -68,12 +86,12 @@
              style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.detail), true)}}</pre>
     </div>
 
-    <div ng-show="cube.visiblePage=='json_model'" class="cube-detail">
-          <pre ng-if="!state.jsonEdit"
-               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.model), true)}}</pre>
-    </div>
-    <div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">
-    </div>
+    <!--<div ng-show="cube.visiblePage=='json_model'" class="cube-detail">-->
+          <!--<pre ng-if="!state.jsonEdit"-->
+               <!--style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>-->
+    <!--</div>-->
+    <!--<div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">-->
+    <!--</div>-->
 
     <div class="cube-detail" ng-if="cube.visiblePage=='access'">
         <div class="row">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubes/cubes.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html
index 4c21d9a..f888c88 100644
--- a/webapp/app/partials/cubes/cubes.html
+++ b/webapp/app/partials/cubes/cubes.html
@@ -114,7 +114,6 @@
                         <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li>
                         <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li>
                         <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li>
-
                     </ul>
                 </div>
                 <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/jobs/job_submit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/job_submit.html b/webapp/app/partials/jobs/job_submit.html
index 1036dee..7887680 100644
--- a/webapp/app/partials/jobs/job_submit.html
+++ b/webapp/app/partials/jobs/job_submit.html
@@ -19,6 +19,7 @@
 <script type="text/ng-template" id="jobSubmit.html">
     <div class="modal-header">
         <h4 tooltip="submit">CUBE BUILD CONFIRM</h4>
+        <span>{{metaModel.model.partition_desc.partition_date_column}}</span>
     </div>
     <div class="modal-body" style="background-color: white">
         <div ng-if="metaModel.model.partition_desc.partition_date_column" class="row">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 355114a..e4e7d57 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -18,7 +18,7 @@
 <div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
 
-    <div class="col-xs-2">
+    <div class="col-xs-3">
         <tabset class="nav-tabs-custom">
             <tab heading="Models" select="toggleTab(true);">
                 <div ng-include src="'partials/models/models_tree.html'"></div>
@@ -28,30 +28,21 @@
             </tab>
         </tabset>
     </div>
-
-    <div ng-show="showModels" class="col-xs-2">
-        <div class="box box-primary">
-            <div class="box-header">
-                Cubes
-            </div>
-            <div class="box-body table-responsive no-padding">
-                <ul class="nav nav-list nav-pills nav-stacked">
-                    <li ng-repeat="cube in selectedCubes">
-                         <a>
-                             <span>{{cube.name}}</span>
-                         </a>
-                    </li>
-                </ul>
-            </div>
-        </div>
-    </div>
-    <div  ng-show="showModels"  class="col-xs-8 models-main">
+    <div  ng-show="showModels&&!cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/models/model_detail.html'"></div>
     </div>
+    <div  ng-show="showModels&&cubeSelected"  class="col-xs-9 models-main">
+        <div ng-include src="'partials/cubes/cube_detail.html'"></div>
+    </div>
 
-    <div ng-show="!showModels" class="col-xs-10 models-main">
+    <div ng-show="!showModels" class="col-xs-9 models-main">
         <div ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
 
 
 </div>
+
+<div ng-include="'partials/jobs/job_submit.html'"></div>
+<div ng-include="'partials/jobs/job_refresh.html'"></div>
+<div ng-include="'partials/jobs/job_merge.html'"></div>
+<div ng-include="'partials/projects/project_create.html'"></div>
\ No newline at end of file


[29/52] [abbrv] incubator-kylin git commit: new model list page update

Posted by ma...@apache.org.
new model list page update


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

Branch: refs/heads/0.8.0
Commit: b998dbc3609fe1a19feb4e46a3f33f82920b863b
Parents: 16b6664
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 24 16:15:12 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/index.html                           |   2 +-
 webapp/app/js/controllers/cubeAdvanceSetting.js |   2 +-
 webapp/app/js/controllers/cubeDimensions.js     |   5 +-
 webapp/app/js/controllers/cubeEdit.js           |  77 ++-
 webapp/app/js/controllers/cubeFilter.js         |   2 +-
 webapp/app/js/controllers/cubeModel.js          |   2 +-
 webapp/app/js/controllers/cubeRefresh.js        |   2 +-
 webapp/app/js/controllers/cubeSchema.js         |   7 +-
 webapp/app/js/controllers/cubes.js              |   7 +-
 webapp/app/js/controllers/models.js             |  30 +-
 .../js/directives/kylin_abn_tree_directive.js   | 492 +++++++++++++++++++
 webapp/app/js/model/cubeDescModel.js            |   1 +
 webapp/app/js/model/modelList.js                |  24 +-
 webapp/app/less/component.less                  |  12 +
 .../app/partials/cubeDesigner/dimensions.html   |   6 +-
 webapp/app/partials/cubeDesigner/info.html      |   9 +-
 webapp/app/partials/cubeDesigner/measures.html  |   2 +-
 webapp/app/partials/cubeDesigner/overview.html  |   6 +-
 webapp/app/partials/models/_models.html         | 117 -----
 webapp/app/partials/models/model_schema.html    |  16 +-
 webapp/app/partials/models/models.html          |  36 +-
 webapp/app/partials/models/models_info.html     |  46 --
 webapp/app/partials/models/models_tree.html     |   6 +-
 webapp/app/partials/tables/table_detail.html    |   2 +-
 webapp/app/routes.json                          |  14 +-
 webapp/grunt.json                               |   1 +
 26 files changed, 678 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index ac5c7b7..8901721 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -102,13 +102,13 @@
 <script src="components/angular-underscore/angular-underscore.js"></script>
 <script src="components/jquery-ui/jquery-ui.min.js"></script>
 <script src="components/angular-ui-sortable/sortable.min.js"></script>
-<script src="components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js"></script>
 
 <script src="js/app.js"></script>
 <script src="js/config.js"></script>
 <script src="js/listeners.js"></script>
 <script src="js/filters/filter.js"></script>
 <script src="js/directives/directives.js"></script>
+<script src="js/directives/kylin_abn_tree_directive.js"></script>
 <script src="js/factories/graph.js"></script>
 <script src="js/services/cache.js"></script>
 <script src="js/services/message.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeAdvanceSetting.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeAdvanceSetting.js b/webapp/app/js/controllers/cubeAdvanceSetting.js
index f1bd991..c9558d8 100644
--- a/webapp/app/js/controllers/cubeAdvanceSetting.js
+++ b/webapp/app/js/controllers/cubeAdvanceSetting.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
     //convert some undefined or null value
     angular.forEach($scope.cubeMetaFrame.rowkey.rowkey_columns,function(rowkey){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index f323d1f..b24e9cc 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -63,7 +63,8 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         var factTable = $scope.metaModel.model.fact_table;
 
         // At first dump the columns of fact table.
-        var cols = $scope.getColumnsByTable(factTable);
+//        var cols = $scope.getColumnsByTable(factTable);
+        var cols = $scope.getDimColumnsByTable(factTable);
 
         // Initialize selected available.
         var factAvailable = {};
@@ -87,7 +88,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         var lookups = $scope.metaModel.model.lookups;
 
         for (var j = 0; j < lookups.length; j++) {
-            var cols2 = $scope.getColumnsByTable(lookups[j].table);
+            var cols2 = $scope.getDimColumnsByTable(lookups[j].table);
 
             // Initialize selected available.
             var lookupAvailable = {};

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index fe099fd..01e1623 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -19,8 +19,12 @@
 'use strict';
 
 
-KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelService,MetaModel,TableModel) {
+KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService) {
     $scope.cubeConfig = cubeConfig;
+
+    $log.info("model name:"+$routeParams.modelName);
+    var modelName = $routeParams.modelName;
+
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.cubeMode = absUrl.indexOf("/cubes/add")!=-1?'addNewCube':absUrl.indexOf("/cubes/edit")!=-1?'editExistCube':'default';
@@ -36,6 +40,31 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         return temp;
     };
 
+    $scope.getDimColumnsByTable = function (tableName) {
+        if(!tableName){
+            return [];
+        }
+        var tableColumns = $scope.getColumnsByTable(tableName);
+        var tableDim = _.find($scope.metaModel.model.dimensions,function(dimension){return dimension.table == tableName});
+        var tableDimColumns = tableDim.columns;
+        var avaColObject = _.filter(tableColumns,function(col){
+            return tableDimColumns.indexOf(col.name)!=-1;
+        });
+        return avaColObject;
+    };
+
+    $scope.getMetricColumnsByTable = function (tableName) {
+        if(!tableName){
+            return [];
+        }
+        var tableColumns = $scope.getColumnsByTable(tableName);
+        var tableMetrics = $scope.metaModel.model.metrics;
+        var avaColObject = _.filter(tableColumns,function(col){
+            return tableMetrics.indexOf(col.name)!=-1;
+        });
+        return avaColObject;
+    };
+
     $scope.getPartitonColumns = function(tableName){
         var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
             return column.datatype==="date"||column.datatype==="string";
@@ -85,32 +114,32 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
-                ModelService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
-                    if (model) {
-                        MetaModel.setMetaModel(model);
-                        $scope.metaModel = MetaModel;
-
-                        //use
-                        //convert GMT mills ,to make sure partition date show GMT Date
-                        //should run only one time
-                        if(model.partition_desc&&model.partition_desc.partition_date_start)
-                        {
-                            MetaModel.converDateToGMT();
-                        }
-                    }
-                });
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });
 
     } else {
         $scope.cubeMetaFrame = CubeDescModel.createNew();
-        MetaModel.initModel();
-        $scope.metaModel = MetaModel;
-        $scope.cubeMetaFrame.project = $scope.projectModel.selectedProject;
+//        MetaModel.initModel();
+//        $scope.metaModel = MetaModel;
+        $scope.cubeMetaFrame.model_name = modelName;
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
     }
 
+    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
+        if (model) {
+            MetaModel.setMetaModel(model);
+            $scope.metaModel = MetaModel;
+            //use
+            //convert GMT mills ,to make sure partition date show GMT Date
+            //should run only one time
+            if(model.partition_desc&&model.partition_desc.partition_date_start)
+            {
+                MetaModel.converDateToGMT();
+            }
+        }
+    });
+
     // ~ public methods
     $scope.aceChanged = function () {
     };
@@ -149,7 +178,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 //        delete $scope.cubeMetaFrame.project;
 
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
-        $scope.state.modelSchema = angular.toJson($scope.metaModel.model, true);
     };
 
     $scope.cubeResultTmpl = function (notification) {
@@ -180,7 +208,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                 loadingRequest.show();
 
                 if ($scope.isEdit) {
-                    CubeService.update({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, cubeName: $routeParams.cubeName, project: $scope.state.project}, function (request) {
+                    CubeService.update({}, {cubeDescData: $scope.state.cubeSchema, cubeName: $routeParams.cubeName, project: $scope.state.project}, function (request) {
                         if (request.successful) {
                             $scope.state.cubeSchema = request.cubeDescData;
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
@@ -210,7 +238,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                         loadingRequest.hide();
                     });
                 } else {
-                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
+                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema, project: $scope.state.project}, function (request) {
                         if(request.successful) {
                             $scope.state.cubeSchema = request.cubeDescData;
 
@@ -357,7 +385,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         //! here get the latest rowkey_columns
         $scope.cubeMetaFrame.rowkey.rowkey_columns = newRowKeyColumns;
 
-        if($scope.modelMode==="editExistCube") {
+        if($scope.cubeMode==="editExistCube") {
             var aggregationGroups = $scope.cubeMetaFrame.rowkey.aggregation_groups;
             // rm unused item from group,will only rm when [edit] dimension
             angular.forEach(aggregationGroups, function (group, index) {
@@ -387,7 +415,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             });
         }
 
-        if($scope.modelMode==="addNewCube"){
+        if($scope.cubeMode==="addNewCube"){
 
           if(!tmpAggregationItems.length) {
               $scope.cubeMetaFrame.rowkey.aggregation_groups=[];
@@ -528,9 +556,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             }
             groups[j].push(groupItems[i]);
         }
-//        if(groups[groups.length-1].length<10){
-//            groups.pop();
-//        }
         return groups;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeFilter.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeFilter.js b/webapp/app/js/controllers/cubeFilter.js
index 3c38f1d..3953169 100644
--- a/webapp/app/js/controllers/cubeFilter.js
+++ b/webapp/app/js/controllers/cubeFilter.js
@@ -18,6 +18,6 @@
 
 'use strict';
 
-KylinApp.controller('CubeFilterCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeFilterCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index cfe0f1c..47014c9 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,GraphService,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log) {
 
     //copy model for show Json in model tab list
     $scope.modelJson = angular.copy($scope.model);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeRefresh.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeRefresh.js b/webapp/app/js/controllers/cubeRefresh.js
index 640f2c8..39a63c7 100644
--- a/webapp/app/js/controllers/cubeRefresh.js
+++ b/webapp/app/js/controllers/cubeRefresh.js
@@ -18,6 +18,6 @@
 
 'use strict';
 
-KylinApp.controller('CubeRefreshCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeRefreshCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index d883b59..69bb25e 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel) {
+KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService) {
 
     $scope.projects = [];
     $scope.newDimension = null;
@@ -27,11 +27,8 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
 
     $scope.wizardSteps = [
         {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false},
-        {title: 'Data Model', src: 'partials/cubeDesigner/data_model.html', isComplete: false},
         {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false},
         {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false},
-        {title: 'Filter', src: 'partials/cubeDesigner/filter.html', isComplete: false},
-        {title: 'Refresh Setting', src: 'partials/cubeDesigner/incremental.html', isComplete: false}
     ];
     if (UserService.hasRole("ROLE_ADMIN")) {
             $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false});
@@ -59,7 +56,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
             }
 
             //init model
-            ModelService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
+            ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
                 if (model) {
                     $scope.metaModel.model = model;
                 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubes.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js
index fce706a..94c6031 100755
--- a/webapp/app/js/controllers/cubes.js
+++ b/webapp/app/js/controllers/cubes.js
@@ -19,7 +19,7 @@
 'use strict';
 
 KylinApp
-    .controller('CubesCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,cubeConfig,ProjectModel,ModelService,MetaModel,CubeList) {
+    .controller('CubesCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,cubeConfig,ProjectModel,ModelService,MetaModel,CubeList,ModelDescService) {
 
         $scope.cubeConfig = cubeConfig;
         $scope.cubeList = CubeList;
@@ -84,8 +84,9 @@ KylinApp
                 CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
                     if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
                         cube.detail = detail[0];
-                        ModelService.get({model_name: cube.detail.model_name}, function (model) {
-                          cube.model = model
+                        ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
+                          cube.model = model;
+                          $scope.metaModel.model= model;
                           defer.resolve(cube.detail);
                        });
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 9f93ab6..f40e8ec 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -23,12 +23,13 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
         $scope.model = {};
         //tree data
         $scope.models_treedata=[];
+        $scope.selectedCubes = [];
 
         $scope.showModels=true;
 
         $scope.toggleTab = function(showModel){
             $scope.showModels = showModel;
-//            console.log($scope.showModels);
+            console.log($scope.showModels);
         }
 
         $scope.modelList = ModelList;
@@ -82,11 +83,21 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                         onSelect:function(branch){
                          // set selecte model
                             $scope.model=branch.data;
+                            $scope.selectedCubes = branch.data.cubes;
                         }
                     };
                     var _children = [];
                     angular.forEach(model.cubes,function(cube){
-                        _children.push(cube.name);
+                        _children.push(
+                            {
+                                label:cube.name,
+                                data:cube,
+                                onSelect:function(branch){
+                                    console.log("cube selected:"+branch.data);
+                                    // set selecte model
+                                }
+                            }
+                        );
                     });
                     if(_children.length){
                          _model.children = _children;
@@ -105,4 +116,19 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 $scope.init();
         });
 
+    $scope.status = {
+        isopen: true
+    };
+
+    $scope.toggled = function(open) {
+        $log.log('Dropdown is now: ', open);
+    };
+
+    $scope.toggleDropdown = function($event) {
+        $event.preventDefault();
+        $event.stopPropagation();
+        $scope.status.isopen = !$scope.status.isopen;
+    };
+
+
     });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/directives/kylin_abn_tree_directive.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/directives/kylin_abn_tree_directive.js b/webapp/app/js/directives/kylin_abn_tree_directive.js
new file mode 100644
index 0000000..f309995
--- /dev/null
+++ b/webapp/app/js/directives/kylin_abn_tree_directive.js
@@ -0,0 +1,492 @@
+(function() {
+  var module,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  module = angular.module('angularBootstrapNavTree', []);
+
+  module.directive('abnTree', [
+    '$timeout', function($timeout) {
+      return {
+        restrict: 'E',
+        template: "<ul class=\"nav nav-list nav-pills nav-stacked abn-tree\">\n  <li ng-repeat=\"row in tree_rows | filter:{visible:true} track by row.branch.uid\" ng-animate=\"'abn-tree-animate'\" ng-class=\"'level-' + {{ row.level }} + (row.branch.selected ? ' active':'') + ' ' +row.classes.join(' ')\" class=\"abn-tree-row\"><a ng-click=\"user_clicks_branch(row.branch)\"><i ng-class=\"row.tree_icon\" ng-click=\"row.branch.expanded = !row.branch.expanded\" class=\"indented tree-icon\"> </i><span class=\"indented tree-label\">{{ row.label }} </span></a></li>\n</ul>",
+        replace: true,
+        scope: {
+          treeData: '=',
+          onSelect: '&',
+          initialSelection: '@',
+          treeControl: '='
+        },
+        link: function(scope, element, attrs) {
+          var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
+          error = function(s) {
+            console.log('ERROR:' + s);
+            debugger;
+            return void 0;
+          };
+          if (attrs.iconExpand == null) {
+            attrs.iconExpand = 'icon-plus  glyphicon glyphicon-plus  fa fa-plus';
+          }
+          if (attrs.iconCollapse == null) {
+            attrs.iconCollapse = 'icon-minus glyphicon glyphicon-minus fa fa-minus';
+          }
+          if (attrs.iconLeaf == null) {
+            attrs.iconLeaf = 'icon-file  glyphicon glyphicon-file  fa fa-file';
+          }
+          if (attrs.expandLevel == null) {
+            attrs.expandLevel = '3';
+          }
+          expand_level = parseInt(attrs.expandLevel, 10);
+          if (!scope.treeData) {
+            alert('no treeData defined for the tree!');
+            return;
+          }
+          if (scope.treeData.length == null) {
+            if (treeData.label != null) {
+              scope.treeData = [treeData];
+            } else {
+              alert('treeData should be an array of root branches');
+              return;
+            }
+          }
+          for_each_branch = function(f) {
+            var do_f, root_branch, _i, _len, _ref, _results;
+            do_f = function(branch, level) {
+              var child, _i, _len, _ref, _results;
+              f(branch, level);
+              if (branch.children != null) {
+                _ref = branch.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  _results.push(do_f(child, level + 1));
+                }
+                return _results;
+              }
+            };
+            _ref = scope.treeData;
+            _results = [];
+            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+              root_branch = _ref[_i];
+              _results.push(do_f(root_branch, 1));
+            }
+            return _results;
+          };
+          selected_branch = null;
+          select_branch = function(branch) {
+            if (!branch) {
+              if (selected_branch != null) {
+                selected_branch.selected = false;
+              }
+              selected_branch = null;
+              return;
+            }
+            if (branch !== selected_branch) {
+              if (selected_branch != null) {
+                selected_branch.selected = false;
+              }
+              branch.selected = true;
+              selected_branch = branch;
+              expand_all_parents(branch);
+              if (branch.onSelect != null) {
+                return $timeout(function() {
+                  return branch.onSelect(branch);
+                });
+              } else {
+                if (scope.onSelect != null) {
+                  return $timeout(function() {
+                    return scope.onSelect({
+                      branch: branch
+                    });
+                  });
+                }
+              }
+            }
+          };
+          scope.user_clicks_branch = function(branch) {
+            if (branch !== selected_branch) {
+              return select_branch(branch);
+            }
+          };
+          get_parent = function(child) {
+            var parent;
+            parent = void 0;
+            if (child.parent_uid) {
+              for_each_branch(function(b) {
+                if (b.uid === child.parent_uid) {
+                  return parent = b;
+                }
+              });
+            }
+            return parent;
+          };
+          for_all_ancestors = function(child, fn) {
+            var parent;
+            parent = get_parent(child);
+            if (parent != null) {
+              fn(parent);
+              return for_all_ancestors(parent, fn);
+            }
+          };
+          expand_all_parents = function(child) {
+            return for_all_ancestors(child, function(b) {
+              return b.expanded = true;
+            });
+          };
+          scope.tree_rows = [];
+          on_treeData_change = function() {
+            var add_branch_to_list, root_branch, _i, _len, _ref, _results;
+            for_each_branch(function(b, level) {
+              if (!b.uid) {
+                return b.uid = "" + Math.random();
+              }
+            });
+            console.log('UIDs are set.');
+            for_each_branch(function(b) {
+              var child, _i, _len, _ref, _results;
+              if (angular.isArray(b.children)) {
+                _ref = b.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  _results.push(child.parent_uid = b.uid);
+                }
+                return _results;
+              }
+            });
+            scope.tree_rows = [];
+            for_each_branch(function(branch) {
+              var child, f;
+              if (branch.children) {
+                if (branch.children.length > 0) {
+                  f = function(e) {
+                    if (typeof e === 'string') {
+                      return {
+                        label: e,
+                        children: []
+                      };
+                    } else {
+                      return e;
+                    }
+                  };
+                  return branch.children = (function() {
+                    var _i, _len, _ref, _results;
+                    _ref = branch.children;
+                    _results = [];
+                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                      child = _ref[_i];
+                      _results.push(f(child));
+                    }
+                    return _results;
+                  })();
+                }
+              } else {
+                return branch.children = [];
+              }
+            });
+            add_branch_to_list = function(level, branch, visible) {
+              var child, child_visible, tree_icon, _i, _len, _ref, _results;
+              if (branch.expanded == null) {
+                branch.expanded = false;
+              }
+              if (branch.classes == null) {
+                branch.classes = [];
+              }
+              if (!branch.noLeaf && (!branch.children || branch.children.length === 0)) {
+                tree_icon = attrs.iconLeaf;
+                if (__indexOf.call(branch.classes, "leaf") < 0) {
+                  branch.classes.push("leaf");
+                }
+              } else {
+                if (branch.expanded) {
+                  tree_icon = attrs.iconCollapse;
+                } else {
+                  tree_icon = attrs.iconExpand;
+                }
+              }
+              scope.tree_rows.push({
+                level: level,
+                branch: branch,
+                label: branch.label,
+                classes: branch.classes,
+                tree_icon: tree_icon,
+                visible: visible
+              });
+              if (branch.children != null) {
+                _ref = branch.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  child_visible = visible && branch.expanded;
+                  _results.push(add_branch_to_list(level + 1, child, child_visible));
+                }
+                return _results;
+              }
+            };
+            _ref = scope.treeData;
+            _results = [];
+            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+              root_branch = _ref[_i];
+              _results.push(add_branch_to_list(1, root_branch, true));
+            }
+            return _results;
+          };
+          scope.$watch('treeData', on_treeData_change, true);
+          if (attrs.initialSelection != null) {
+            for_each_branch(function(b) {
+              if (b.label === attrs.initialSelection) {
+                return $timeout(function() {
+                  return select_branch(b);
+                });
+              }
+            });
+          }
+          n = scope.treeData.length;
+          console.log('num root branches = ' + n);
+          for_each_branch(function(b, level) {
+            b.level = level;
+            return b.expanded = b.level < expand_level;
+          });
+          if (scope.treeControl != null) {
+            if (angular.isObject(scope.treeControl)) {
+              tree = scope.treeControl;
+              tree.expand_all = function() {
+                return for_each_branch(function(b, level) {
+                  return b.expanded = true;
+                });
+              };
+              tree.collapse_all = function() {
+                return for_each_branch(function(b, level) {
+                  return b.expanded = false;
+                });
+              };
+              tree.get_first_branch = function() {
+                n = scope.treeData.length;
+                if (n > 0) {
+                  return scope.treeData[0];
+                }
+              };
+              tree.select_first_branch = function() {
+                var b;
+                b = tree.get_first_branch();
+                return tree.select_branch(b);
+              };
+              tree.get_selected_branch = function() {
+                return selected_branch;
+              };
+              tree.get_parent_branch = function(b) {
+                return get_parent(b);
+              };
+              tree.select_branch = function(b) {
+                select_branch(b);
+                return b;
+              };
+              tree.get_children = function(b) {
+                return b.children;
+              };
+              tree.select_parent_branch = function(b) {
+                var p;
+                if (b == null) {
+                  b = tree.get_selected_branch();
+                }
+                if (b != null) {
+                  p = tree.get_parent_branch(b);
+                  if (p != null) {
+                    tree.select_branch(p);
+                    return p;
+                  }
+                }
+              };
+              tree.add_branch = function(parent, new_branch) {
+                if (parent != null) {
+                  parent.children.push(new_branch);
+                  parent.expanded = true;
+                } else {
+                  scope.treeData.push(new_branch);
+                }
+                return new_branch;
+              };
+              tree.add_root_branch = function(new_branch) {
+                tree.add_branch(null, new_branch);
+                return new_branch;
+              };
+              tree.expand_branch = function(b) {
+                if (b == null) {
+                  b = tree.get_selected_branch();
+                }
+                if (b != null) {
+                  b.expanded = true;
+                  return b;
+                }
+              };
+              tree.collapse_branch = function(b) {
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  b.expanded = false;
+                  return b;
+                }
+              };
+              tree.get_siblings = function(b) {
+                var p, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  p = tree.get_parent_branch(b);
+                  if (p) {
+                    siblings = p.children;
+                  } else {
+                    siblings = scope.treeData;
+                  }
+                  return siblings;
+                }
+              };
+              tree.get_next_sibling = function(b) {
+                var i, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  siblings = tree.get_siblings(b);
+                  n = siblings.length;
+                  i = siblings.indexOf(b);
+                  if (i < n) {
+                    return siblings[i + 1];
+                  }
+                }
+              };
+              tree.get_prev_sibling = function(b) {
+                var i, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                siblings = tree.get_siblings(b);
+                n = siblings.length;
+                i = siblings.indexOf(b);
+                if (i > 0) {
+                  return siblings[i - 1];
+                }
+              };
+              tree.select_next_sibling = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_next_sibling(b);
+                  if (next != null) {
+                    return tree.select_branch(next);
+                  }
+                }
+              };
+              tree.select_prev_sibling = function(b) {
+                var prev;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev = tree.get_prev_sibling(b);
+                  if (prev != null) {
+                    return tree.select_branch(prev);
+                  }
+                }
+              };
+              tree.get_first_child = function(b) {
+                var _ref;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  if (((_ref = b.children) != null ? _ref.length : void 0) > 0) {
+                    return b.children[0];
+                  }
+                }
+              };
+              tree.get_closest_ancestor_next_sibling = function(b) {
+                var next, parent;
+                next = tree.get_next_sibling(b);
+                if (next != null) {
+                  return next;
+                } else {
+                  parent = tree.get_parent_branch(b);
+                  return tree.get_closest_ancestor_next_sibling(parent);
+                }
+              };
+              tree.get_next_branch = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_first_child(b);
+                  if (next != null) {
+                    return next;
+                  } else {
+                    next = tree.get_closest_ancestor_next_sibling(b);
+                    return next;
+                  }
+                }
+              };
+              tree.select_next_branch = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_next_branch(b);
+                  if (next != null) {
+                    tree.select_branch(next);
+                    return next;
+                  }
+                }
+              };
+              tree.last_descendant = function(b) {
+                var last_child;
+                if (b == null) {
+                  debugger;
+                }
+                n = b.children.length;
+                if (n === 0) {
+                  return b;
+                } else {
+                  last_child = b.children[n - 1];
+                  return tree.last_descendant(last_child);
+                }
+              };
+              tree.get_prev_branch = function(b) {
+                var parent, prev_sibling;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev_sibling = tree.get_prev_sibling(b);
+                  if (prev_sibling != null) {
+                    return tree.last_descendant(prev_sibling);
+                  } else {
+                    parent = tree.get_parent_branch(b);
+                    return parent;
+                  }
+                }
+              };
+              return tree.select_prev_branch = function(b) {
+                var prev;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev = tree.get_prev_branch(b);
+                  if (prev != null) {
+                    tree.select_branch(prev);
+                    return prev;
+                  }
+                }
+              };
+            }
+          }
+        }
+      };
+    }
+  ]);
+
+}).call(this);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/model/cubeDescModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/cubeDescModel.js b/webapp/app/js/model/cubeDescModel.js
index 773ce95..ad87393 100644
--- a/webapp/app/js/model/cubeDescModel.js
+++ b/webapp/app/js/model/cubeDescModel.js
@@ -24,6 +24,7 @@ KylinApp.service('CubeDescModel',function(){
     this.createNew = function () {
             var cubeMeta = {
                 "name": "",
+                "model_name": "",
                 "description": "",
                 "dimensions": [],
                 "measures": [

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 6d56a10..e5be622 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -23,21 +23,29 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
     this.list = function(queryParam){
 
         var defer = $q.defer();
+        var cubeDetail = [];
         ModelService.list(queryParam, function (_models) {
+
             angular.forEach(_models, function (model, index) {
                 AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
                     model.accessEntities = accessEntities;
                 });
 //                add cube info to model
-                CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
-                    model.cubes=_cubes;
-                });
+                cubeDetail.push(
+                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+                    model.cubes = _cubes;
+                    }).$promise
+                );
 
-                model.project =ProjectModel.getProjectByCubeModel(model.name);
+                model.project = ProjectModel.getProjectByCubeModel(model.name);
             });
-            _models = _.filter(_models,function(models){return models.name!=undefined});
-            _this.models = _this.models.concat(_models);
-            defer.resolve(_this.models);
+            $q.all(cubeDetail).then(
+                function(result){
+                    _models = _.filter(_models,function(models){return models.name!=undefined});
+                    _this.models = _this.models.concat(_models);
+                    defer.resolve(_this.models);
+                }
+            );
         },function(){
             defer.reject("Failed to load models");
         });
@@ -54,7 +62,7 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
     }
 
     this.removeAll = function(){
-        _this.models=[];
+        _this.models = [];
     };
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index cb58e3f..b99c765 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -883,6 +883,12 @@ span.input-icon {
   color: black !important;
 }
 
+.callout.callout-warning {
+  background-color: #fefbed !important;
+  border-color: #f1e7bc !important;
+  color: black !important;
+}
+
 ul.messenger-theme-ice .messenger-message{
   color:#666667 !important;
 }
@@ -946,4 +952,10 @@ Angular 1.2.0 Animation
 }
 .model-design .btn-box-tool{
   font-size: 13px !important;
+}
+
+.models-main {
+  min-height: 100%;
+  background-color: #ecf0f5;
+  z-index: 800;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index dbbc46d..1267b3f 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -183,7 +183,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[0]" ng-options="column.name as column.name for column in getColumnsByTable(newDimension.table)">
+                                    ng-model="newDimension.column[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
                                 <option value=""></option>
                             </select>
                         </div>
@@ -205,7 +205,7 @@
                                             <select chosen style="width: 100%"
                                                     data-placeholder="Dimension Hierarchy Column"
                                                     ng-model="newDimension.column[$index]"
-                                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(newDimension.table)" >
+                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
                                                 <option value="">-- Select Column --</option>
                                             </select>
                                         </div>
@@ -244,7 +244,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 getColumnsByTable(newDimension.table)" >
+                                                ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.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/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index 3aaa314..bd6aed2 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -22,16 +22,13 @@
         <div class="form-group">
             <div class="row">
                 <label class="col-xs-12 col-sm-3 control-label no-padding-right">
-                    <a ng-if="state.mode=='edit'" href="projects">
-                        <b>Project</b>
-                    </a>
-                    <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
+                    <b>Model Name</b>
                 </label>
                 <div class="col-xs-12 col-sm-6">
                     <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="cubeMetaFrame.project" disabled/>
+                           ng-model="cubeMetaFrame.model_name"/>
                     <span ng-if="state.mode=='view'">
-                        {{cubeMetaFrame.project}}
+                        {{cubeMetaFrame.model_name}}
                     </span>
                 </div>
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index a260e28..ef8c8bf 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -148,7 +148,7 @@
                                     ng-if="newMeasure.function.parameter.type == 'column'"
                                     ng-model="newMeasure.function.parameter.value"
                                     ng-change="measureReturnTypeUpdate();"
-                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
+                                    ng-options="columns.name as columns.name for columns in getMetricColumnsByTable(metaModel.model.fact_table)" >
                                     <option value="">-- Select a Fact Table Column --</option>
                                 </select>
                             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/overview.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/overview.html b/webapp/app/partials/cubeDesigner/overview.html
index bbb5dc6..4bf14ff 100644
--- a/webapp/app/partials/cubeDesigner/overview.html
+++ b/webapp/app/partials/cubeDesigner/overview.html
@@ -23,8 +23,8 @@
                 <tbody>
                     <!--Project Name-->
                     <tr>
-                        <th>Project Name</th>
-                        <td>{{cubeMetaFrame.project}}</td>
+                        <th>Model Name</th>
+                        <td>{{metaModel.model.name}}</td>
                     </tr>
                     <!--Cube Name-->
                     <tr>
@@ -34,7 +34,7 @@
                     <!--Fact Table-->
                     <tr>
                         <th>Fact Table</th>
-                        <td class="tb-breakword">{{cubeMetaFrame.fact_table}}</td>
+                        <td class="tb-breakword">{{metaModel.model.fact_table}}</td>
                     </tr>
                     <!--Lookup Table-->
                     <tr>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/_models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/_models.html b/webapp/app/partials/models/_models.html
deleted file mode 100644
index ac433c1..0000000
--- a/webapp/app/partials/models/_models.html
+++ /dev/null
@@ -1,117 +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.
--->
-
-<div class="page-header row">
-    <!--Project-->
-    <div class="col-xs-3">
-        <form ng-if="userService.isAuthorized()">
-            <div class="form-group">
-                <!--Project-->
-                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
-                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
-                    <i class="fa fa-plus"></i>
-                </a>
-            </div>
-        </form>
-    </div>
-    <!--Model Name-->
-    <div class="col-xs-3">
-        <form ng-submit="" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
-                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
-                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
-            </span>
-        </form>
-    </div>
-    <div class="pull-right">
-        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
-    </div>
-</div>
-<div ng-if="!loading && modelList.models.length == 0">
-    <div no-result text="No Model."></div>
-</div>
-<loading ng-if="loading" text="Loading Models..."></loading>
-
-<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
-    <div class="row">
-        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
-    </div>
-    <table class="table table-striped table-bordered table-hover dataTable no-footer">
-        <!--Header-->
-        <thead>
-        <tr style="cursor: pointer">
-            <th ng-repeat="theaditem in modelConfig.theaditems"
-                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
-                {{theaditem.name}}
-                <i ng-if="state.reverseColumn!= theaditem.attr"
-                   class="fa fa-unsorted"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
-                   class="fa fa-sort-asc"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
-                   class="fa fa-sort-desc"></i>
-            </th>
-            <th>Actions</th>
-        </tr>
-        </thead>
-        <!--Body-->
-        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
-        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
-            <td>
-                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
-                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
-                {{ model.name}}
-            </td>
-            <td>
-                    {{ model.fact_table}}
-            </td>
-            <td>
-                    {{ model.last_modified | utcToConfigTimeZone}}
-            </td>
-            <td>
-                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
-                            data-toggle="dropdown">
-                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
-                    </button>
-                    <ul class="dropdown-menu" role="menu">
-                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
-                        <li ng-show="false" ng-if="userService.hasRole('ROLE_ADMIN')">
-                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
-
-                    </ul>
-                </div>
-                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
-                    N/A
-                </span>
-            </td>
-        </tr>
-        <tr ng-show="model.showDetail">
-            <td colspan="9" style="padding: 10px 30px 10px 30px;">
-                <div ng-include src="'partials/models/model_detail.html'"></div>
-            </td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
-
-<div class="row">
-    <div class="col-xs-12">
-        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
-    </div>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 7648f93..f19b9d3 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -16,11 +16,12 @@
 * limitations under the License.
 -->
 
-<div class="box box-primary model-design">
+<div class="box box-primary model-design" ng-hide="state.mode=='view'&&!model.name">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
-        <div class="box-tools pull-right">
+        <div ng-if="state.mode=='view'" class="box-tools pull-right">
             <a class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
+            <a class="btn btn-box-tool" tooltip="Add Cube" href="cubes/add/{{model.name}}" data-widget="collapse"><i class="fa fa-cube"></i></a>
         </div>
     </div>
     <div class="box-body">
@@ -69,3 +70,14 @@
         </ng-form>
     </div>
 </div>
+
+<div ng-show="state.mode=='view'&&!model.name">
+    <div class="box box-primary">
+        <div class="box-header with-border">
+            <h3 class="box-title">No model selected</h3>
+        </div>
+        <div class="box-body">
+            Plese choose your model
+        </div><!-- /.box-body -->
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 28a8fb3..355114a 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -15,21 +15,43 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-<div class="row">
+<div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
-    <div class="col-xs-3">
-        <tabset>
+
+    <div class="col-xs-2">
+        <tabset class="nav-tabs-custom">
             <tab heading="Models" select="toggleTab(true);">
                 <div ng-include src="'partials/models/models_tree.html'"></div>
             </tab>
-            <tab heading="Data source"  select="toggleTab(false);">
+            <tab heading="Data Source"  select="toggleTab(false);">
                 <div ng-include src="'partials/tables/source_table_tree.html'"></div>
             </tab>
         </tabset>
     </div>
 
-    <div class="col-xs-9" style="padding-top:39px;">
-        <div ng-show="showModels" ng-include src="'partials/models/model_detail.html'"></div>
-        <div ng-show="!showModels" ng-include src="'partials/tables/table_detail.html'"></div>
+    <div ng-show="showModels" class="col-xs-2">
+        <div class="box box-primary">
+            <div class="box-header">
+                Cubes
+            </div>
+            <div class="box-body table-responsive no-padding">
+                <ul class="nav nav-list nav-pills nav-stacked">
+                    <li ng-repeat="cube in selectedCubes">
+                         <a>
+                             <span>{{cube.name}}</span>
+                         </a>
+                    </li>
+                </ul>
+            </div>
+        </div>
+    </div>
+    <div  ng-show="showModels"  class="col-xs-8 models-main">
+        <div ng-include src="'partials/models/model_detail.html'"></div>
+    </div>
+
+    <div ng-show="!showModels" class="col-xs-10 models-main">
+        <div ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
+
+
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_info.html b/webapp/app/partials/models/models_info.html
deleted file mode 100644
index f381077..0000000
--- a/webapp/app/partials/models/models_info.html
+++ /dev/null
@@ -1,46 +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.
--->
-
-<div class="tree-border">
-    <div class="row">
-        <div class="col-xs-7">
-            <h3 class="text-info">Tables</h3>
-        </div>
-
-        <!--button-->
-        <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;">
-            <div class="pull-right">
-                <a class="btn btn-xs btn-primary" tooltip="Load Hive Table"  ng-if="userService.hasRole('ROLE_ADMIN')"  ng-click="openModal()"><i class="fa fa-download"></i></a>
-                <a class="btn btn-xs btn-success" tooltip="Refresh Tables" ng-click="aceSrcTbChanged()"><i class="fa fa-refresh"></i></a>
-            </div>
-        </div>
-
-    </div>
-    <div class="space-4"></div>
-    <!--tree-->
-    <div style="width:100%; height:{{window}}px; overflow:auto;">
-        <treecontrol ng-if="tableModel.selectedSrcDb.length > 0" class="tree-light"
-                     dirSelection="true"
-                     tree-model="tableModel.selectedSrcDb"
-                     options="tableModel.treeOptions"
-                     on-selection="showSelected(node)"
-                     selected-node="tableModel.selectedSrcTable">
-            {{node.name}} {{!!(node.datatype)?'(' + trimType(node.datatype) + ')' : ''}}
-        </treecontrol>
-    </div>
-</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 40b7c3a..58921ae 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -28,10 +28,8 @@
                 <a class="btn btn-xs btn-primary" href='models/add' tooltip="Create Model"  ng-if="userService.hasRole('ROLE_ADMIN')"><i class="fa fa-plus"></i></a>
             </div>
         </div>
-
-    </div>
     </div>
-    <div class="space-4 box-header with-border"></div>
+    <!--<div class="space-4 box-header with-border"></div>-->
     <!--tree-->
     <div style="width:100%; height:{{window}}px; overflow:auto;">
         <abn-tree
@@ -41,7 +39,7 @@
                 icon-expand       = "fa fa-plus"
                 icon-collapse     = "fa fa-minus"
                 expand-level      = "2"
-                initial-selection = "Vegetable">
+                initial-selection = "">
             ></abn-tree>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/tables/table_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html
index b20825c..9801eb1 100644
--- a/webapp/app/partials/tables/table_detail.html
+++ b/webapp/app/partials/tables/table_detail.html
@@ -1,5 +1,5 @@
 <div  ng-controller="SourceMetaCtrl" class="nav-tabs-custom">
-    <div class="col-xs-9">
+    <div class="col-xs-12">
         <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
         <div class="tabbable nav-tabs-custom">
             <ul class="nav nav-tabs">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 8ee6fc3..1accb01 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -10,7 +10,7 @@
         "url": "/cubes",
         "params": {
             "templateUrl": "partials/cubes/cubes.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubesCtrl"
         }
     },
@@ -31,10 +31,10 @@
         }
     },
     {
-        "url": "/cubes/add",
+        "url": "/cubes/add/:modelName",
         "params": {
             "templateUrl": "partials/cubes/cube_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -42,7 +42,7 @@
         "url": "/cubes/add/json",
         "params": {
             "templateUrl": "partials/cubes/cube_json_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -50,7 +50,7 @@
         "url": "/cubes/edit/:cubeName/json",
         "params": {
             "templateUrl": "partials/cubes/cube_json_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -58,7 +58,7 @@
         "url": "/cubes/edit/:cubeName",
         "params": {
             "templateUrl": "partials/cubes/cube_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -66,7 +66,7 @@
         "url": "/cubes/:projectName/:cubeName",
         "params": {
             "templateUrl": "partials/cubes/cubes.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubesCtrl"
         }
     },

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/grunt.json
----------------------------------------------------------------------
diff --git a/webapp/grunt.json b/webapp/grunt.json
index 9a4499f..48ed483 100755
--- a/webapp/grunt.json
+++ b/webapp/grunt.json
@@ -59,6 +59,7 @@
                 "app/components/angular-chosen-localytics/chosen-spinner.css",
                 "app/components/nvd3/nv.d3.min.css",
                 "app/css/AdminLTE.css",
+                "app/css/skins/_all-skins.min.css",
                 "app/components/bootstrap-sweetalert/lib/sweet-alert.css",
                 "tmp/css/styles.css"
             ],


[08/52] [abbrv] incubator-kylin git commit: KYLIN-759 add test cases and bug fix

Posted by ma...@apache.org.
KYLIN-759 add test cases and bug fix


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

Branch: refs/heads/0.8.0
Commit: 0e42b2dfae6f490ae25e33241f3982f7de66fd59
Parents: bc426cc
Author: honma <ho...@ebay.com>
Authored: Thu May 14 13:57:31 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Thu May 14 20:22:04 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/common/util/IdentityUtils.java |  35 +++++
 .../org/apache/kylin/common/util/BasicTest.java |  24 ++--
 .../kylin/common/util/IdentityUtilTest.java     |  30 ++++
 .../apache/kylin/query/test/KylinQueryTest.java |   2 +-
 .../kylin/storage/ICachableStorageEngine.java   |   7 +
 .../cache/CacheFledgedDynamicStorageEngine.java |   5 +-
 .../cache/CacheFledgedStaticStorageEngine.java  |   2 +-
 .../kylin/storage/cache/StreamSQLResult.java    |   3 +
 .../org/apache/kylin/storage/tuple/Tuple.java   |   8 +-
 .../apache/kylin/storage/cache/EhcacheTest.java |   5 -
 .../kylin/storage/test/DynamicCacheTest.java    | 141 +++++++++++++++++++
 .../kylin/storage/test/StaticCacheTest.java     |  95 +++++++++++++
 .../kylin/storage/test/StorageMockUtils.java    | 132 +++++++++++++++++
 .../apache/kylin/storage/test/StorageTest.java  | 119 ++--------------
 14 files changed, 476 insertions(+), 132 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/common/src/main/java/org/apache/kylin/common/util/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/IdentityUtils.java b/common/src/main/java/org/apache/kylin/common/util/IdentityUtils.java
new file mode 100644
index 0000000..d0691da
--- /dev/null
+++ b/common/src/main/java/org/apache/kylin/common/util/IdentityUtils.java
@@ -0,0 +1,35 @@
+package org.apache.kylin.common.util;
+
+import java.util.Collection;
+import java.util.IdentityHashMap;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public class IdentityUtils {
+    public static <K> boolean collectionReferenceEquals(Collection<K> collectionA, Collection<K> collectionB) {
+        if (collectionA == null || collectionB == null) {
+            throw new RuntimeException("input must be not null");
+        }
+
+        IdentityHashMap<K, Void> mapA = new IdentityHashMap<>();
+        IdentityHashMap<K, Void> mapB = new IdentityHashMap<>();
+        for (K key : collectionA) {
+            mapA.put(key, null);
+        }
+        for (K key : collectionB) {
+            mapB.put(key, null);
+        }
+
+        if (mapA.keySet().size() != mapB.keySet().size()) {
+            return false;
+        }
+
+        for (K key : mapA.keySet()) {
+            if (!mapB.keySet().contains(key)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
index e0226f8..b8fb5e7 100644
--- a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
@@ -19,8 +19,8 @@
 package org.apache.kylin.common.util;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Ranges;
 import org.apache.commons.configuration.ConfigurationException;
+import org.junit.Assert;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.slf4j.LoggerFactory;
@@ -31,6 +31,7 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.IdentityHashMap;
 
 /**
 * <p/>
@@ -60,16 +61,21 @@ public class BasicTest {
     }
 
     @Test
+    public void test0() throws Exception {
+
+        IdentityHashMap<String, Void> a = new IdentityHashMap<>();
+        IdentityHashMap<String, Void> b = new IdentityHashMap<>();
+        String s1 = new String("s1");
+        String s2 = new String("s1");
+        Assert.assertEquals(s1, s2);
+        Assert.assertTrue(s1 != s2);
+        a.put(s1, null);
+        b.put(s2, null);
+    }
+
+    @Test
     @Ignore("convenient trial tool for dev")
     public void test1() throws Exception {
-        Number xx =new Long(0L);
-        System.out.println(xx.getClass().getName());
-
-        System.out.println(time(1367798400000L));
-
-        System.out.println(org.apache.kylin.common.util.DateFormat.formatToTimeStr(1000L * Integer.MAX_VALUE));
-
-        System.out.println(Ranges.open(3, 5).isConnected(Ranges.open(3, 10)));
 
         String bb = "\\x00\\x00\\x00\\x00\\x01\\x3F\\xD0\\x2D\\58\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00";//2013/07/12 07:59:37
         String cc = "\\x00\\x00\\x00\\x00\\x01\\x41\\xBE\\x8F\\xD8\\x00\\x00\\x00\\x00\\x00\\x00\\x00";//2013/10/16 08:00:00

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/common/src/test/java/org/apache/kylin/common/util/IdentityUtilTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/IdentityUtilTest.java b/common/src/test/java/org/apache/kylin/common/util/IdentityUtilTest.java
new file mode 100644
index 0000000..99385f6
--- /dev/null
+++ b/common/src/test/java/org/apache/kylin/common/util/IdentityUtilTest.java
@@ -0,0 +1,30 @@
+package org.apache.kylin.common.util;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.collections.CollectionUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public class IdentityUtilTest {
+    @Test
+    public void basicTest()
+    {
+        String s1 = new String("hi");
+        String s2 = new String("hi");
+
+        List<String> c1 = Lists.newArrayList(s1);
+        List<String> c2 = Lists.newArrayList(s2);
+        List<String> c3 = Lists.newArrayList(s2);
+
+        Assert.assertTrue(CollectionUtils.isEqualCollection(c1,c2));
+        Assert.assertTrue(CollectionUtils.isEqualCollection(c3,c2));
+
+        Assert.assertFalse(IdentityUtils.collectionReferenceEquals(c1,c2));
+        Assert.assertTrue(IdentityUtils.collectionReferenceEquals(c3,c2));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/query/src/test/java/org/apache/kylin/query/test/KylinQueryTest.java
----------------------------------------------------------------------
diff --git a/query/src/test/java/org/apache/kylin/query/test/KylinQueryTest.java b/query/src/test/java/org/apache/kylin/query/test/KylinQueryTest.java
index 40372ff..cea8ee2 100644
--- a/query/src/test/java/org/apache/kylin/query/test/KylinQueryTest.java
+++ b/query/src/test/java/org/apache/kylin/query/test/KylinQueryTest.java
@@ -95,7 +95,7 @@ public class KylinQueryTest extends KylinTestBase {
     @Test
     public void testSingleRunQuery() throws Exception {
 
-        String queryFileName = "src/test/resources/query/sql_derived/query07.sql";
+        String queryFileName = "src/test/resources/query/sql/query00.sql";
 
         File sqlFile = new File(queryFileName);
         if (sqlFile.exists()) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
new file mode 100644
index 0000000..eadef09
--- /dev/null
+++ b/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
@@ -0,0 +1,7 @@
+package org.apache.kylin.storage;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public interface ICachableStorageEngine extends IStorageEngine{
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
index 0d7ab18..65672ae 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
@@ -41,7 +41,8 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
 
     @Override
     public ITupleIterator search(final StorageContext context, final SQLDigest sqlDigest, final TupleInfo returnTupleInfo) {
-        //if isDynamicStorage && query involves filter on partition column, the cache requires updating after query done.
+        //enable dynamic cache iff group by columns contains partition col
+        //because cache extraction requires partition col value as selection key
         boolean needUpdateCache = sqlDigest.groupbyColumns.contains(partitionColRef);
 
         streamSQLDigest = new StreamSQLDigest(sqlDigest, partitionColRef);
@@ -106,7 +107,7 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
             logger.info("decision: use cache");
         }
 
-        if (needUpdateCache || !queryCacheExists) {
+        if (needUpdateCache) {
             //use another nested ITupleIterator to deal with cache
             final TeeTupleIterator tee = new TeeTupleIterator(ret);
             tee.addCloseListener(this);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
index a4aceed..860dea2 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
@@ -51,7 +51,7 @@ public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorage
             logger.info("decision: use cache");
         }
 
-        if (queryCacheExists) {
+        if (!queryCacheExists) {
             //use another nested ITupleIterator to deal with cache
             final TeeTupleIterator tee = new TeeTupleIterator(ret);
             tee.addCloseListener(this);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
index e895d8e..924044b 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
@@ -39,6 +39,9 @@ public class StreamSQLResult {
                     }
                 }
             } else {
+                if (!this.sortedRows.containsKey(0L)) {
+                    this.sortedRows.put(0L, Lists.<ITuple> newArrayList());
+                }
                 this.sortedRows.get(0L).add(row);
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/main/java/org/apache/kylin/storage/tuple/Tuple.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/tuple/Tuple.java b/storage/src/main/java/org/apache/kylin/storage/tuple/Tuple.java
index 7224cfe..efa1bc2 100644
--- a/storage/src/main/java/org/apache/kylin/storage/tuple/Tuple.java
+++ b/storage/src/main/java/org/apache/kylin/storage/tuple/Tuple.java
@@ -135,7 +135,9 @@ public class Tuple implements ITuple {
         return 1L * days * (1000 * 3600 * 24);
     }
 
-    public static int millisToEpicDays(long millis) {
+    public static int dateToEpicDays(String strValue) {
+        Date dateValue = DateFormat.stringToDate(strValue); // NOTE: forces GMT timezone
+        long millis = dateValue.getTime();
         return (int) (millis / (1000 * 3600 * 24));
     }
 
@@ -158,9 +160,7 @@ public class Tuple implements ITuple {
         // TODO use data type enum instead of string comparison
         if ("date".equals(dataTypeName)) {
             // convert epoch time
-            Date dateValue = DateFormat.stringToDate(strValue); // NOTE: forces GMT timezone
-            long millis = dateValue.getTime();
-            return millisToEpicDays(millis);// Optiq expects Integer instead of Long. by honma
+            return dateToEpicDays(strValue);// Optiq expects Integer instead of Long. by honma
         } else if ("timestamp".equals(dataTypeName) || "datetime".equals(dataTypeName)) {
             return Long.parseLong(strValue);
         } else if ("tinyint".equals(dataTypeName)) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
index e86771d..1dec9e6 100644
--- a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
@@ -1,9 +1,7 @@
 package org.apache.kylin.storage.cache;
 
-import com.google.common.collect.Maps;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
 import net.sf.ehcache.config.CacheConfiguration;
 import net.sf.ehcache.config.MemoryUnit;
 import net.sf.ehcache.config.PersistenceConfiguration;
@@ -11,9 +9,6 @@ import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
 
 import org.junit.Test;
 
-import java.util.HashMap;
-import java.util.HashSet;
-
 /**
  */
 public class EhcacheTest {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java b/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
new file mode 100644
index 0000000..0d962cb
--- /dev/null
+++ b/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
@@ -0,0 +1,141 @@
+package org.apache.kylin.storage.test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import com.google.common.collect.Ranges;
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.kylin.common.util.DateFormat;
+import org.apache.kylin.common.util.IdentityUtils;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.realization.SQLDigest;
+import org.apache.kylin.metadata.tuple.ITuple;
+import org.apache.kylin.metadata.tuple.ITupleIterator;
+import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
+import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.StorageContext;
+import org.apache.kylin.storage.cache.CacheFledgedDynamicStorageEngine;
+import org.apache.kylin.storage.hbase.coprocessor.endpoint.TsConditionExtractor;
+import org.apache.kylin.storage.tuple.Tuple;
+import org.apache.kylin.storage.tuple.TupleInfo;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public class DynamicCacheTest {
+
+    class TsOnlyTuple implements ITuple {
+        private TblColRef partitionCol;
+        private String tsStr;
+
+        public TsOnlyTuple(TblColRef partitionCol, String tsStr) {
+            this.partitionCol = partitionCol;
+            this.tsStr = tsStr;
+        }
+
+        @Override
+        public List<String> getAllFields() {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public List<TblColRef> getAllColumns() {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public Object[] getAllValues() {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public ITuple makeCopy() {
+            return new TsOnlyTuple(this.partitionCol, this.tsStr);
+        }
+
+        @Override
+        public Object getValue(TblColRef col) {
+            if (col.equals(partitionCol)) {
+                return Tuple.dateToEpicDays(this.tsStr);
+            } else {
+                throw new NotImplementedException();
+            }
+        }
+    }
+
+    @Test
+    public void basicTest() {
+
+        final StorageContext context = new StorageContext();
+        final List<TblColRef> groups = StorageMockUtils.buildGroups();
+        final TblColRef partitionCol = groups.get(0);
+        final List<FunctionDesc> aggregations = StorageMockUtils.buildAggregations();
+        final TupleInfo tupleInfo = StorageMockUtils.newTupleInfo(groups, aggregations);
+
+        SQLDigest sqlDigest = new SQLDigest("default.test_kylin_fact", null, null, Lists.<TblColRef> newArrayList(), groups, Lists.newArrayList(partitionCol), Lists.<TblColRef>newArrayList(), aggregations);
+
+        ITuple aTuple = new TsOnlyTuple(partitionCol, "2011-02-01");
+        ITuple bTuple = new TsOnlyTuple(partitionCol, "2012-02-01");
+        final List<ITuple> allTuples = Lists.newArrayList(aTuple, bTuple);
+
+        //counts for verifying
+        final AtomicInteger underlyingSEHitCount = new AtomicInteger(0);
+        final List<Integer> returnedRowPerSearch = Lists.newArrayList();
+
+        CacheFledgedDynamicStorageEngine dynamicCache = new CacheFledgedDynamicStorageEngine(new IStorageEngine() {
+            @Override
+            public ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo) {
+                Range<Long> tsRagneInQuery = TsConditionExtractor.extractTsCondition(partitionCol, sqlDigest.filter);
+                List<ITuple> ret = Lists.newArrayList();
+                for (ITuple tuple : allTuples) {
+                    if (tsRagneInQuery.contains(Tuple.getTs(tuple, partitionCol))) {
+                        ret.add(tuple);
+                    }
+                }
+
+                underlyingSEHitCount.incrementAndGet();
+                returnedRowPerSearch.add(ret.size());
+
+                return new SimpleTupleIterator(ret.iterator());
+            }
+
+            @Override
+            public boolean isDynamic() {
+                return true;
+            }
+
+            @Override
+            public Range<Long> getVolatilePeriod() {
+                return Ranges.greaterThan(DateFormat.stringToMillis("2011-02-01"));
+            }
+        }, partitionCol);
+
+        sqlDigest.filter = StorageMockUtils.buildTs2010Filter(groups.get(0));
+        ITupleIterator firstIterator = dynamicCache.search(context, sqlDigest, tupleInfo);
+        IdentityHashMap<ITuple, Void> firstResults = new IdentityHashMap<>();
+        while (firstIterator.hasNext()) {
+            firstResults.put(firstIterator.next(), null);
+        }
+        firstIterator.close();
+
+        sqlDigest.filter = StorageMockUtils.buildTs2011Filter(groups.get(0));
+        ITupleIterator secondIterator = dynamicCache.search(context, sqlDigest, tupleInfo);
+        IdentityHashMap<ITuple, Void> secondResults = new IdentityHashMap<>();
+        while (secondIterator.hasNext()) {
+            secondResults.put(secondIterator.next(), null);
+        }
+        secondIterator.close();
+
+        Assert.assertEquals(2, firstResults.size());
+        IdentityUtils.collectionReferenceEquals(firstResults.keySet(), secondResults.keySet());
+        Assert.assertEquals(2, underlyingSEHitCount.get());
+        Assert.assertEquals(new Integer(2), returnedRowPerSearch.get(0));
+        Assert.assertEquals(new Integer(1), returnedRowPerSearch.get(1));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java b/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
new file mode 100644
index 0000000..9b69830
--- /dev/null
+++ b/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
@@ -0,0 +1,95 @@
+package org.apache.kylin.storage.test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import org.apache.kylin.common.util.IdentityUtils;
+import org.apache.kylin.metadata.filter.TupleFilter;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.realization.SQLDigest;
+import org.apache.kylin.metadata.tuple.ITuple;
+import org.apache.kylin.metadata.tuple.ITupleIterator;
+import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
+import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.StorageContext;
+import org.apache.kylin.storage.cache.CacheFledgedStaticStorageEngine;
+import org.apache.kylin.storage.tuple.Tuple;
+import org.apache.kylin.storage.tuple.TupleInfo;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public class StaticCacheTest {
+
+    @Test
+    public void basicTest() {
+
+        final StorageContext context = new StorageContext();
+        final List<TblColRef> groups = StorageMockUtils.buildGroups();
+        final List<FunctionDesc> aggregations = StorageMockUtils.buildAggregations();
+        final TupleFilter filter = StorageMockUtils.buildFilter1(groups.get(0));
+        final SQLDigest sqlDigest = new SQLDigest("default.test_kylin_fact", filter, null, Collections.<TblColRef> emptySet(), groups, Collections.<TblColRef> emptySet(), Collections.<TblColRef> emptySet(), aggregations);
+        final TupleInfo tupleInfo = StorageMockUtils.newTupleInfo(groups, aggregations);
+
+        final List<ITuple> ret = Lists.newArrayList();
+        ret.add(new Tuple(tupleInfo));
+        ret.add(new Tuple(tupleInfo));
+        ret.add(new Tuple(tupleInfo));
+
+        final AtomicInteger underlyingSEHitCount = new AtomicInteger(0);
+
+        CacheFledgedStaticStorageEngine cacheFledgedStaticStorageEngine = new CacheFledgedStaticStorageEngine(new IStorageEngine() {
+            @Override
+            public ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo) {
+                underlyingSEHitCount.incrementAndGet();
+                return new SimpleTupleIterator(ret.iterator());
+            }
+
+            @Override
+            public boolean isDynamic() {
+                return false;
+            }
+
+            @Override
+            public Range<Long> getVolatilePeriod() {
+                return null;
+            }
+        });
+
+        ITupleIterator firstIterator = cacheFledgedStaticStorageEngine.search(context, sqlDigest, tupleInfo);
+        IdentityHashMap<ITuple, Void> firstResults = new IdentityHashMap<>();
+        while (firstIterator.hasNext()) {
+            firstResults.put(firstIterator.next(), null);
+        }
+        firstIterator.close();
+
+        ITupleIterator secondIterator = cacheFledgedStaticStorageEngine.search(context, sqlDigest, tupleInfo);
+        IdentityHashMap<ITuple,Void> secondResults = new IdentityHashMap<>();
+        while(secondIterator.hasNext())
+        {
+            secondResults.put(secondIterator.next(),null);
+        }
+        secondIterator.close();
+
+        ITupleIterator thirdIterator = cacheFledgedStaticStorageEngine.search(context, sqlDigest, tupleInfo);
+        IdentityHashMap<ITuple,Void> thirdResults = new IdentityHashMap<>();
+        while(thirdIterator.hasNext())
+        {
+            thirdResults.put(thirdIterator.next(),null);
+        }
+        thirdIterator.close();
+
+        Assert.assertEquals(3, firstResults.size());
+        IdentityUtils.collectionReferenceEquals(firstResults.keySet(), secondResults.keySet());
+        IdentityUtils.collectionReferenceEquals(thirdResults.keySet(), secondResults.keySet());
+
+        Assert.assertEquals(1, underlyingSEHitCount.get());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/test/java/org/apache/kylin/storage/test/StorageMockUtils.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/StorageMockUtils.java b/storage/src/test/java/org/apache/kylin/storage/test/StorageMockUtils.java
new file mode 100644
index 0000000..d6a6da1
--- /dev/null
+++ b/storage/src/test/java/org/apache/kylin/storage/test/StorageMockUtils.java
@@ -0,0 +1,132 @@
+package org.apache.kylin.storage.test;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.kylin.metadata.filter.*;
+import org.apache.kylin.metadata.model.*;
+import org.apache.kylin.storage.tuple.TupleInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/14/15.
+ */
+public class StorageMockUtils {
+    public static  TupleInfo newTupleInfo(List<TblColRef> groups, List<FunctionDesc> aggregations) {
+        TupleInfo info = new TupleInfo();
+        int idx = 0;
+
+        for (TblColRef col : groups) {
+            info.setField(col.getName(), col, idx++);
+        }
+
+        TableDesc sourceTable = groups.get(0).getColumnDesc().getTable();
+        for (FunctionDesc func : aggregations) {
+            TblColRef col = new TblColRef(func.newFakeRewriteColumn(sourceTable));
+            info.setField(col.getName(), col, idx++);
+        }
+
+        return info;
+    }
+
+    public static  List<TblColRef> buildGroups() {
+        List<TblColRef> groups = new ArrayList<TblColRef>();
+
+        TableDesc t1 = TableDesc.mockup("DEFAULT.TEST_KYLIN_FACT");
+        ColumnDesc c1 = ColumnDesc.mockup(t1, 2, "CAL_DT", "date");
+        TblColRef cf1 = new TblColRef(c1);
+        groups.add(cf1);
+
+        TableDesc t2 = TableDesc.mockup("DEFAULT.TEST_CATEGORY_GROUPINGS");
+        ColumnDesc c2 = ColumnDesc.mockup(t2, 14, "META_CATEG_NAME", "string");
+        TblColRef cf2 = new TblColRef(c2);
+        groups.add(cf2);
+
+        return groups;
+    }
+
+    public static  List<FunctionDesc> buildAggregations() {
+        List<FunctionDesc> functions = new ArrayList<FunctionDesc>();
+
+        TableDesc t1 = TableDesc.mockup("DEFAULT.TEST_KYLIN_FACT");
+        TblColRef priceCol = new TblColRef(ColumnDesc.mockup(t1, 7, "PRICE", "decimal(19,4)"));
+        TblColRef sellerCol = new TblColRef(ColumnDesc.mockup(t1, 9, "SELLER_ID", "bigint"));
+
+        FunctionDesc f1 = new FunctionDesc();
+        f1.setExpression("SUM");
+        ParameterDesc p1 = new ParameterDesc();
+        p1.setType("column");
+        p1.setValue("PRICE");
+        p1.setColRefs(ImmutableList.of(priceCol));
+        f1.setParameter(p1);
+        functions.add(f1);
+
+        FunctionDesc f2 = new FunctionDesc();
+        f2.setExpression("COUNT_DISTINCT");
+        ParameterDesc p2 = new ParameterDesc();
+        p2.setType("column");
+        p2.setValue("SELLER_ID");
+        p2.setColRefs(ImmutableList.of(sellerCol));
+        f2.setParameter(p2);
+        functions.add(f2);
+
+        return functions;
+    }
+
+
+    public static  CompareTupleFilter buildTs2010Filter(TblColRef column) {
+        CompareTupleFilter compareFilter = new CompareTupleFilter(TupleFilter.FilterOperatorEnum.GT);
+        ColumnTupleFilter columnFilter1 = new ColumnTupleFilter(column);
+        compareFilter.addChild(columnFilter1);
+        ConstantTupleFilter constantFilter1 = new ConstantTupleFilter("2010-01-01");
+        compareFilter.addChild(constantFilter1);
+        return compareFilter;
+    }
+
+    public static  CompareTupleFilter buildTs2011Filter(TblColRef column) {
+        CompareTupleFilter compareFilter = new CompareTupleFilter(TupleFilter.FilterOperatorEnum.GT);
+        ColumnTupleFilter columnFilter1 = new ColumnTupleFilter(column);
+        compareFilter.addChild(columnFilter1);
+        ConstantTupleFilter constantFilter1 = new ConstantTupleFilter("2011-01-01");
+        compareFilter.addChild(constantFilter1);
+        return compareFilter;
+    }
+
+    public static  CompareTupleFilter buildFilter1(TblColRef column) {
+        CompareTupleFilter compareFilter = new CompareTupleFilter(TupleFilter.FilterOperatorEnum.EQ);
+        ColumnTupleFilter columnFilter1 = new ColumnTupleFilter(column);
+        compareFilter.addChild(columnFilter1);
+        ConstantTupleFilter constantFilter1 = new ConstantTupleFilter("2012-05-23");
+        compareFilter.addChild(constantFilter1);
+        return compareFilter;
+    }
+
+    public static  CompareTupleFilter buildFilter2(TblColRef column) {
+        CompareTupleFilter compareFilter = new CompareTupleFilter(TupleFilter.FilterOperatorEnum.EQ);
+        ColumnTupleFilter columnFilter2 = new ColumnTupleFilter(column);
+        compareFilter.addChild(columnFilter2);
+        ConstantTupleFilter constantFilter2 = new ConstantTupleFilter("ClothinShoes & Accessories");
+        compareFilter.addChild(constantFilter2);
+        return compareFilter;
+    }
+
+    @SuppressWarnings("unused")
+    public static  TupleFilter buildAndFilter(List<TblColRef> columns) {
+        CompareTupleFilter compareFilter1 = buildFilter1(columns.get(0));
+        CompareTupleFilter compareFilter2 = buildFilter2(columns.get(1));
+        LogicalTupleFilter andFilter = new LogicalTupleFilter(TupleFilter.FilterOperatorEnum.AND);
+        andFilter.addChild(compareFilter1);
+        andFilter.addChild(compareFilter2);
+        return andFilter;
+    }
+
+    @SuppressWarnings("unused")
+    public static  TupleFilter buildOrFilter(List<TblColRef> columns) {
+        CompareTupleFilter compareFilter1 = buildFilter1(columns.get(0));
+        CompareTupleFilter compareFilter2 = buildFilter2(columns.get(1));
+        LogicalTupleFilter logicFilter = new LogicalTupleFilter(TupleFilter.FilterOperatorEnum.OR);
+        logicFilter.addChild(compareFilter1);
+        logicFilter.addChild(compareFilter2);
+        return logicFilter;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/0e42b2df/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java b/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
index fece398..f9a6212 100644
--- a/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
@@ -18,14 +18,13 @@
 
 package org.apache.kylin.storage.test;
 
-import com.google.common.collect.ImmutableList;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.util.HBaseMetadataTestCase;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
-import org.apache.kylin.metadata.filter.*;
-import org.apache.kylin.metadata.filter.TupleFilter.FilterOperatorEnum;
-import org.apache.kylin.metadata.model.*;
+import org.apache.kylin.metadata.filter.TupleFilter;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITuple;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
@@ -33,10 +32,8 @@ import org.apache.kylin.storage.IStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.StorageEngineFactory;
 import org.apache.kylin.storage.hbase.ScanOutOfLimitException;
-import org.apache.kylin.storage.tuple.TupleInfo;
 import org.junit.*;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -78,17 +75,17 @@ public class StorageTest extends HBaseMetadataTestCase {
     @Ignore
     public void testScanOutOfLimit() {
         context.setThreshold(1);
-        List<TblColRef> groups = buildGroups();
-        List<FunctionDesc> aggregations = buildAggregations();
+        List<TblColRef> groups = StorageMockUtils.buildGroups();
+        List<FunctionDesc> aggregations = StorageMockUtils.buildAggregations();
 
         search(groups, aggregations, null, context);
     }
 
     @Test
     public void test01() {
-        List<TblColRef> groups = buildGroups();
-        List<FunctionDesc> aggregations = buildAggregations();
-        TupleFilter filter = buildFilter1(groups.get(0));
+        List<TblColRef> groups = StorageMockUtils.buildGroups();
+        List<FunctionDesc> aggregations = StorageMockUtils.buildAggregations();
+        TupleFilter filter = StorageMockUtils.buildFilter1(groups.get(0));
 
         int count = search(groups, aggregations, filter, context);
         assertTrue(count > 0);
@@ -139,7 +136,7 @@ public class StorageTest extends HBaseMetadataTestCase {
         ITupleIterator iterator = null;
         try {
             SQLDigest sqlDigest = new SQLDigest("default.test_kylin_fact", filter, null, Collections.<TblColRef> emptySet(), groups, Collections.<TblColRef> emptySet(), Collections.<TblColRef> emptySet(), aggregations);
-            iterator = storageEngine.search(context, sqlDigest, newTupleInfo(groups, aggregations));
+            iterator = storageEngine.search(context, sqlDigest, StorageMockUtils.newTupleInfo(groups, aggregations));
             while (iterator.hasNext()) {
                 ITuple tuple = iterator.next();
                 System.out.println("Tuple = " + tuple);
@@ -154,102 +151,4 @@ public class StorageTest extends HBaseMetadataTestCase {
         return count;
     }
 
-    private TupleInfo newTupleInfo(List<TblColRef> groups, List<FunctionDesc> aggregations) {
-        TupleInfo info = new TupleInfo();
-        int idx = 0;
-        
-        for (TblColRef col : groups) {
-            info.setField(col.getName(), col, idx++);
-        }
-        
-        TableDesc sourceTable = groups.get(0).getColumnDesc().getTable();
-        for (FunctionDesc func : aggregations) {
-            TblColRef col = new TblColRef(func.newFakeRewriteColumn(sourceTable));
-            info.setField(col.getName(), col, idx++);
-        }
-        
-        return info;
-    }
-
-    private List<TblColRef> buildGroups() {
-        List<TblColRef> groups = new ArrayList<TblColRef>();
-        
-        TableDesc t1 = TableDesc.mockup("DEFAULT.TEST_KYLIN_FACT");
-        ColumnDesc c1 = ColumnDesc.mockup(t1, 2, "CAL_DT", "string");
-        TblColRef cf1 = new TblColRef(c1);
-        groups.add(cf1);
-
-        TableDesc t2 = TableDesc.mockup("DEFAULT.TEST_CATEGORY_GROUPINGS");
-        ColumnDesc c2 = ColumnDesc.mockup(t2, 14, "META_CATEG_NAME", "string");
-        TblColRef cf2 = new TblColRef(c2);
-        groups.add(cf2);
-
-        return groups;
-    }
-
-    private List<FunctionDesc> buildAggregations() {
-        List<FunctionDesc> functions = new ArrayList<FunctionDesc>();
-
-        TableDesc t1 = TableDesc.mockup("DEFAULT.TEST_KYLIN_FACT");
-        TblColRef priceCol = new TblColRef(ColumnDesc.mockup(t1, 7, "PRICE", "decimal(19,4)"));
-        TblColRef sellerCol = new TblColRef(ColumnDesc.mockup(t1, 9, "SELLER_ID", "bigint"));
-        
-        FunctionDesc f1 = new FunctionDesc();
-        f1.setExpression("SUM");
-        ParameterDesc p1 = new ParameterDesc();
-        p1.setType("column");
-        p1.setValue("PRICE");
-        p1.setColRefs(ImmutableList.of(priceCol));
-        f1.setParameter(p1);
-        functions.add(f1);
-
-        FunctionDesc f2 = new FunctionDesc();
-        f2.setExpression("COUNT_DISTINCT");
-        ParameterDesc p2 = new ParameterDesc();
-        p2.setType("column");
-        p2.setValue("SELLER_ID");
-        p2.setColRefs(ImmutableList.of(sellerCol));
-        f2.setParameter(p2);
-        functions.add(f2);
-
-        return functions;
-    }
-
-    private CompareTupleFilter buildFilter1(TblColRef column) {
-        CompareTupleFilter compareFilter = new CompareTupleFilter(FilterOperatorEnum.EQ);
-        ColumnTupleFilter columnFilter1 = new ColumnTupleFilter(column);
-        compareFilter.addChild(columnFilter1);
-        ConstantTupleFilter constantFilter1 = new ConstantTupleFilter("2012-05-23");
-        compareFilter.addChild(constantFilter1);
-        return compareFilter;
-    }
-
-    private CompareTupleFilter buildFilter2(TblColRef column) {
-        CompareTupleFilter compareFilter = new CompareTupleFilter(FilterOperatorEnum.EQ);
-        ColumnTupleFilter columnFilter2 = new ColumnTupleFilter(column);
-        compareFilter.addChild(columnFilter2);
-        ConstantTupleFilter constantFilter2 = new ConstantTupleFilter("ClothinShoes & Accessories");
-        compareFilter.addChild(constantFilter2);
-        return compareFilter;
-    }
-
-    @SuppressWarnings("unused")
-    private TupleFilter buildAndFilter(List<TblColRef> columns) {
-        CompareTupleFilter compareFilter1 = buildFilter1(columns.get(0));
-        CompareTupleFilter compareFilter2 = buildFilter2(columns.get(1));
-        LogicalTupleFilter andFilter = new LogicalTupleFilter(FilterOperatorEnum.AND);
-        andFilter.addChild(compareFilter1);
-        andFilter.addChild(compareFilter2);
-        return andFilter;
-    }
-
-    @SuppressWarnings("unused")
-    private TupleFilter buildOrFilter(List<TblColRef> columns) {
-        CompareTupleFilter compareFilter1 = buildFilter1(columns.get(0));
-        CompareTupleFilter compareFilter2 = buildFilter2(columns.get(1));
-        LogicalTupleFilter logicFilter = new LogicalTupleFilter(FilterOperatorEnum.OR);
-        logicFilter.addChild(compareFilter1);
-        logicFilter.addChild(compareFilter2);
-        return logicFilter;
-    }
 }



[33/52] [abbrv] incubator-kylin git commit: validation on cube submit

Posted by ma...@apache.org.
validation on cube submit


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

Branch: refs/heads/0.8.0
Commit: 992fd74fb599e2452232ad7c80670c99c1e29d70
Parents: 3754d62
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 31 19:45:12 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeDimensions.js     |  65 ++-
 webapp/app/js/controllers/cubeEdit.js           |  14 +-
 webapp/app/js/controllers/cubeSchema.js         |  79 ++-
 webapp/app/js/controllers/job.js                |   7 +-
 webapp/app/js/controllers/modelEdit.js          |   7 +-
 webapp/app/js/controllers/modelSchema.js        |  86 ++-
 webapp/app/js/model/modelList.js                |   6 +-
 webapp/app/js/services/query.js                 |   2 +-
 .../cubeDesigner/advanced_settings.html         |  26 -
 .../app/partials/cubeDesigner/dimensions.html   | 560 +++++++++----------
 webapp/app/partials/cubeDesigner/info.html      | 108 ++--
 webapp/app/partials/cubeDesigner/measures.html  | 118 ++--
 webapp/app/partials/cubes/cube_schema.html      |   3 +-
 .../modelDesigner/conditions_settings.html      |  19 +-
 .../modelDesigner/model_dimensions.html         | 144 +++--
 .../partials/modelDesigner/model_measures.html  |   1 +
 webapp/app/partials/models/model_schema.html    |   4 +-
 17 files changed, 718 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index b24e9cc..f114ccb 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -7,7 +7,7 @@
  * "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
+ *     http://www.apache.org/license$s/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,
@@ -217,7 +217,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
     };
 
     // Controller for cube dimension add/edit modal.
-    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType) {
+    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType,SweetAlert) {
         $scope.dimType = dimType;
 
         $scope.ok = function () {
@@ -227,6 +227,65 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         $scope.cancel = function () {
             $modalInstance.dismiss('cancel');
         };
+
+        $scope.checkDimension = function(){
+            var errors = [];
+            // null validate
+
+            if($scope.dimType[0]=="hierarchy"){
+                if($scope.newDimension.column.length<2){
+                    errors.push("Please define at least 2 hierarchy columns.");
+                }else{
+                    for(var i = 0;i<$scope.newDimension.column.length;i++){
+                        if($scope.newDimension.column[i]===""){
+                            errors.push("Hierarchy value can't be null.");
+                            break;
+                        }
+                    }
+                    var _columns = angular.copy($scope.newDimension.column).sort();
+                    for(var i = 0;i<_columns.length-1;i++){
+                        if(_columns[i]==_columns[i+1]&&_columns[i]!==""){
+                            errors.push("Duplicate column "+_columns[i]+".");
+                        }
+                    }
+                }
+            }
+
+            if($scope.dimType[0]=="derived"){
+                if(!$scope.newDimension.derived.length){
+                    errors.push("Please define your derived columns.");
+                }
+                for(var i = 0;i<$scope.newDimension.derived.length;i++){
+                    if($scope.newDimension.derived[i]===""){
+                        errors.push("Derived value can't be null.");
+                        break;
+                    }
+                }
+                if($scope.newDimension.derived.length>1){
+                    var _columns = angular.copy($scope.newDimension.derived).sort();
+                    for(var i = 0;i<_columns.length-1;i++){
+                        if(_columns[i]==_columns[i+1]&&_columns[i]!==""){
+                            errors.push("Duplicate column "+_columns[i]+".");
+                        }
+                    }
+                }
+
+            }
+
+            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;
+            }
+        }
+
+
     };
 
     $scope.addDim = function (dimType) {
@@ -391,8 +450,6 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         $scope.dimConflicts = conflicts;
     }, true);
 
-
-
     if ($scope.state.mode == 'edit') {
         $scope.$on('$destroy', function () {
            // $scope.dimensionsAdapter();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 6b84e6a..2bbdd05 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -106,7 +106,8 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     // ~ Define data
     $scope.state = {
-        "cubeSchema": ""
+        "cubeSchema": "",
+        "mode":'edit'
     };
 
     //fetch cube info and model info in edit model
@@ -115,9 +116,16 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
-                $scope.metaModel ={
-                    model : ModelList.getModel($scope.cubeMetaFrame.model_name)
+                $scope.metaModel = {};
+
+                //get model from API when page refresh
+                if(!ModelList.getModels().length){
+                    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (_model) {
+                        $scope.metaModel.model = _model;
+                    });
                 }
+                $scope.metaModel.model=ModelList.getModel($scope.cubeMetaFrame.model_name);
+
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 37aa849..a3bbd89 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -18,22 +18,21 @@
 
 'use strict';
 
-KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService) {
+KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService,SweetAlert) {
 
     $scope.projects = [];
     $scope.newDimension = null;
     $scope.newMeasure = null;
-
-
+    $scope.forms={};
     $scope.wizardSteps = [
-        {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false},
-        {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false},
-        {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false},
+        {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false,form:'cube_info_form'},
+        {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false,form:'cube_dimension_form'},
+        {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false,form:'cube_measure_form'},
     ];
     if (UserService.hasRole("ROLE_ADMIN")) {
-            $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false});
+            $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false,form:'cube_setting_form'});
     }
-    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false});
+    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false,form:'cube_overview_form'});
 
     $scope.curStep = $scope.wizardSteps[0];
 
@@ -174,6 +173,70 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         }
     }
 
+    $scope.checkCubeForm = function(){
+        if(!$scope.curStep.form){
+            return true;
+        }
+        if($scope.state.mode==='view'){
+            return true;
+        }
+        else{
+            //form validation
+            if($scope.forms[$scope.curStep.form].$invalid){
+                return false;
+            }else{
+                //business rule check
+                switch($scope.curStep.form){
+                    case 'cube_dimension_form':
+                        return $scope.check_cube_dimension();
+                        break;
+                    case 'cube_measure_form':
+                        return $scope.check_cube_measure();
+                        break;
+                    default:
+                        return true;
+                        break;
+                }
+            }
+        }
+    };
+
+
+    $scope.check_cube_dimension = function(){
+        var errors = [];
+        if(!$scope.cubeMetaFrame.dimensions.length){
+            errors.push("Dimension can't be null");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    };
+
+    $scope.check_cube_measure = function(){
+        var errors = [];
+        if(!$scope.cubeMetaFrame.measures||!$scope.cubeMetaFrame.measures.length){
+            errors.push("Please define your metrics.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    }
+
+
     // ~ private methods
     function initProject() {
         ProjectService.list({}, function (projects) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/job.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/job.js b/webapp/app/js/controllers/job.js
index 0e65578..364bf92 100644
--- a/webapp/app/js/controllers/job.js
+++ b/webapp/app/js/controllers/job.js
@@ -55,10 +55,6 @@ KylinApp
               return  defer.promise;
             }
             offset = (!!offset) ? offset : 0;
-            var selectedJob = null;
-            if (angular.isDefined($scope.state.selectedJob)) {
-                selectedJob = $scope.state.selectedJob;
-            }
 
             var statusIds = [];
             angular.forEach($scope.status, function (statusObj, index) {
@@ -77,6 +73,9 @@ KylinApp
             var defer = $q.defer();
             return JobList.list(jobRequest).then(function(resp){
                 $scope.state.loading = false;
+                if (angular.isDefined($scope.state.selectedJob)) {
+                    $scope.state.selectedJob = JobList.jobs[ $scope.state.selectedJob.uuid];
+                }
                 defer.resolve(resp);
                 return defer.promise;
             });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 30f4c21..8e676d2 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -23,6 +23,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
+    $scope.cubeConfig = cubeConfig;
 
 
     $scope.getPartitonColumns = function(tableName){
@@ -123,7 +124,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         return $interpolate($templateCache.get(tmpl))(notification);
     };
 
-    $scope.saveModel = function (design_form) {
+    $scope.saveModel = function () {
 
         try {
             angular.fromJson($scope.state.modelSchema);
@@ -149,10 +150,6 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         if (request.successful) {
                             $scope.state.modelSchema = request.modelSchema;
                             MessageService.sendMsg($scope.modelResultTmpl({'text':'Updated the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
-
-                            if (design_form) {
-                                design_form.$invalid = true;
-                            }
                         } else {
                             $scope.saveModelRollBack();
                                 var message =request.message;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 883bb3a..2ec1fa7 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -32,9 +32,9 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     $scope.wizardSteps = [
         {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false,form:'model_info_form'},
         {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false,form:'data_model_form'},
-        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:'model_dimensions'},
-        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:null},
-        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:null}
+        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:'model_dimensions_form'},
+        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:'model_measure_form'},
+        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:'model_setting_form'}
     ];
 
     $scope.curStep = $scope.wizardSteps[0];
@@ -111,7 +111,16 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
                 switch($scope.curStep.form){
                     case 'data_model_form':
                         return $scope.check_data_model();
-                     break;
+                         break;
+                    case 'model_dimensions_form':
+                        return $scope.check_model_dimensions();
+                         break;
+                    case 'model_measure_form':
+                        return $scope.check_model_measure();
+                         break;
+                    case 'model_setting_form':
+                        return $scope.check_model_setting();
+                         break;
                     default:
                         return true;
                         break;
@@ -141,6 +150,75 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
     }
 
+    /*
+    * dimensions validation
+    * 1.dimension can't be null
+    */
+    $scope.check_model_dimensions = function(){
+
+        var errors = [];
+        if(!$scope.model.dimensions.length){
+            errors.push("No dimensions defined.");
+        }
+        angular.forEach($scope.model.dimensions,function(_dimension){
+            if(!_dimension.columns||!_dimension.columns.length){
+            errors.push("No dimension columns defined for Table["+_dimension.table+"]");
+            }
+        });
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+
+    };
+
+    /*
+     * dimensions validation
+     * 1.metric can't be null
+     */
+    $scope.check_model_measure = function(){
+
+        var errors = [];
+        if(!$scope.model.metrics||!$scope.model.metrics.length){
+            errors.push("Please define your metrics.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+
+    };
+    $scope.check_model_setting = function(){
+        var errors = [];
+        if($scope.model.partition_desc.partition_date_column!=null&& $scope.model.partition_desc.partition_date_start==null){
+            errors.push("Please indicate start date when partition date column selected.");
+        }
+        if($scope.model.partition_desc.partition_date_column==null&& $scope.model.partition_desc.partition_date_start!=null){
+            errors.push("Please select your partitoin date column.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    }
 
 
     $scope.goToStep = function(stepIndex){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index b7dba7b..388cabc 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -17,8 +17,8 @@
 */
 
 KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel,$log){
-    var models=[];
     var _this = this;
+    this.models=[];
 
     this.list = function(queryParam){
 
@@ -72,6 +72,10 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
         })
     }
 
+    this.getModels = function(){
+        return _this.models;
+    }
+
     this.getModelByCube = function(cubeName){
         return  _.find(_this.models,function(model){
             return _.some(model.cubes,function(_cube){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/services/query.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/query.js b/webapp/app/js/services/query.js
index cb82a54..6434a7e 100644
--- a/webapp/app/js/services/query.js
+++ b/webapp/app/js/services/query.js
@@ -18,7 +18,7 @@
 
 KylinApp.factory('QueryService', ['$resource', function ($resource, config) {
     return $resource(Config.service.url + ':subject/:subject_id/:propName/:propValue/:action', {}, {
-        query: {method: 'POST', params: {action: 'query'}, isArray: false},
+        query: {method: 'POST', params: {action: 'query'},timeout:300000, isArray: false},
         save: {method: 'POST', params: {subject: 'saved_queries'}, isArray: false},
         delete: {method: 'DELETE', params: {subject: 'saved_queries'}, isArray: false},
         list: {method: 'GET', params: {subject: 'saved_queries'}, isArray: true},

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/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 164ca05..cb2eaed 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -18,32 +18,6 @@
 
 <div ng-controller="CubeAdvanceSettingCtrl">
 <div>
-
-    <div class="form-group">
-
-        <table style="margin-left:42px; width:92%"
-               class="table table-hover list">
-            <tr>
-                <td>
-                    <!--Cube Size-->
-                    <div class="form-group" ng-show="userService.hasRole('ROLE_ADMIN')">
-                        <div class="row">
-                            <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Cube Size</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <select class="form-control" ng-if="state.mode=='edit'" style="width: 360px;"
-                                        chosen ng-model="metaModel.model.capacity" required
-                                        ng-options="cc as cc for cc in cubeConfig.cubeCapacities">
-                                    <option value=""></option>
-                                </select>
-                                <span ng-if="state.mode=='view'">{{metaModel.model.capacity}}</span>
-                            </div>
-                        </div>
-                    </div>
-                </td>
-            </tr>
-        </table>
-
-    </div>
     <div class="form-group">
         <h4 style="margin-left:42px">Aggregation Groups</h4>
         <table style="margin-left:42px; width:92%"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 5a025f4..94ce1fd 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -17,338 +17,338 @@
 -->
 
 <div ng-controller="CubeDimensionsCtrl">
-
+<ng-form name="forms.cube_dimension_form" novalidate>
 <!-- Dimensions Summary -->
-<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">
-                    <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+    <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">
+                        <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"
+                        ng-click="openAutoGenModal()">
+                    <i class="fa fa-building-o"></i> Auto Generator
                 </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"
-                    ng-click="openAutoGenModal()">
-                <i class="fa fa-building-o"></i> Auto Generator
-            </button>
-        </div>
-        <div class="col-xs-6" ng-if="state.mode!='edit'">
-        </div>
-        <div class="col-xs-6">
-            <b>Dimensions</b>
-            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
-                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
-                <i class="ace-icon fa fa-search nav-search-icon"></i>
-            </span>
+            <div class="col-xs-6" ng-if="state.mode!='edit'">
+            </div>
+            <div class="col-xs-6">
+                <b>Dimensions</b>
+                <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
         </div>
-    </div>
-    <table class="table table-striped table-hover" ng-if="cubeMetaFrame.dimensions.length > 0">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Name</th>
-                <th>Table Name</th>
-                <th>Type</th>
-                <th></th>
-                <th ng-if="state.mode=='edit'">Actions</th>
-            </tr>
-        </thead>
-        <tbody class="cube-dimension">
-            <tr ng-repeat="dimension in cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
-                <!--ID -->
-                <td>
-                    <b>{{dimension.id = ($index + 1)}}</b>
-                </td>
-                <!--Name -->
-                <td>
-                    <span>{{dimension.name}}</span>
-                </td>
-                <!--Table Name -->
-                <td>
-                    <span tooltip="{{dimension.table == metaModel.model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
-                </td>
-                <!--Type-->
-                <td>
-                    <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
-                </td>
-                <!--Columns-->
-                <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>
+        <table class="table table-striped table-hover" ng-if="cubeMetaFrame.dimensions.length > 0">
+            <thead>
+                <tr>
+                    <th>ID</th>
+                    <th>Name</th>
+                    <th>Table Name</th>
+                    <th>Type</th>
+                    <th></th>
+                    <th ng-if="state.mode=='edit'">Actions</th>
+                </tr>
+            </thead>
+            <tbody class="cube-dimension">
+                <tr ng-repeat="dimension in cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
+                    <!--ID -->
+                    <td>
+                        <b>{{dimension.id = ($index + 1)}}</b>
+                    </td>
+                    <!--Name -->
+                    <td>
+                        <span>{{dimension.name}}</span>
+                    </td>
+                    <!--Table Name -->
+                    <td>
+                        <span tooltip="{{dimension.table == metaModel.model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                    </td>
+                    <!--Type-->
+                    <td>
+                        <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+                    </td>
+                    <!--Columns-->
+                    <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>
+                            </div>
                         </div>
-                    </div>
-                </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--edit button-->
-                    <button class="btn btn-xs btn-info"
-                            ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
-                    </button>
-                    <!-- remove button-->
-                    <button class="btn btn-xs btn-danger"
-                            ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
-                    </button>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-</div>
+                    </td>
+                    <td ng-if="state.mode=='edit'">
+                        <!--edit button-->
+                        <button class="btn btn-xs btn-info"
+                                ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
+                        </button>
+                        <!-- remove button-->
+                        <button class="btn btn-xs btn-danger"
+                                ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+                        </button>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
 
-<div class="space-16"></div>
-<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
-    <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
-    <div class="row" ng-repeat="c in dimConflicts">
-        <div class="col-xs-3">
-            <code>{{c.table}}.{{c.column}}</code>
-        </div>
-        <div class="col-xs-3">
-            <ul class="list-unstyled">
-                <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
-            </ul>
+    <div class="space-16"></div>
+    <div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
+        <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
+        <div class="row" ng-repeat="c in dimConflicts">
+            <div class="col-xs-3">
+                <code>{{c.table}}.{{c.column}}</code>
+            </div>
+            <div class="col-xs-3">
+                <ul class="list-unstyled">
+                    <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
+                </ul>
+            </div>
         </div>
     </div>
-</div>
 
-<!-- Edit Dimension Form -->
-<script type="text/ng-template" id="addEditDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
-            <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
-        </h4>
-    </div>
-    <div class="modal-body">
-        <ng-form name="edit_dim_form">
-        <div class="row">
-            <div class="col-xs-8">
-                <!--Name-->
-                <div class="form-group">
-                    <div class="row">
-                        <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
-                        <div class="col-xs-12 col-sm-6">
-                            <input type="text" placeholder="Name.." class="form-control" name="dim_name"
-                                   tooltip="dimension name.." tooltip-trigger="focus"
-                                   ng-model="newDimension.name" required />
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
-                                The Dimension Name is required.
+    <!-- Edit Dimension Form -->
+    <script type="text/ng-template" id="addEditDimension.html">
+        <div class="modal-header">
+            <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
+                <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
+            </h4>
+        </div>
+        <div class="modal-body">
+            <ng-form name="edit_dim_form">
+            <div class="row">
+                <div class="col-xs-8">
+                    <!--Name-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <input type="text" placeholder="Name.." class="form-control" name="dim_name"
+                                       tooltip="dimension name.." tooltip-trigger="focus"
+                                       ng-model="newDimension.name" required />
+                            </div>
+                            <div class="col-xs-12 col-sm-3">
+                                <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
+                                    The Dimension Name is required.
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Table Name: derived dimension only allows lookup tables-->
-                <div class="form-group">
-                    <div class="row">
-                        <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)">
-                                <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">
-                                <option value=""></option>
-                            </select>
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
-                                Derived dimension only comes from lookup table.
+                    <!--Table Name: derived dimension only allows lookup tables-->
+                    <div class="form-group">
+                        <div class="row">
+                            <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)">
+                                    <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">
+                                    <option value=""></option>
+                                </select>
+                            </div>
+                            <div class="col-xs-12 col-sm-3">
+                                <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
+                                    Derived dimension only comes from lookup table.
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Normal Dimension: choose one column-->
-                <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
-                    <div class="row">
-                        <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[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
-                                <option value=""></option>
-                            </select>
+                    <!--Normal Dimension: choose one column-->
+                    <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
+                        <div class="row">
+                            <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[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
+                                    <option value=""></option>
+                                </select>
+                            </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Hierarchy Dimension-->
-                <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
-                    <div class="row">
-                        <div class="col-sm-6 col-sm-offset-3">
-                            <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
-                                 ng-model="newDimension.column" class="hierarchy-container">
-                                <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
-                                    <div class="row">
-                                        <div class="col-xs-2">
-                                            <span class="badge">{{$index + 1}}</span>
-                                        </div>
-                                        <div class="col-xs-8">
-                                            <select chosen style="width: 100%"
-                                                    data-placeholder="Dimension Hierarchy Column"
-                                                    ng-model="newDimension.column[$index]"
-                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
-                                                <option value="">-- Select Column --</option>
-                                            </select>
-                                        </div>
-                                        <div class="col-xs-2">
-                                            <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                    ng-click="newDimension.column.splice($index, 1);">
-                                                <i class="fa fa-trash-o"></i>
-                                            </button>
+                    <!--Hierarchy Dimension-->
+                    <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
+                        <div class="row">
+                            <div class="col-sm-6 col-sm-offset-3">
+                                <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
+                                     ng-model="newDimension.column" class="hierarchy-container">
+                                    <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
+                                        <div class="row">
+                                            <div class="col-xs-2">
+                                                <span class="badge">{{$index + 1}}</span>
+                                            </div>
+                                            <div class="col-xs-8">
+                                                <select chosen style="width: 100%"
+                                                        data-placeholder="Dimension Hierarchy Column"
+                                                        ng-model="newDimension.column[$index]"
+                                                        ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
+                                                    <option value="">-- Select Column --</option>
+                                                </select>
+                                            </div>
+                                            <div class="col-xs-2">
+                                                <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                        ng-click="newDimension.column.splice($index, 1);">
+                                                    <i class="fa fa-trash-o"></i>
+                                                </button>
+                                            </div>
                                         </div>
                                     </div>
                                 </div>
-                            </div>
 
-                            <div class="space-8"></div>
+                                <div class="space-8"></div>
 
-                            <div class="row">
-                                <div class="col-xs-4">
-                                    <button class="btn btn-xs btn-info"
-                                            ng-click="newDimension.column.push('');">
-                                        <i class="fa fa-plus"></i> New Hierarchy</button>
-                                </div>
-                                <div class="col-xs-8">
-                                    <p class="help-block">Drag level into the order you prefer.</p>
+                                <div class="row">
+                                    <div class="col-xs-4">
+                                        <button class="btn btn-xs btn-info"
+                                                ng-click="newDimension.column.push('');">
+                                            <i class="fa fa-plus"></i> New Hierarchy</button>
+                                    </div>
+                                    <div class="col-xs-8">
+                                        <p class="help-block">Drag level into the order you prefer.</p>
+                                    </div>
                                 </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Derived Dimension-->
-                <div ng-if="dimType.indexOf('derived') >= 0">
-                    <div class="form-group">
-                        <div class="row">
-                            <div class="col-sm-6 col-sm-offset-3">
-                                <div ng-repeat="derived in newDimension.derived track by $index">
-                                    <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)" >
-                                            <option value=""></option>
-                                        </select>
-                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                ng-click="newDimension.derived.splice($index, 1);">
-                                            <i class="fa fa-trash-o"></i>
-                                        </button>
-                                        <div class="space-4"></div>
+                    <!--Derived Dimension-->
+                    <div ng-if="dimType.indexOf('derived') >= 0">
+                        <div class="form-group">
+                            <div class="row">
+                                <div class="col-sm-6 col-sm-offset-3">
+                                    <div ng-repeat="derived in newDimension.derived track by $index">
+                                        <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)" >
+                                                <option value=""></option>
+                                            </select>
+                                            <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                    ng-click="newDimension.derived.splice($index, 1);">
+                                                <i class="fa fa-trash-o"></i>
+                                            </button>
+                                            <div class="space-4"></div>
+                                        </div>
                                     </div>
+                                    <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
+                                        <i class="fa fa-plus"></i> New Derived</button>
                                 </div>
-                                <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
-                                    <i class="fa fa-plus"></i> New Derived</button>
                             </div>
                         </div>
                     </div>
                 </div>
-            </div>
 
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Tips</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Type in any input box for auto suggestion</li>
-                                    <li>Pick up Fact Table from Star Schema Tables first</li>
-                                    <li>Data Type should match with Hive Table's Data Type</li>
-                                    <li>Join Type have to be same as will be used in query</li>
-                                    <li>Using Hierarchy to inherit one dimension another</li>
-                                    <li>Using Derived for One-One relationship between columns, like ID and Name</li>
-                                </ol>
+                <!--Tips-->
+                <div class="col-xs-4">
+                    <div class="box box-solid">
+                        <div class="box-header">
+                            <h4 class="box-title">Tips</h4>
+                        </div>
+                        <div class="box-body">
+                            <div class="row">
+                                <div class="col-xs-12">
+                                    <ol class="text-info">
+                                        <li>Type in any input box for auto suggestion</li>
+                                        <li>Pick up Fact Table from Star Schema Tables first</li>
+                                        <li>Data Type should match with Hive Table's Data Type</li>
+                                        <li>Join Type have to be same as will be used in query</li>
+                                        <li>Using Hierarchy to inherit one dimension another</li>
+                                        <li>Using Derived for One-One relationship between columns, like ID and Name</li>
+                                    </ol>
+                                </div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
+            </ng-form>
         </div>
-        </ng-form>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="checkDimension()?ok():''">OK</button>
+            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
 
 
-<script type="text/ng-template" id="autoGenDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
-    </div>
-    <div class="modal-body">
-        <div class="row">
-            <div class="col-xs-8">
-                <div class="box box-solid">
-                    <div class="box-header"><h4>Columns</h4></div>
-                    <div class="box-body">
-                        <ul class="list-unstyled columns-region">
-                            <li ng-repeat="table in availableTables track by $index">
-                                <h5 class="table-name-underline">
-                                    <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
-                                </h5>
-                                <ul class="list-unstyled">
-                                    <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
-                                        <label>
-                                            <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
-                                                   ng-disabled="selectedColumns[table][col.name].disabled">
-                                            {{col.name}}
-                                        </label>
-                                    </li>
-                                </ul>
-                            </li>
-                        </ul>
+    <script type="text/ng-template" id="autoGenDimension.html">
+        <div class="modal-header">
+            <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
+        </div>
+        <div class="modal-body">
+            <div class="row">
+                <div class="col-xs-8">
+                    <div class="box box-solid">
+                        <div class="box-header"><h4>Columns</h4></div>
+                        <div class="box-body">
+                            <ul class="list-unstyled columns-region">
+                                <li ng-repeat="table in availableTables track by $index">
+                                    <h5 class="table-name-underline">
+                                        <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
+                                    </h5>
+                                    <ul class="list-unstyled">
+                                        <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
+                                            <label>
+                                                <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
+                                                       ng-disabled="selectedColumns[table][col.name].disabled">
+                                                {{col.name}}
+                                            </label>
+                                        </li>
+                                    </ul>
+                                </li>
+                            </ul>
+                        </div>
                     </div>
                 </div>
-            </div>
 
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Auto Generate Rules</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Column is disabled once there is already a dimension referred this column.</li>
-                                    <li>In fact table: one normal dimension will be auto generated per column.</li>
-                                    <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
-                                </ol>
+                <!--Tips-->
+                <div class="col-xs-4">
+                    <div class="box box-solid">
+                        <div class="box-header">
+                            <h4 class="box-title">Auto Generate Rules</h4>
+                        </div>
+                        <div class="box-body">
+                            <div class="row">
+                                <div class="col-xs-12">
+                                    <ol class="text-info">
+                                        <li>Column is disabled once there is already a dimension referred this column.</li>
+                                        <li>In fact table: one normal dimension will be auto generated per column.</li>
+                                        <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
+                                    </ol>
+                                </div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
         </div>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
-
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
+            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
+    </ng-form>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index bd6aed2..d724ffd 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -18,73 +18,71 @@
 
 <div class="row">
     <div class="col-xs-8">
-        <!--Project-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right">
-                    <b>Model Name</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="cubeMetaFrame.model_name"/>
-                    <span ng-if="state.mode=='view'">
-                        {{cubeMetaFrame.model_name}}
-                    </span>
+        <ng-form name="forms.cube_info_form" novalidate>
+            <!--Project-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right">
+                        <b>Model Name</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6"  ng-class="forms.cube_info_form.model_name.$invalid?'has-error':''">
+                        <input ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
+                               ng-model="cubeMetaFrame.model_name"/>
+                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required">The model is required</small>
+                        <span ng-if="state.mode=='view'">
+                            {{cubeMetaFrame.model_name}}
+                        </span>
+                    </div>
                 </div>
             </div>
-        </div>
 
-        <!--Cube Name-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Cube Name</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
-                           ng-model="cubeMetaFrame.name" required
-                           placeholder="You can use letters, numbers, and '_'"
-                           ng-maxlength=100 ng-pattern="/^\w+$/" />
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
-                </div>
-                <div class="col-xs-12 col-sm-3">
-                    <div class="text-warning" ng-if="design_form.cube_name.$error.required  && design_form.cube_name.$dirty">
-                        Cube name is required.
-                    </div>
-                    <div class="text-warning" ng-if="design_form.cube_name.$invalid && design_form.cube_name.$dirty && !design_form.cube_name.$error.required">
-                        Cube name is invalid.
+            <!--Cube Name-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Cube Name</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6" ng-class="forms.cube_info_form.cube_name.$invalid?'has-error':''">
+                        <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
+                               ng-model="cubeMetaFrame.name" required
+                               placeholder="You can use letters, numbers, and '_'"
+                               ng-maxlength=100 ng-pattern="/^\w+$/" />
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required  && forms.cube_info_form.cube_name.$dirty">Cube name is required.</small>
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$invalid && forms.cube_info_form.cube_name.$dirty && !forms.cube_info_form.cube_name.$error.required">Cube name is invalid.</small>
+
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <!--Notification-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Notification List</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input type="text" class="form-control" placeholder="Comma Separated"
-                           ng-model="cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.notify_list}}</span>
+            <!--Notification-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Notification List</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6">
+                        <input type="text" class="form-control" placeholder="Comma Separated"
+                               ng-model="cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.notify_list}}</span>
+                    </div>
                 </div>
             </div>
-        </div>
 
-        <!--Description-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Description</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <textarea ng-if="state.mode=='edit'" class="form-control box-default"
-                        name="comment" id="comment" ng-model="cubeMetaFrame.description"></textarea>
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.description}}</span>
+            <!--Description-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Description</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6">
+                        <textarea ng-if="state.mode=='edit'" class="form-control box-default"
+                            name="comment" id="comment" ng-model="cubeMetaFrame.description"></textarea>
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.description}}</span>
+                    </div>
                 </div>
             </div>
-        </div>
+        </ng-form>
     </div>
 
     <!--Tips-->

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index ef8c8bf..c426e95 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -17,65 +17,67 @@
 -->
 
 <!-- Measures Summary -->
-<div class="dataTables_wrapper form-inline no-footer" ng-if="cubeMetaFrame.measures.length > 0">
-    <div class="row">
-        <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
-            <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
-            <i class="ace-icon fa fa-search nav-search-icon"></i>
-        </span>
+<ng-form name="forms.cube_measure_form">
+    <div class="dataTables_wrapper form-inline no-footer" ng-if="cubeMetaFrame.measures.length > 0">
+            <div class="row">
+                <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
+            <table class="table table-striped table-hover">
+                <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Name</th>
+                        <th>Expression</th>
+                        <th>Param Type</th>
+                        <th>Param Value</th>
+                        <th>Return Type</th>
+                        <th ng-if="state.mode=='edit'">Actions</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr ng-repeat="measure in cubeMetaFrame.measures | filter: state.measureFilter track by $index">
+                        <td>
+                            <!--ID -->
+                            <b>{{measure.id = ($index + 1)}}</b>
+                        </td>
+                        <td>
+                            <!--Name -->
+                            <span tooltip="measure name..">{{measure.name}}</span>
+                        </td>
+                        <td>
+                            <!--Expression -->
+                            <span>{{measure.function.expression}}</span>
+                        </td>
+                        <td>
+                            <!--Param Type -->
+                            <span>{{measure.function.parameter.type}}</span>
+                        </td>
+                        <td>
+                            <!--Param Value -->
+                            <span>{{measure.function.parameter.value}}</span>
+                        </td>
+                        <td>
+                            <!--Return Type -->
+                            <span>{{measure.function.returntype}}</span>
+                        </td>
+                        <td ng-if="state.mode=='edit'">
+                            <!--Edit Button -->
+                            <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
+                                <i class="fa fa-pencil"></i>
+                            </button>
+                            <!--Remove Button -->
+                            <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
+                                <i class="fa fa-trash-o"></i>
+                            </button>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
     </div>
-    <table class="table table-striped table-hover">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Name</th>
-                <th>Expression</th>
-                <th>Param Type</th>
-                <th>Param Value</th>
-                <th>Return Type</th>
-                <th ng-if="state.mode=='edit'">Actions</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr ng-repeat="measure in cubeMetaFrame.measures | filter: state.measureFilter track by $index">
-                <td>
-                    <!--ID -->
-                    <b>{{measure.id = ($index + 1)}}</b>
-                </td>
-                <td>
-                    <!--Name -->
-                    <span tooltip="measure name..">{{measure.name}}</span>
-                </td>
-                <td>
-                    <!--Expression -->
-                    <span>{{measure.function.expression}}</span>
-                </td>
-                <td>
-                    <!--Param Type -->
-                    <span>{{measure.function.parameter.type}}</span>
-                </td>
-                <td>
-                    <!--Param Value -->
-                    <span>{{measure.function.parameter.value}}</span>
-                </td>
-                <td>
-                    <!--Return Type -->
-                    <span>{{measure.function.returntype}}</span>
-                </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--Edit Button -->
-                    <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
-                        <i class="fa fa-pencil"></i>
-                    </button>
-                    <!--Remove Button -->
-                    <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
-                        <i class="fa fa-trash-o"></i>
-                    </button>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-</div>
+</ng-form>
 
 <!--Add Measures Button-->
 <div class="form-group">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubes/cube_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_schema.html b/webapp/app/partials/cubes/cube_schema.html
index 3fa16e5..6f3475c 100644
--- a/webapp/app/partials/cubes/cube_schema.html
+++ b/webapp/app/partials/cubes/cube_schema.html
@@ -28,7 +28,7 @@
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
                         class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
-                        <span style="cursor:pointer;" ng-click="goToStep($index)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span style="cursor:pointer;" ng-click="checkCubeForm()?goToStep($index):''" class="step">{{step.step = ($index + 1)}}</span>
                         <span class="title">{{step.title}}</span>
                      </li>
                 </ul>
@@ -41,7 +41,6 @@
             <div class="wizard-actions">
                 <div class="row">
                     <div class="col-xs-8">
-                        <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
                         <div>
                             <a href="cubes" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Cubes</a>
                         </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/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 308e793..98ad8e3 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -19,7 +19,7 @@
 <div ng-controller="CubeRefreshCtrl">
 <div class="row">
     <div class="col-xs-8">
-
+      <ng-form name="forms.model_setting_form" novalidate>
         <!--Cube Partition Type-->
         <div class="form-group" ng-hide="true">
             <div class="row">
@@ -43,7 +43,6 @@
                 <div class="col-xs-12 col-sm-6">
 
                     <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
-                            ng-required="model.partition_desc.partition_date_start"
                             ng-model="model.partition_desc.partition_date_column"
                             ng-if="state.mode=='edit'"
                             data-placement=""
@@ -72,6 +71,21 @@
             </div>
         </div>
 
+          <div class="form-group" ng-show="userService.hasRole('ROLE_ADMIN')">
+              <div class="row">
+                  <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Cube Size</b></label>
+                  <div class="col-xs-12 col-sm-6">
+                      <select class="form-control"
+                              ng-if="state.mode=='edit'"
+                              chosen ng-model="model.capacity"
+                              ng-options="ddt as ddt for ddt in cubeConfig.cubeCapacities">
+                          <option value=""></option>
+                      </select>
+                      <span ng-if="state.mode=='view'">{{model.capacity}}</span>
+                  </div>
+              </div>
+          </div>
+
         <!--Filter Condition-->
         <div class="form-group">
             <div class="row">
@@ -103,6 +117,7 @@
                 </div>
             </div>
         </div>
+       </ng-form>
     </div>
 
     <div class="col-xs-4">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/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 10a8d77..095203d 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -18,87 +18,79 @@
 
 <div ng-controller="ModelDimensionsCtrl">
 
-<!-- Dimensions Summary -->
-<div class="dataTables_wrapper form-inline no-footer">
-    <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
-        <div class="col-xs-6">
-            <b>Dimensions</b>
+    <!-- Dimensions Summary -->
+    <div class="dataTables_wrapper form-inline no-footer">
+        <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
+            <div class="col-xs-6">
+                <b>Dimensions</b>
+            </div>
+            <div class="col-xs-6">
+                <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
         </div>
-        <div class="col-xs-6">
-            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
-                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
-                <i class="ace-icon fa fa-search nav-search-icon"></i>
-            </span>
-        </div>
-    </div>
 
-    <ng-form name="model_dimensions" novalidate>
-     <!-- VIEW MODE -->
-        <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
-            <thead>
-                <tr>
-                    <th>ID</th>
-                    <th>Table Name</th>
-                    <th>Columns</th>
+        <ng-form name="forms.model_dimensions_form" novalidate>
+         <!-- VIEW MODE -->
+            <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
+                <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Table Name</th>
+                        <th>Columns</th>
+                    </tr>
+                </thead>
+                <tbody class="cube-dimension">
+                    <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                        <!--ID -->
+                        <td>
+                            <b>{{dimension.id = ($index + 1)}}</b>
+                        </td>
+                        <!--Name -->
+                        <td>
+                            <span>{{dimension.table}}</span>
+                        </td>
+                        <!--Table Name -->
+                        <td>
+                            <span>{{dimension.columns}}</span>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </ng-form>
+        <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
+            <h4 style="margin-left:42px">Dimensions</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="model.dimensions.length > 0"
+                   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>
-            </thead>
-            <tbody class="cube-dimension">
-                <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
-                    <!--ID -->
-                    <td>
-                        <b>{{dimension.id = ($index + 1)}}</b>
+
+                <tr ng-repeat="dimension in model.dimensions" class="row">
+                    <td class="col-xs-1">
+                        <!-- ID -->
+                        <b>{{($index + 1)}}</b>
                     </td>
-                    <!--Name -->
-                    <td>
-                        <span>{{dimension.table}}</span>
+                    <td class="col-xs-2">
+                            {{dimension.table}}
                     </td>
-                    <!--Table Name -->
-                    <td>
-                        <span>{{dimension.columns}}</span>
+                    <td class="col-xs-9">
+                        <!-- Dimensions -->
+                        <select ng-if="state.mode=='edit'" style="width: 100%"
+                                ng-model="model.dimensions[$index].columns" required chosen multiple
+                                ng-change=""
+                                ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
+                            <option value=""></option>
+                        </select>
                     </td>
                 </tr>
-            </tbody>
-        </table>
-    </ng-form>
-    <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
-        <h4 style="margin-left:42px">Dimensions</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="model.dimensions.length > 0"
-               class="table table-hover list">
-            <tr class="row">
-                <th class="col-xs-1">ID</th>
-                <th class="col-xs-1">Table Name</th>
-                <th class="col-xs-9">Columns</th>
-                <th class="col-xs-1"></th>
-            </tr>
-
-            <tr ng-repeat="dimension in model.dimensions" class="row">
-                <td class="col-xs-1">
-                    <!-- ID -->
-                    <b>{{($index + 1)}}</b>
-                </td>
-                <td class="col-xs-1">
-                        {{dimension.table}}
-                </td>
-                <td class="col-xs-9">
-                    <!-- Dimensions -->
-                    <select ng-if="state.mode=='edit'" style="width: 100%"
-                            ng-model="model.dimensions[$index].columns" required chosen multiple
-                            ng-change=""
-                            ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
-                        <option value=""></option>
-                    </select>
-                </td>
-                <td class="col-xs-1">
-                    <button class="btn btn-xs btn-info"
-                            ng-click="removeTableDimensions($index)"><i
-                            class="fa fa-minus"></i>
-                    </button>
-                </td>
-            </tr>
-        </table>
+            </table>
+         </div>
 
-
-</div>
-
-</div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/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 9451569..f324788 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -17,6 +17,7 @@
 -->
 
 <!-- Measures Summary -->
+<ng-form name="forms.model_measure_form" novalidate>
 <div class="dataTables_wrapper form-inline no-footer">
 
     <table ng-if="state.mode=='view'&&model.metrics.length > 0" class="table table-striped table-hover">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 86a3196..2f58bed 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -50,12 +50,12 @@
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''" ng-disabled="design_form.$invalid"
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''"
                                 ng-show="curStep.title!='Settings'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareModel();saveModel(design_form)" ng-disabled="design_form.$invalid"
+                        <button class="btn btn-primary" ng-click="prepareModel();saveModel()"
                                 ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>


[09/52] [abbrv] incubator-kylin git commit: KYLIN-759 refactor storage layer cache

Posted by ma...@apache.org.
KYLIN-759 refactor storage layer cache


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

Branch: refs/heads/0.8.0
Commit: bc426cc008e4424c81c62e7541cd244ac9ad811b
Parents: 6924057
Author: honma <ho...@ebay.com>
Authored: Wed May 13 16:59:45 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Thu May 14 20:22:04 2015 +0800

----------------------------------------------------------------------
 .../org/apache/kylin/common/util/RangeUtil.java |  14 +-
 .../org/apache/kylin/common/util/BasicTest.java |   3 +
 .../metadata/tuple/CompoundTupleIterator.java   |  25 +--
 .../kylin/metadata/tuple/ITupleIterator.java    |  14 --
 .../metadata/tuple/SimpleTupleIterator.java     |   6 -
 .../kylin/metadata/tuple/TeeTupleIterator.java  |  26 +--
 .../metadata/tuple/TeeTupleItrListener.java     |  10 +
 .../kylin/query/enumerator/OLAPEnumerator.java  |   2 +-
 .../apache/kylin/storage/IStorageEngine.java    |  23 +++
 .../kylin/storage/StorageEngineFactory.java     |  51 +++--
 .../AbstractCacheFledgedStorageEngine.java      |  49 +++++
 .../cache/CacheFledgedDynamicStorageEngine.java | 148 +++++++++++++++
 .../cache/CacheFledgedStaticStorageEngine.java  |  80 ++++++++
 .../cache/CacheFledgedStorageEngine.java        | 186 -------------------
 .../kylin/storage/cache/StorageLayerCache.java  |   7 -
 .../kylin/storage/cache/StreamSQLResult.java    |  44 +++--
 .../kylin/storage/cube/CubeStorageEngine.java   |  22 ++-
 .../cube/SerializedCubeTupleIterator.java       |   9 +-
 .../storage/hbase/CubeSegmentTupleIterator.java |  19 +-
 .../kylin/storage/hbase/CubeStorageEngine.java  |  47 +++--
 .../hbase/InvertedIndexStorageEngine.java       |  19 +-
 .../hbase/SerializedHBaseTupleIterator.java     |   4 -
 .../endpoint/EndpointTupleIterator.java         |  21 ++-
 .../endpoint/TsConditionExtractor.java          |   9 +-
 .../storage/hybrid/HybridStorageEngine.java     |  38 ++--
 .../apache/kylin/storage/test/StorageTest.java  |  15 +-
 26 files changed, 512 insertions(+), 379 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java b/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
index 33d6770..05e4d35 100644
--- a/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
@@ -1,11 +1,11 @@
 package org.apache.kylin.common.util;
 
+import com.google.common.collect.*;
+
 import java.util.Collections;
 import java.util.List;
 import java.util.NavigableMap;
 
-import com.google.common.collect.*;
-
 /**
  */
 public class RangeUtil {
@@ -44,6 +44,16 @@ public class RangeUtil {
         return range.upperBoundType() == BoundType.CLOSED;
     }
 
+    public static <C extends Comparable<?>> Range<C> merge(Range<C> a, Range<C> b) {
+        if (a == null && b == null) {
+            return null;
+        } else if (a == null || b == null) {
+            return a == null ? b : a;
+        } else {
+            return a.span(b);
+        }
+    }
+
     /**
      * remove from self the elements that exist in other
      * @return

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
index 2f4943d..e0226f8 100644
--- a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
@@ -62,6 +62,9 @@ public class BasicTest {
     @Test
     @Ignore("convenient trial tool for dev")
     public void test1() throws Exception {
+        Number xx =new Long(0L);
+        System.out.println(xx.getClass().getName());
+
         System.out.println(time(1367798400000L));
 
         System.out.println(org.apache.kylin.common.util.DateFormat.formatToTimeStr(1000L * Integer.MAX_VALUE));

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
index b87c633..f5d8dd6 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
@@ -1,14 +1,13 @@
 package org.apache.kylin.metadata.tuple;
 
-import java.util.Iterator;
-import java.util.List;
-
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterators;
-import com.google.common.collect.Range;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Iterator;
+import java.util.List;
+
 /**
  */
 public class CompoundTupleIterator implements ITupleIterator {
@@ -30,24 +29,6 @@ public class CompoundTupleIterator implements ITupleIterator {
     }
 
     @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        Range<Long> timeSpan = null;
-        for (ITupleIterator itt : this.backends) {
-            Range<Long> excluded = itt.getCacheExcludedPeriod();
-            if (excluded != null && !excluded.isEmpty()) {
-                if (timeSpan == null) {
-                    //first one
-                    timeSpan = excluded;
-                } else {
-                    logger.warn("There are two excluded period, use a span to replace them: " + timeSpan + " and " + excluded );
-                    timeSpan = timeSpan.span(excluded);
-                }
-            }
-        }
-        return timeSpan;
-    }
-
-    @Override
     public boolean hasNext() {
         return this.compoundIterator.hasNext();
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/metadata/src/main/java/org/apache/kylin/metadata/tuple/ITupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/ITupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/ITupleIterator.java
index 9e92eb9..6bab137 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/ITupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/ITupleIterator.java
@@ -20,8 +20,6 @@ package org.apache.kylin.metadata.tuple;
 
 import java.util.Iterator;
 
-import com.google.common.collect.Range;
-
 /**
  * @author xjiang
  *
@@ -46,22 +44,10 @@ public interface ITupleIterator extends Iterator<ITuple> {
         @Override
         public void close() {
         }
-
-        @Override
-        public Range<Long> getCacheExcludedPeriod() {
-            return null;
-        }
     };
 
     void close();
 
-    /**
-     * tells storage layer cache what time period of data should not be cached.
-     * for static storage like cube, it will return null
-     * for dynamic storage like ii, it will for example exclude the last two minutes for possible data latency
-     * @return
-     */
-    Range<Long> getCacheExcludedPeriod();
 
     /**
      * if hasNext() returns false because there's no more data, return true

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
index ebdcb5d..92006e1 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
@@ -2,8 +2,6 @@ package org.apache.kylin.metadata.tuple;
 
 import java.util.Iterator;
 
-import com.google.common.collect.Range;
-
 /**
  *
  */
@@ -34,8 +32,4 @@ public class SimpleTupleIterator implements ITupleIterator {
     public void close() {
     }
 
-    @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        return null;
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
index 556fca6..0618b45 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
@@ -1,10 +1,8 @@
 package org.apache.kylin.metadata.tuple;
 
-import java.util.List;
-
-import com.google.common.base.Function;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Range;
+
+import java.util.List;
 
 /**
  *
@@ -13,29 +11,21 @@ import com.google.common.collect.Range;
  */
 public class TeeTupleIterator implements ITupleIterator {
 
-    private Function<List<ITuple>, Void> actionOnSeeingWholeData;
     private ITupleIterator underlying;
     private List<ITuple> duplicatedData;
+    private List<TeeTupleItrListener> listeners = Lists.newArrayList();
 
     public TeeTupleIterator(ITupleIterator underlying) {
         this.underlying = underlying;
         this.duplicatedData = Lists.newArrayList();
     }
 
-    public void setActionOnSeeingWholeData(Function<List<ITuple>, Void> actionOnSeeingWholeData) {
-        this.actionOnSeeingWholeData = actionOnSeeingWholeData;
-    }
-
     @Override
     public void close() {
         this.underlying.close();
-        //if(this.underlying.isDrained)
-        actionOnSeeingWholeData.apply(duplicatedData);
-    }
-
-    @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        return this.underlying.getCacheExcludedPeriod();
+        for (TeeTupleItrListener listener : this.listeners) {
+            listener.notify(this.duplicatedData);
+        }
     }
 
     @Override
@@ -54,4 +44,8 @@ public class TeeTupleIterator implements ITupleIterator {
     public void remove() {
         this.underlying.remove();
     }
+
+    public void addCloseListener(TeeTupleItrListener listener) {
+        this.listeners.add(listener);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleItrListener.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleItrListener.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleItrListener.java
new file mode 100644
index 0000000..50b94bd
--- /dev/null
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleItrListener.java
@@ -0,0 +1,10 @@
+package org.apache.kylin.metadata.tuple;
+
+import java.util.List;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/13/15.
+ */
+public interface TeeTupleItrListener {
+    void notify(List<ITuple> duplicated);
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/query/src/main/java/org/apache/kylin/query/enumerator/OLAPEnumerator.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/enumerator/OLAPEnumerator.java b/query/src/main/java/org/apache/kylin/query/enumerator/OLAPEnumerator.java
index a5019ab..63f06f1 100644
--- a/query/src/main/java/org/apache/kylin/query/enumerator/OLAPEnumerator.java
+++ b/query/src/main/java/org/apache/kylin/query/enumerator/OLAPEnumerator.java
@@ -112,7 +112,7 @@ public class OLAPEnumerator implements Enumerator<Object[]> {
         olapContext.resetSQLDigest();
 
         // query storage engine
-        IStorageEngine storageEngine = StorageEngineFactory.getStorageEngine(olapContext.realization, true);
+        IStorageEngine storageEngine = StorageEngineFactory.getStorageEngine(olapContext.realization);
         ITupleIterator iterator = storageEngine.search(olapContext.storageContext, olapContext.getSQLDigest(), olapContext.returnTupleInfo);
         if (logger.isDebugEnabled()) {
             logger.debug("return TupleIterator...");

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
index 9a88676..d6b777a 100644
--- a/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
@@ -22,6 +22,8 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
 import org.apache.kylin.storage.tuple.TupleInfo;
 
+import com.google.common.collect.Range;
+
 /**
  * 
  * @author xjiang
@@ -31,4 +33,25 @@ public interface IStorageEngine {
 
     ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo);
 
+    /**
+     *
+     * being dynamic => getVolatilePeriod() return not null
+     * being dynamic => partition column of its realization not null
+     *
+     * @return true for static storage like cubes
+     *          false for dynamic storage like II
+     */
+    boolean isDynamic();
+
+    /**
+     * volatile period is the period of time in which the returned data is not stable
+     * e.g. inverted index's last several minutes' data is dynamic as time goes by.
+     * data in this period cannot be cached
+     *
+     * This method should not be called before ITupleIterator.close() is called
+     *
+     * @return null if the underlying storage guarantees the data is static
+     */
+    Range<Long> getVolatilePeriod();
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java b/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
index 4d150ad..29a53fd 100644
--- a/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
+++ b/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
@@ -18,37 +18,66 @@
 
 package org.apache.kylin.storage;
 
+import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.invertedindex.IIInstance;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.model.PartitionDesc;
+import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.RealizationType;
-import org.apache.kylin.storage.cache.CacheFledgedStorageEngine;
+import org.apache.kylin.storage.cache.CacheFledgedDynamicStorageEngine;
+import org.apache.kylin.storage.cache.CacheFledgedStaticStorageEngine;
 import org.apache.kylin.storage.hbase.CubeStorageEngine;
 import org.apache.kylin.storage.hbase.InvertedIndexStorageEngine;
 import org.apache.kylin.storage.hybrid.HybridInstance;
 import org.apache.kylin.storage.hybrid.HybridStorageEngine;
 
+import com.google.common.base.Preconditions;
+
 /**
  * @author xjiang
  */
 public class StorageEngineFactory {
+    private static boolean allowStorageLayerCache = true;
 
-    public static IStorageEngine getStorageEngine(IRealization realization, boolean allowCache) {
-        if (realization.getType() == RealizationType.CUBE) {
-            allowCache = false;
-        }
-        
-        if (allowCache) {
-            return new CacheFledgedStorageEngine(realization);
-        }
+    public static IStorageEngine getStorageEngine(IRealization realization) {
 
         if (realization.getType() == RealizationType.INVERTED_INDEX) {
-            return new InvertedIndexStorageEngine((IIInstance) realization);
+            IStorageEngine ret = new InvertedIndexStorageEngine((IIInstance) realization);
+            if (allowStorageLayerCache) {
+                return wrapWithCache(ret, realization);
+            } else {
+                return ret;
+            }
         } else if (realization.getType() == RealizationType.CUBE) {
-            return new CubeStorageEngine((CubeInstance) realization);
+            IStorageEngine ret = new CubeStorageEngine((CubeInstance) realization);
+            if (allowStorageLayerCache) {
+                return wrapWithCache(ret, realization);
+            } else {
+                return ret;
+            }
         } else {
             return new HybridStorageEngine((HybridInstance) realization);
         }
     }
 
+    private static IStorageEngine wrapWithCache(IStorageEngine underlyingStorageEngine, IRealization realization) {
+        if (underlyingStorageEngine.isDynamic()) {
+            return new CacheFledgedDynamicStorageEngine(underlyingStorageEngine, getPartitionCol(realization));
+        } else {
+            return new CacheFledgedStaticStorageEngine(underlyingStorageEngine);
+        }
+    }
+
+    private static TblColRef getPartitionCol(IRealization realization) {
+        String modelName = realization.getModelName();
+        DataModelDesc dataModelDesc = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv()).getDataModelDesc(modelName);
+        PartitionDesc partitionDesc = dataModelDesc.getPartitionDesc();
+        Preconditions.checkArgument(partitionDesc != null, "PartitionDesc for " + realization + " is null!");
+        TblColRef partitionColRef = partitionDesc.getPartitionDateColumnRef();
+        Preconditions.checkArgument(partitionColRef != null, "getPartitionDateColumnRef for " + realization + " is null");
+        return partitionColRef;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
new file mode 100644
index 0000000..d8e2fc0
--- /dev/null
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
@@ -0,0 +1,49 @@
+package org.apache.kylin.storage.cache;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.config.CacheConfiguration;
+import net.sf.ehcache.config.MemoryUnit;
+import net.sf.ehcache.config.PersistenceConfiguration;
+import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
+
+import org.apache.kylin.metadata.realization.StreamSQLDigest;
+import org.apache.kylin.storage.IStorageEngine;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/13/15.
+ */
+public abstract class AbstractCacheFledgedStorageEngine {
+    private static final Logger logger = LoggerFactory.getLogger(AbstractCacheFledgedStorageEngine.class);
+    protected static CacheManager cacheManager = CacheManager.create();
+
+    protected final IStorageEngine underlyingStorage;
+    protected StreamSQLDigest streamSQLDigest;
+    protected boolean queryCacheExists;
+
+    public AbstractCacheFledgedStorageEngine(IStorageEngine underlyingStorage) {
+        this.underlyingStorage = underlyingStorage;
+        this.queryCacheExists = false;
+        this.makeCacheIfNecessary(underlyingStorage.getClass().getName());
+    }
+
+    private void makeCacheIfNecessary(String storageClassName) {
+        if (cacheManager.getCache(storageClassName) == null) {
+            logger.info("Cache for {} initting:", storageClassName);
+            // TODO: L4J [2015-04-20 10:44:03,817][WARN][net.sf.ehcache.pool.sizeof.ObjectGraphWalker] - The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. This can be avoided by setting the CacheManger or Cache <sizeOfPolicy> elements maxDepthExceededBehavior to "abort" or adding stop points with @IgnoreSizeOf annotations. If performance degradation is NOT an issue at the configured limit, raise the limit value using the CacheManager or Cache <sizeOfPolicy
+            //Create a Cache specifying its configuration.
+            Cache storageCache = new Cache(new CacheConfiguration(storageClassName, 0).//
+                    memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU).//
+                    eternal(false).//
+                    timeToIdleSeconds(86400).//
+                    diskExpiryThreadIntervalSeconds(0).//
+                    maxBytesLocalHeap(256, MemoryUnit.MEGABYTES).//
+                    persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)));
+            //TODO: deal with failed queries, and only cache too long query
+
+            cacheManager.addCache(storageCache);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
new file mode 100644
index 0000000..0d7ab18
--- /dev/null
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
@@ -0,0 +1,148 @@
+package org.apache.kylin.storage.cache;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+import org.apache.kylin.common.util.RangeUtil;
+import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.realization.SQLDigest;
+import org.apache.kylin.metadata.realization.SQLDigestUtil;
+import org.apache.kylin.metadata.realization.StreamSQLDigest;
+import org.apache.kylin.metadata.tuple.*;
+import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.StorageContext;
+import org.apache.kylin.storage.hbase.coprocessor.endpoint.TsConditionExtractor;
+import org.apache.kylin.storage.tuple.TupleInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/11/15.
+ */
+public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
+    private static final Logger logger = LoggerFactory.getLogger(CacheFledgedDynamicStorageEngine.class);
+
+    private final TblColRef partitionColRef;
+
+    private Range<Long> ts;
+
+    public CacheFledgedDynamicStorageEngine(IStorageEngine underlyingStorage, TblColRef partitionColRef) {
+        super(underlyingStorage);
+        this.partitionColRef = partitionColRef;
+
+        Preconditions.checkArgument(this.partitionColRef != null, "For dynamic columns like " + //
+                this.underlyingStorage.getClass().getName() + ", partition column must be provided");
+    }
+
+    @Override
+    public ITupleIterator search(final StorageContext context, final SQLDigest sqlDigest, final TupleInfo returnTupleInfo) {
+        //if isDynamicStorage && query involves filter on partition column, the cache requires updating after query done.
+        boolean needUpdateCache = sqlDigest.groupbyColumns.contains(partitionColRef);
+
+        streamSQLDigest = new StreamSQLDigest(sqlDigest, partitionColRef);
+        StreamSQLResult cachedResult = null;
+        Cache cache = cacheManager.getCache(this.underlyingStorage.getClass().getName());
+        Element element = cache.get(streamSQLDigest);
+        if (element != null) {
+            this.queryCacheExists = true;
+            cachedResult = (StreamSQLResult) element.getObjectValue();
+        }
+
+        ts = TsConditionExtractor.extractTsCondition(partitionColRef, sqlDigest.filter);
+        if (ts == null || ts.isEmpty()) {
+            logger.info("ts range in the query conflicts,return empty directly");
+            return ITupleIterator.EMPTY_TUPLE_ITERATOR;
+        }
+
+        ITupleIterator ret = null;
+        if (cachedResult != null) {
+            Range<Long> reusePeriod = cachedResult.getReusableResults(ts);
+
+            logger.info("existing cache    : " + cachedResult);
+            logger.info("ts Range in query: " + RangeUtil.formatTsRange(ts));
+            logger.info("potential reusable range   : " + RangeUtil.formatTsRange(reusePeriod));
+
+            if (reusePeriod != null) {
+                List<Range<Long>> remainings = RangeUtil.remove(ts, reusePeriod);
+                if (remainings.size() == 1) {//if using cache causes two underlyingStorage searches, we'd rather not use the cache
+
+                    SimpleTupleIterator reusedTuples = new SimpleTupleIterator(cachedResult.reuse(reusePeriod));
+                    List<ITupleIterator> iTupleIteratorList = Lists.newArrayList();
+                    iTupleIteratorList.add(reusedTuples);
+
+                    for (Range<Long> remaining : remainings) {
+                        logger.info("Appending ts " + RangeUtil.formatTsRange(remaining) + " as additional filter");
+
+                        ITupleIterator freshTuples = SQLDigestUtil.appendTsFilterToExecute(sqlDigest, partitionColRef, remaining, new Function<Void, ITupleIterator>() {
+                            @Override
+                            public ITupleIterator apply(Void input) {
+                                return underlyingStorage.search(context, sqlDigest, returnTupleInfo);
+                            }
+                        });
+                        iTupleIteratorList.add(freshTuples);
+                    }
+
+                    ret = new CompoundTupleIterator(iTupleIteratorList);
+                } else if (remainings.size() == 0) {
+                    needUpdateCache = false;
+                    ret = new SimpleTupleIterator(cachedResult.reuse(reusePeriod));
+                } else {
+                    //if using cache causes two underlyingStorage searches, we'd rather not use the cache
+                }
+            }
+        } else {
+            logger.info("no cache entry for this query");
+        }
+
+        if (ret == null) {
+            logger.info("decision: not using cache");
+            ret = underlyingStorage.search(context, sqlDigest, returnTupleInfo);
+        } else {
+            logger.info("decision: use cache");
+        }
+
+        if (needUpdateCache || !queryCacheExists) {
+            //use another nested ITupleIterator to deal with cache
+            final TeeTupleIterator tee = new TeeTupleIterator(ret);
+            tee.addCloseListener(this);
+            return tee;
+        } else {
+            return ret;
+        }
+    }
+
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return underlyingStorage.getVolatilePeriod();
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return true;
+    }
+
+    @Override
+    public void notify(List<ITuple> duplicated) {
+        Range<Long> cacheExclude = this.underlyingStorage.getVolatilePeriod();
+        if (cacheExclude != null) {
+            List<Range<Long>> cachablePeriods = RangeUtil.remove(ts, cacheExclude);
+            if (cachablePeriods.size() == 1) {
+                if (!ts.equals(cachablePeriods.get(0))) {
+                    logger.info("With respect to each shard's build status, the cacheable tsRange shrinks from " + RangeUtil.formatTsRange(ts) + " to " + RangeUtil.formatTsRange(cachablePeriods.get(0)));
+                }
+                ts = cachablePeriods.get(0);
+            } else {
+                //give up updating the cache, in avoid to make cache complicated
+            }
+        }
+
+        StreamSQLResult newCacheEntry = new StreamSQLResult(duplicated, ts, partitionColRef);
+        cacheManager.getCache(this.underlyingStorage.getClass().getName()).put(new Element(streamSQLDigest, newCacheEntry));
+        logger.info("cache after the query: " + newCacheEntry);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
new file mode 100644
index 0000000..a4aceed
--- /dev/null
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
@@ -0,0 +1,80 @@
+package org.apache.kylin.storage.cache;
+
+import com.google.common.collect.Range;
+import com.google.common.collect.Ranges;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+import org.apache.kylin.metadata.realization.SQLDigest;
+import org.apache.kylin.metadata.realization.StreamSQLDigest;
+import org.apache.kylin.metadata.tuple.*;
+import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.StorageContext;
+import org.apache.kylin.storage.tuple.TupleInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Created by Hongbin Ma(Binmahone) on 5/11/15.
+ */
+public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
+    private static final Logger logger = LoggerFactory.getLogger(CacheFledgedStaticStorageEngine.class);
+
+    public CacheFledgedStaticStorageEngine(IStorageEngine underlyingStorage) {
+        super(underlyingStorage);
+    }
+
+    @Override
+    public ITupleIterator search(final StorageContext context, final SQLDigest sqlDigest, final TupleInfo returnTupleInfo) {
+
+        streamSQLDigest = new StreamSQLDigest(sqlDigest, null);
+        StreamSQLResult cachedResult = null;
+        Cache cache = cacheManager.getCache(this.underlyingStorage.getClass().getName());
+        Element element = cache.get(streamSQLDigest);
+        if (element != null) {
+            this.queryCacheExists = true;
+            cachedResult = (StreamSQLResult) element.getObjectValue();
+        }
+
+        ITupleIterator ret = null;
+        if (cachedResult != null) {
+            ret = new SimpleTupleIterator(cachedResult.reuse(Ranges.<Long> all()));
+        } else {
+            logger.info("no cache entry for this query");
+        }
+
+        if (ret == null) {
+            logger.info("decision: not using cache");
+            ret = underlyingStorage.search(context, sqlDigest, returnTupleInfo);
+        } else {
+            logger.info("decision: use cache");
+        }
+
+        if (queryCacheExists) {
+            //use another nested ITupleIterator to deal with cache
+            final TeeTupleIterator tee = new TeeTupleIterator(ret);
+            tee.addCloseListener(this);
+            return tee;
+        } else {
+            return ret;
+        }
+    }
+
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return underlyingStorage.getVolatilePeriod();
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return false;
+    }
+
+    @Override
+    public void notify(List<ITuple> duplicated) {
+        StreamSQLResult newCacheEntry = new StreamSQLResult(duplicated, Ranges.<Long> all(), null);
+        cacheManager.getCache(this.underlyingStorage.getClass().getName()).put(new Element(streamSQLDigest, newCacheEntry));
+        logger.info("cache after the query: " + newCacheEntry);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
deleted file mode 100644
index 068619e..0000000
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.apache.kylin.storage.cache;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-import net.sf.ehcache.config.CacheConfiguration;
-import net.sf.ehcache.config.MemoryUnit;
-import net.sf.ehcache.config.PersistenceConfiguration;
-import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.RangeUtil;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.apache.kylin.metadata.model.PartitionDesc;
-import org.apache.kylin.metadata.model.TblColRef;
-import org.apache.kylin.metadata.realization.IRealization;
-import org.apache.kylin.metadata.realization.RealizationType;
-import org.apache.kylin.metadata.realization.SQLDigest;
-import org.apache.kylin.metadata.realization.SQLDigestUtil;
-import org.apache.kylin.metadata.realization.StreamSQLDigest;
-import org.apache.kylin.metadata.tuple.CompoundTupleIterator;
-import org.apache.kylin.metadata.tuple.ITuple;
-import org.apache.kylin.metadata.tuple.ITupleIterator;
-import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
-import org.apache.kylin.metadata.tuple.TeeTupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
-import org.apache.kylin.storage.StorageContext;
-import org.apache.kylin.storage.StorageEngineFactory;
-import org.apache.kylin.storage.hbase.coprocessor.endpoint.TsConditionExtractor;
-import org.apache.kylin.storage.tuple.TupleInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Range;
-
-/**
- */
-public class CacheFledgedStorageEngine implements IStorageEngine {
-
-    private static final Logger logger = LoggerFactory.getLogger(CacheFledgedStorageEngine.class);
-
-    public static final String STORAGE_LAYER_TUPLE_CACHE = "STORAGE_LAYER_TUPLE_CACHE";
-    //TODO: deal with failed queries
-
-    static CacheManager cacheManager;
-
-    static {
-        // TODO: L4J [2015-04-20 10:44:03,817][WARN][net.sf.ehcache.pool.sizeof.ObjectGraphWalker] - The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. This can be avoided by setting the CacheManger or Cache <sizeOfPolicy> elements maxDepthExceededBehavior to "abort" or adding stop points with @IgnoreSizeOf annotations. If performance degradation is NOT an issue at the configured limit, raise the limit value using the CacheManager or Cache <sizeOfPolicy
-        cacheManager = CacheManager.create();
-
-        //Create a Cache specifying its configuration.
-        Cache successCache = new Cache(new CacheConfiguration(STORAGE_LAYER_TUPLE_CACHE, 0).//
-                memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU).//
-                eternal(false).//
-                timeToIdleSeconds(86400).//
-                diskExpiryThreadIntervalSeconds(0).//
-                maxBytesLocalHeap(1, MemoryUnit.GIGABYTES).//
-                persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)));
-
-        cacheManager.addCache(successCache);
-    }
-
-    private TblColRef partitionColRef;
-    private IRealization realization;
-
-    public CacheFledgedStorageEngine(IRealization realization) {
-        this.realization = realization;
-
-        Preconditions.checkArgument(realization.getType() != RealizationType.CUBE, "Cube realization does not need dynamic cache!");
-        String modelName = realization.getModelName();
-        DataModelDesc dataModelDesc = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv()).getDataModelDesc(modelName);
-        PartitionDesc partitionDesc = dataModelDesc.getPartitionDesc();
-        Preconditions.checkArgument(partitionDesc != null, "PartitionDesc for " + realization + " is null!");
-        assert partitionDesc != null;
-        partitionColRef = partitionDesc.getPartitionDateColumnRef();
-        Preconditions.checkArgument(partitionColRef != null, "getPartitionDateColumnRef for " + realization + " is null");
-    }
-
-    @Override
-    public ITupleIterator search(final StorageContext context, final SQLDigest sqlDigest, final TupleInfo returnTupleInfo) {
-
-        //enable storage layer cache iff ts column is contained in filter
-        boolean needUpdateCache = sqlDigest.groupbyColumns.contains(partitionColRef);
-
-        final StreamSQLDigest streamSQLDigest = new StreamSQLDigest(sqlDigest, partitionColRef);
-        StreamSQLResult cachedResult = null;
-        Cache cache = cacheManager.getCache(STORAGE_LAYER_TUPLE_CACHE);
-        Element element = cache.get(streamSQLDigest);
-        if (element != null) {
-            cachedResult = (StreamSQLResult) element.getObjectValue();
-        }
-
-        Range<Long> ts = TsConditionExtractor.extractTsCondition(partitionColRef, sqlDigest.filter);
-        if (ts == null || ts.isEmpty()) {
-            logger.info("ts range in the query conflicts,return empty directly");
-            return ITupleIterator.EMPTY_TUPLE_ITERATOR;
-        }
-
-        ITupleIterator ret = null;
-        if (cachedResult != null) {
-            logger.debug("existing cache    : " + cachedResult);
-            Range<Long> reusePeriod = cachedResult.getReusableResults(ts);
-
-            logger.info("ts Range in query: " + RangeUtil.formatTsRange(ts));
-            logger.info("potential reusable range   : " + RangeUtil.formatTsRange(reusePeriod));
-
-            if (reusePeriod != null) {
-
-                List<Range<Long>> remainings = RangeUtil.remove(ts, reusePeriod);
-                if (remainings.size() == 1) {
-
-                    SimpleTupleIterator reusedTuples = new SimpleTupleIterator(cachedResult.reuse(reusePeriod));
-                    Range<Long> remaining = remainings.get(0);
-                    logger.info("Appending ts " + RangeUtil.formatTsRange(remaining) + " as additional filter");
-                    ITupleIterator freshTuples = SQLDigestUtil.appendTsFilterToExecute(sqlDigest, partitionColRef, remaining, new Function<Void, ITupleIterator>() {
-                        @Override
-                        public ITupleIterator apply(Void input) {
-                            return StorageEngineFactory.getStorageEngine(realization, false).search(context, sqlDigest, returnTupleInfo);
-                        }
-                    });
-
-                    ret = new CompoundTupleIterator(Lists.newArrayList(reusedTuples, freshTuples));
-                } else if (remainings.size() == 0) {
-                    needUpdateCache = false;
-                    ret = new SimpleTupleIterator(cachedResult.reuse(reusePeriod));
-                }
-                //if remaining size > 1, we skip using cache , i.e, ret will == null
-            }
-        } else {
-            logger.info("no cache entry for this query");
-        }
-
-        if (ret == null) {
-            logger.info("decision: not using cache");
-            //cache cannot reuse case:
-            ret = StorageEngineFactory.getStorageEngine(realization, false).search(context, sqlDigest, returnTupleInfo);
-        } else {
-            logger.info("decision: use cache");
-        }
-
-        if (needUpdateCache) {
-            //the tsRange in cache should reflect data aliveness
-            final Range<Long> finalTs = ts;
-
-            //use another nested ITupleIterator to deal with cache
-            final TeeTupleIterator tee = new TeeTupleIterator(ret);
-            tee.setActionOnSeeingWholeData(new Function<List<ITuple>, Void>() {
-                @Nullable
-                @Override
-                public Void apply(List<ITuple> input) {
-                    Range<Long> tsRange = finalTs;
-                    Range<Long> cacheExclude = tee.getCacheExcludedPeriod();
-                    if (cacheExclude != null) {
-                        List<Range<Long>> cachablePeriods = RangeUtil.remove(tsRange, cacheExclude);
-                        if (cachablePeriods.size() == 1) {
-                            if (!tsRange.equals(cachablePeriods.get(0))) {
-                                logger.info("With respect to each shard's build status, the cacheable tsRange shrinks from " + RangeUtil.formatTsRange(tsRange) + " to " + RangeUtil.formatTsRange(cachablePeriods.get(0)));
-                            }
-                            tsRange = cachablePeriods.get(0);
-                        } else {
-                            //give up updating the cache, in avoid to make cache complicated
-                            return null;
-                        }
-                    }
-
-                    StreamSQLResult newCacheEntry = new StreamSQLResult(input, tsRange, partitionColRef);
-                    cacheManager.getCache(STORAGE_LAYER_TUPLE_CACHE).put(new Element(streamSQLDigest, newCacheEntry));
-                    logger.debug("cache after the query: " + newCacheEntry);
-                    return null;
-                }
-            });
-
-            return tee;
-        } else {
-            return ret;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java b/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
deleted file mode 100644
index 9b4caa5..0000000
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.apache.kylin.storage.cache;
-
-/**
- */
-public interface StorageLayerCache {
-    boolean isCacheEnabled();
-}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
index 5e58822..e895d8e 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
@@ -1,22 +1,19 @@
 package org.apache.kylin.storage.cache;
 
-import java.util.Iterator;
-import java.util.List;
-import java.util.NavigableMap;
-
-import javax.annotation.Nullable;
-
-import com.google.common.base.Preconditions;
-import org.apache.kylin.common.util.RangeUtil;
-import org.apache.kylin.metadata.model.TblColRef;
-import org.apache.kylin.metadata.tuple.ITuple;
-import org.apache.kylin.storage.tuple.Tuple;
-
 import com.google.common.base.Function;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Range;
+import org.apache.kylin.common.util.RangeUtil;
+import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.tuple.ITuple;
+import org.apache.kylin.storage.tuple.Tuple;
+
+import javax.annotation.Nullable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NavigableMap;
 
 /**
  */
@@ -27,20 +24,22 @@ public class StreamSQLResult {
 
     public StreamSQLResult(List<ITuple> rows, Range<Long> timeCovered, TblColRef partitionCol) {
 
-        Preconditions.checkArgument(timeCovered.hasUpperBound(),"StreamSQLResult requires timeCovered having a upperBound");
-
         sortedRows = Maps.newTreeMap();
         for (ITuple row : rows) {
 
-            long t = Tuple.getTs(row,partitionCol);
+            if (partitionCol != null) {
+                long t = Tuple.getTs(row, partitionCol);
 
-            //will only cache rows that are within the time range
-            if (timeCovered.contains(t)) {
-                if (!this.sortedRows.containsKey(t)) {
-                    this.sortedRows.put(t, Lists.newArrayList(row));
-                } else {
-                    this.sortedRows.get(t).add(row);
+                //will only cache rows that are within the time range
+                if (timeCovered.contains(t)) {
+                    if (!this.sortedRows.containsKey(t)) {
+                        this.sortedRows.put(t, Lists.newArrayList(row));
+                    } else {
+                        this.sortedRows.get(t).add(row);
+                    }
                 }
+            } else {
+                this.sortedRows.get(0L).add(row);
             }
         }
         this.timeCovered = timeCovered;
@@ -76,8 +75,7 @@ public class StreamSQLResult {
         return sortedRows.size() + " tuples cached for period " + RangeUtil.formatTsRange(timeCovered);
     }
 
-    public long getEndTime()
-    {
+    public long getEndTime() {
         return this.timeCovered.upperEndpoint();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
index 1633f25..a353f49 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
@@ -1,11 +1,8 @@
 package org.apache.kylin.storage.cube;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import com.google.common.collect.Sets;
 import org.apache.kylin.common.util.Pair;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
@@ -31,8 +28,7 @@ import org.apache.kylin.storage.tuple.TupleInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import java.util.*;
 
 public class CubeStorageEngine implements IStorageEngine {
 
@@ -97,6 +93,16 @@ public class CubeStorageEngine implements IStorageEngine {
         return new SerializedCubeTupleIterator(scanners);
     }
 
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return null;
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return false;
+    }
+
     private void buildDimensionsAndMetrics(SQLDigest sqlDigest, Collection<TblColRef> dimensions, Collection<FunctionDesc> metrics) {
         for (FunctionDesc func : sqlDigest.aggregations) {
             if (!func.isDimensionAsMetric()) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/cube/SerializedCubeTupleIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cube/SerializedCubeTupleIterator.java b/storage/src/main/java/org/apache/kylin/storage/cube/SerializedCubeTupleIterator.java
index e69a1c7..7b9286c 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cube/SerializedCubeTupleIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cube/SerializedCubeTupleIterator.java
@@ -1,11 +1,10 @@
 package org.apache.kylin.storage.cube;
 
-import java.util.List;
-
-import com.google.common.collect.Range;
 import org.apache.kylin.metadata.tuple.ITuple;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
 
+import java.util.List;
+
 public class SerializedCubeTupleIterator implements ITupleIterator {
 
     public SerializedCubeTupleIterator(List<CubeScanner> scanners) {
@@ -35,9 +34,5 @@ public class SerializedCubeTupleIterator implements ITupleIterator {
 
     }
 
-    @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        return null;
-    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/CubeSegmentTupleIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeSegmentTupleIterator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeSegmentTupleIterator.java
index a9b4f92..a8027c0 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeSegmentTupleIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeSegmentTupleIterator.java
@@ -18,23 +18,15 @@
 
 package org.apache.kylin.storage.hbase;
 
-import java.text.MessageFormat;
-import java.util.*;
-
 import com.google.common.collect.Lists;
-import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.client.*;
 import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
 import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.filter.FilterList;
 import org.apache.hadoop.hbase.filter.FuzzyRowFilter;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
-import org.apache.kylin.common.util.Bytes;
-import org.apache.hadoop.hbase.util.Pair;
 import org.apache.kylin.common.persistence.StorageException;
+import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.cube.CubeSegment;
 import org.apache.kylin.cube.cuboid.Cuboid;
 import org.apache.kylin.cube.kv.RowValueDecoder;
@@ -49,7 +41,8 @@ import org.apache.kylin.storage.tuple.TupleInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Range;
+import java.text.MessageFormat;
+import java.util.*;
 
 /**
  * @author xjiang
@@ -106,10 +99,6 @@ public class CubeSegmentTupleIterator implements ITupleIterator {
         }
     }
 
-    @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        return null;
-    }
 
     @Override
     public boolean hasNext() {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
index ab75a3c..699cc41 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
@@ -18,44 +18,43 @@
 
 package org.apache.kylin.storage.hbase;
 
-import java.util.*;
-
-import org.apache.kylin.metadata.model.FunctionDesc;
-import org.apache.kylin.metadata.model.MeasureDesc;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.metadata.model.TblColRef;
-import org.apache.kylin.metadata.realization.SQLDigest;
-import org.apache.kylin.storage.hbase.coprocessor.observer.ObserverEnabler;
-import org.apache.kylin.storage.tuple.TupleInfo;
-import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.kylin.common.util.Bytes;
-import org.apache.kylin.common.util.Pair;
-import org.apache.kylin.storage.StorageContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Range;
 import com.google.common.collect.Sets;
-
+import org.apache.hadoop.hbase.client.HConnection;
 import org.apache.kylin.common.persistence.HBaseConnection;
+import org.apache.kylin.common.util.Bytes;
+import org.apache.kylin.common.util.Pair;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
 import org.apache.kylin.cube.CubeSegment;
 import org.apache.kylin.cube.cuboid.Cuboid;
 import org.apache.kylin.cube.kv.RowValueDecoder;
 import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.CubeDesc.DeriveInfo;
 import org.apache.kylin.cube.model.HBaseColumnDesc;
 import org.apache.kylin.cube.model.HBaseMappingDesc;
-import org.apache.kylin.cube.model.CubeDesc.DeriveInfo;
 import org.apache.kylin.dict.lookup.LookupStringTable;
-import org.apache.kylin.storage.IStorageEngine;
 import org.apache.kylin.metadata.filter.ColumnTupleFilter;
 import org.apache.kylin.metadata.filter.CompareTupleFilter;
 import org.apache.kylin.metadata.filter.LogicalTupleFilter;
 import org.apache.kylin.metadata.filter.TupleFilter;
 import org.apache.kylin.metadata.filter.TupleFilter.FilterOperatorEnum;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.metadata.model.TblColRef;
+import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
+import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.StorageContext;
+import org.apache.kylin.storage.hbase.coprocessor.observer.ObserverEnabler;
+import org.apache.kylin.storage.tuple.TupleInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
 
 /**
  * @author xjiang, yangli9
@@ -133,6 +132,16 @@ public class CubeStorageEngine implements IStorageEngine {
         return new SerializedHBaseTupleIterator(conn, scans, cubeInstance, dimensionsD, filterD, groupsCopD, valueDecoders, context, returnTupleInfo);
     }
 
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return null;
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return false;
+    }
+
     private void buildDimensionsAndMetrics(Collection<TblColRef> dimensions, Collection<FunctionDesc> metrics, SQLDigest sqlDigest) {
 
         for (FunctionDesc func : sqlDigest.aggregations) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
index 9259db6..c94222e 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
@@ -18,8 +18,7 @@
 
 package org.apache.kylin.storage.hbase;
 
-import java.util.ArrayList;
-
+import com.google.common.collect.Range;
 import org.apache.hadoop.hbase.client.HConnection;
 import org.apache.kylin.common.persistence.HBaseConnection;
 import org.apache.kylin.invertedindex.IIInstance;
@@ -33,6 +32,8 @@ import org.apache.kylin.storage.tuple.TupleInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+
 /**
  * @author yangli9
  */
@@ -41,6 +42,7 @@ public class InvertedIndexStorageEngine implements IStorageEngine {
     private static Logger logger = LoggerFactory.getLogger(InvertedIndexStorageEngine.class);
 
     private IISegment seg;
+    private EndpointTupleIterator dataIterator;
 
     public InvertedIndexStorageEngine(IIInstance ii) {
         this.seg = ii.getFirstSegment();
@@ -54,10 +56,21 @@ public class InvertedIndexStorageEngine implements IStorageEngine {
         @SuppressWarnings("deprecation")
         HConnection conn = HBaseConnection.get(context.getConnUrl());
         try {
-            return new EndpointTupleIterator(seg, sqlDigest.filter, sqlDigest.groupbyColumns, new ArrayList<>(sqlDigest.aggregations), context, conn, returnTupleInfo);
+            dataIterator = new EndpointTupleIterator(seg, sqlDigest.filter, sqlDigest.groupbyColumns, new ArrayList<>(sqlDigest.aggregations), context, conn, returnTupleInfo);
+            return dataIterator;
         } catch (Throwable e) {
             logger.error("Error when connecting to II htable " + tableName, e);
             throw new IllegalStateException("Error when connecting to II htable " + tableName, e);
         }
     }
+
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return dataIterator.getCacheExcludedPeriod();
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/SerializedHBaseTupleIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/SerializedHBaseTupleIterator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/SerializedHBaseTupleIterator.java
index 3bb8b80..9cc9eb2 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/SerializedHBaseTupleIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/SerializedHBaseTupleIterator.java
@@ -149,8 +149,4 @@ public class SerializedHBaseTupleIterator implements ITupleIterator {
         }
     }
 
-    @Override
-    public Range<Long> getCacheExcludedPeriod() {
-        return null;
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
index d9ede57..9cb5f36 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
@@ -19,10 +19,10 @@
 package org.apache.kylin.storage.hbase.coprocessor.endpoint;
 
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.*;
 import com.google.protobuf.ByteString;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.NotImplementedException;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.hadoop.hbase.client.HConnection;
 import org.apache.hadoop.hbase.client.HTableInterface;
@@ -82,7 +82,7 @@ public class EndpointTupleIterator implements ITupleIterator {
     private HTableInterface table = null;
 
     private TblColRef partitionCol;
-    private long lastDataTime;
+    private long lastDataTime = -1;
     private int rowsInAllMetric = 0;
 
     public EndpointTupleIterator(IISegment segment, TupleFilter rootFilter, Collection<TblColRef> groupBy, List<FunctionDesc> measures, StorageContext context, HConnection conn, TupleInfo returnTupleInfo) throws Throwable {
@@ -139,8 +139,7 @@ public class EndpointTupleIterator implements ITupleIterator {
 
         //decompress
         Collection<IIProtos.IIResponseInternal> shardResults = new ArrayList<>();
-        for(IIProtos.IIResponse input : compressedShardResults)
-        {
+        for (IIProtos.IIResponse input : compressedShardResults) {
             byte[] compressed = input.getBlob().toByteArray();
             try {
                 byte[] decompressed = CompressionUtils.decompress(compressed);
@@ -251,8 +250,14 @@ public class EndpointTupleIterator implements ITupleIterator {
         logger.info("Closed after " + rowsInAllMetric + " rows are fetched");
     }
 
-    @Override
+    /**
+     * tells storage layer cache what time period of data should not be cached.
+     * for static storage like cube, it will return null
+     * for dynamic storage like ii, it will for example exclude the last two minutes for possible data latency
+     * @return
+     */
     public Range<Long> getCacheExcludedPeriod() {
+        Preconditions.checkArgument(lastDataTime != -1, "lastDataTime is not set yet");
         return Ranges.greaterThan(lastDataTime);
     }
 
@@ -333,7 +338,7 @@ public class EndpointTupleIterator implements ITupleIterator {
             }
 
             index++;
-            
+
             return tupleConverter.makeTuple(this.tableRecord, this.measureValues, this.tuple);
         }
 
@@ -346,9 +351,5 @@ public class EndpointTupleIterator implements ITupleIterator {
         public void close() {
         }
 
-        @Override
-        public Range<Long> getCacheExcludedPeriod() {
-            throw new NotImplementedException();
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
index 18155c6..27a919c 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
@@ -1,13 +1,13 @@
 package org.apache.kylin.storage.hbase.coprocessor.endpoint;
 
-import com.google.common.collect.Ranges;
+import org.apache.kylin.common.util.DateFormat;
 import org.apache.kylin.metadata.filter.CompareTupleFilter;
 import org.apache.kylin.metadata.filter.LogicalTupleFilter;
 import org.apache.kylin.metadata.filter.TupleFilter;
 import org.apache.kylin.metadata.model.TblColRef;
-import org.apache.kylin.common.util.DateFormat;
 
 import com.google.common.collect.Range;
+import com.google.common.collect.Ranges;
 
 /**
  */
@@ -23,6 +23,9 @@ public class TsConditionExtractor {
     }
 
     private static Range<Long> extractTsConditionInternal(TupleFilter filter, TblColRef colRef) {
+        if (filter == null) {
+            return Ranges.all();
+        }
 
         if (filter instanceof LogicalTupleFilter) {
             if (filter.getOperator() == TupleFilter.FilterOperatorEnum.AND) {
@@ -41,6 +44,8 @@ public class TsConditionExtractor {
                 }
                 return ret.isEmpty() ? null : ret;
             } else {
+                //for conditions like date > DATE'2000-11-11' OR date < DATE '1999-01-01'
+                //we will use Ranges.all() rather than two ranges to represent them
                 return Ranges.all();
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
index 87ff26b..f9cea05 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
@@ -1,12 +1,14 @@
 package org.apache.kylin.storage.hybrid;
 
-import javax.annotation.Nullable;
-
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import com.google.common.collect.Ranges;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.RangeUtil;
 import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.model.TblColRef;
-import org.apache.kylin.metadata.realization.IRealization;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.realization.SQLDigestUtil;
 import org.apache.kylin.metadata.tuple.CompoundTupleIterator;
@@ -16,25 +18,27 @@ import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.StorageEngineFactory;
 import org.apache.kylin.storage.tuple.TupleInfo;
 
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Ranges;
+import javax.annotation.Nullable;
 
 /**
  */
 public class HybridStorageEngine implements IStorageEngine {
 
     private HybridInstance hybridInstance;
+    private IStorageEngine historicalStorageEngine;
+    private IStorageEngine realtimeStorageEngine;
 
     public HybridStorageEngine(HybridInstance hybridInstance) {
         this.hybridInstance = hybridInstance;
+        this.historicalStorageEngine = StorageEngineFactory.getStorageEngine(this.hybridInstance.getHistoryRealizationInstance());
+        this.realtimeStorageEngine = StorageEngineFactory.getStorageEngine(this.hybridInstance.getRealTimeRealizationInstance());
     }
 
     @Override
     public ITupleIterator search(final StorageContext context, final SQLDigest sqlDigest, final TupleInfo returnTupleInfo) {
 
         // search the historic realization
-        ITupleIterator iterator1 = searchRealization(hybridInstance.getHistoryRealizationInstance(), context, sqlDigest, returnTupleInfo);
+        ITupleIterator historicalDataIterator = this.historicalStorageEngine.search(context, sqlDigest, returnTupleInfo);
 
         String modelName = hybridInstance.getModelName();
         MetadataManager metaMgr = getMetadataManager();
@@ -42,28 +46,32 @@ public class HybridStorageEngine implements IStorageEngine {
 
         // if the model isn't partitioned, only query the history
         if (modelDesc.getPartitionDesc() == null || modelDesc.getPartitionDesc().getPartitionDateColumnRef() == null)
-            return iterator1;
+            return historicalDataIterator;
 
         TblColRef partitionColRef = modelDesc.getPartitionDesc().getPartitionDateColumnRef();
 
-        ITupleIterator iterator2 = SQLDigestUtil.appendTsFilterToExecute(sqlDigest, partitionColRef, //
+        ITupleIterator realtimeDataIterator = SQLDigestUtil.appendTsFilterToExecute(sqlDigest, partitionColRef, //
                 Ranges.atLeast(hybridInstance.getHistoryRealizationInstance().getDateRangeEnd()),//
                 new Function<Void, ITupleIterator>() {
                     @Nullable
                     @Override
                     public ITupleIterator apply(@Nullable Void input) {
-                        ITupleIterator iterator2 = searchRealization(hybridInstance.getRealTimeRealizationInstance(), context, sqlDigest, returnTupleInfo);
-                        return iterator2;
+                        return realtimeStorageEngine.search(context, sqlDigest, returnTupleInfo);
                     }
                 });
 
         // combine history and real-time tuple iterator
-        return new CompoundTupleIterator(Lists.newArrayList(iterator1, iterator2));
+        return new CompoundTupleIterator(Lists.newArrayList(historicalDataIterator, realtimeDataIterator));
+    }
+
+    @Override
+    public Range<Long> getVolatilePeriod() {
+        return RangeUtil.merge(historicalStorageEngine.getVolatilePeriod(), realtimeStorageEngine.getVolatilePeriod());
     }
 
-    private ITupleIterator searchRealization(IRealization realization, StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo) {
-        IStorageEngine storageEngine = StorageEngineFactory.getStorageEngine(realization, false);
-        return storageEngine.search(context, sqlDigest, returnTupleInfo);
+    @Override
+    public boolean isDynamic() {
+        return true;
     }
 
     private MetadataManager getMetadataManager() {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/bc426cc0/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java b/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
index 2a258df..fece398 100644
--- a/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/test/StorageTest.java
@@ -18,12 +18,7 @@
 
 package org.apache.kylin.storage.test;
 
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
+import com.google.common.collect.ImmutableList;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.util.HBaseMetadataTestCase;
 import org.apache.kylin.cube.CubeInstance;
@@ -41,7 +36,11 @@ import org.apache.kylin.storage.hbase.ScanOutOfLimitException;
 import org.apache.kylin.storage.tuple.TupleInfo;
 import org.junit.*;
 
-import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
 
 public class StorageTest extends HBaseMetadataTestCase {
 
@@ -64,7 +63,7 @@ public class StorageTest extends HBaseMetadataTestCase {
         CubeManager cubeMgr = CubeManager.getInstance(getTestConfig());
         cube = cubeMgr.getCube("TEST_KYLIN_CUBE_WITHOUT_SLR_EMPTY");
         Assert.assertNotNull(cube);
-        storageEngine = StorageEngineFactory.getStorageEngine(cube, false);
+        storageEngine = StorageEngineFactory.getStorageEngine(cube);
         String url = KylinConfig.getInstanceFromEnv().getStorageUrl();
         context = new StorageContext();
         context.setConnUrl(url);


[52/52] [abbrv] incubator-kylin git commit: Merge pull request #457 from janzhongi/awesome

Posted by ma...@apache.org.
Merge pull request #457 from janzhongi/awesome

merge latest version Gui(refactor model&cube)


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

Branch: refs/heads/0.8.0
Commit: 5092c48435cd646ab81912eb196acf5d60404a71
Parents: 4b50834 10dc6a2
Author: Zhong,Jian <ji...@ebay.com>
Authored: Wed Apr 22 15:04:08 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:40:22 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/common/util/StringUtil.java    |    8 +-
 .../org/apache/kylin/cube/CubeDescManager.java  |    5 +
 .../org/apache/kylin/cube/CubeInstance.java     |    7 +-
 .../test_case_data/sandbox/kylin.properties     |  196 +-
 .../kylin/invertedindex/IIDescManager.java      |    5 +
 .../apache/kylin/invertedindex/IIInstance.java  |    9 +-
 .../apache/kylin/metadata/MetadataManager.java  |   82 +-
 .../kylin/metadata/model/DataModelDesc.java     |   70 +
 .../kylin/metadata/project/ProjectInstance.java |   33 +-
 .../kylin/metadata/project/ProjectManager.java  |   43 +-
 .../metadata/realization/IRealization.java      |    3 +
 .../kylin/rest/controller/CubeController.java   |   79 +-
 .../kylin/rest/controller/ModelController.java  |  183 +-
 .../rest/controller/ModelDescController.java    |   61 +
 .../rest/controller/PerformanceController.java  |   20 +
 .../rest/controller/ProjectController.java      |    7 +-
 .../kylin/rest/filter/RequestLoggingFilter.java |   30 +
 .../apache/kylin/rest/model/Performance.java    |  127 +
 .../apache/kylin/rest/request/CubeRequest.java  |   29 +-
 .../apache/kylin/rest/request/ModelRequest.java |  109 +
 .../kylin/rest/response/HBaseResponse.java      |   26 +
 .../kylin/rest/security/AclEntityFactory.java   |    8 +
 .../apache/kylin/rest/service/CubeService.java  |   36 +-
 .../apache/kylin/rest/service/ModelService.java |  140 +
 .../kylin/rest/service/PerformanceService.java  |   17 +
 .../kylin/rest/service/ProjectService.java      |   10 +-
 .../apache/kylin/rest/service/QueryService.java |   16 +-
 .../kylin/rest/util/PerformanceMonitorTask.java |   27 +
 .../src/main/resources/applicationContext.xml   |    3 +
 server/src/main/resources/log4j.properties      |   10 +
 server/src/main/webapp/WEB-INF/web.xml          |   29 +-
 .../rest/controller/CubeControllerTest.java     |   11 +-
 .../kylin/rest/service/CacheServiceTest.java    |    2 +-
 .../kylin/rest/service/CubeServiceTest.java     |    4 +-
 .../kylin/storage/hybrid/HybridInstance.java    |   13 +-
 webapp/app/css/AdminLTE.css                     | 4600 ++++++++++--------
 webapp/app/index.html                           |   44 +-
 webapp/app/js/app.js                            |    2 +-
 webapp/app/js/controllers/cube.js               |  361 +-
 webapp/app/js/controllers/cubeAdvanceSetting.js |    5 +-
 webapp/app/js/controllers/cubeDimensions.js     |   83 +-
 webapp/app/js/controllers/cubeEdit.js           |  141 +-
 webapp/app/js/controllers/cubeFilter.js         |    2 +-
 webapp/app/js/controllers/cubeModel.js          |  122 +-
 webapp/app/js/controllers/cubeRefresh.js        |    2 +-
 webapp/app/js/controllers/cubeSchema.js         |  183 +-
 webapp/app/js/controllers/cubes.js              |   15 +-
 webapp/app/js/controllers/job.js                |    9 +-
 webapp/app/js/controllers/modelDimensions.js    |   73 +
 webapp/app/js/controllers/modelEdit.js          |  251 +
 webapp/app/js/controllers/modelMeasures.js      |   27 +
 webapp/app/js/controllers/modelRefresh.js       |   23 +
 webapp/app/js/controllers/modelSchema.js        |  248 +
 webapp/app/js/controllers/models.js             |  121 +
 webapp/app/js/controllers/page.js               |   13 +-
 webapp/app/js/controllers/projectMeta.js        |   68 +-
 webapp/app/js/controllers/projects.js           |    2 +-
 webapp/app/js/controllers/query.js              |    6 +-
 .../js/directives/kylin_abn_tree_directive.js   |  496 ++
 webapp/app/js/model/cubeDescModel.js            |    1 +
 webapp/app/js/model/cubeListModel.js            |    7 +-
 webapp/app/js/model/cubesManager.js             |    4 +
 webapp/app/js/model/jobListModel.js             |    4 +
 webapp/app/js/model/metaModel.js                |  181 +-
 webapp/app/js/model/modelConfig.js              |   26 +
 webapp/app/js/model/modelsManager.js            |  178 +
 webapp/app/js/model/projectModel.js             |   27 +-
 webapp/app/js/model/tableModel.js               |   90 +-
 webapp/app/js/services/message.js               |    2 +-
 webapp/app/js/services/model.js                 |    2 +-
 webapp/app/js/services/models.js                |   26 +
 webapp/app/js/services/query.js                 |    2 +-
 webapp/app/js/services/tree.js                  |  106 +-
 webapp/app/js/services/users.js                 |    6 +-
 webapp/app/less/app.less                        |   24 +-
 webapp/app/less/component.less                  |  137 +
 .../cubeDesigner/advanced_settings.html         |  262 +-
 .../app/partials/cubeDesigner/data_model.html   |  199 -
 .../app/partials/cubeDesigner/dimensions.html   |  560 +--
 webapp/app/partials/cubeDesigner/info.html      |  115 +-
 webapp/app/partials/cubeDesigner/measures.html  |  121 +-
 webapp/app/partials/cubeDesigner/overview.html  |   14 +-
 webapp/app/partials/cubes/cube_detail.html      |  110 +-
 webapp/app/partials/cubes/cube_json_edit.html   |   15 -
 webapp/app/partials/cubes/cube_schema.html      |   13 +-
 webapp/app/partials/cubes/cubes.html            |   11 +-
 webapp/app/partials/header.html                 |   26 +-
 webapp/app/partials/jobs/job_merge.html         |   16 +-
 webapp/app/partials/jobs/job_refresh.html       |   12 +-
 webapp/app/partials/jobs/job_submit.html        |   10 +-
 webapp/app/partials/jobs/jobs.html              |   13 +-
 webapp/app/partials/login.html                  |    2 +-
 .../modelDesigner/conditions_settings.html      |  143 +
 .../app/partials/modelDesigner/data_model.html  |  203 +
 .../modelDesigner/model_dimensions.html         |   98 +
 .../app/partials/modelDesigner/model_info.html  |   99 +
 .../partials/modelDesigner/model_measures.html  |   54 +
 webapp/app/partials/models/model_detail.html    |   63 +
 webapp/app/partials/models/model_edit.html      |   33 +
 webapp/app/partials/models/model_schema.html    |   94 +
 webapp/app/partials/models/models.html          |   60 +
 webapp/app/partials/models/models_tree.html     |   46 +
 .../partials/projects/project_table_tree.html   |   17 +-
 webapp/app/partials/query/query.html            |    9 -
 webapp/app/partials/query/query_detail.html     |   15 +-
 webapp/app/partials/tables/source_metadata.html |  185 -
 .../app/partials/tables/source_table_tree.html  |   19 +-
 webapp/app/partials/tables/table_detail.html    |  184 +
 webapp/app/routes.json                          |   51 +-
 webapp/bower.json                               |    7 +-
 webapp/grunt.json                               |    1 +
 111 files changed, 8265 insertions(+), 3793 deletions(-)
----------------------------------------------------------------------



[25/52] [abbrv] incubator-kylin git commit: new model GUI

Posted by ma...@apache.org.
new model GUI


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

Branch: refs/heads/0.8.0
Commit: a2f4d320b6752333d0a7dafce064101943a7b757
Parents: 6fed6cb
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 17 18:10:37 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:27 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/common/util/StringUtil.java    |   8 +-
 .../apache/kylin/metadata/MetadataManager.java  |  30 +-
 .../kylin/metadata/project/ProjectInstance.java |  36 +-
 .../kylin/metadata/project/ProjectManager.java  |  43 ++-
 .../kylin/rest/controller/ModelController.java  |   2 +-
 .../apache/kylin/rest/service/ModelService.java |  18 +-
 .../apache/kylin/rest/service/QueryService.java |  16 +-
 webapp/app/js/controllers/cube.js               |   4 +-
 webapp/app/js/controllers/cubeModel.js          |   4 +-
 webapp/app/js/controllers/modelDimensions.js    | 370 +------------------
 webapp/app/js/controllers/modelEdit.js          |  87 +++--
 webapp/app/js/controllers/modelSchema.js        |  66 +---
 webapp/app/js/controllers/projectMeta.js        |   2 -
 webapp/app/js/model/metaModel.js                | 100 ++---
 .../modelDesigner/conditions_settings.html      | 127 +++++++
 .../app/partials/modelDesigner/incremental.html |  94 -----
 .../modelDesigner/model_dimensions.html         | 339 +++--------------
 .../app/partials/modelDesigner/model_info.html  |   6 +-
 .../partials/modelDesigner/model_measures.html  | 156 +-------
 webapp/app/partials/models/model_edit.html      |   3 +-
 webapp/app/partials/models/model_schema.html    |  12 +-
 21 files changed, 455 insertions(+), 1068 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/StringUtil.java b/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
index 2d7b170..f4aed14 100644
--- a/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
@@ -50,9 +50,11 @@ public class StringUtil {
     }
 
     public static void toUpperCaseArray(String[] source, String[] target) {
-        for (int i = 0; i < source.length; i++) {
-            if (source[i] != null) {
-                target[i] = source[i].toUpperCase();
+        if(source!=null) {
+            for (int i = 0; i < source.length; i++) {
+                if (source[i] != null) {
+                    target[i] = source[i].toUpperCase();
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index 9d489e2..ea03933 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -27,6 +27,8 @@ import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -253,7 +255,6 @@ public class MetadataManager {
         ResourceStore store = getStore();
         TableDesc t = store.getResource(path, TableDesc.class, TABLE_SERIALIZER);
         if (t == null) {
-            logger.error("Didn't load table at " + path);
             return null;
         }
         t.init();
@@ -283,7 +284,24 @@ public class MetadataManager {
     }
 
     public List<DataModelDesc> getModels() {
-        return new ArrayList<DataModelDesc>(dataModelDescMap.values());
+        return new ArrayList<>(dataModelDescMap.values());
+    }
+
+    public List<DataModelDesc> getModels(String projectName){
+        ProjectInstance projectInstance =  ProjectManager.getInstance(config).getProject(projectName);
+        HashSet<DataModelDesc> ret = new HashSet<>();
+        if (projectInstance != null) {
+            for (String modelName : projectInstance.getModels()) {
+                DataModelDesc model = getDataModelDesc(modelName);
+                if (null != model) {
+                    ret.add(model);
+                } else {
+                    logger.error("Failed to load model" + modelName);
+                }
+            }
+        }
+
+        return new ArrayList<>(ret);
     }
 
 
@@ -322,12 +340,12 @@ public class MetadataManager {
         }
     }
 
-    public DataModelDesc createDataModelDesc(DataModelDesc dataModelDesc) throws IOException {
-        String name = dataModelDesc.getName();
+    public DataModelDesc createDataModelDesc(DataModelDesc desc,String projectName,String owner) throws IOException {
+        String name = desc.getName();
         if (dataModelDescMap.containsKey(name))
             throw new IllegalArgumentException("DataModelDesc '" + name + "' already exists");
-
-        return saveDataModelDesc(dataModelDesc);
+        ProjectManager.getInstance(config).updateModelToProject(name,projectName,owner);
+        return saveDataModelDesc(desc);
     }
 
     public DataModelDesc updateDataModelDesc(DataModelDesc desc) throws IOException {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
index 096d2ac..387f735 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
@@ -68,6 +68,9 @@ public class ProjectInstance extends RootPersistentEntity {
     @JsonProperty("realizations")
     private List<RealizationEntry> realizationEntries;
 
+    @JsonProperty("models")
+    private List<String> models;
+
     public String getResourcePath() {
         return concatResourcePath(name);
     }
@@ -83,7 +86,7 @@ public class ProjectInstance extends RootPersistentEntity {
         return project.toUpperCase();
     }
 
-    public static ProjectInstance create(String name, String owner, String description, List<RealizationEntry> realizationEntries) {
+    public static ProjectInstance create(String name, String owner, String description, List<RealizationEntry> realizationEntries,List<String> models) {
         ProjectInstance projectInstance = new ProjectInstance();
 
         projectInstance.updateRandomUuid();
@@ -96,7 +99,10 @@ public class ProjectInstance extends RootPersistentEntity {
             projectInstance.setRealizationEntries(realizationEntries);
         else
             projectInstance.setRealizationEntries(Lists.<RealizationEntry> newArrayList());
-
+        if (models != null)
+            projectInstance.setModels(models);
+        else
+            projectInstance.setModels(new ArrayList<String>());
         return projectInstance;
     }
 
@@ -231,6 +237,32 @@ public class ProjectInstance extends RootPersistentEntity {
         this.realizationEntries = entries;
     }
 
+    public List<String> getModels() {
+        return models;
+    }
+
+    public boolean containsModel(String modelName) {
+        modelName = modelName.toUpperCase();
+        return models!=null&&models.contains(modelName);
+    }
+
+    public void setModels(List<String> models) { this.models = models; }
+
+    public void addModel(String modelName) {
+        modelName = modelName.toUpperCase();
+        if(this.getModels()==null){
+            this.setModels(new ArrayList<String>());
+        }
+        this.getModels().add(modelName);
+    }
+
+    public void removeModel(String modelName){
+        modelName = modelName.toUpperCase();
+        if(this.getModels()!=null) {
+            this.getModels().remove(modelName);
+        }
+    }
+
     public void init() {
         if (name == null)
             name = ProjectInstance.DEFAULT_PROJECT_NAME;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index 33d0867..fb2d298 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -164,7 +164,7 @@ public class ProjectManager {
 
         ProjectInstance currentProject = getProject(projectName);
         if (currentProject == null) {
-            currentProject = ProjectInstance.create(projectName, owner, description, null);
+            currentProject = ProjectInstance.create(projectName, owner, description, null,null);
         } else {
             throw new IllegalStateException("The project named " + projectName + "already exists");
         }
@@ -220,6 +220,36 @@ public class ProjectManager {
         }
     }
 
+    public boolean isModelInProject(String projectName, String modelName) {
+        return this.getProject(projectName).containsModel(modelName);
+    }
+
+    public ProjectInstance updateModelToProject(String modelName, String newProjectName, String owner) throws IOException {
+        removeModelFromProjects(modelName);
+
+        return addModelToProject(modelName, newProjectName, owner);
+    }
+
+    public void removeModelFromProjects(String modelName) throws IOException {
+        for (ProjectInstance projectInstance : findProjects(modelName)) {
+            projectInstance.removeModel(modelName);
+
+            saveResource(projectInstance);
+        }
+    }
+
+    private ProjectInstance addModelToProject(String modelName, String project, String user) throws IOException {
+        String newProjectName = ProjectInstance.getNormalizedProjectName(project);
+        ProjectInstance newProject = getProject(newProjectName);
+        if (newProject == null) {
+            newProject = this.createProject(newProjectName, user, "This is a project automatically added when adding model " + modelName);
+        }
+        newProject.addModel(modelName);
+        saveResource(newProject);
+
+        return newProject;
+    }
+
     public ProjectInstance moveRealizationToProject(RealizationType type, String realizationName, String newProjectName, String owner) throws IOException {
         removeRealizationsFromProjects(type, realizationName);
         return addRealizationToProject(type, realizationName, newProjectName, owner);
@@ -288,6 +318,17 @@ public class ProjectManager {
         return result;
     }
 
+    private List<ProjectInstance> findProjects(String modelName) {
+        List<ProjectInstance> projects = new ArrayList<ProjectInstance>();
+        for (ProjectInstance projectInstance : projectMap.values()) {
+            if (projectInstance.containsModel(modelName)) {
+                projects.add(projectInstance);
+            }
+        }
+
+        return projects;
+    }
+
     public List<TableDesc> listDefinedTables(String project) throws IOException {
         return l2Cache.listDefinedTables(norm(project));
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 97a5d32..ce53474 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -123,7 +123,7 @@ public class ModelController extends BasicController {
 
         String descData = JsonUtil.writeValueAsIndentString(modelDesc);
         modelRequest.setModelDescData(descData);
-
+        modelRequest.setSuccessful(true);
         return modelRequest;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 093efe3..e423c37 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.rest.service;
 
 
-import org.apache.kylin.job.exception.JobException;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.constant.Constant;
@@ -29,10 +28,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
-import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -56,9 +55,8 @@ public class ModelService extends BasicService {
         if (null == project) {
             models = getMetadataManager().getModels();
         } else {
-            //TO-DO
-//            models = listAllModels(projectName);
-            models=Collections.emptyList();
+            models = getMetadataManager().getModels(projectName);
+            project.getModels();
         }
 
         List<DataModelDesc> filterModels = new ArrayList();
@@ -97,9 +95,10 @@ public class ModelService extends BasicService {
             throw new InternalErrorException("The model named " + desc.getName() + " already exists");
         }
         DataModelDesc createdDesc = null;
-        createdDesc = getMetadataManager().createDataModelDesc(desc);
-//        ProjectInstance project = getProjectManager().getProject(projectName);
-//        accessService.inherit(createdDesc, project);
+        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+        createdDesc = getMetadataManager().createDataModelDesc(desc,projectName,owner);
+        ProjectInstance project = getProjectManager().getProject(projectName);
+        accessService.inherit(desc, project);
         return createdDesc;
     }
 
@@ -108,7 +107,8 @@ public class ModelService extends BasicService {
     public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
         DataModelDesc existingModel = getMetadataManager().getDataModelDesc(desc.getName());
         if (existingModel == null) {
-            getMetadataManager().createDataModelDesc(desc);
+            String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+            getMetadataManager().createDataModelDesc(desc,newProjectName,owner);
         } else {
             getMetadataManager().updateDataModelDesc(desc);
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
index 027202d..8f81d2d 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
@@ -28,16 +28,7 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javax.sql.DataSource;
 
@@ -60,6 +51,7 @@ import org.apache.kylin.rest.request.SQLRequest;
 import org.apache.kylin.rest.response.SQLResponse;
 import org.apache.kylin.rest.util.QueryUtil;
 import org.apache.kylin.rest.util.Serializer;
+import org.h2.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.AccessDeniedException;
@@ -280,7 +272,9 @@ public class QueryService extends BasicService {
         Connection conn = null;
         ResultSet columnMeta = null;
         List<TableMeta> tableMetas = null;
-
+        if(StringUtils.isNullOrEmpty(project)){
+            return Collections.emptyList();
+        }
         try {
             DataSource dataSource = getOLAPDataSource(project);
             conn = dataSource.getConnection();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 607706d..2765a45 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,12 +18,12 @@
 
 'use strict';
 
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, CubeGraphService, UserService,SweetAlert) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert) {
     $scope.newAccess = null;
     $scope.state = {jsonEdit: false};
 
     $scope.buildGraph = function (cube) {
-        CubeGraphService.buildTree(cube);
+       GraphService.buildTree(cube);
     };
 
     $scope.getCubeSql = function (cube) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index fc2cca8..cfe0f1c 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,13 +18,13 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,CubeGraphService,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,GraphService,$log) {
 
     //copy model for show Json in model tab list
     $scope.modelJson = angular.copy($scope.model);
 
     $scope.buildGraph = function (model) {
-        CubeGraphService.buildTree(model);
+        GraphService.buildTree(model);
     };
 
     $scope.cubeConfig = cubeConfig;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDimensions.js b/webapp/app/js/controllers/modelDimensions.js
index aa197e6..c89e6a6 100644
--- a/webapp/app/js/controllers/modelDimensions.js
+++ b/webapp/app/js/controllers/modelDimensions.js
@@ -28,375 +28,45 @@ KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel) {
 
     // 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.
-     * 2. hierarchy dimension: column array, the array index is the hierarchy level.
-     * 3. derived dimension: derived columns array.
-     * TODO new cube schema change
-     */
-    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.hierarchy) {
-            referredCols.push(dim.column);
-        }
-
-        return referredCols;
-    };
+    $scope.dimensions=[];
 
     // Dump available columns plus column table name, whether is from lookup table.
     $scope.initColumns = function () {
         var factTable = $scope.model.fact_table;
 
-        // At first dump the columns of fact table.
-        var cols = $scope.getColumnsByTable(factTable);
-
-        // Initialize selected available.
-        var factAvailable = {};
-        var factSelectAvailable = {};
-
-        for (var i = 0; i < cols.length; i++) {
-            cols[i].table = factTable;
-            cols[i].isLookup = false;
-
-            factAvailable[cols[i].name] = cols[i];
-
-            // Default not selected and not disabled.
-            factSelectAvailable[cols[i].name] = {selected: false, disabled: false};
-        }
-
-        $scope.availableColumns[factTable] = factAvailable;
-        $scope.selectedColumns[factTable] = factSelectAvailable;
-        $scope.availableTables.push(factTable);
-
-        // Then dump each lookup tables.
+        $scope.availableTables.push($scope.model.fact_table);
         var lookups = $scope.model.lookups;
-
         for (var j = 0; j < lookups.length; j++) {
-            var cols2 = $scope.getColumnsByTable(lookups[j].table);
-
-            // Initialize selected available.
-            var lookupAvailable = {};
-            var lookupSelectAvailable = {};
-
-            for (var k = 0; k < cols2.length; k++) {
-                cols2[k].table = lookups[j].table;
-                cols2[k].isLookup = true;
-
-                lookupAvailable[cols2[k].name] = cols2[k];
-
-                // Default not selected and not disabled.
-                lookupSelectAvailable[cols2[k].name] = {selected: false, disabled: false};
-            }
-
-            $scope.availableColumns[lookups[j].table] = lookupAvailable;
-            $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
             $scope.availableTables.push(lookups[j].table);
         }
-    };
 
-    // Check column status: selected or disabled based on current cube dimensions.
-    $scope.initColumnStatus = function () {
-        angular.forEach($scope.model.dimensions, function (dim) {
-            var cols = dimCols(dim);
-
-            angular.forEach(cols, function (colName) {
-                $scope.selectedColumns[dim.table][colName] = {selected: true, disabled: true};
-            });
-        });
-    };
+//        init dimension only when dimen
+//        if(!$scope.model.dimensions.length){
 
-    // Initialize data for columns widget in auto-gen when add/edit cube.
-    if ($scope.state.mode == 'edit') {
-        $scope.initColumns();
-    }
+            for(var i = 0;i<$scope.availableTables.length;i++){
+                var tableInUse = _.some($scope.model.dimensions,function(item){
+                    return item.table == $scope.availableTables[i];
+                });
 
-    // Initialize params for add/edit dimension.
-    $scope.dimState = {
-        editing: false,
-        editingIndex: -1,
-        filter: ''
-    };
-
-    // Init the dimension, dimension name default as the column key. TODO new cube schema change.
-    var Dimension = function (table, selectedCols, dimType) {
-        var origin = {name: '', table: table,hierarchy:false,derived:null,column:null};
-
-        switch (dimType) {
-            case 'normal':
-                // Default name as 1st column name.
-                if (table && selectedCols.length) {
-                    origin.name = table + '.' + selectedCols[0];
-                }
-
-                origin.column = selectedCols;
-                break;
-
-            case 'derived':
-                if (table && selectedCols.length) {
-                    origin.name = table + '_derived';
-                }
-
-                origin.derived = selectedCols;
-                break;
-
-            case 'hierarchy':
-                if (table && selectedCols.length) {
-                    origin.name = table + '_hierarchy';
+                if(!tableInUse){
+                    $scope.model.dimensions.push(new Dimension($scope.availableTables[i]));
                 }
-
-                origin.hierarchy = true;
-                origin.column = selectedCols;
-                break;
-        }
-
-        return origin;
-    };
-
-    // Since old schema may be both derived and hierarchy. TODO new cube schema change.
-    $scope.getDimType = function (dim) {
-        var types = [];
-
-        if (dim.derived && dim.derived.length) {
-            types.push('derived');
-        }
-
-        if (dim.hierarchy && dim.column.length) {
-            types.push('hierarchy');
-        }
-
-        if (!types.length) {
-            types.push('normal');
-        }
-
-        return types;
-    };
-
-    var dimList = $scope.model.dimensions;
-
-    // Open add/edit dimension modal.
-    $scope.openDimModal = function (dimType) {
-        var modalInstance = $modal.open({
-            templateUrl: 'addEditDimension.html',
-            controller: cubeDimModalCtrl,
-            backdrop: 'static',
-            scope: $scope,
-            resolve: {
-                dimType: function () {
-                    // For old schema compatibility, convert into array here. TODO new cube schema change.
-                    return angular.isArray(dimType) ? dimType : [dimType];
-                }
-            }
-        });
-
-        modalInstance.result.then(function () {
-            if (!$scope.dimState.editing) {
-                $scope.doneAddDim();
-            } else {
-                $scope.doneEditDim();
             }
+//        }
 
-        }, function () {
-            $scope.cancelDim();
-        });
-    };
-
-    // Controller for cube dimension add/edit modal.
-    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType) {
-        $scope.dimType = dimType;
-
-        $scope.ok = function () {
-            $modalInstance.close();
-        };
-
-        $scope.cancel = function () {
-            $modalInstance.dismiss('cancel');
-        };
-    };
-
-    $scope.addDim = function (dimType) {
-        $scope.newDimension = Dimension('', [], dimType);
-
-        $scope.openDimModal(dimType);
-    };
-
-    $scope.editDim = function (dim) {
-        $scope.dimState.editingIndex = dimList.indexOf(dim);
-        $scope.dimState.editing = true;
-
-        // Make a copy of model will be editing.
-        $scope.newDimension = angular.copy(dim);
-
-        $scope.openDimModal($scope.getDimType(dim));
-    };
-
-    $scope.doneAddDim = function () {
-        // Push new dimension which bound user input data.
-        dimList.push(angular.copy($scope.newDimension));
-
-        $scope.resetParams();
-    };
-
-    $scope.doneEditDim = function () {
-        // Copy edited model to destination model.
-        angular.copy($scope.newDimension, dimList[$scope.dimState.editingIndex]);
-
-        $scope.resetParams();
-    };
-
-    $scope.cancelDim = function () {
-        $scope.resetParams();
-    };
-
-    $scope.removeDim = function (dim) {
-        dimList.splice(dimList.indexOf(dim), 1);
-    };
-
-    $scope.resetParams = function () {
-        $scope.dimState.editing = false;
-        $scope.dimState.editingIndex = -1;
-
-        $scope.newDimension = {};
-    };
-
-    // Open auto-gen dimension modal.
-    $scope.openAutoGenModal = function (dimType) {
-        // Init columns status.
-        $scope.initColumnStatus();
-
-        var modalInstance = $modal.open({
-            templateUrl: 'autoGenDimension.html',
-            controller: cubeAutoGenDimModalCtrl,
-            backdrop: 'static',
-            scope: $scope
-        });
-
-        modalInstance.result.then(function () {
-            $scope.autoGenDims();
-        }, function () {
-            $scope.resetGenDims();
-        });
-    };
-
-    // Controller for cube dimension auto-gen modal.
-    var cubeAutoGenDimModalCtrl = function ($scope, $modalInstance) {
-        $scope.ok = function () {
-            $modalInstance.close();
-        };
-
-        $scope.cancel = function () {
-            $modalInstance.dismiss('cancel');
-        };
-    };
-
-    // Helper func to get the selected status in auto gen.
-    $scope.getSelectedCols = function () {
-        var selectedCols = {};
-
-        angular.forEach($scope.selectedColumns, function (value, table) {
-            angular.forEach(value, function (status, colName) {
-                if (status.selected && !status.disabled) {
-                    if (!selectedCols[table]) {
-                        selectedCols[table] = [];
-                    }
-
-                    selectedCols[table].push(colName);
-                }
-            });
-        });
-
-        return selectedCols;
-    };
-
-    // Auto generate dimensions.
-    $scope.autoGenDims = function () {
-        var selectedCols = $scope.getSelectedCols();
-
-        angular.forEach(selectedCols, function (cols, table) {
-            if ($scope.model.fact_table == table) {
-                // Fact table: for each selected column, create one normal dimension.
-                for (var i = 0; i < cols.length; i++) {
-                    dimList.push(Dimension(table, [cols[i]], 'normal'));
-                }
-            } else {
-                // Per lookup table, create one derived dimension for all its selected columns;
-                if (cols.length) {
-                    dimList.push(Dimension(table, cols, 'derived'));
-                }
-            }
-        });
-    };
+        // At first dump the columns of fact table.
+//        var cols = $scope.getColumnsByTable(factTable);
 
-    // Just reset the selected status of columns.
-    $scope.resetGenDims = function () {
-        var selectedCols = $scope.getSelectedCols();
 
-        angular.forEach(selectedCols, function (cols, table) {
-            for (var i = 0; i < cols.length; i++) {
-                $scope.selectedColumns[table][cols[i]].selected = false;
-            }
-        });
     };
 
-    // Check whether there is column conflicts.
-    $scope.dimConflicts = [];
-
-    $scope.$watch('cubeMetaFrame.dimensions', function (newVal, oldVal) {
-        if (!newVal || !newVal.length) {
-            return;
-        }
-
-        var referredCols = {};
-
-        angular.forEach(newVal, function (curDim) {
-            var table = curDim.table;
-            var cols = dimCols(curDim);
-
-            for (var i = 0; i < cols.length; i++) {
-                var key = table + '.' + cols[i];
-
-                if (!referredCols[key]) {
-                    referredCols[key] = [];
-                }
-
-                referredCols[key].push({id: curDim.id, name: curDim.name});
-            }
-        });
-
-        var conflicts = [];
-
-        angular.forEach(referredCols, function (dims, key) {
-            if (dims.length > 1) {
-                // More than 1 dimensions has referred this column.
-                var colInfo = key.split('.');
-                conflicts.push({table: colInfo[0], column: colInfo[1], dims: dims});
-            }
-        });
-
-        $scope.dimConflicts = conflicts;
-    }, true);
-
-
+    var Dimension = function(table){
+        this.table = table;
+        this.columns = [];
+    }
 
+    // Initialize data for columns widget in auto-gen when add/edit cube.
     if ($scope.state.mode == 'edit') {
-        $scope.$on('$destroy', function () {
-           // $scope.dimensionsAdapter();
-            // Emit dimensions edit event in order to re-generate row key.
-            $scope.$emit('DimensionsEdited');
-        });
-    }
+        $scope.initColumns();
+    };
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 2741d2c..38290f7 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -19,8 +19,7 @@
 'use strict';
 
 
-KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel) {
-    $scope.cubeConfig = cubeConfig;
+KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, ModelService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel,ProjectService,ProjectModel) {
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
@@ -57,12 +56,16 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
     // ~ Define data
     $scope.state = {
-        "modelSchema": ""
+        "modelSchema": "",
+        mode:'edit',
+        modelName: $scope.routeParams.modelName,
+        project:$scope.projectModel.selectedProject
     };
 
     // ~ init
     if ($scope.isEdit = !!$routeParams.modelName) {
-        ModelDescService.get({model_name: $routeParams.modelName}, function (model) {
+        var modelName = $routeParams.modelName;
+        ModelDescService.get({model_name: modelName}, function (model) {
                     if (model) {
                         $scope.model = model;
                         //use
@@ -74,19 +77,43 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         }
                     }
                 });
+        //init project
+            ProjectService.list({}, function (projects) {
+                $scope.projects = projects;
+                if (modelName) {
+                    var projName = null;
+                    if(ProjectModel.getSelectedProject()){
+                        projName=ProjectModel.getSelectedProject();
+                    }else{
+                        angular.forEach($scope.projects, function (project, index) {
+                            angular.forEach(project.models, function (unit, index) {
+                                if (!projName && unit === modelName) {
+                                    projName = project.name;
+                                }
+                            });
+                        });
+                    }
 
-    } else {
-        $scope.model = MetaModel.createNew();;
-    }
+                    if(!ProjectModel.getSelectedProject()){
+                        ProjectModel.setSelectedProject(projName);
+                        TableModel.aceSrcTbLoaded();
+                    }
 
-    // ~ public methods
-    $scope.aceChanged = function () {
-    };
+                    $scope.state.project = projName;
+                }
+
+                angular.forEach($scope.projects, function (project, index) {
+                    $scope.listAccess(project, 'ProjectInstance');
+                });
+            });
 
-    $scope.aceLoaded = function(){
-    };
 
-    $scope.prepareCube = function () {
+    } else {
+        MetaModel.initModel();
+        $scope.model = MetaModel.getMetaModel();
+    }
+
+    $scope.prepareModel = function () {
         // generate column family
 
         if ($scope.model.partition_desc.partition_date_column&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
@@ -102,22 +129,22 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
         }
         $scope.state.modelSchema = angular.toJson($scope.model, true);
-        $scope.state.project = $scope.projectModel.selectedProject;
+//        $scope.state.project = $scope.projectModel.selectedProject;
 
     };
 
-    $scope.cubeResultTmpl = function (notification) {
+    $scope.modelResultTmpl = function (notification) {
         // Get the static notification template.
-        var tmpl = notification.type == 'success' ? 'cubeResultSuccess.html' : 'cubeResultError.html';
+        var tmpl = notification.type == 'success' ? 'modelResultSuccess.html' : 'modelResultError.html';
         return $interpolate($templateCache.get(tmpl))(notification);
     };
 
     $scope.saveModel = function (design_form) {
 
         try {
-            angular.fromJson($scope.state.cubeSchema);
+            angular.fromJson($scope.state.modelSchema);
         } catch (e) {
-            SweetAlert.swal('Oops...', 'Invalid cube json format..', 'error');
+            SweetAlert.swal('Oops...', 'Invalid model json format..', 'error');
             return;
         }
 
@@ -134,10 +161,10 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                 loadingRequest.show();
 
                 if ($scope.isEdit) {
-                    CubeService.update({}, {modelDescData:$scope.state.modelSchema, modelName: $routeParams.modelName, project: $scope.state.project}, function (request) {
+                    ModelService.update({}, {modelDescData:$scope.state.modelSchema, modelName: $routeParams.modelName, project: $scope.state.project}, function (request) {
                         if (request.successful) {
                             $scope.state.modelSchema = request.modelSchema;
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':'Updated the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
 
                             if (design_form) {
                                 design_form.$invalid = true;
@@ -146,7 +173,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                             $scope.saveModelRollBack();
                                 var message =request.message;
                                 var msg = !!(message) ? message : 'Failed to take action.';
-                                MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                                MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         }
                         //end loading
                         loadingRequest.hide();
@@ -156,23 +183,23 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         if(e.data&& e.data.exception){
                             var message =e.data.exception;
                             var msg = !!(message) ? message : 'Failed to take action.';
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         } else {
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         }
                         loadingRequest.hide();
                     });
                 } else {
-                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
+                    ModelService.save({}, {modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
                         if(request.successful) {
                             $scope.state.modelSchema = request.modelSchema;
 
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Created the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':'Created the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
                         } else {
                             $scope.saveModelRollBack();
                             var message =request.message;
                             var msg = !!(message) ? message : 'Failed to take action.';
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         }
 
                         //end loading
@@ -183,9 +210,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         if (e.data && e.data.exception) {
                             var message =e.data.exception;
                             var msg = !!(message) ? message : 'Failed to take action.';
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         } else {
-                            MessageService.sendMsg($scope.cubeResultTmpl({'text':"Failed to take action.",'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                            MessageService.sendMsg($scope.modelResultTmpl({'text':"Failed to take action.",'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
                         }
                         //end loading
                         loadingRequest.hide();
@@ -207,6 +234,10 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         }
     };
 
+    $scope.removeTableDimensions = function(tableIndex){
+        $scope.model.dimensions.splice(tableIndex,1);
+    }
+
     $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
         if(!newValue){
             return;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 112507e..198a9a3 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -32,7 +32,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false},
         {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false},
         {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false},
-        {title: 'Refresh Setting', src: 'partials/modelDesigner/incremental.html', isComplete: false}
+        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false}
     ];
 
     $scope.curStep = $scope.wizardSteps[0];
@@ -58,70 +58,6 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         return $scope.userService.hasRole('ROLE_ADMIN') || $scope.hasPermission(project,$scope.permissions.ADMINISTRATION.mask);
     };
 
-    $scope.addNewMeasure = function (measure) {
-        $scope.newMeasure = (!!measure)? measure:CubeDescModel.createMeasure();
-    };
-
-    $scope.clearNewMeasure = function () {
-        $scope.newMeasure = null;
-    };
-
-    $scope.saveNewMeasure = function () {
-        if ($scope.cubeMetaFrame.measures.indexOf($scope.newMeasure) === -1) {
-            $scope.cubeMetaFrame.measures.push($scope.newMeasure);
-        }
-        $scope.newMeasure = null;
-    };
-
-    //map right return type for param
-    $scope.measureReturnTypeUpdate = function(){
-        if($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
-
-
-            switch($scope.newMeasure.function.expression){
-                case "SUM":
-                    if(colType==="smallint"||colType==="int"||colType==="bigint"){
-                        $scope.newMeasure.function.returntype= 'bigint';
-                    }else{
-                        $scope.newMeasure.function.returntype= 'decimal';
-                    }
-                    break;
-                case "MIN":
-                case "MAX":
-                    $scope.newMeasure.function.returntype = colType;
-                    break;
-                case "COUNT":
-                    $scope.newMeasure.function.returntype = "bigint";
-                    break;
-                default:
-                    $scope.newMeasure.function.returntype = "";
-                    break;
-            }
-        }
-    }
-
-    $scope.addNewRowkeyColumn = function () {
-        $scope.cubeMetaFrame.rowkey.rowkey_columns.push({
-            "column": "",
-            "length": 0,
-            "dictionary": "true",
-            "mandatory": false
-        });
-    };
-
-    $scope.addNewAggregationGroup = function () {
-        $scope.cubeMetaFrame.rowkey.aggregation_groups.push([]);
-    };
-
-    $scope.refreshAggregationGroup = function (list, index, aggregation_groups) {
-        if (aggregation_groups) {
-            list[index] = aggregation_groups;
-        }
-    };
-
     $scope.removeElement = function (arr, element) {
         var index = arr.indexOf(element);
         if (index > -1) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/projectMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projectMeta.js b/webapp/app/js/controllers/projectMeta.js
index d1ba98a..aa35d03 100644
--- a/webapp/app/js/controllers/projectMeta.js
+++ b/webapp/app/js/controllers/projectMeta.js
@@ -78,9 +78,7 @@ KylinApp
 
 
         $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
-            if(newValue){
                 $scope.projectMetaLoad();
-            }
         });
 
         $scope.trimType = function(typeName){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 74714d9..28e9f69 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -21,58 +21,74 @@
  */
 KylinApp.service('MetaModel',function(){
 
-    var _this = this;
     //data model when edit model
-    this.name=null;
-    this.fact_table=null;
-    this.lookups=[];
-    this.filter_condition=null;
-    this.capacity=null;
-    this.dimensions=[];
-    this.metrics=[];
-    this.partition_desc = {
-        "partition_date_column" : '',
-        "partition_date_start" : 0,
-        "partition_type" : 'APPEND'
+    this.model={
+        name: null,
+        fact_table: null,
+        lookups: [],
+        filter_condition:null,
+        capacity:null,
+        dimensions:[],
+        metrics:[],
+        "partition_desc" : {
+            "partition_date_column" : '',
+            "partition_date_start" : 0,
+            "partition_type" : 'APPEND'
+        },
+        last_modified:0
     };
-    this.last_modified=0;
+
 
     this.setMetaModel =function(model){
-        _this.name = model.name;
-        _this.fact_table = model.fact_table;
-        _this.lookups =model.lookups;
-        _this.filter_condition = model.filter_condition;
-        _this.capacity = model.capacity;
-        _this.partition_desc = model.partition_desc;
-        _this.last_modified = model.last_modified;
-        _this.metrics  = model.metrics;
-        _this.dimensions = model.dimensions;
+        var _model = {};
+        _model.name = model.name;
+        _model.fact_table = model.fact_table;
+        _model.lookups =model.lookups;
+        _model.filter_condition = model.filter_condition;
+        _model.capacity = model.capacity;
+        _model.dimensions = model.dimensions;
+        _model.metrics = model.metrics;
+        _model.partition_desc = model.partition_desc;
+        _model.last_modified = model.last_modified;
+        this.model = _model;
+    };
+
+    this.initModel = function(){
+        this.model = this.createNew();
+    }
+
+    this.getMetaModel = function(){
+        return this.model;
+    };
+
+    this.setFactTable = function(fact_table) {
+        this.model.fact_table =fact_table;
     };
 
 
     this.converDateToGMT = function(){
-        if(this.partition_desc&&this.partition_desc.partition_date_start){
-            this.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+        if(this.model.partition_desc&&this.model.partition_desc.partition_date_start){
+            this.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
         }
     };
     //
     this.createNew = function () {
-            var metaModel = {
-                name: '',
-                fact_table: '',
-                lookups: [],
-                filter_condition:'',
-                capacity:'MEDIUM',
-                dimensions:[],
-                metrics:[],
-                "partition_desc" : {
-                    "partition_date_column" : '',
-                    "partition_date_start" : 0,
-                    "partition_type" : 'APPEND'
-                },
-                last_modified:0
-            };
+        var metaModel = {
+            name: '',
+            fact_table: '',
+            lookups: [],
+            filter_condition:'',
+            capacity:'MEDIUM',
+            dimensions:[],
+            metrics:[],
+            "partition_desc" : {
+                "partition_date_column" : '',
+                "partition_date_start" : 0,
+                "partition_type" : 'APPEND'
+            },
+            last_modified:0
+        };
 
-            return metaModel;
-        }
-})
+        return metaModel;
+    }
+})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/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
new file mode 100644
index 0000000..7994fa1
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -0,0 +1,127 @@
+<!--
+* 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.
+-->
+
+<div ng-controller="CubeRefreshCtrl">
+<div class="row">
+    <div class="col-xs-8">
+
+        <!--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="model.partition_desc.partition_type"
+                        ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
+                        <option value=""></option>
+                    </select>
+                    <span ng-if="state.mode=='view'">{{model.partition_desc.partition_type}}</span>
+                </div>
+            </div>
+        </div>
+
+        <!--Partition Column-->
+        <div class="form-group">
+            <div class="row">
+                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></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-required="model.partition_desc.partition_date_start"
+                            ng-model="model.partition_desc.partition_date_column"
+                            ng-if="state.mode=='edit'"
+                            data-placement=""
+                            ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
+                        <option value="">--Select Partition Column--</option>
+                    </select>
+                    <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+                    <span ng-if="state.mode=='view'">
+                        {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
+                </div>
+            </div>
+        </div>
+
+        <!--Data Range Start-->
+        <div class="form-group">
+            <div class="row">
+                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
+                <div class="col-xs-12 col-sm-6">
+                  <!--edit model will convert in MetaModel.converDateToGMT-->
+                    <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
+                           ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
+                           placeholder="Click to choose start date..." is-open="opened" />
+                  <!--vier model will convert use filter-->
+                    <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
+                </div>
+            </div>
+        </div>
+
+        <!--Filter Condition-->
+        <div class="form-group">
+            <div class="row">
+                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Filter</b></label>
+                <div class="col-xs-12 col-sm-6">
+
+                    <!--edit mode-->
+                    <div class="form-group" ng-if="state.mode=='edit'"
+                         style="font-family:'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro'">
+                        <label for="filter_condition"
+                               style="color: #930f80;"><b>WHERE</b></label>
+                        <textarea id="filter_condition" type="text"
+                                  style="height:150px"
+                                  class="form-control box-default"
+                                  placeholder="Please input WHERE clause without typing 'WHERE'"
+                                  ng-model="model.filter_condition">
+                        </textarea>
+                    </div>
+
+                    <!--view mode-->
+                    <div class="form-group row" ng-if="state.mode=='view'"
+                         style="font-family:'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro'">
+                        <div ng-if="model.filter_condition" class="col-md-11 col-md-offset-1">
+                            <p style="color: #930f80;"><b>WHERE</b></p>
+                            <span>{{model.filter_condition}}</span>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <div class="box box-solid">
+            <div class="box-header">
+                <h4 class="box-title">Tips</h4>
+            </div>
+            <div class="box-body">
+                <div class="row">
+                    <div class="col-xs-12">
+                        <ol class="text-info">
+                            <li>Not required,leave as default if this cube always need full build</li>
+                            <li>Partition column will select 'date' or 'string' type column from fact table</li>
+                            <li>If column selected,please indicate start date to just pull certain data from source</li>
+                        </ol>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/incremental.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/incremental.html b/webapp/app/partials/modelDesigner/incremental.html
deleted file mode 100644
index 3238b1c..0000000
--- a/webapp/app/partials/modelDesigner/incremental.html
+++ /dev/null
@@ -1,94 +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.
--->
-
-<div ng-controller="ModelRefreshCtrl">
-<div class="row">
-    <div class="col-xs-8">
-
-        <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="model.partition_desc.partition_type"
-                        ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
-                        <option value=""></option>
-                    </select>
-                    <span ng-if="state.mode=='view'">{{model.partition_desc.partition_type}}</span>
-                </div>
-            </div>
-        </div>
-
-        <!--Partition Column-->
-        <div class="form-group">
-            <div class="row">
-                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></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-required="model.partition_desc.partition_date_start"
-                            ng-model="model.partition_desc.partition_date_column"
-                            ng-if="state.mode=='edit'"
-                            data-placement=""
-                            ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
-                        <option value="">--Select Partition Column--</option>
-                    </select>
-                    <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
-                    <span ng-if="state.mode=='view'">
-                        {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
-                </div>
-            </div>
-        </div>
-
-        <!--Data Range Start-->
-        <div class="form-group">
-            <div class="row">
-                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
-                <div class="col-xs-12 col-sm-6">
-                  <!--edit model will convert in MetaModel.converDateToGMT-->
-                    <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
-                           ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
-                           placeholder="Click to choose start date..." is-open="opened" />
-                  <!--vier model will convert use filter-->
-                    <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="col-xs-4">
-        <div class="box box-solid">
-            <div class="box-header">
-                <h4 class="box-title">Tips</h4>
-            </div>
-            <div class="box-body">
-                <div class="row">
-                    <div class="col-xs-12">
-                        <ol class="text-info">
-                            <li>Not required,leave as default if cube always need full build</li>
-                            <li>Partition column will select 'date' or 'string' type column from fact table</li>
-                            <li>If column selected,please indicate start date to just pull certain data from source</li>
-                        </ol>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/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 8be67d1..cd529d9 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -20,24 +20,8 @@
 
 <!-- Dimensions Summary -->
 <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">
-                    <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="!model.fact_table.length"
-                    ng-click="openAutoGenModal()">
-                <i class="fa fa-building-o"></i> Auto Generator
-            </button>
-        </div>
-        <div class="col-xs-6" ng-if="state.mode!='edit'">
+    <div class="row"  ng-if="state.mode=='view'">
+        <div class="col-xs-6">
             <b>Dimensions</b>
         </div>
         <div class="col-xs-6">
@@ -47,15 +31,14 @@
             </span>
         </div>
     </div>
-    <table class="table table-striped table-hover" ng-if="model.dimensions.length > 0">
+
+     <!-- VIEW MODE -->
+    <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
         <thead>
             <tr>
                 <th>ID</th>
-                <th>Name</th>
                 <th>Table Name</th>
-                <th>Type</th>
-                <th></th>
-                <th ng-if="state.mode=='edit'">Actions</th>
+                <th>Columns</th>
             </tr>
         </thead>
         <tbody class="cube-dimension">
@@ -66,289 +49,55 @@
                 </td>
                 <!--Name -->
                 <td>
-                    <span>{{dimension.name}}</span>
+                    <span>{{dimension.table}}</span>
                 </td>
                 <!--Table Name -->
                 <td>
-                    <span tooltip="{{dimension.table == model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                    <span>{{dimension.columns}}</span>
                 </td>
-                <!--Type-->
-                <td>
-                    <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+            </tr>
+        </tbody>
+    </table>
+
+    <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
+        <h4 style="margin-left:42px">Dimensions</h4>
+        <table style="margin-left:42px; width:92%"
+               ng-if="model.dimensions.length > 0"
+               class="table table-hover list">
+            <tr class="row">
+                <th class="col-xs-1">ID</th>
+                <th class="col-xs-1">Table Name</th>
+                <th class="col-xs-9">Columns</th>
+                <th class="col-xs-1"></th>
+            </tr>
+
+            <tr ng-repeat="dimension in model.dimensions" class="row">
+                <td class="col-xs-1">
+                    <!-- ID -->
+                    <b>{{($index + 1)}}</b>
                 </td>
-                <!--Columns-->
-                <td  style="word-wrap:break-word;word-break:break-all;">
-                    <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.columns}}</dd>
-                            </dl>
-                        </div>
-                    </div>
+                <td class="col-xs-1">
+                        {{dimension.table}}
                 </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--edit button-->
+                <td class="col-xs-9">
+                    <!-- Dimensions -->
+                    <select ng-if="state.mode=='edit'" style="width: 100%"
+                            ng-model="model.dimensions[$index].columns" required chosen multiple
+                            ng-change=""
+                            ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
+                        <option value=""></option>
+                    </select>
+                </td>
+                <td class="col-xs-1">
                     <button class="btn btn-xs btn-info"
-                            ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
-                    </button>
-                    <!-- remove button-->
-                    <button class="btn btn-xs btn-danger"
-                            ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+                            ng-click="removeTableDimensions($index)"><i
+                            class="fa fa-minus"></i>
                     </button>
                 </td>
             </tr>
-        </tbody>
-    </table>
-</div>
-
-<div class="space-16"></div>
-<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
-    <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
-    <div class="row" ng-repeat="c in dimConflicts">
-        <div class="col-xs-3">
-            <code>{{c.table}}.{{c.column}}</code>
-        </div>
-        <div class="col-xs-3">
-            <ul class="list-unstyled">
-                <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
-            </ul>
-        </div>
-    </div>
-</div>
-
-<!-- Edit Dimension Form -->
-<script type="text/ng-template" id="addEditDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
-            <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
-        </h4>
-    </div>
-    <div class="modal-body">
-        <ng-form name="edit_dim_form">
-        <div class="row">
-            <div class="col-xs-8">
-                <!--Name-->
-                <div class="form-group">
-                    <div class="row">
-                        <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
-                        <div class="col-xs-12 col-sm-6">
-                            <input type="text" placeholder="Name.." class="form-control" name="dim_name"
-                                   tooltip="dimension name.." tooltip-trigger="focus"
-                                   ng-model="newDimension.name" required />
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
-                                The Dimension Name is required.
-                            </div>
-                        </div>
-                    </div>
-                </div>
-
-                <!--Table Name: derived dimension only allows lookup tables-->
-                <div class="form-group">
-                    <div class="row">
-                        <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)">
-                                <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">
-                                <option value=""></option>
-                            </select>
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
-                                Derived dimension only comes from lookup table.
-                            </div>
-                        </div>
-                    </div>
-                </div>
-
-                <!--Normal Dimension: choose one column-->
-                <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
-                    <div class="row">
-                        <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[0]" ng-options="column.name as column.name for column in getColumnsByTable(newDimension.table)">
-                                <option value=""></option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
+        </table>
 
-                <!--Hierarchy Dimension-->
-                <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
-                    <div class="row">
-                        <div class="col-sm-6 col-sm-offset-3">
-                            <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
-                                 ng-model="newDimension.column" class="hierarchy-container">
-                                <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
-                                    <div class="row">
-                                        <div class="col-xs-2">
-                                            <span class="badge">{{$index + 1}}</span>
-                                        </div>
-                                        <div class="col-xs-8">
-                                            <select chosen style="width: 100%"
-                                                    data-placeholder="Dimension Hierarchy Column"
-                                                    ng-model="newDimension.column[$index]"
-                                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(newDimension.table)" >
-                                                <option value="">-- Select Column --</option>
-                                            </select>
-                                        </div>
-                                        <div class="col-xs-2">
-                                            <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                    ng-click="newDimension.column.splice($index, 1);">
-                                                <i class="fa fa-trash-o"></i>
-                                            </button>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
 
-                            <div class="space-8"></div>
-
-                            <div class="row">
-                                <div class="col-xs-4">
-                                    <button class="btn btn-xs btn-info"
-                                            ng-click="newDimension.column.push('');">
-                                        <i class="fa fa-plus"></i> New Hierarchy</button>
-                                </div>
-                                <div class="col-xs-8">
-                                    <p class="help-block">Drag level into the order you prefer.</p>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-
-                <!--Derived Dimension-->
-                <div ng-if="dimType.indexOf('derived') >= 0">
-                    <div class="form-group">
-                        <div class="row">
-                            <div class="col-sm-6 col-sm-offset-3">
-                                <div ng-repeat="derived in newDimension.derived track by $index">
-                                    <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 getColumnsByTable(newDimension.table)" >
-                                            <option value=""></option>
-                                        </select>
-                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                ng-click="newDimension.derived.splice($index, 1);">
-                                            <i class="fa fa-trash-o"></i>
-                                        </button>
-                                        <div class="space-4"></div>
-                                    </div>
-                                </div>
-                                <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
-                                    <i class="fa fa-plus"></i> New Derived</button>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Tips</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Type in any input box for auto suggestion</li>
-                                    <li>Pick up Fact Table from Star Schema Tables first</li>
-                                    <li>Data Type should match with Hive Table's Data Type</li>
-                                    <li>Join Type have to be same as will be used in query</li>
-                                    <li>Using Hierarchy to inherit one dimension another</li>
-                                    <li>Using Derived for One-One relationship between columns, like ID and Name</li>
-                                </ol>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-        </ng-form>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
-
-
-<script type="text/ng-template" id="autoGenDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
-    </div>
-    <div class="modal-body">
-        <div class="row">
-            <div class="col-xs-8">
-                <div class="box box-solid">
-                    <div class="box-header"><h4>Columns</h4></div>
-                    <div class="box-body">
-                        <ul class="list-unstyled columns-region">
-                            <li ng-repeat="table in availableTables track by $index">
-                                <h5 class="table-name-underline">
-                                    <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
-                                </h5>
-                                <ul class="list-unstyled">
-                                    <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
-                                        <label>
-                                            <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
-                                                   ng-disabled="selectedColumns[table][col.name].disabled">
-                                            {{col.name}}
-                                        </label>
-                                    </li>
-                                </ul>
-                            </li>
-                        </ul>
-                    </div>
-                </div>
-            </div>
-
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Auto Generate Rules</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Column is disabled once there is already a dimension referred this column.</li>
-                                    <li>In fact table: one normal dimension will be auto generated per column.</li>
-                                    <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
-                                </ol>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
+</div>
 
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index d91a0f0..9b9e786 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -29,7 +29,7 @@
                 </label>
                 <div class="col-xs-12 col-sm-6">
                     <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="model.project" disabled/>
+                           ng-model="state.project"/>
                     <span ng-if="state.mode=='view'">
                         {{model.project}}
                     </span>
@@ -37,11 +37,11 @@
             </div>
         </div>
 
-        <!--Cube Name-->
+        <!--Model Name-->
         <div class="form-group">
             <div class="row">
                 <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Cube Name</b>
+                    <b>Model Name</b>
                 </label>
                 <div class="col-xs-12 col-sm-6">
                     <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"


[17/52] [abbrv] incubator-kylin git commit: model wizard sperate from cube wizard

Posted by ma...@apache.org.
model wizard sperate from cube wizard


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

Branch: refs/heads/0.8.0
Commit: fb405ebd0941fc7be5ebd7de5db60b641eaad858
Parents: 7b52624
Author: jiazhong <ji...@ebay.com>
Authored: Fri Mar 13 18:22:37 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:49 2015 +0800

----------------------------------------------------------------------
 webapp/app/index.html                           |   1 +
 webapp/app/js/controllers/cubeEdit.js           |   4 +-
 webapp/app/js/controllers/cubeModel.js          |  30 +--
 webapp/app/js/controllers/modelEdit.js          | 228 +++++++++++++++++++
 webapp/app/js/controllers/modelSchema.js        |   5 +-
 webapp/app/js/model/metaModel.js                |  61 +++--
 webapp/app/js/services/model.js                 |   2 +-
 webapp/app/partials/cubes/cube_detail.html      |   2 -
 .../modelDesigner/model_dimensions.html         |   4 +-
 .../app/partials/modelDesigner/model_info.html  |  84 +++++++
 webapp/app/partials/models/model_detail.html    |  13 +-
 webapp/app/partials/models/model_edit.html      |   4 +-
 webapp/app/routes.json                          |   8 +
 13 files changed, 372 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 9e7317f..c8698ac 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -170,6 +170,7 @@
 <script src="js/controllers/modelSchema.js"></script>
 <script src="js/controllers/modelDimensions.js"></script>
 <script src="js/controllers/modelRefresh.js"></script>
+<script src="js/controllers/modelEdit.js"></script>
 
 <!--New GUI-->
 <script src="js/controllers/models.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 356a5b5..fe099fd 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -357,7 +357,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         //! here get the latest rowkey_columns
         $scope.cubeMetaFrame.rowkey.rowkey_columns = newRowKeyColumns;
 
-        if($scope.cubeMode==="editExistCube") {
+        if($scope.modelMode==="editExistCube") {
             var aggregationGroups = $scope.cubeMetaFrame.rowkey.aggregation_groups;
             // rm unused item from group,will only rm when [edit] dimension
             angular.forEach(aggregationGroups, function (group, index) {
@@ -387,7 +387,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             });
         }
 
-        if($scope.cubeMode==="addNewCube"){
+        if($scope.modelMode==="addNewCube"){
 
           if(!tmpAggregationItems.length) {
               $scope.cubeMetaFrame.rowkey.aggregation_groups=[];

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index 038f7be..fc2cca8 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -20,25 +20,11 @@
 
 KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,CubeGraphService,$log) {
 
+    //copy model for show Json in model tab list
+    $scope.modelJson = angular.copy($scope.model);
 
-    $scope.buildGraph = function (cube) {
-        CubeGraphService.buildTree(cube);
-    };
-    $scope.cleanStatus = function(model){
-
-        if (!model)
-        {
-            return;
-        }
-        var newModel = jQuery.extend(true, {}, model);
-        delete newModel.visiblePage;
-        delete newModel.showDetail;
-
-        angular.forEach(newModel.dimensions, function(dimension, index){
-            delete dimension.status;
-        });
-
-        return newModel;
+    $scope.buildGraph = function (model) {
+        CubeGraphService.buildTree(model);
     };
 
     $scope.cubeConfig = cubeConfig;
@@ -132,7 +118,7 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelSe
     };
 
         $scope.removeLookup = function (lookup) {
-            var dimExist = _.some($scope.cubeMetaFrame.dimensions,function(item,index){
+            var dimExist = _.some($scope.model.dimensions,function(item,index){
                 return item.table===lookup.table;
             });
             if(dimExist) {
@@ -146,9 +132,9 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelSe
                     closeOnConfirm: true
                 }, function (isConfirm) {
                     if (isConfirm) {
-                        for (var i = $scope.cubeMetaFrame.dimensions.length - 1; i >= 0; i--) {
-                            if ($scope.cubeMetaFrame.dimensions[i].table === lookup.table) {
-                                $scope.cubeMetaFrame.dimensions.splice(i, 1);
+                        for (var i = $scope.model.dimensions.length - 1; i >= 0; i--) {
+                            if ($scope.model.dimensions[i].table === lookup.table) {
+                                $scope.model.dimensions.splice(i, 1);
                             }
                         }
                         lookupList.splice(lookupList.indexOf(lookup), 1);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
new file mode 100644
index 0000000..2741d2c
--- /dev/null
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -0,0 +1,228 @@
+/*
+ * 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('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel) {
+    $scope.cubeConfig = cubeConfig;
+    //add or edit ?
+    var absUrl = $location.absUrl();
+    $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
+
+
+    $scope.getPartitonColumns = function(tableName){
+        var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
+            return column.datatype==="date"||column.datatype==="string";
+        });
+        return columns;
+    };
+
+    $scope.getColumnsByTable = function (tableName) {
+        var temp = [];
+        angular.forEach(TableModel.selectProjectTables, function (table) {
+            if (table.name == tableName) {
+                temp = table.columns;
+            }
+        });
+        return temp;
+    };
+
+    $scope.getColumnType = function (_column,table){
+        var columns = $scope.getColumnsByTable(table);
+        var type;
+        angular.forEach(columns,function(column){
+            if(_column === column.name){
+                type = column.datatype;
+                return;
+            }
+        });
+        return type;
+    };
+
+    // ~ Define data
+    $scope.state = {
+        "modelSchema": ""
+    };
+
+    // ~ init
+    if ($scope.isEdit = !!$routeParams.modelName) {
+        ModelDescService.get({model_name: $routeParams.modelName}, function (model) {
+                    if (model) {
+                        $scope.model = model;
+                        //use
+                        //convert GMT mills ,to make sure partition date show GMT Date
+                        //should run only one time
+                        if(model.partition_desc&&model.partition_desc.partition_date_start)
+                        {
+                            MetaModel.converDateToGMT();
+                        }
+                    }
+                });
+
+    } else {
+        $scope.model = MetaModel.createNew();;
+    }
+
+    // ~ public methods
+    $scope.aceChanged = function () {
+    };
+
+    $scope.aceLoaded = function(){
+    };
+
+    $scope.prepareCube = function () {
+        // generate column family
+
+        if ($scope.model.partition_desc.partition_date_column&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
+            var dateStart = new Date($scope.model.partition_desc.partition_date_start);
+            dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
+            //switch selected time to utc timestamp
+            $scope.model.partition_desc.partition_date_start = new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
+
+
+            if($scope.model.partition_desc.partition_date_column.indexOf(".")==-1){
+            $scope.model.partition_desc.partition_date_column=$scope.model.fact_table+"."+$scope.model.partition_desc.partition_date_column;
+            }
+
+        }
+        $scope.state.modelSchema = angular.toJson($scope.model, true);
+        $scope.state.project = $scope.projectModel.selectedProject;
+
+    };
+
+    $scope.cubeResultTmpl = function (notification) {
+        // Get the static notification template.
+        var tmpl = notification.type == 'success' ? 'cubeResultSuccess.html' : 'cubeResultError.html';
+        return $interpolate($templateCache.get(tmpl))(notification);
+    };
+
+    $scope.saveModel = function (design_form) {
+
+        try {
+            angular.fromJson($scope.state.cubeSchema);
+        } catch (e) {
+            SweetAlert.swal('Oops...', 'Invalid cube json format..', 'error');
+            return;
+        }
+
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to save the Model ?',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+                loadingRequest.show();
+
+                if ($scope.isEdit) {
+                    CubeService.update({}, {modelDescData:$scope.state.modelSchema, modelName: $routeParams.modelName, project: $scope.state.project}, function (request) {
+                        if (request.successful) {
+                            $scope.state.modelSchema = request.modelSchema;
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+
+                            if (design_form) {
+                                design_form.$invalid = true;
+                            }
+                        } else {
+                            $scope.saveModelRollBack();
+                                var message =request.message;
+                                var msg = !!(message) ? message : 'Failed to take action.';
+                                MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        }
+                        //end loading
+                        loadingRequest.hide();
+                    }, function (e) {
+                        $scope.saveModelRollBack();
+
+                        if(e.data&& e.data.exception){
+                            var message =e.data.exception;
+                            var msg = !!(message) ? message : 'Failed to take action.';
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        } else {
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        }
+                        loadingRequest.hide();
+                    });
+                } else {
+                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
+                        if(request.successful) {
+                            $scope.state.modelSchema = request.modelSchema;
+
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':'Created the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+                        } else {
+                            $scope.saveModelRollBack();
+                            var message =request.message;
+                            var msg = !!(message) ? message : 'Failed to take action.';
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        }
+
+                        //end loading
+                        loadingRequest.hide();
+                    }, function (e) {
+                        $scope.saveModelRollBack();
+
+                        if (e.data && e.data.exception) {
+                            var message =e.data.exception;
+                            var msg = !!(message) ? message : 'Failed to take action.';
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        } else {
+                            MessageService.sendMsg($scope.cubeResultTmpl({'text':"Failed to take action.",'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+                        }
+                        //end loading
+                        loadingRequest.hide();
+
+                    });
+                }
+            }
+            else{
+                $scope.saveModelRollBack();
+            }
+        });
+    };
+
+//    reverse the date
+    $scope.saveModelRollBack = function (){
+        if($scope.model&&($scope.model.partition_desc.partition_date_start||$scope.model.partition_desc.partition_date_start==0))
+        {
+            $scope.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+        }
+    };
+
+    $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
+        if(!newValue){
+            return;
+        }
+        var param = {
+            ext: true,
+            project:newValue
+        };
+        if(newValue){
+            TableModel.initTables();
+            TableService.list(param, function (tables) {
+                angular.forEach(tables, function (table) {
+                    table.name = table.database+"."+table.name;
+                    TableModel.addTable(table);
+                });
+            });
+        }
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 638e119..112507e 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -28,6 +28,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
 
     $scope.wizardSteps = [
+        {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false},
         {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false},
         {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false},
         {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false},
@@ -42,11 +43,11 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         $scope.state = {mode: "view"};
     }
 
-    $scope.$watch('cubeMetaFrame', function (newValue, oldValue) {
+    $scope.$watch('model', function (newValue, oldValue) {
         if(!newValue){
             return;
         }
-        if ($scope.cubeMode=="editExistCube"&&newValue && !newValue.project) {
+        if ($scope.modelMode=="editExistModel"&&newValue && !newValue.project) {
             initProject();
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 021dda7..74714d9 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -21,49 +21,38 @@
  */
 KylinApp.service('MetaModel',function(){
 
+    var _this = this;
     //data model when edit model
-    this.model={
-        name: null,
-        fact_table: null,
-        lookups: [],
-        filter_condition:null,
-        capacity:null,
-        "partition_desc" : {
-            "partition_date_column" : '',
-            "partition_date_start" : 0,
-            "partition_type" : 'APPEND'
-        },
-        last_modified:0
+    this.name=null;
+    this.fact_table=null;
+    this.lookups=[];
+    this.filter_condition=null;
+    this.capacity=null;
+    this.dimensions=[];
+    this.metrics=[];
+    this.partition_desc = {
+        "partition_date_column" : '',
+        "partition_date_start" : 0,
+        "partition_type" : 'APPEND'
     };
+    this.last_modified=0;
 
     this.setMetaModel =function(model){
-        var _model = {};
-        _model.name = model.name;
-        _model.fact_table = model.fact_table;
-        _model.lookups =model.lookups;
-        _model.filter_condition = model.filter_condition;
-        _model.capacity = model.capacity;
-        _model.partition_desc = model.partition_desc;
-        _model.last_modified = model.last_modified;
-        this.model = _model;
-    };
-
-    this.initModel = function(){
-        this.model = this.createNew();
-    }
-
-    this.getMetaModel = function(){
-        return this.model;
-    };
-
-    this.setFactTable = function(fact_table) {
-        this.model.fact_table =fact_table;
+        _this.name = model.name;
+        _this.fact_table = model.fact_table;
+        _this.lookups =model.lookups;
+        _this.filter_condition = model.filter_condition;
+        _this.capacity = model.capacity;
+        _this.partition_desc = model.partition_desc;
+        _this.last_modified = model.last_modified;
+        _this.metrics  = model.metrics;
+        _this.dimensions = model.dimensions;
     };
 
 
     this.converDateToGMT = function(){
-        if(this.model.partition_desc&&this.model.partition_desc.partition_date_start){
-            this.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+        if(this.partition_desc&&this.partition_desc.partition_date_start){
+            this.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
         }
     };
     //
@@ -74,6 +63,8 @@ KylinApp.service('MetaModel',function(){
                 lookups: [],
                 filter_condition:'',
                 capacity:'MEDIUM',
+                dimensions:[],
+                metrics:[],
                 "partition_desc" : {
                     "partition_date_column" : '',
                     "partition_date_start" : 0,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/js/services/model.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/model.js b/webapp/app/js/services/model.js
index 681ce75..ae9bbb0 100644
--- a/webapp/app/js/services/model.js
+++ b/webapp/app/js/services/model.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.factory('ModelService', ['$resource', function ($resource, config) {
+KylinApp.factory('ModelDescService', ['$resource', function ($resource, config) {
     return $resource(Config.service.url + 'model/:model_name/:propName/:propValue/:action', {}, {
         get: {method: 'GET', params: {}, isArray: false}
     });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 51196cf..59f2d69 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -107,8 +107,6 @@
                 <ul>
                     <li>Region Count: <span class="red">{{table.regionCount}}</span></li>
                     <li>Size: <span class="red">{{table.tableSize | bytes:2}}</span></li>
-                    <li>Start Date (Include): <span class="red">{{table.dateRangeStart | reverseToGMT0}}</span></li>
-                    <li>End Date (Exclude): <span class="red">{{table.dateRangeStart | reverseToGMT0}}</span></li>
                 </ul>
             </div>
             <div ng-if="cube.hbase">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/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 9067807..8be67d1 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -77,7 +77,7 @@
                     <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
                 </td>
                 <!--Columns-->
-                <td>
+                <td  style="word-wrap:break-word;word-break:break-all;">
                     <div ng-repeat="t in getDimType(dimension)">
                         <div ng-switch="t">
                             <dl class="dl-horizontal" ng-switch-when="hierarchy">
@@ -90,7 +90,7 @@
                             </dl>
                             <dl class="dl-horizontal" ng-switch-when="normal">
                                 <dt>Column</dt>
-                                <dd>{{dimension.column}}</dd>
+                                <dd>{{dimension.columns}}</dd>
                             </dl>
                         </div>
                     </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
new file mode 100644
index 0000000..d91a0f0
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -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.
+-->
+
+<div class="row">
+    <div class="col-xs-8">
+        <!--Project-->
+        <div class="form-group">
+            <div class="row">
+                <label class="col-xs-12 col-sm-3 control-label no-padding-right">
+                    <a ng-if="state.mode=='edit'" href="projects">
+                        <b>Project</b>
+                    </a>
+                    <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
+                </label>
+                <div class="col-xs-12 col-sm-6">
+                    <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
+                           ng-model="model.project" disabled/>
+                    <span ng-if="state.mode=='view'">
+                        {{model.project}}
+                    </span>
+                </div>
+            </div>
+        </div>
+
+        <!--Cube Name-->
+        <div class="form-group">
+            <div class="row">
+                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                    <b>Cube Name</b>
+                </label>
+                <div class="col-xs-12 col-sm-6">
+                    <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
+                           ng-model="model.name" required
+                           placeholder="You can use letters, numbers, and '_'"
+                           ng-maxlength=100 ng-pattern="/^\w+$/" />
+                    <span ng-if="state.mode=='view'">{{model.name}}</span>
+                </div>
+                <div class="col-xs-12 col-sm-3">
+                    <div class="text-warning" ng-if="design_form.model_name.$error.required  && design_form.model_name.$dirty">
+                        Model name is required.
+                    </div>
+                    <div class="text-warning" ng-if="design_form.model_name.$invalid && design_form.model_name.$dirty && !design_form.model_name.$error.required">
+                        Model name is invalid.
+                    </div>
+                </div>
+            </div>
+        </div>
+
+    </div>
+
+    <!--Tips-->
+    <div class="col-xs-4">
+        <div class="box box-solid">
+            <div class="box-header widget-header-flat">
+                <h4 class="box-title">Tips</h4>
+            </div>
+            <div class="box-body">
+                <div class="row">
+                    <div class="col-xs-12">
+                        <ol class="text-info">
+                            <li>Model must belong to project which you have privilege to create</li>
+                            <li>Model name is unique name of entire system</li>
+                        </ol>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/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 96a64c0..a4ae287 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -22,7 +22,7 @@
             <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
         </li>
         <li class="{{model.visiblePage=='graph'? 'active':''}}">
-            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);">Visualization</a>
+            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);$event.stopPropagation();">Visualization</a>
         </li>
         <li class="{{model.visiblePage=='json_model'? 'active':''}}"
             ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
@@ -32,12 +32,13 @@
 
     <div class="model-detail" ng-if="!model.visiblePage || model.visiblePage=='metadata'">
         <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
-             ng-init="state={mode:'view', modelName:model.name}"></div>
+             ng-init="state={mode:'view', modelName:model.name}">
+        </div>
     </div>
-    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
-          <pre
-               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>
+    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="model-detail model_graph">
     </div>
-    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="cube-detail cube_graph">
+    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
+          <pre ng-if="!state.jsonEdit"
+               style="background-color: white;border: 0px">{{angular.toJson(modelJson, true)}}</pre>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/partials/models/model_edit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_edit.html b/webapp/app/partials/models/model_edit.html
index 07c3913..82d0348 100644
--- a/webapp/app/partials/models/model_edit.html
+++ b/webapp/app/partials/models/model_edit.html
@@ -24,8 +24,8 @@
         <form role="form" name="cube_form" novalidate>
             <!-- This margin in order to align with table tree in left part -->
             <div style="margin-top: 20px;">
-                <div ng-include="'partials/cubes/cube_schema.html'" ng-controller="CubeSchemaCtrl"
-                     ng-init="state={mode:'edit', cubeName: routeParams.cubeName}">
+                <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
+                     ng-init="state={mode:'edit', modelName: routeParams.modelName}">
                 </div>
             </div>
         </form>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fb405ebd/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 0b4af3f..31071c5 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -111,5 +111,13 @@
             "tab": "models",
             "controller": "ModelsCtrl"
         }
+    },
+    {
+        "url": "/models/edit/:modelName",
+        "params": {
+            "templateUrl": "partials/models/model_edit.html",
+            "tab": "models",
+            "controller": "ModelEditCtrl"
+        }
     }
 ]
\ No newline at end of file


[41/52] [abbrv] incubator-kylin git commit: add delete model

Posted by ma...@apache.org.
add delete model


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

Branch: refs/heads/0.8.0
Commit: d60f726c97083f059d413e9dbf2682cb4d90c82e
Parents: 0aca96b
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 3 16:21:08 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:32 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/metadata/MetadataManager.java  |  1 -
 .../kylin/rest/controller/ModelController.java  | 21 ++++++++++++++++++--
 .../apache/kylin/rest/service/CubeService.java  |  2 +-
 .../apache/kylin/rest/service/ModelService.java | 12 ++++++++++-
 webapp/app/js/controllers/cube.js               |  9 +--------
 webapp/app/js/controllers/cubes.js              |  4 ----
 webapp/app/js/controllers/modelEdit.js          | 12 +++--------
 webapp/app/js/controllers/projects.js           |  2 +-
 8 files changed, 36 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index ae64f4c..933826b 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -295,7 +295,6 @@ public class MetadataManager {
         ProjectInstance projectInstance =  ProjectManager.getInstance(config).getProject(projectName);
         HashSet<DataModelDesc> ret = new HashSet<>();
 
-
         if (projectInstance != null&&projectInstance.getModels()!=null) {
             for (String modelName : projectInstance.getModels()) {
                 DataModelDesc model = getDataModelDesc(modelName);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 3e17be1..ba45df1 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -24,11 +24,13 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import org.apache.commons.lang.StringUtils;
 import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.exception.BadRequestException;
 import org.apache.kylin.rest.exception.ForbiddenException;
 import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.exception.NotFoundException;
 import org.apache.kylin.rest.request.ModelRequest;
 import org.apache.kylin.rest.service.ModelService;
 import org.slf4j.Logger;
@@ -119,7 +121,7 @@ public class ModelController extends BasicController {
             return modelRequest;
         }
         try {
-            modelDesc =  modelService.updateModelAndDesc(modelDesc,modelRequest.getProject());
+            modelDesc =  modelService.updateModelAndDesc(modelDesc);
         } catch (AccessDeniedException accessDeniedException) {
             throw new ForbiddenException("You don't have right to update this cube.");
         }  catch (Exception e) {
@@ -138,7 +140,22 @@ public class ModelController extends BasicController {
         return modelRequest;
     }
 
-
+//    @RequestMapping(value = "/{cubeName}", method = {RequestMethod.DELETE})
+//    @ResponseBody
+//    @Metered(name = "deleteCube")
+//    public void deleteCube(@PathVariable String cubeName) {
+//        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+//        if (null == cube) {
+//            throw new NotFoundException("Cube with name " + cubeName + " not found..");
+//        }
+//
+//        try {
+//            cubeService.deleteCube(cube);
+//        } catch (Exception e) {
+//            logger.error(e.getLocalizedMessage(), e);
+//            throw new InternalErrorException("Failed to delete cube. " + " Caused by: " + e.getMessage(), e);
+//        }
+//    }
 
     private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
         DataModelDesc desc = null;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index 7f63d34..d168ddd 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -235,7 +235,7 @@ public class CubeService extends BasicService {
     }
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String newProjectName) throws UnknownHostException, IOException, JobException {
+    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String newProjectName) throws  IOException, JobException {
         final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
         if (!cubingJobs.isEmpty()) {
             throw new JobException("Cube schema shouldn't be changed with running job.");

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index d210077..3c349cc 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -109,11 +109,21 @@ public class ModelService extends BasicService {
 
 
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
+    public DataModelDesc updateModelAndDesc(DataModelDesc desc) throws IOException {
 
         getMetadataManager().updateDataModelDesc(desc);
         return desc;
     }
 
 
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public void deleteCube(DataModelDesc desc) throws IOException {
+//        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
+
+
+
+
+//        getCubeManager().dropCube(cube.getName(), true);
+//        accessService.clean(cube, true);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 2585345..d9e7764 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -222,11 +222,9 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
 
                 loadingRequest.show();
                 CubeService.drop({cubeId: cube.name}, {}, function (result) {
-
                     loadingRequest.hide();
-//                    CubeList.removeCube(cube);
                     SweetAlert.swal('Success!', 'Cube drop is done successfully', 'success');
-
+                    location.reload();
                 },function(e){
 
                     loadingRequest.hide();
@@ -437,11 +435,6 @@ var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageServic
 
     $scope.updateDate = function() {
 
-
-//        if ($scope.cube.detail.partition_desc.cube_partition_type=='UPDATE_INSERT')
-//        {
-//            $scope.jobBuildRequest.startTime=$scope.formatDate($scope.jobBuildRequest.startTime);
-//        }
         $scope.jobBuildRequest.endTime=$scope.formatDate($scope.jobBuildRequest.endTime);
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/webapp/app/js/controllers/cubes.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js
index 94c6031..fdea880 100755
--- a/webapp/app/js/controllers/cubes.js
+++ b/webapp/app/js/controllers/cubes.js
@@ -238,10 +238,6 @@ KylinApp
                     CubeService.drop({cubeId: cube.name}, {}, function (result) {
 
                     loadingRequest.hide();
-//                    var cubeIndex = CubeList.cubes.indexOf(cube);
-//                    if (cubeIndex > -1) {
-//                        $scope.cubes.splice(cubeIndex, 1);
-//                    }
                      CubeList.removeCube(cube);
                     SweetAlert.swal('Success!', 'Cube drop is done successfully', 'success');
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 5ca95b1..a571611 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -71,8 +71,6 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     // ~ init
     if ($scope.isEdit = !!$routeParams.modelName) {
 
-
-
         var modelName = $routeParams.modelName;
         ModelDescService.get({model_name: modelName}, function (model) {
                     if (model) {
@@ -112,10 +110,6 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
             $scope.model.partition_desc.partition_date_start = new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
 
 
-            if($scope.model.partition_desc.partition_date_column.indexOf(".")==-1){
-            $scope.model.partition_desc.partition_date_column=$scope.model.fact_table+"."+$scope.model.partition_desc.partition_date_column;
-            }
-
         }
         if($scope.model.partition_desc.partition_date_column==null){
             $scope.model.partition_desc.partition_date_start=null;
@@ -145,9 +139,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         }
 
         SweetAlert.swal({
-            title: '',
-            text: 'Are you sure to save the Model ?',
-            type: '',
+            title: 'Are you sure to update the model?',
+            text: $scope.isEdit?' Please note: if model schema is changed, all cubes of the model will be affected.':'Are you sure to save the Model ?',
+            type: 'warning',
             showCancelButton: true,
             confirmButtonColor: '#DD6B55',
             confirmButtonText: "Yes",

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d60f726c/webapp/app/js/controllers/projects.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projects.js b/webapp/app/js/controllers/projects.js
index e906188..e0cc64d 100644
--- a/webapp/app/js/controllers/projects.js
+++ b/webapp/app/js/controllers/projects.js
@@ -77,7 +77,7 @@ KylinApp
                     if (pIndex > -1) {
                         $scope.projects.splice(pIndex, 1);
                     }
-                    ProjectModel.removeProject(project.name);
+                ProjectModel.removeProject(project.name);
                 SweetAlert.swal('Success!',"Project [" + project.name + "] has been deleted successfully!", 'success');
                 },function(e){
                     if(e.data&& e.data.exception){


[12/52] [abbrv] incubator-kylin git commit: add start&end date for hbase info in cubeDesigner KYLIN-637

Posted by ma...@apache.org.
add start&end date for hbase info in cubeDesigner KYLIN-637


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

Branch: refs/heads/0.8.0
Commit: be5b810b700fcf26b1476ce092d5d3499686e0bd
Parents: 603fe3f
Author: jiazhong <ji...@ebay.com>
Authored: Thu Mar 12 11:39:44 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:34:17 2015 +0800

----------------------------------------------------------------------
 .../kylin/rest/controller/CubeController.java   |  2 ++
 .../kylin/rest/response/HBaseResponse.java      | 26 ++++++++++++++++++++
 webapp/app/partials/cubes/cube_detail.html      |  2 ++
 webapp/app/partials/cubes/cubes.html            |  2 +-
 webapp/app/partials/jobs/jobs.html              |  6 +++--
 5 files changed, 35 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be5b810b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index 556e21b..231c834 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -448,6 +448,8 @@ public class CubeController extends BasicController {
             }
 
             hr.setTableName(tableName);
+            hr.setDateRangeStart(segment.getDateRangeStart());
+            hr.setDateRangeEnd(segment.getDateRangeEnd());
             hbase.add(hr);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be5b810b/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java b/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
index cd32ae5..302cb02 100644
--- a/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
+++ b/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
@@ -25,6 +25,8 @@ public class HBaseResponse implements Serializable {
     private String tableName;
     private long tableSize;
     private int regionCount;
+    private long dateRangeStart;
+    private long dateRangeEnd;
 
     public HBaseResponse() {
     }
@@ -73,4 +75,28 @@ public class HBaseResponse implements Serializable {
     public void setRegionCount(int regionCount) {
         this.regionCount = regionCount;
     }
+
+    /**
+     * @return the segmentStartTime
+     */
+    public long getDateRangeStart() {
+        return dateRangeStart;
+    }
+
+    /**
+     * @param segmentStartTime
+     *            the segmentStartTime to set
+     */
+    public void setDateRangeStart(long dateRangeStart) { this.dateRangeStart = dateRangeStart; }
+
+    /**
+     * @return the segmentEndTime
+     */
+    public long getDateRangeEnd() { return dateRangeEnd; }
+
+    /**
+     * @param segmentEndTime
+     *            the segmentEndTime to set
+     */
+    public void setDateRangeEnd(long dateRangeEnd) { this.dateRangeEnd = dateRangeEnd; }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be5b810b/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 59f2d69..51196cf 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -107,6 +107,8 @@
                 <ul>
                     <li>Region Count: <span class="red">{{table.regionCount}}</span></li>
                     <li>Size: <span class="red">{{table.tableSize | bytes:2}}</span></li>
+                    <li>Start Date (Include): <span class="red">{{table.dateRangeStart | reverseToGMT0}}</span></li>
+                    <li>End Date (Exclude): <span class="red">{{table.dateRangeStart | reverseToGMT0}}</span></li>
                 </ul>
             </div>
             <div ng-if="cube.hbase">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be5b810b/webapp/app/partials/cubes/cubes.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html
index 9e6976f..4c21d9a 100644
--- a/webapp/app/partials/cubes/cubes.html
+++ b/webapp/app/partials/cubes/cubes.html
@@ -32,7 +32,7 @@
     <!--Cube Name-->
     <div class="col-xs-3">
         <form ng-submit="cubeList.removeAll();list()" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search"><b>Cube Name:</b>
+            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Cube Name:</b>
                 <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="listParams.cubeName" />
                 <i class="ace-icon fa fa-search blue" ng-click="cubeList.removeAll();list()"></i>
             </span>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be5b810b/webapp/app/partials/jobs/jobs.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/jobs.html b/webapp/app/partials/jobs/jobs.html
index 3b2ee04..fca5f88 100644
--- a/webapp/app/partials/jobs/jobs.html
+++ b/webapp/app/partials/jobs/jobs.html
@@ -29,12 +29,14 @@
         </form>
     </div>
     <!--Cube Name: -->
-        <form class="pull-right" ng-submit="jobList.removeAll();reload()" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search"><b>Job Name:</b>
+    <div class="col-xs-3">
+        <form class="" ng-submit="jobList.removeAll();reload()" style="display: inline" >
+            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Cube Name:</b>
                 <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="cubeName" />
                 <i class="ace-icon fa fa-search blue" ng-click="jobList.removeAll();reload()"></i>
             </span>
         </form>
+    </div>
 </div>
 
 <!--Jobs Table-->


[49/52] [abbrv] incubator-kylin git commit: KYLIN-675

Posted by ma...@apache.org.
KYLIN-675


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

Branch: refs/heads/0.8.0
Commit: 570d5a856d2510278b31f7fa70f4a757e8aa0d43
Parents: 2dda4e1
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 10 14:48:32 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:39:12 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cube.js                    |  4 ++--
 webapp/app/js/controllers/cubeModel.js               |  4 ++--
 webapp/app/js/services/tree.js                       |  2 +-
 .../partials/modelDesigner/conditions_settings.html  |  4 ++--
 webapp/app/partials/query/query.html                 |  2 +-
 webapp/app/partials/query/query_detail.html          | 15 ++++++---------
 webapp/app/routes.json                               | 15 ---------------
 7 files changed, 14 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 55c54f0..f53b590 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert,loadingRequest,modelsManager,$modal,cubesManager) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, ModelGraphService, UserService,SweetAlert,loadingRequest,modelsManager,$modal,cubesManager) {
     $scope.newAccess = null;
     $scope.state = {jsonEdit: false};
 
@@ -26,7 +26,7 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
     $scope.cubesManager = cubesManager;
 
     $scope.buildGraph = function (cube) {
-       GraphService.buildTree(cube);
+       ModelGraphService.buildTree(cube);
     };
 
     $scope.getCubeSql = function (cube) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index dd7991d..9466f18 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,14 +18,14 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel,ModelService,loadingRequest,modelsManager) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,ModelGraphService,$log,TableModel,ModelService,loadingRequest,modelsManager) {
 
     $scope.modelsManager = modelsManager;
 
     $scope.buildGraph = function (model) {
 //        var newModel = jQuery.extend(true, {}, model);
         var newModel = angular.copy(model);
-        GraphService.buildTree(newModel);
+        ModelGraphService.buildTree(newModel);
     };
 
     $scope.cleanStatus = function(model){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index d61629c..acc4626 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('GraphService', function () {
+KylinApp.service('ModelGraphService', function () {
 
     var margin = {top: 20, right: 100, bottom: 20, left: 100},
         width = 1100 - margin.right - margin.left,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/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 d066930..b27bae3 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -131,8 +131,8 @@
                 <div class="row">
                     <div class="col-xs-12">
                         <ol class="text-info">
-                            <li>Not required,leave as default if cube always need full build</li>
-                            <li>Partition column will select 'date' or 'string' type column from fact table</li>
+                            <li>Partition date column not required,leave as default if cube always need full build</li>
+                            <li>Partition date column will select 'date' or 'string' type column from fact table</li>
                         </ol>
                     </div>
                 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/partials/query/query.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/query/query.html b/webapp/app/partials/query/query.html
index 7947788..d34dbc7 100644
--- a/webapp/app/partials/query/query.html
+++ b/webapp/app/partials/query/query.html
@@ -193,7 +193,7 @@
                         class="{{(query==curQuery)? 'active':''}}">
                         <span>
                             <button class="btn {{(query==curQuery)?'active':''}} btn-default btn-xs" style="width: 50px"
-                                    ng-click="refreshCurQuery();$event.stopPropagation();">
+                                    ng-click="refreshCurQuery()">
                                 {{$index+1}}
                                 <span ng-if="query.status=='failed'">
                                     <i style="color: #f0ad4e" class="fa fa-exclamation-triangle"></i>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/partials/query/query_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/query/query_detail.html b/webapp/app/partials/query/query_detail.html
index 7157e9c..9217257 100644
--- a/webapp/app/partials/query/query_detail.html
+++ b/webapp/app/partials/query/query_detail.html
@@ -82,17 +82,15 @@
       </button>
       </span>
     <div class="pull-right" ng-if="curQuery.status=='success'">
-        <button class="btn btn-default btn-xs"
-                ng-click="curQuery.graph.show=!curQuery.graph.show;buildGraphMetadata(curQuery);resetGraph(curQuery);refreshGraphData(curQuery)">
+        <button class="btn btn-default btn-xs"  ng-click="curQuery.graph.show=!curQuery.graph.show;buildGraphMetadata(curQuery);resetGraph(curQuery);refreshGraphData(curQuery)">
             <span ng-if="!curQuery.graph.show"><i class="fa fa-bar-chart-o"></i> Visualization</span>
             <span ng-if="curQuery.graph.show"><i class="fa fa-list-ul"></i> Grid</span>
         </button>
-        <a class="btn btn-default btn-xs"
-           href="{{config.service.url}}query/format/csv?sql={{sanitate(curQuery.sql)}}&project={{curQuery.project}}" target="_blank"><i
-                class="fa fa-cloud-download"></i> Export</a>
-        <a class="btn btn-default btn-xs"
-           ng-click="refreshUi();"><i
-                ng-class="{true: 'fa fa-compress', false: 'fa fa-expand'}[ui.fullScreen]"></i></a>
+        <a class="btn btn-default btn-xs" href="{{config.service.url}}query/format/csv?sql={{sanitate(curQuery.sql)}}&project={{curQuery.project}}" target="_blank">
+            <i class="fa fa-cloud-download"></i> Export</a>
+        <a class="btn btn-default btn-xs" ng-click="refreshUi();">
+            <i ng-class="{true: 'fa fa-compress', false: 'fa fa-expand'}[ui.fullScreen]"></i>
+        </a>
     </div>
 
     <div ng-if="!curQuery.graph.show">
@@ -139,7 +137,6 @@
 
             <div class="graph_content">
                 <label>Dimensions</label>
-
                 <div>
                     <select
                             chosen style="width: 100%"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/570d5a85/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 1accb01..3121123 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -1,20 +1,5 @@
 [
     {
-        "url": "/home",
-        "params": {
-            "templateUrl": "partials/home.html",
-            "controller": "IndexCtrl"
-        }
-    },
-    {
-        "url": "/cubes",
-        "params": {
-            "templateUrl": "partials/cubes/cubes.html",
-            "tab": "models",
-            "controller": "CubesCtrl"
-        }
-    },
-    {
         "url": "/jobs",
         "params": {
             "templateUrl": "partials/jobs/jobs.html",


[26/52] [abbrv] incubator-kylin git commit: switch tab models, data source in models page

Posted by ma...@apache.org.
switch tab models,data source in models page


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

Branch: refs/heads/0.8.0
Commit: 16b6664144cac64f8c0606e472b71e4cd6a97d17
Parents: c3394d6
Author: jiazhong <ji...@ebay.com>
Authored: Thu Mar 19 19:56:55 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:51 2015 +0800

----------------------------------------------------------------------
 .../kylin/metadata/model/DataModelDesc.java     |  34 +++++
 .../kylin/metadata/project/ProjectInstance.java |   3 -
 .../kylin/rest/controller/CubeController.java   |   4 +-
 .../kylin/rest/controller/ModelController.java  |  35 +++--
 webapp/app/js/controllers/modelEdit.js          |  43 ++----
 webapp/app/js/controllers/modelSchema.js        |  29 ----
 webapp/app/js/controllers/models.js             |  42 +++---
 webapp/app/js/controllers/page.js               |  13 +-
 webapp/app/js/model/modelList.js                |   5 +-
 webapp/app/js/model/projectModel.js             |  27 +++-
 webapp/app/js/services/tree.js                  |  33 -----
 webapp/app/less/component.less                  |   3 +
 webapp/app/partials/header.html                 |   2 +-
 webapp/app/partials/login.html                  |   2 +-
 .../modelDesigner/conditions_settings.html      |   2 +-
 .../modelDesigner/model_dimensions.html         |   2 +-
 .../app/partials/modelDesigner/model_info.html  |   3 +-
 .../partials/modelDesigner/model_measures.html  |   2 +-
 webapp/app/partials/models/model_detail.html    |  25 +---
 webapp/app/partials/models/model_schema.html    |   9 +-
 webapp/app/partials/models/models.html          |  16 ++-
 .../app/partials/tables/source_table_tree.html  |   2 +-
 webapp/app/partials/tables/table_detail.html    | 138 +++++++++++++++++++
 23 files changed, 302 insertions(+), 172 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
index cd0caee..7e888c2 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -61,6 +61,13 @@ public class DataModelDesc extends RootPersistentEntity {
     @JsonProperty("capacity")
     private RealizationCapacity capacity = RealizationCapacity.MEDIUM;
 
+
+    /**
+     * Error messages during resolving json metadata
+     */
+    private List<String> errors = new ArrayList<String>();
+
+
     public String getName() {
         return name;
     }
@@ -214,6 +221,33 @@ public class DataModelDesc extends RootPersistentEntity {
         }
     }
 
+    /**
+     * Add error info and thrown exception out
+     *
+     * @param message
+     */
+    public void addError(String message) {
+        addError(message, false);
+    }
+
+    /**
+     * @param message
+     *            error message
+     * @param silent
+     *            if throw exception
+     */
+    public void addError(String message, boolean silent) {
+        if (!silent) {
+            throw new IllegalStateException(message);
+        } else {
+            this.errors.add(message);
+        }
+    }
+
+    public List<String> getError() {
+        return this.errors;
+    }
+
     @Override
     public String toString() {
         return "DataModelDesc [name=" + name + "]";

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
index 387f735..7575ff7 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
@@ -242,14 +242,12 @@ public class ProjectInstance extends RootPersistentEntity {
     }
 
     public boolean containsModel(String modelName) {
-        modelName = modelName.toUpperCase();
         return models!=null&&models.contains(modelName);
     }
 
     public void setModels(List<String> models) { this.models = models; }
 
     public void addModel(String modelName) {
-        modelName = modelName.toUpperCase();
         if(this.getModels()==null){
             this.setModels(new ArrayList<String>());
         }
@@ -257,7 +255,6 @@ public class ProjectInstance extends RootPersistentEntity {
     }
 
     public void removeModel(String modelName){
-        modelName = modelName.toUpperCase();
         if(this.getModels()!=null) {
             this.getModels().remove(modelName);
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index bc8f09a..fb1870b 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -358,12 +358,12 @@ public class CubeController extends BasicController {
         if (desc.getError().isEmpty()) {
             cubeRequest.setSuccessful(true);
         } else {
-            logger.warn("Cube " + desc.getName() + " fail to create because " + desc.getError());
+            logger.warn("Cube " + desc.getName() + " fail to update because " + desc.getError());
             updateRequest(cubeRequest, false, omitMessage(desc.getError()));
         }
         String descData = JsonUtil.writeValueAsIndentString(desc);
         cubeRequest.setCubeDescData(descData);
-
+        cubeRequest.setSuccessful(true);
         return cubeRequest;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 97a5d32..5a18a3b 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -17,7 +17,7 @@
 */
 
 package org.apache.kylin.rest.controller;
-
+import java.util.Iterator;
 import com.codahale.metrics.annotation.Metered;
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -27,12 +27,14 @@ import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
 import org.apache.kylin.rest.exception.InternalErrorException;
 import org.apache.kylin.rest.request.ModelRequest;
 import org.apache.kylin.rest.service.ModelService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 
@@ -106,24 +108,27 @@ public class ModelController extends BasicController {
     @ResponseBody
     @Metered(name = "updateModel")
     public ModelRequest updateModelDesc(@RequestBody ModelRequest modelRequest) throws JsonProcessingException {
-
-        //Update Model
         DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
         if (modelDesc == null) {
             return modelRequest;
         }
-
         try {
-            modelService.updateModelAndDesc(modelDesc,modelRequest.getProject());
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
+            modelDesc =  modelService.updateModelAndDesc(modelDesc,modelRequest.getProject());
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this cube.");
+        }  catch (Exception e) {
             logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
             throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
         }
 
+        if (modelDesc.getError().isEmpty()) {
+            modelRequest.setSuccessful(true);
+        } else {
+            logger.warn("Model " + modelDesc.getName() + " fail to update because " + modelDesc.getError());
+            updateRequest(modelRequest, false, omitMessage(modelDesc.getError()));
+        }
         String descData = JsonUtil.writeValueAsIndentString(modelDesc);
         modelRequest.setModelDescData(descData);
-
         return modelRequest;
     }
 
@@ -156,5 +161,17 @@ public class ModelController extends BasicController {
         this.modelService = modelService;
     }
 
-
+    /**
+     * @param errors
+     * @return
+     */
+    private String omitMessage(List<String> errors) {
+        StringBuffer buffer = new StringBuffer();
+        for (Iterator<String> iterator = errors.iterator(); iterator.hasNext();) {
+            String string = (String) iterator.next();
+            buffer.append(string);
+            buffer.append("\n");
+        }
+        return buffer.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 38290f7..364919d 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -64,10 +64,20 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
     // ~ init
     if ($scope.isEdit = !!$routeParams.modelName) {
+
+
+
         var modelName = $routeParams.modelName;
         ModelDescService.get({model_name: modelName}, function (model) {
                     if (model) {
                         $scope.model = model;
+                        $scope.model.project = ProjectModel.getProjectByCubeModel(modelName);
+
+                        if(!ProjectModel.getSelectedProject()){
+                            ProjectModel.setSelectedProject($scope.model.project);
+                            TableModel.aceSrcTbLoaded();
+                        }
+
                         //use
                         //convert GMT mills ,to make sure partition date show GMT Date
                         //should run only one time
@@ -78,39 +88,11 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                     }
                 });
         //init project
-            ProjectService.list({}, function (projects) {
-                $scope.projects = projects;
-                if (modelName) {
-                    var projName = null;
-                    if(ProjectModel.getSelectedProject()){
-                        projName=ProjectModel.getSelectedProject();
-                    }else{
-                        angular.forEach($scope.projects, function (project, index) {
-                            angular.forEach(project.models, function (unit, index) {
-                                if (!projName && unit === modelName) {
-                                    projName = project.name;
-                                }
-                            });
-                        });
-                    }
-
-                    if(!ProjectModel.getSelectedProject()){
-                        ProjectModel.setSelectedProject(projName);
-                        TableModel.aceSrcTbLoaded();
-                    }
-
-                    $scope.state.project = projName;
-                }
-
-                angular.forEach($scope.projects, function (project, index) {
-                    $scope.listAccess(project, 'ProjectInstance');
-                });
-            });
-
 
     } else {
         MetaModel.initModel();
         $scope.model = MetaModel.getMetaModel();
+        $scope.model.project = ProjectModel.getSelectedProject();
     }
 
     $scope.prepareModel = function () {
@@ -128,8 +110,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
             }
 
         }
+        $scope.state.project = $scope.model.project;
+        delete $scope.model.project;
         $scope.state.modelSchema = angular.toJson($scope.model, true);
-//        $scope.state.project = $scope.projectModel.selectedProject;
 
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 198a9a3..b2b7ba7 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -112,35 +112,6 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
     // ~ private methods
     function initProject() {
-        ProjectService.list({}, function (projects) {
-            $scope.projects = projects;
-
-            var cubeName = (!!$scope.routeParams.cubeName)? $scope.routeParams.cubeName:$scope.state.cubeName;
-            if (cubeName) {
-                var projName = null;
-                if(ProjectModel.getSelectedProject()){
-                    projName=ProjectModel.getSelectedProject();
-                }else{
-                    angular.forEach($scope.projects, function (project, index) {
-                        angular.forEach(project.realizations, function (unit, index) {
-                            if (!projName && unit.type=="CUBE"&&unit.realization === cubeName) {
-                                projName = project.name;
-                            }
-                        });
-                    });
-                }
-
-                if(!ProjectModel.getSelectedProject()){
-                    ProjectModel.setSelectedProject(projName);
-                    TableModel.aceSrcTbLoaded();
-                }
-
-                $scope.cubeMetaFrame.project = projName;
-            }
 
-            angular.forEach($scope.projects, function (project, index) {
-                $scope.listAccess(project, 'ProjectInstance');
-            });
-        });
     }
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index fb6c964..9f93ab6 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -18,8 +18,19 @@
 
 'use strict';
 
-KylinApp
-    .controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window,$modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
+KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window,$modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
+        //selected model
+        $scope.model = {};
+        //tree data
+        $scope.models_treedata=[];
+
+        $scope.showModels=true;
+
+        $scope.toggleTab = function(showModel){
+            $scope.showModels = showModel;
+//            console.log($scope.showModels);
+        }
+
         $scope.modelList = ModelList;
         $scope.modelConfig = modelConfig;
         ModelList.removeAll();
@@ -32,10 +43,6 @@ KylinApp
         };
 
 
-        //tree data
-        $scope.models_treedata=[];
-
-
         //  TODO offset&limit
         $scope.list = function (offset, limit) {
             if(!$scope.projectModel.projects.length){
@@ -68,31 +75,34 @@ KylinApp
             $scope.list().then(function(resp){
                 $scope.models_treedata = [];
                 angular.forEach(ModelList.models,function(model){
-                    var _model = {label:model.name,noLeaf:true}
-                    var _children = []
+                    var _model = {
+                        label:model.name,
+                        noLeaf:true,
+                        data:model,
+                        onSelect:function(branch){
+                         // set selecte model
+                            $scope.model=branch.data;
+                        }
+                    };
+                    var _children = [];
                     angular.forEach(model.cubes,function(cube){
                         _children.push(cube.name);
                     });
                     if(_children.length){
                          _model.children = _children;
                     }
-//                    _model.children=[''];
                     $scope.models_treedata.push(_model);
                 });
+                $scope.models_treedata = _.sortBy($scope.models_treedata, function (i) { return i.label.toLowerCase(); });
 
             });
         };
 
         $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
-            if(newValue||newValue==null){
                 ModelList.removeAll();
+                //init selected model
+                $scope.model = {};
                 $scope.init();
-            }
-
         });
-        $scope.reload = function () {
-            // trigger reload action in pagination directive
-            $scope.action.reload = !$scope.action.reload;
-        };
 
     });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/controllers/page.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/page.js b/webapp/app/js/controllers/page.js
index 6cc2762..73bcf0f 100644
--- a/webapp/app/js/controllers/page.js
+++ b/webapp/app/js/controllers/page.js
@@ -46,9 +46,10 @@ KylinApp.controller('PageCtrl', function ($scope, $q, AccessService,$modal, $loc
     ProjectService.list({}, function (projects) {
         var _projects = [];
         angular.forEach(projects, function(project, index){
-            _projects.push(project.name);
+            $scope.listAccess(project, 'ProjectInstance');
+            _projects.push(project);
         });
-        _projects = _.sortBy(_projects, function (i) { return i.toLowerCase(); });
+        _projects = _.sortBy(_projects, function (i) { return i.name.toLowerCase(); });
 
         ProjectModel.setProjects(_projects);
 
@@ -251,10 +252,10 @@ var projCtrl = function ($scope,$location, $modalInstance, ProjectService, Messa
             ProjectService.save({}, $scope.proj, function (newProj) {
                 SweetAlert.swal('Success!', 'New project created successfully!', 'success');
                 $modalInstance.dismiss('cancel');
-                if(projects) {
-                    projects.push(newProj);
-                }
-                ProjectModel.addProject(newProj.name);
+//                if(projects) {
+//                    projects.push(newProj);
+//                }
+//                ProjectModel.addProject(newProj);
                 $cookieStore.put("project",newProj.name);
                 location.reload();
             }, function(e){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 1161f47..6d56a10 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService){
+KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel){
     var models=[];
     var _this = this;
 
@@ -32,6 +32,8 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService)
                 CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
                     model.cubes=_cubes;
                 });
+
+                model.project =ProjectModel.getProjectByCubeModel(model.name);
             });
             _models = _.filter(_models,function(models){return models.name!=undefined});
             _this.models = _this.models.concat(_models);
@@ -54,4 +56,5 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService)
     this.removeAll = function(){
         _this.models=[];
     };
+
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/model/projectModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/projectModel.js b/webapp/app/js/model/projectModel.js
index b0c05fe..934424f 100644
--- a/webapp/app/js/model/projectModel.js
+++ b/webapp/app/js/model/projectModel.js
@@ -23,9 +23,7 @@ KylinApp.service('ProjectModel',function(){
 
 
     this.setSelectedProject = function(project) {
-        if(this.projects.indexOf(project) > -1) {
             this.selectedProject = project;
-        }
     };
     this.getSelectedProject = function(project) {
          return this.selectedProject;
@@ -52,9 +50,11 @@ KylinApp.service('ProjectModel',function(){
     }
 
     this.updateProject = function (_new,_old) {
-        var index =this.projects.indexOf(_old);
-        if(index>-1){
-            this.projects[index] = _new;
+        for(var i = 0;i<projects.length; i++){
+          if(projects[i].name === _old){
+              projects[i].name = _new;
+              break;
+          }
         }
     }
 
@@ -62,8 +62,23 @@ KylinApp.service('ProjectModel',function(){
         return this.projects;
     }
 
+    this.getProjectByCubeModel = function(modelName){
+        for(var i = 0;i<this.projects.length;i++){
+            if(!this.projects[i].models){
+                continue;
+            }
+            for(var j = 0;j<this.projects[i].models.length;j++){
+                var model = this.projects[i].models[j];
+                if(model.toUpperCase()===modelName.toUpperCase()){
+                    return this.projects[i].name;
+                }
+            }
+        };
+        return this.getSelectedProject();
+    }
+
     this.sortProjects = function (){
-        this.projects = _.sortBy(this.projects, function (i) { return i.toLowerCase(); });
+        this.projects = _.sortBy(this.projects, function (i) { return i.name.toLowerCase(); });
     }
 
 })

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index 4b1ef2d..d61629c 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -94,39 +94,6 @@ KylinApp.service('GraphService', function () {
                       });
                   }
           });
-
-          if (dimension.derived&&dimension.derived.length)
-          {
-              angular.forEach(dimension.derived, function(derived, index){
-                  for (var i = 0; i < lookup._children.length; i++) {
-                      if(lookup._children[i].name == derived)
-                          break;
-                  }
-                  if(i == lookup._children.length) {
-                    lookup._children.push({
-                          "type": "column",
-                          "name": derived + "(DERIVED)"
-                      });
-                  }
-              });
-          }
-
-          if (dimension.hierarchy)
-          {
-              angular.forEach(dimension.column, function(hierarchy, index){
-                  for (var i = 0; i < lookup._children.length; i++) {
-                      if(lookup._children[i].name == hierarchy)
-                          break;
-                  }
-                  if(i == lookup._children.length) {
-                    lookup._children.push({
-                          "type": "column",
-                          "name": hierarchy + "(HIERARCHY)"
-                      });
-                  }
-              });
-          }
-
         };
       });
         model.graph.columnsCount = 0;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 7da1b69..cb58e3f 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -943,4 +943,7 @@ Angular 1.2.0 Animation
 .abn-tree .indented  {
   font-size: 13px;
   color: #3a87ad;
+}
+.model-design .btn-box-tool{
+  font-size: 13px !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index cfc1aa2..43bf27d 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -33,7 +33,7 @@
                 <ul class="nav navbar-nav">
                     <li class="project-cntnr"  style="padding:7px 15px;background-color:#2e8965;" ng-if="userService.isAuthorized()">
                         <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                                ng-options="project as project for project in projectModel.projects"
+                                ng-options="project.name as project.name for project in projectModel.projects"
                                 style="width: 150px"
                                 data-placeholder="select a project"
                                 class="chosen-select">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/login.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/login.html b/webapp/app/partials/login.html
index 22b7a9b..e64f9d5 100644
--- a/webapp/app/partials/login.html
+++ b/webapp/app/partials/login.html
@@ -46,7 +46,7 @@
                                     <span>
 
                                         <select  ng-required="projectModel.projects.length" chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                                                ng-options="project as project for project in projectModel.projects "
+                                                ng-options="project.name as project.name for project in projectModel.projects "
                                                 style="width: 100% !important;"
                                                 data-placeholder="select a project"
                                                 class="chosen-select">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/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 7994fa1..308e793 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -114,7 +114,7 @@
                 <div class="row">
                     <div class="col-xs-12">
                         <ol class="text-info">
-                            <li>Not required,leave as default if this cube always need full build</li>
+                            <li>Not required,leave as default if cube always need full build</li>
                             <li>Partition column will select 'date' or 'string' type column from fact table</li>
                             <li>If column selected,please indicate start date to just pull certain data from source</li>
                         </ol>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/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 cd529d9..62af873 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -20,7 +20,7 @@
 
 <!-- Dimensions Summary -->
 <div class="dataTables_wrapper form-inline no-footer">
-    <div class="row"  ng-if="state.mode=='view'">
+    <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
         <div class="col-xs-6">
             <b>Dimensions</b>
         </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index 9b9e786..92c1ef0 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -29,7 +29,7 @@
                 </label>
                 <div class="col-xs-12 col-sm-6">
                     <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="state.project"/>
+                           ng-model="model.project"/>
                     <span ng-if="state.mode=='view'">
                         {{model.project}}
                     </span>
@@ -43,6 +43,7 @@
                 <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
                     <b>Model Name</b>
                 </label>
+
                 <div class="col-xs-12 col-sm-6">
                     <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
                            ng-model="model.name" required

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/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 74bf9ae..9451569 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -19,7 +19,7 @@
 <!-- Measures Summary -->
 <div class="dataTables_wrapper form-inline no-footer">
 
-    <table ng-if="state.mode=='view'" class="table table-striped table-hover">
+    <table ng-if="state.mode=='view'&&model.metrics.length > 0" class="table table-striped table-hover">
         <thead>
             <tr>
                 <th>ID</th>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/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 a4ae287..6d43210 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -17,28 +17,7 @@
 -->
 
 <div ng-controller="CubeModelCtrl" class="nav-tabs-custom">
-    <ul class="nav nav-tabs">
-        <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
-            <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
-        </li>
-        <li class="{{model.visiblePage=='graph'? 'active':''}}">
-            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);$event.stopPropagation();">Visualization</a>
-        </li>
-        <li class="{{model.visiblePage=='json_model'? 'active':''}}"
-            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
-            <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
-        </li>
-    </ul>
-
-    <div class="model-detail" ng-if="!model.visiblePage || model.visiblePage=='metadata'">
-        <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
-             ng-init="state={mode:'view', modelName:model.name}">
-        </div>
-    </div>
-    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="model-detail model_graph">
-    </div>
-    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
-          <pre ng-if="!state.jsonEdit"
-               style="background-color: white;border: 0px">{{angular.toJson(modelJson, true)}}</pre>
+    <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
+         ng-init="state={mode:'view', modelName:model.name}">
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 0cd0b5e..7648f93 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -16,9 +16,12 @@
 * limitations under the License.
 -->
 
-<div class="box box-primary">
+<div class="box box-primary model-design">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
+        <div class="box-tools pull-right">
+            <a class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
+        </div>
     </div>
     <div class="box-body">
         <ng-form name="design_form" ng-submit="">
@@ -40,13 +43,13 @@
             <hr/>
             <div class="wizard-actions">
                 <div class="row">
-                    <div class="col-xs-8">
+                    <div class="col-xs-8" style="display:none;">
                         <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
                         <div>
                             <a href="models" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Models</a>
                         </div>
                     </div>
-                    <div class="col-xs-4">
+                    <div class="col-xs-4 pull-right">
                         <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Model Info'">
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 49343aa..28a8fb3 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -17,11 +17,19 @@
 -->
 <div class="row">
     <!--table_tree-->
-    <div class="col-xs-3 overwriteLTE">
-        <div ng-include src="'partials/models/models_tree.html'"></div>
+    <div class="col-xs-3">
+        <tabset>
+            <tab heading="Models" select="toggleTab(true);">
+                <div ng-include src="'partials/models/models_tree.html'"></div>
+            </tab>
+            <tab heading="Data source"  select="toggleTab(false);">
+                <div ng-include src="'partials/tables/source_table_tree.html'"></div>
+            </tab>
+        </tabset>
     </div>
 
-    <div class="col-xs-9">
-        <h3>Model Info</h3>
+    <div class="col-xs-9" style="padding-top:39px;">
+        <div ng-show="showModels" ng-include src="'partials/models/model_detail.html'"></div>
+        <div ng-show="!showModels" ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/tables/source_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_table_tree.html b/webapp/app/partials/tables/source_table_tree.html
index f381077..627234e 100755
--- a/webapp/app/partials/tables/source_table_tree.html
+++ b/webapp/app/partials/tables/source_table_tree.html
@@ -16,7 +16,7 @@
 * limitations under the License.
 -->
 
-<div class="tree-border">
+<div class="tree-border" ng-controller="SourceMetaCtrl">
     <div class="row">
         <div class="col-xs-7">
             <h3 class="text-info">Tables</h3>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/16b66641/webapp/app/partials/tables/table_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html
new file mode 100644
index 0000000..b20825c
--- /dev/null
+++ b/webapp/app/partials/tables/table_detail.html
@@ -0,0 +1,138 @@
+<div  ng-controller="SourceMetaCtrl" class="nav-tabs-custom">
+    <div class="col-xs-9">
+        <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
+        <div class="tabbable nav-tabs-custom">
+            <ul class="nav nav-tabs">
+                <li class="active">
+                    <a data-toggle="tab" href="#column">Columns</a>
+                </li>
+                <li>
+                    <a data-toggle="tab" href="#schema">Extend Information</a>
+                </li>
+            </ul>
+            <div class="tab-content">
+                <!--Schema-->
+                <div id="schema" class="tab-pane">
+                    <div ng-if="tableModel.selectedSrcTable.uuid" class="table-responsive">
+                        <table class="table">
+                            <tbody>
+                            <tr>
+                                <th style="width:20%">NAME</th>
+                                <td>{{ tableModel.selectedSrcTable.name}}</td>
+                            </tr>
+                            <tr>
+                                <th>Hive DATABASE</th>
+                                <td>{{tableModel.selectedSrcTable.database}}</td>
+                            </tr>
+                            <tr>
+                                <th>SNAPSHOT TIME</th>
+                                <td>{{tableModel.selectedSrcTable.exd.lastUpdateTime | utcToConfigTimeZone}}</td>
+                            </tr>
+                            <tr>
+                                <th>LOCATION</th>
+                                <td>{{tableModel.selectedSrcTable.exd.location}}</td>
+                            </tr>
+                            <tr>
+                                <th>INPUT FORMAT</th>
+                                <td>{{tableModel.selectedSrcTable.exd.inputformat}}</td>
+                            </tr>
+                            <tr>
+                                <th>OUTPUT FORMAT</th>
+                                <td>{{tableModel.selectedSrcTable.exd.outputformat}}</td>
+                            </tr>
+                            <tr>
+                                <th>OWNER</th>
+                                <td><a href="mailto:{{tableModel.selectedSrcTable.exd.owner}}">{{tableModel.selectedSrcTable.exd.owner}}</a></td>
+                            </tr>
+                            <tr>
+                                <th>TOTAL FILE NUMBER</th>
+                                <td>{{tableModel.selectedSrcTable.exd.totalNumberFiles}}</td>
+                            </tr>
+                            <tr>
+                                <th>TOTAL FILE SIZE</th>
+                                <td>{{tableModel.selectedSrcTable.exd.totalFileSize}}</td>
+                            </tr>
+                            <tr>
+                                <th>PARTITIONED</th>
+                                <td>{{tableModel.selectedSrcTable.exd.partitioned}}</td>
+                            </tr>
+                            <tr>
+                                <th>PARTITION COLUMNS</th>
+                                <td>{{tableModel.selectedSrcTable.exd.partitionColumns}}</td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+                <!--Columns-->
+                <div id="column" class="tab-pane active">
+                    <div class="profile-user-info">
+                        <div>
+                            <label class="table-header-text">Columns</label>
+                            <span class="input-icon form-search nav-search pull-right">
+                                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="columnName"/>
+                                <i class="ace-icon fa fa-search nav-search-icon"></i>
+                            </span>
+                        </div>
+                        <div class="space-6"></div>
+                        <div ng-if="(tableModel.selectedSrcTable.columns | filter: columnName).length>0">
+                            <table class="table table-hover table-striped list">
+                                <thead>
+                                <tr style="cursor: pointer">
+                                    <th ng-repeat="theaditem in tableConfig.theaditems"
+                                        ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
+                                        {{theaditem.name}}
+                                        <i ng-if="state.reverseColumn!= theaditem.attr"
+                                           class="fa fa-unsorted"></i>
+                                        <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
+                                           class="fa fa-sort-asc"></i>
+                                        <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
+                                           class="fa fa-sort-desc"></i>
+                                    </th>
+                                </tr>
+                                </thead>
+
+                                <tr ng-repeat="column in tableModel.selectedSrcTable.columns | filter: columnName | orderObjectBy:state.filterAttr:state.filterReverse">
+                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
+                                        {{ column.id}}
+                                    </td>
+                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
+                                        {{ column.name}}
+                                    </td>
+                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
+                                        {{ column.datatype}}
+                                    </td>
+                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
+                                        <!--{{ tableModel.selectedSrcTable.cardinality[column.name]}}-->
+                                        {{column.cardinality}}
+                                    </td>
+                                </tr>
+                            </table>
+                        </div>
+                        <div ng-if="(tableModel.selectedSrcTable.columns | filter: columnName).length == 0" no-result
+                             text="No Matched Table Column."></div>
+                        <div ng-if="!!!tableModel.selectedSrcTable.uuid">
+                            <div no-result text="No Table Selected."></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <script type="text/ng-template" id="addHiveTable.html">
+        <div class="modal-header">
+            <h4>Load Hive Table Metadata</h4>
+        </div>
+        <div class="modal-body">
+            <span><strong>Project: </strong>{{ $parent.projectName!=null?$parent.projectName:'NULL'}}</span>
+            <label for="tables"> Table Names:(Seperate with comma)</label>
+            <textarea ng-model="$parent.tableNames" class="form-control" id="tables"
+                      placeholder="table1,table2  By default,system will choose 'Default' as database,you can specify database like this 'database.table'"></textarea>
+        </div>
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-click="add()">Sync</button>
+            <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
+</div>



[06/52] [abbrv] incubator-kylin git commit: KYLIN-759 make storage cache realization independent

Posted by ma...@apache.org.
KYLIN-759 make storage cache realization independent


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

Branch: refs/heads/0.8.0
Commit: 91792351312dee2c54c6c3b0f861e35722caa9df
Parents: ac515a7
Author: honma <ho...@ebay.com>
Authored: Thu May 14 17:31:19 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Thu May 14 20:22:04 2015 +0800

----------------------------------------------------------------------
 .../AbstractCacheFledgedStorageEngine.java      | 23 +++++----
 .../cache/CacheFledgedDynamicStorageEngine.java |  6 +--
 .../cache/CacheFledgedStaticStorageEngine.java  |  4 +-
 .../apache/kylin/storage/cache/EhcacheTest.java | 51 +++++++++++---------
 4 files changed, 47 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/91792351/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
index 09f0026..8e1b50a 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
@@ -3,10 +3,9 @@ package org.apache.kylin.storage.cache;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.CacheManager;
 import net.sf.ehcache.config.CacheConfiguration;
-import net.sf.ehcache.config.MemoryUnit;
+import net.sf.ehcache.config.Configuration;
 import net.sf.ehcache.config.PersistenceConfiguration;
 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
-
 import org.apache.kylin.metadata.realization.StreamSQLDigest;
 import org.apache.kylin.metadata.tuple.TeeTupleItrListener;
 import org.apache.kylin.storage.ICachableStorageEngine;
@@ -19,7 +18,13 @@ import org.slf4j.LoggerFactory;
  */
 public abstract class AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
     private static final Logger logger = LoggerFactory.getLogger(AbstractCacheFledgedStorageEngine.class);
-    protected static CacheManager cacheManager = CacheManager.create();
+    protected static CacheManager cacheManager;
+
+    static {
+        Configuration conf = new Configuration();
+        conf.setMaxBytesLocalHeap("1024M");
+        cacheManager = CacheManager.create(conf);
+    }
 
     protected final ICachableStorageEngine underlyingStorage;
     protected StreamSQLDigest streamSQLDigest;
@@ -28,20 +33,20 @@ public abstract class AbstractCacheFledgedStorageEngine implements IStorageEngin
     public AbstractCacheFledgedStorageEngine(ICachableStorageEngine underlyingStorage) {
         this.underlyingStorage = underlyingStorage;
         this.queryCacheExists = false;
-        this.makeCacheIfNecessary(underlyingStorage.getClass().getName());
+        this.makeCacheIfNecessary(underlyingStorage.getStorageUUID());
     }
 
-    private void makeCacheIfNecessary(String storageClassName) {
-        if (cacheManager.getCache(storageClassName) == null) {
-            logger.info("Cache for {} initting:", storageClassName);
+    private void makeCacheIfNecessary(String realizationUUID) {
+        if (cacheManager.getCache(realizationUUID) == null) {
+            logger.info("Cache for {} initting...", realizationUUID);
             // TODO: L4J [2015-04-20 10:44:03,817][WARN][net.sf.ehcache.pool.sizeof.ObjectGraphWalker] - The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. This can be avoided by setting the CacheManger or Cache <sizeOfPolicy> elements maxDepthExceededBehavior to "abort" or adding stop points with @IgnoreSizeOf annotations. If performance degradation is NOT an issue at the configured limit, raise the limit value using the CacheManager or Cache <sizeOfPolicy
             //Create a Cache specifying its configuration.
-            Cache storageCache = new Cache(new CacheConfiguration(storageClassName, 0).//
+            Cache storageCache = new Cache(new CacheConfiguration(realizationUUID, 0).//
                     memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU).//
                     eternal(false).//
                     timeToIdleSeconds(86400).//
                     diskExpiryThreadIntervalSeconds(0).//
-                    maxBytesLocalHeap(256, MemoryUnit.MEGABYTES).//
+                    //maxBytesLocalHeap(256, MemoryUnit.MEGABYTES).//already defined at manager scope
                     persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)));
             //TODO: deal with failed queries, and only cache too long query
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/91792351/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
index 0a4fd2a..f62551b 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
@@ -36,7 +36,7 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
         this.partitionColRef = partitionColRef;
 
         Preconditions.checkArgument(this.partitionColRef != null, "For dynamic columns like " + //
-                this.underlyingStorage.getClass().getName() + ", partition column must be provided");
+                this.underlyingStorage.getStorageUUID()+ ", partition column must be provided");
     }
 
     @Override
@@ -47,7 +47,7 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
 
         streamSQLDigest = new StreamSQLDigest(sqlDigest, partitionColRef);
         StreamSQLResult cachedResult = null;
-        Cache cache = cacheManager.getCache(this.underlyingStorage.getClass().getName());
+        Cache cache = cacheManager.getCache(this.underlyingStorage.getStorageUUID());
         Element element = cache.get(streamSQLDigest);
         if (element != null) {
             this.queryCacheExists = true;
@@ -133,7 +133,7 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
         }
 
         StreamSQLResult newCacheEntry = new StreamSQLResult(duplicated, ts, partitionColRef);
-        cacheManager.getCache(this.underlyingStorage.getClass().getName()).put(new Element(streamSQLDigest, newCacheEntry));
+        cacheManager.getCache(this.underlyingStorage.getStorageUUID()).put(new Element(streamSQLDigest, newCacheEntry));
         logger.info("cache after the query: " + newCacheEntry);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/91792351/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
index a309c24..72372c6 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
@@ -32,7 +32,7 @@ public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorage
 
         streamSQLDigest = new StreamSQLDigest(sqlDigest, null);
         StreamSQLResult cachedResult = null;
-        Cache cache = cacheManager.getCache(this.underlyingStorage.getClass().getName());
+        Cache cache = cacheManager.getCache(this.underlyingStorage.getStorageUUID());
         Element element = cache.get(streamSQLDigest);
         if (element != null) {
             this.queryCacheExists = true;
@@ -66,7 +66,7 @@ public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorage
     @Override
     public void notify(List<ITuple> duplicated) {
         StreamSQLResult newCacheEntry = new StreamSQLResult(duplicated, Ranges.<Long> all(), null);
-        cacheManager.getCache(this.underlyingStorage.getClass().getName()).put(new Element(streamSQLDigest, newCacheEntry));
+        cacheManager.getCache(this.underlyingStorage.getStorageUUID()).put(new Element(streamSQLDigest, newCacheEntry));
         logger.info("cache after the query: " + newCacheEntry);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/91792351/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
index 1dec9e6..fe390de 100644
--- a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
@@ -2,8 +2,9 @@ package org.apache.kylin.storage.cache;
 
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
 import net.sf.ehcache.config.CacheConfiguration;
-import net.sf.ehcache.config.MemoryUnit;
+import net.sf.ehcache.config.Configuration;
 import net.sf.ehcache.config.PersistenceConfiguration;
 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
 
@@ -14,7 +15,11 @@ import org.junit.Test;
 public class EhcacheTest {
     @Test
     public void basicTest() throws InterruptedException {
-        CacheManager cacheManager = CacheManager.create();
+        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
+
+        Configuration conf = new Configuration();
+        conf.setMaxBytesLocalHeap("100M");
+        CacheManager cacheManager = CacheManager.create(conf);
 
         //Create a Cache specifying its configuration.
         Cache testCache = //Create a Cache specifying its configuration.
@@ -23,31 +28,31 @@ public class EhcacheTest {
                 eternal(false).//
                 timeToIdleSeconds(86400).//
                 diskExpiryThreadIntervalSeconds(0).//
-                maxBytesLocalHeap(100, MemoryUnit.MEGABYTES).//
+                //maxBytesLocalHeap(1000, MemoryUnit.MEGABYTES).//
                 persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)));
 
         cacheManager.addCache(testCache);
 
-        //
-        //        byte[] blob2 = new byte[(1024 * 400 * 1024)];//400M
-        //
-        //        testCache.put(new Element("1", blob));
-        //        System.out.println(testCache.get("1") == null);
-        //        System.out.println(testCache.getSize());
-        //        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
-        //        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
-        //        testCache.put(new Element("2", blob));
-        //        System.out.println(testCache.get("1") == null);
-        //        System.out.println(testCache.getSize());
-        //        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
-        //        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
-        //        testCache.put(new Element("3", blob));
-        //        System.out.println(testCache.get("1") == null);
-        //        System.out.println(testCache.get("2") == null);
-        //        System.out.println(testCache.get("3") == null);
-        //        System.out.println(testCache.getSize());
-        //        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
-        //        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
+        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
+        byte[] blob = new byte[(1024 * 40 * 1024)];//400M
+
+        testCache.put(new Element("1", blob));
+        System.out.println(testCache.get("1") == null);
+        System.out.println(testCache.getSize());
+        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
+        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
+        testCache.put(new Element("2", blob));
+        System.out.println(testCache.get("1") == null);
+        System.out.println(testCache.getSize());
+        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
+        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
+        testCache.put(new Element("3", blob));
+        System.out.println(testCache.get("1") == null);
+        System.out.println(testCache.get("2") == null);
+        System.out.println(testCache.get("3") == null);
+        System.out.println(testCache.getSize());
+        System.out.println(testCache.getStatistics().getLocalHeapSizeInBytes());
+        System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
 
         cacheManager.shutdown();
     }


[28/52] [abbrv] incubator-kylin git commit: add tip when no models listed in project

Posted by ma...@apache.org.
add tip when no models listed in project


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

Branch: refs/heads/0.8.0
Commit: db883f41df6aa1bd1a14c4cf7332456093d00ac9
Parents: ef5ccb5
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 25 19:16:59 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/models.js          |  5 +++--
 webapp/app/partials/cubes/cube_detail.html   |  2 +-
 webapp/app/partials/models/model_detail.html |  3 ++-
 webapp/app/partials/models/model_schema.html | 22 ++++++++++++++++++++--
 4 files changed, 26 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/db883f41/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 973ede0..e9e942f 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -48,8 +48,10 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
         //  TODO offset&limit
         $scope.list = function () {
+            var defer = $q.defer();
             if(!$scope.projectModel.projects.length){
-                return [];
+                defer.resolve([]);
+                return defer.promise;
             }
 //            offset = (!!offset) ? offset : null;
 //            limit = (!!limit) ? limit : null;
@@ -62,7 +64,6 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
             $scope.loading = true;
 
-            var defer = $q.defer();
              ModelList.list(queryParam).then(function(resp){
                 $scope.loading = false;
                 defer.resolve(resp);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/db883f41/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 91e5afe..5ee5e3e 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -16,7 +16,7 @@
 * limitations under the License.
 -->
 
-<div ng-controller="CubeCtrl" class="nav-tabs-custom">
+<div ng-controller="CubeCtrl" class="nav-tabs-custom" style="margin-top:40px;">
     <ul class="nav nav-tabs">
         <li class="{{(!cube.visiblePage || cube.visiblePage=='metadata')? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='metadata'">Grid</a>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/db883f41/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 b116a0a..5f2830d 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -16,7 +16,8 @@
 * limitations under the License.
 -->
 
-<div ng-controller="CubeModelCtrl" class="nav-tabs-custom">
+<!--show detail when exist models-->
+<div ng-controller="CubeModelCtrl" class="nav-tabs-custom" style="margin-top:40px;">
     <ul ng-show="model.name" class="nav nav-tabs">
         <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
             <a href="" ng-click="model.visiblePage='metadata'">Grid</a>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/db883f41/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 898343a..aef280b 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -16,6 +16,7 @@
 * limitations under the License.
 -->
 
+<!--hide when view model and no model selected-->
 <div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
@@ -67,13 +68,30 @@
     </div>
 </div>
 
-<div ng-show="state.mode=='view'&&!model.name">
+<!--show create model tip when no models list-->
+<div ng-show="state.mode=='view'&&!models_treedata.length" style="margin-top:40px;">
+    <div class="box box-primary">
+        <div class="box-header with-border">
+            <h3 class="box-title">No model</h3>
+        </div>
+        <div class="box-body">
+            <p>
+                <a href="models/add" ng-if="userService.hasRole('ROLE_MODELER')">Click here to create your model</a>
+            </p>
+        </div><!-- /.box-body -->
+    </div>
+</div>
+
+<!--show select model tip when models not empty and no model selected-->
+<div ng-show="state.mode=='view'&&!!models_treedata.length&&!model.name" style="margin-top:40px;">
     <div class="box box-primary">
         <div class="box-header with-border">
             <h3 class="box-title">No model selected</h3>
         </div>
         <div class="box-body">
-            Plese choose your model
+            <p>
+               Select your model
+            </p>
         </div><!-- /.box-body -->
     </div>
 </div>
\ No newline at end of file


[27/52] [abbrv] incubator-kylin git commit: new model page

Posted by ma...@apache.org.
new model page


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

Branch: refs/heads/0.8.0
Commit: c3394d6e157f9dc4127224b19401e16d38ea34bd
Parents: 4c456a2
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 18 20:46:34 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:51 2015 +0800

----------------------------------------------------------------------
 .../kylin/rest/controller/CubeController.java   |   4 +-
 .../kylin/rest/controller/ModelController.java  |   2 +-
 .../apache/kylin/rest/service/CubeService.java  |  25 ++--
 .../rest/controller/CubeControllerTest.java     |   4 +-
 .../kylin/rest/service/CubeServiceTest.java     |   4 +-
 webapp/app/index.html                           |   6 +-
 webapp/app/js/app.js                            |   2 +-
 webapp/app/js/controllers/job.js                |   2 +-
 webapp/app/js/controllers/models.js             |  41 +++++--
 webapp/app/js/model/modelList.js                |   9 +-
 webapp/app/less/app.less                        |   2 +-
 webapp/app/less/component.less                  |  51 ++++++++
 webapp/app/partials/models/_models.html         | 117 +++++++++++++++++++
 webapp/app/partials/models/models.html          | 102 +---------------
 webapp/app/partials/models/models_info.html     |  46 ++++++++
 webapp/app/partials/models/models_tree.html     |  47 ++++++++
 webapp/bower.json                               |   5 +-
 17 files changed, 338 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index d4cef18..bc8f09a 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -89,8 +89,8 @@ public class CubeController extends BasicController {
     @RequestMapping(value = "", method = {RequestMethod.GET})
     @ResponseBody
     @Metered(name = "listCubes")
-    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam("limit") Integer limit, @RequestParam("offset") Integer offset) {
-        return cubeService.getCubes(cubeName, projectName, (null == limit) ? 20 : limit, offset);
+    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName,@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam("limit") Integer limit, @RequestParam("offset") Integer offset) {
+        return cubeService.getCubes(cubeName, projectName, modelName,(null == limit) ? 20 : limit, offset);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index ce53474..97a5d32 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -123,7 +123,7 @@ public class ModelController extends BasicController {
 
         String descData = JsonUtil.writeValueAsIndentString(modelDesc);
         modelRequest.setModelDescData(descData);
-        modelRequest.setSuccessful(true);
+
         return modelRequest;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
index d786b1e..8dc0345 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -81,7 +81,7 @@ public class CubeService extends BasicService {
     private AccessService accessService;
 
     @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<CubeInstance> listAllCubes(final String cubeName, final String projectName) {
+    public List<CubeInstance> listAllCubes(final String cubeName, final String projectName,final String modelName) {
         List<CubeInstance> cubeInstances = null;
         ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
 
@@ -91,8 +91,21 @@ public class CubeService extends BasicService {
             cubeInstances = listAllCubes(projectName);
         }
 
+        List<CubeInstance> filterModelCubes = new ArrayList<CubeInstance>();
+
+        if(modelName!=null){
+            for (CubeInstance cubeInstance : cubeInstances) {
+                boolean isCubeMatch = cubeInstance.getDescriptor().getModelName().toLowerCase().equals(modelName.toLowerCase());
+                if (isCubeMatch) {
+                    filterModelCubes.add(cubeInstance);
+                }
+            }
+        }else{
+            filterModelCubes = cubeInstances;
+        }
+
         List<CubeInstance> filterCubes = new ArrayList<CubeInstance>();
-        for (CubeInstance cubeInstance : cubeInstances) {
+        for (CubeInstance cubeInstance : filterModelCubes) {
             boolean isCubeMatch = (null == cubeName) || cubeInstance.getName().toLowerCase().contains(cubeName.toLowerCase());
 
             if (isCubeMatch) {
@@ -103,12 +116,12 @@ public class CubeService extends BasicService {
         return filterCubes;
     }
 
-    public List<CubeInstance> getCubes(final String cubeName, final String projectName, final Integer limit, final Integer offset) {
+    public List<CubeInstance> getCubes(final String cubeName, final String projectName,final String modelName ,final Integer limit, final Integer offset) {
         int climit = (null == limit) ? 30 : limit;
         int coffset = (null == offset) ? 0 : offset;
 
         List<CubeInstance> cubes;
-        cubes = listAllCubes(cubeName, projectName);
+        cubes = listAllCubes(cubeName, projectName,modelName);
 
         if (cubes.size() <= coffset) {
             return Collections.emptyList();
@@ -302,7 +315,6 @@ public class CubeService extends BasicService {
      * @param cube
      * @return
      * @throws IOException
-     * @throws CubeIntegrityException
      * @throws JobException
      */
     @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
@@ -328,7 +340,6 @@ public class CubeService extends BasicService {
      * Update a cube status from ready to disabled.
      *
      * @return
-     * @throws CubeIntegrityException
      * @throws IOException
      * @throws JobException
      */
@@ -356,7 +367,6 @@ public class CubeService extends BasicService {
      * Update a cube status from disable to ready.
      *
      * @return
-     * @throws CubeIntegrityException
      * @throws IOException
      * @throws JobException
      */
@@ -518,7 +528,6 @@ public class CubeService extends BasicService {
      *
      * @throws IOException
      * @throws JobException
-     * @throws CubeIntegrityException
      */
     private void releaseAllSegments(CubeInstance cube) throws IOException, JobException {
         final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
index 52c2d77..1ec27d5 100644
--- a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
@@ -66,7 +66,7 @@ public class CubeControllerTest extends ServiceTestBase {
         CubeDesc[] cubes = (CubeDesc[]) cubeDescController.getCube("test_kylin_cube_with_slr_ready");
         Assert.assertNotNull(cubes);
         Assert.assertNotNull(cubeController.getSql("test_kylin_cube_with_slr_ready", "20130331080000_20131212080000"));
-        Assert.assertNotNull(cubeController.getCubes(null, null, 0, 5));
+        Assert.assertNotNull(cubeController.getCubes(null, null, null,0, 5));
 
         CubeDesc cube = cubes[0];
         CubeDesc newCube = new CubeDesc();
@@ -109,7 +109,7 @@ public class CubeControllerTest extends ServiceTestBase {
         cubeController.updateNotifyList(newCubeName, notifyList);
         cubeController.updateCubeCost(newCubeName, 80);
 
-        List<CubeInstance> cubeInstances = cubeController.getCubes(newCubeName, "default", 1, 0);
+        List<CubeInstance> cubeInstances = cubeController.getCubes(newCubeName, "default",null, 1, 0);
 
         CubeInstance cubeInstance = cubeInstances.get(0);
         Assert.assertTrue(cubeInstance.getDescriptor().getNotifyList().contains("john@example.com"));

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/server/src/test/java/org/apache/kylin/rest/service/CubeServiceTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/service/CubeServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/CubeServiceTest.java
index 7bf2516..88e31f4 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/CubeServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/CubeServiceTest.java
@@ -48,13 +48,13 @@ public class CubeServiceTest extends ServiceTestBase {
         Assert.assertTrue(CubeService.getCubeDescNameFromCube("testCube").equals("testCube_desc"));
         Assert.assertTrue(CubeService.getCubeNameFromDesc("testCube_desc").equals("testCube"));
 
-        List<CubeInstance> cubes = cubeService.getCubes(null, null, null, null);
+        List<CubeInstance> cubes = cubeService.getCubes(null, null, null, null,null);
         Assert.assertNotNull(cubes);
         CubeInstance cube = cubes.get(0);
         cubeService.isCubeDescEditable(cube.getDescriptor());
         cubeService.isCubeEditable(cube);
 
-        cubes = cubeService.getCubes(null, null, 1, 0);
+        cubes = cubeService.getCubes(null, null,null, 1, 0);
         Assert.assertTrue(cubes.size() == 1);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 8c6bb2d..ac5c7b7 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -29,7 +29,7 @@
 
     <!-- ref:css css/styles.min.<%= buildNumber %>.css -->
     <link rel="stylesheet" type="text/css" href="components/bootstrap/dist/css/bootstrap.min.css">
-    <link rel="stylesheet" type="text/css" href="components/font-awesome/css/font-awesome.css">
+    <link rel="stylesheet" type="text/css" href="components/components-font-awesome/css/font-awesome.css">
 
     <link rel="stylesheet" type="text/css" href="components/angular-tree-control/css/tree-control.css">
     <link rel="stylesheet" type="text/css" href="components/angular-tree-control/css/tree-control-attribute.css">
@@ -44,6 +44,7 @@
     <link rel="stylesheet" type="text/css" href="css/AdminLTE-fonts.css">
     <link rel="stylesheet" type="text/css" href="css/AdminLTE.css">
     <link rel="stylesheet" type="text/css" href="components/bootstrap-sweetalert/lib/sweet-alert.css">
+    <link rel="stylesheet" type="text/css" href="components/angular-bootstrap-nav-tree/dist/abn_tree.css">
 
     <link rel="stylesheet/less" href="less/build.less">
     <!-- endref -->
@@ -100,7 +101,8 @@
 <script src="components/underscore/underscore.js"></script>
 <script src="components/angular-underscore/angular-underscore.js"></script>
 <script src="components/jquery-ui/jquery-ui.min.js"></script>
-<script src="components/angular-ui-sortable/sortable.js"></script>
+<script src="components/angular-ui-sortable/sortable.min.js"></script>
+<script src="components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js"></script>
 
 <script src="js/app.js"></script>
 <script src="js/config.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/js/app.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/app.js b/webapp/app/js/app.js
index ba24cb1..1e00bdc 100644
--- a/webapp/app/js/app.js
+++ b/webapp/app/js/app.js
@@ -17,4 +17,4 @@
 */
 
 //Kylin Application Module
-KylinApp = angular.module('kylin', ['ngRoute', 'ngResource', 'ngGrid', 'ui.bootstrap', 'ui.ace', 'base64', 'angularLocalStorage', 'localytics.directives', 'treeControl', 'nvd3ChartDirectives','ngLoadingRequest','oitozero.ngSweetAlert','ngCookies','angular-underscore', 'ngAnimate', 'ui.sortable']);
+KylinApp = angular.module('kylin', ['ngRoute', 'ngResource', 'ngGrid', 'ui.bootstrap', 'ui.ace', 'base64', 'angularLocalStorage', 'localytics.directives', 'treeControl', 'nvd3ChartDirectives','ngLoadingRequest','oitozero.ngSweetAlert','ngCookies','angular-underscore', 'ngAnimate', 'ui.sortable','angularBootstrapNavTree']);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/js/controllers/job.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/job.js b/webapp/app/js/controllers/job.js
index 0054915..0e65578 100644
--- a/webapp/app/js/controllers/job.js
+++ b/webapp/app/js/controllers/job.js
@@ -78,7 +78,7 @@ KylinApp
             return JobList.list(jobRequest).then(function(resp){
                 $scope.state.loading = false;
                 defer.resolve(resp);
-                defer.promise;
+                return defer.promise;
             });
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 1777723..fb6c964 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -19,24 +19,30 @@
 'use strict';
 
 KylinApp
-    .controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
+    .controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window,$modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
         $scope.modelList = ModelList;
         $scope.modelConfig = modelConfig;
         ModelList.removeAll();
         $scope.loading = false;
         $scope.action = {};
-
+        $scope.window = 0.68 * $window.innerHeight;
         $scope.listParams={
             cubeName: $routeParams.cubeName,
             projectName: $routeParams.projectName
         };
 
+
+        //tree data
+        $scope.models_treedata=[];
+
+
+        //  TODO offset&limit
         $scope.list = function (offset, limit) {
             if(!$scope.projectModel.projects.length){
                 return [];
             }
             offset = (!!offset) ? offset : 0;
-            limit = (!!limit) ? limit : 20;
+            limit = (!!limit) ? limit : 70;
 
             var queryParam = {offset: offset, limit: limit};
             if ($scope.listParams.modelName) {
@@ -47,27 +53,40 @@ KylinApp
             $scope.loading = true;
 
             var defer = $q.defer();
-            return ModelList.list(queryParam).then(function(resp){
+             ModelList.list(queryParam).then(function(resp){
                 $scope.loading = false;
                 defer.resolve(resp);
-                defer.promise;
             },function(resp){
                 $scope.loading = false;
                 defer.resolve([]);
-                defer.promise;
             });
+
+            return  defer.promise;
         };
 
+        $scope.init = function(){
+            $scope.list().then(function(resp){
+                $scope.models_treedata = [];
+                angular.forEach(ModelList.models,function(model){
+                    var _model = {label:model.name,noLeaf:true}
+                    var _children = []
+                    angular.forEach(model.cubes,function(cube){
+                        _children.push(cube.name);
+                    });
+                    if(_children.length){
+                         _model.children = _children;
+                    }
+//                    _model.children=[''];
+                    $scope.models_treedata.push(_model);
+                });
 
-        $scope.loadDetail = function (model) {
-            $log.info(model);
+            });
         };
 
-
         $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
-            if(newValue!=oldValue||newValue==null){
+            if(newValue||newValue==null){
                 ModelList.removeAll();
-                $scope.reload();
+                $scope.init();
             }
 
         });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 9e92ed9..1161f47 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('ModelList',function(ModelService,$q,AccessService){
+KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService){
     var models=[];
     var _this = this;
 
@@ -28,10 +28,14 @@ KylinApp.service('ModelList',function(ModelService,$q,AccessService){
                 AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
                     model.accessEntities = accessEntities;
                 });
+//                add cube info to model
+                CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+                    model.cubes=_cubes;
+                });
             });
             _models = _.filter(_models,function(models){return models.name!=undefined});
             _this.models = _this.models.concat(_models);
-            defer.resolve(_this.models.length);
+            defer.resolve(_this.models);
         },function(){
             defer.reject("Failed to load models");
         });
@@ -39,6 +43,7 @@ KylinApp.service('ModelList',function(ModelService,$q,AccessService){
 
     };
 
+
     this.removemodels = function(models){
         var modelsIndex = _this.models.indexOf(models);
         if (modelsIndex > -1) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index 7296eb9..c829ca1 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -375,7 +375,7 @@ input.ng-invalid-required:after {
 
 .nav-pills>li {
 cursor: pointer;
-background-color: #094868;
+//background-color: #094868;
 }
 
 .alert-info {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 0289bc4..7da1b69 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -893,3 +893,54 @@ ul.messenger-theme-ice .messenger-message{
 .model-dimension-edit .chosen-container{
   width:100% !important;
 }
+
+
+//overwrite style for abn-tree
+.abn-tree-animate-enter,
+li.abn-tree-row.ng-enter {
+  transition: 200ms linear all;
+  position: relative;
+  display: block;
+  opacity: 0;
+  max-height:0px;
+}
+.abn-tree-animate-enter.abn-tree-animate-enter-active,
+li.abn-tree-row.ng-enter-active{
+  opacity: 1;
+  max-height:30px;
+}
+
+.abn-tree-animate-leave,
+li.abn-tree-row.ng-leave {
+  transition: 200ms linear all;
+  position: relative;
+  display: block;
+  height:30px;
+  max-height: 30px;
+  opacity: 1;
+}
+.abn-tree-animate-leave.abn-tree-animate-leave-active,
+li.abn-tree-row.ng-leave-active {
+  height: 0px;
+  max-height:0px;
+  opacity: 0;
+}
+
+
+/*
+------------------------------------------
+Angular 1.2.0 Animation
+*/
+
+
+.abn-tree-animate.ng-enter{
+
+}
+.abn-tree-animate.ng-enter{
+
+}
+
+.abn-tree .indented  {
+  font-size: 13px;
+  color: #3a87ad;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/partials/models/_models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/_models.html b/webapp/app/partials/models/_models.html
new file mode 100644
index 0000000..ac433c1
--- /dev/null
+++ b/webapp/app/partials/models/_models.html
@@ -0,0 +1,117 @@
+<!--
+* 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.
+-->
+
+<div class="page-header row">
+    <!--Project-->
+    <div class="col-xs-3">
+        <form ng-if="userService.isAuthorized()">
+            <div class="form-group">
+                <!--Project-->
+                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
+                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
+                    <i class="fa fa-plus"></i>
+                </a>
+            </div>
+        </form>
+    </div>
+    <!--Model Name-->
+    <div class="col-xs-3">
+        <form ng-submit="" style="display: inline" >
+            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
+                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
+                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
+            </span>
+        </form>
+    </div>
+    <div class="pull-right">
+        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
+    </div>
+</div>
+<div ng-if="!loading && modelList.models.length == 0">
+    <div no-result text="No Model."></div>
+</div>
+<loading ng-if="loading" text="Loading Models..."></loading>
+
+<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
+    <div class="row">
+        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
+    </div>
+    <table class="table table-striped table-bordered table-hover dataTable no-footer">
+        <!--Header-->
+        <thead>
+        <tr style="cursor: pointer">
+            <th ng-repeat="theaditem in modelConfig.theaditems"
+                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
+                {{theaditem.name}}
+                <i ng-if="state.reverseColumn!= theaditem.attr"
+                   class="fa fa-unsorted"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
+                   class="fa fa-sort-asc"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
+                   class="fa fa-sort-desc"></i>
+            </th>
+            <th>Actions</th>
+        </tr>
+        </thead>
+        <!--Body-->
+        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
+        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
+            <td>
+                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
+                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
+                {{ model.name}}
+            </td>
+            <td>
+                    {{ model.fact_table}}
+            </td>
+            <td>
+                    {{ model.last_modified | utcToConfigTimeZone}}
+            </td>
+            <td>
+                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
+                            data-toggle="dropdown">
+                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                    </button>
+                    <ul class="dropdown-menu" role="menu">
+                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
+                        <li ng-show="false" ng-if="userService.hasRole('ROLE_ADMIN')">
+                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
+
+                    </ul>
+                </div>
+                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
+                    N/A
+                </span>
+            </td>
+        </tr>
+        <tr ng-show="model.showDetail">
+            <td colspan="9" style="padding: 10px 30px 10px 30px;">
+                <div ng-include src="'partials/models/model_detail.html'"></div>
+            </td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+
+<div class="row">
+    <div class="col-xs-12">
+        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index ac433c1..49343aa 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -15,103 +15,13 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-
-<div class="page-header row">
-    <!--Project-->
-    <div class="col-xs-3">
-        <form ng-if="userService.isAuthorized()">
-            <div class="form-group">
-                <!--Project-->
-                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
-                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
-                    <i class="fa fa-plus"></i>
-                </a>
-            </div>
-        </form>
-    </div>
-    <!--Model Name-->
-    <div class="col-xs-3">
-        <form ng-submit="" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
-                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
-                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
-            </span>
-        </form>
-    </div>
-    <div class="pull-right">
-        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
+<div class="row">
+    <!--table_tree-->
+    <div class="col-xs-3 overwriteLTE">
+        <div ng-include src="'partials/models/models_tree.html'"></div>
     </div>
-</div>
-<div ng-if="!loading && modelList.models.length == 0">
-    <div no-result text="No Model."></div>
-</div>
-<loading ng-if="loading" text="Loading Models..."></loading>
 
-<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
-    <div class="row">
-        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
+    <div class="col-xs-9">
+        <h3>Model Info</h3>
     </div>
-    <table class="table table-striped table-bordered table-hover dataTable no-footer">
-        <!--Header-->
-        <thead>
-        <tr style="cursor: pointer">
-            <th ng-repeat="theaditem in modelConfig.theaditems"
-                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
-                {{theaditem.name}}
-                <i ng-if="state.reverseColumn!= theaditem.attr"
-                   class="fa fa-unsorted"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
-                   class="fa fa-sort-asc"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
-                   class="fa fa-sort-desc"></i>
-            </th>
-            <th>Actions</th>
-        </tr>
-        </thead>
-        <!--Body-->
-        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
-        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
-            <td>
-                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
-                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
-                {{ model.name}}
-            </td>
-            <td>
-                    {{ model.fact_table}}
-            </td>
-            <td>
-                    {{ model.last_modified | utcToConfigTimeZone}}
-            </td>
-            <td>
-                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
-                            data-toggle="dropdown">
-                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
-                    </button>
-                    <ul class="dropdown-menu" role="menu">
-                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
-                        <li ng-show="false" ng-if="userService.hasRole('ROLE_ADMIN')">
-                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
-
-                    </ul>
-                </div>
-                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
-                    N/A
-                </span>
-            </td>
-        </tr>
-        <tr ng-show="model.showDetail">
-            <td colspan="9" style="padding: 10px 30px 10px 30px;">
-                <div ng-include src="'partials/models/model_detail.html'"></div>
-            </td>
-        </tr>
-        </tbody>
-    </table>
 </div>
-
-
-<div class="row">
-    <div class="col-xs-12">
-        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
-    </div>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/partials/models/models_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_info.html b/webapp/app/partials/models/models_info.html
new file mode 100644
index 0000000..f381077
--- /dev/null
+++ b/webapp/app/partials/models/models_info.html
@@ -0,0 +1,46 @@
+<!--
+* 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.
+-->
+
+<div class="tree-border">
+    <div class="row">
+        <div class="col-xs-7">
+            <h3 class="text-info">Tables</h3>
+        </div>
+
+        <!--button-->
+        <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;">
+            <div class="pull-right">
+                <a class="btn btn-xs btn-primary" tooltip="Load Hive Table"  ng-if="userService.hasRole('ROLE_ADMIN')"  ng-click="openModal()"><i class="fa fa-download"></i></a>
+                <a class="btn btn-xs btn-success" tooltip="Refresh Tables" ng-click="aceSrcTbChanged()"><i class="fa fa-refresh"></i></a>
+            </div>
+        </div>
+
+    </div>
+    <div class="space-4"></div>
+    <!--tree-->
+    <div style="width:100%; height:{{window}}px; overflow:auto;">
+        <treecontrol ng-if="tableModel.selectedSrcDb.length > 0" class="tree-light"
+                     dirSelection="true"
+                     tree-model="tableModel.selectedSrcDb"
+                     options="tableModel.treeOptions"
+                     on-selection="showSelected(node)"
+                     selected-node="tableModel.selectedSrcTable">
+            {{node.name}} {{!!(node.datatype)?'(' + trimType(node.datatype) + ')' : ''}}
+        </treecontrol>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
new file mode 100644
index 0000000..40b7c3a
--- /dev/null
+++ b/webapp/app/partials/models/models_tree.html
@@ -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.
+-->
+
+<div class="tree-border">
+    <div class="row">
+        <div class="col-xs-7">
+            <h3 class="text-info">Models</h3>
+        </div>
+
+        <!--button-->
+        <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;">
+            <div class="pull-right">
+                <a class="btn btn-xs btn-primary" href='models/add' tooltip="Create Model"  ng-if="userService.hasRole('ROLE_ADMIN')"><i class="fa fa-plus"></i></a>
+            </div>
+        </div>
+
+    </div>
+    </div>
+    <div class="space-4 box-header with-border"></div>
+    <!--tree-->
+    <div style="width:100%; height:{{window}}px; overflow:auto;">
+        <abn-tree
+                tree-data         = "models_treedata"
+                tree-control      = "my_tree"
+                icon-leaf         = "fa fa-cube"
+                icon-expand       = "fa fa-plus"
+                icon-collapse     = "fa fa-minus"
+                expand-level      = "2"
+                initial-selection = "Vegetable">
+            ></abn-tree>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/c3394d6e/webapp/bower.json
----------------------------------------------------------------------
diff --git a/webapp/bower.json b/webapp/bower.json
index be8eca3..b3f9a8d 100755
--- a/webapp/bower.json
+++ b/webapp/bower.json
@@ -27,8 +27,9 @@
     "underscore": "~1.7.0",
     "fuelux": "~3.5.1",
     "angular-animate": "1.2",
-    "angular-cookies":"1.2"
-
+    "angular-cookies": "1.2",
+    "angular-bootstrap-nav-tree": "*",
+    "components-font-awesome": "~4.3.0"
   },
   "devDependencies": {
     "less.js": "~1.4.0",



[23/52] [abbrv] incubator-kylin git commit: add DataModelDesc ACL & fix KYLIN-645

Posted by ma...@apache.org.
add DataModelDesc ACL & fix KYLIN-645


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

Branch: refs/heads/0.8.0
Commit: 4c456a21e144d80b32acf291e000a80d13421135
Parents: a2f4d32
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 18 14:47:48 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:27 2015 +0800

----------------------------------------------------------------------
 .../java/org/apache/kylin/metadata/MetadataManager.java   |  4 ++--
 .../apache/kylin/rest/controller/ProjectController.java   |  7 +++++--
 .../org/apache/kylin/rest/security/AclEntityFactory.java  |  8 ++++++++
 .../java/org/apache/kylin/rest/service/ModelService.java  |  7 +++++--
 .../org/apache/kylin/rest/service/ProjectService.java     | 10 ++++------
 .../org/apache/kylin/rest/service/CacheServiceTest.java   |  2 +-
 webapp/app/js/model/cubeListModel.js                      |  7 +++++--
 webapp/app/js/model/modelList.js                          | 10 +++++-----
 webapp/app/js/services/models.js                          |  2 +-
 webapp/app/partials/models/models.html                    |  4 ++--
 10 files changed, 38 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index ea03933..86d33f7 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -284,13 +284,13 @@ public class MetadataManager {
     }
 
     public List<DataModelDesc> getModels() {
-        return new ArrayList<>(dataModelDescMap.values());
+        return new ArrayList<DataModelDesc>(dataModelDescMap.values());
     }
 
     public List<DataModelDesc> getModels(String projectName){
         ProjectInstance projectInstance =  ProjectManager.getInstance(config).getProject(projectName);
         HashSet<DataModelDesc> ret = new HashSet<>();
-        if (projectInstance != null) {
+        if (projectInstance != null&&projectInstance.getModels()!=null) {
             for (String modelName : projectInstance.getModels()) {
                 DataModelDesc model = getDataModelDesc(modelName);
                 if (null != model) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java b/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
index 3a87858..bb984af 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
@@ -92,7 +92,8 @@ public class ProjectController extends BasicController {
 
         ProjectInstance updatedProj = null;
         try {
-            updatedProj = projectService.updateProject(projectRequest);
+            ProjectInstance currentProject = projectService.getProjectManager().getProject(projectRequest.getFormerProjectName());
+            updatedProj = projectService.updateProject(projectRequest,currentProject);
         } catch (Exception e) {
             logger.error("Failed to deal with the request.", e);
             throw new InternalErrorException(e.getLocalizedMessage());
@@ -106,7 +107,9 @@ public class ProjectController extends BasicController {
     @Metered(name = "deleteProject")
     public void deleteProject(@PathVariable String projectName) {
         try {
-            projectService.deleteProject(projectName);
+
+            ProjectInstance project = projectService.getProjectManager().getProject(projectName);
+            projectService.deleteProject(projectName,project);
         } catch (Exception e) {
             logger.error(e.getLocalizedMessage(), e);
             throw new InternalErrorException("Failed to delete project. " + " Caused by: " + e.getMessage(), e);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java b/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
index 0730a55..621fbe4 100644
--- a/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
+++ b/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
@@ -21,6 +21,7 @@ package org.apache.kylin.rest.security;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.job.JobInstance;
+import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 
 /**
@@ -37,6 +38,13 @@ public class AclEntityFactory {
             return cubeInstance;
         }
 
+        if ("DataModelDesc".equals(entityType)) {
+            DataModelDesc modelInstance = new DataModelDesc();
+            modelInstance.setUuid(uuid);
+
+            return modelInstance;
+        }
+
         if ("JobInstance".equals(entityType)) {
             JobInstance jobInstance = new JobInstance();
             jobInstance.setUuid(uuid);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index e423c37..181ccdf 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -23,6 +23,7 @@ import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.rest.constant.Constant;
 import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.security.AclPermission;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -97,13 +98,15 @@ public class ModelService extends BasicService {
         DataModelDesc createdDesc = null;
         String owner = SecurityContextHolder.getContext().getAuthentication().getName();
         createdDesc = getMetadataManager().createDataModelDesc(desc,projectName,owner);
+
+        accessService.init(createdDesc, AclPermission.ADMINISTRATION);
         ProjectInstance project = getProjectManager().getProject(projectName);
-        accessService.inherit(desc, project);
+        accessService.inherit(createdDesc, project);
         return createdDesc;
     }
 
 
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#model, 'ADMINISTRATION') or hasPermission(#model, 'MANAGEMENT')")
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
     public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
         DataModelDesc existingModel = getMetadataManager().getDataModelDesc(desc.getName());
         if (existingModel == null) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java b/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
index 9b6464c..2013a9f 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
@@ -65,13 +65,12 @@ public class ProjectService extends BasicService {
         return createdProject;
     }
 
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public ProjectInstance updateProject(UpdateProjectRequest projectRequest) throws IOException {
+    @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();
 
-        ProjectInstance currentProject = getProjectManager().getProject(formerProjectName);
 
         if (currentProject == null) {
             throw new InternalErrorException("The project named " + formerProjectName + " does not exists");
@@ -101,9 +100,8 @@ public class ProjectService extends BasicService {
         return projects.subList(coffset, coffset + climit);
     }
 
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public void deleteProject(String projectName) throws IOException {
-        ProjectInstance project = getProjectManager().getProject(projectName);
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public void deleteProject(String projectName,ProjectInstance project) throws IOException {
         getProjectManager().dropProject(projectName);
 
         accessService.clean(project, true);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
index 64a71c4..6407b06 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
@@ -303,7 +303,7 @@ public class CacheServiceTest extends LocalFileMetadataTestCase {
         assertTrue(metadataManagerB.getDataModelDesc(dataModelName) == null);
 
         dataModelDesc.setName(dataModelName);
-        metadataManager.createDataModelDesc(dataModelDesc);
+        metadataManager.createDataModelDesc(dataModelDesc,"default","ADMIN");
         //only one for data model update
         assertEquals(1, broadcaster.getCounterAndClear());
         waitForCounterAndClear(1);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/webapp/app/js/model/cubeListModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/cubeListModel.js b/webapp/app/js/model/cubeListModel.js
index 3cd1b2b..3e3834f 100755
--- a/webapp/app/js/model/cubeListModel.js
+++ b/webapp/app/js/model/cubeListModel.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('CubeList',function(CubeService,$q){
+KylinApp.service('CubeList',function(CubeService,$q,AccessService){
     var cubes=[];
     var _this = this;
 
@@ -25,8 +25,11 @@ KylinApp.service('CubeList',function(CubeService,$q){
         var defer = $q.defer();
         CubeService.list(queryParam, function (_cubes) {
             angular.forEach(_cubes, function (cube, index) {
+                AccessService.list({type: "CubeInstance", uuid: cube.uuid}, function (accessEntities) {
+                    cube.accessEntities = accessEntities;
+                });
+
                 if(cube.name){
-//                    $scope.listAccess(cube, 'CubeInstance');
                     if (cube.segments && cube.segments.length > 0) {
                         for(var i= cube.segments.length-1;i>=0;i--){
                             if(cube.segments[i].status==="READY"){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 30e9b70..9e92ed9 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('ModelList',function(ModelService,$q){
+KylinApp.service('ModelList',function(ModelService,$q,AccessService){
     var models=[];
     var _this = this;
 
@@ -24,10 +24,10 @@ KylinApp.service('ModelList',function(ModelService,$q){
 
         var defer = $q.defer();
         ModelService.list(queryParam, function (_models) {
-            angular.forEach(_models, function (models, index) {
-                if(models.name){
-//                    $scope.listAccess(models, 'modelsInstance');
-                }
+            angular.forEach(_models, function (model, index) {
+                AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
+                    model.accessEntities = accessEntities;
+                });
             });
             _models = _.filter(_models,function(models){return models.name!=undefined});
             _this.models = _this.models.concat(_models);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/webapp/app/js/services/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/models.js b/webapp/app/js/services/models.js
index 7698e49..fff4c4f 100644
--- a/webapp/app/js/services/models.js
+++ b/webapp/app/js/services/models.js
@@ -21,6 +21,6 @@ KylinApp.factory('ModelService', ['$resource', function ($resource, config) {
         list: {method: 'GET', params: {}, isArray: true},
         drop: {method: 'DELETE', params: {}, isArray: false},
         save: {method: 'POST', params: {}, isArray: false},
-        update: {method: 'PUT', params: {}, isArray: false},
+        update: {method: 'PUT', params: {}, isArray: false}
     });
 }]);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4c456a21/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 85f7cad..ac433c1 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -85,12 +85,12 @@
             <td>
                 <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
                     <button type="button" class="btn btn-default btn-xs dropdown-toggle"
-                            data-toggle="dropdown" ng-click="listAccess(model, 'ModelInstance')">
+                            data-toggle="dropdown">
                         Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
                     </button>
                     <ul class="dropdown-menu" role="menu">
                         <li><a href="models/edit/{{model.name}}">Edit</a></li>
-                        <li ng-if="userService.hasRole('ROLE_ADMIN')">
+                        <li ng-show="false" ng-if="userService.hasRole('ROLE_ADMIN')">
                             <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
 
                     </ul>


[14/52] [abbrv] incubator-kylin git commit: move project to header and update AdminLTE css to v2.0.4

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/css/AdminLTE.css
----------------------------------------------------------------------
diff --git a/webapp/app/css/AdminLTE.css b/webapp/app/css/AdminLTE.css
index e1dda0e..0b9307d 100644
--- a/webapp/app/css/AdminLTE.css
+++ b/webapp/app/css/AdminLTE.css
@@ -1,116 +1,145 @@
 /*!
- *   AdminLTE v1.2
- *   Author: AlmsaeedStudio.com
+ *   AdminLTE v2.0.4
+ *   Author: Almsaeed Studio
+ *	 Website: Almsaeed Studio <http://almsaeedstudio.com>
  *   License: Open source - MIT
  *           Please visit http://opensource.org/licenses/MIT for more information
 !*/
 /*
-    Core: General style
-----------------------------
-*/
+ * Core: Genral Layout Style
+ * -------------------------
+ */
 html,
 body {
-  font-family: 'Source Sans Pro', sans-serif;
-  -webkit-font-smoothing: antialiased;
   min-height: 100%;
 }
-a {
-  color: #3c8dbc;
+.layout-boxed html,
+.layout-boxed body {
+  height: 100%;
 }
-a:hover,
-a:active,
-a:focus {
-  outline: none;
-  text-decoration: none;
-  color: #72afd2;
+body {
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  font-weight: 400;
+  overflow-x: hidden;
+  overflow-y: auto;
 }
-/* Layouts */
+/* Layout */
 .wrapper {
   min-height: 100%;
+  position: static;
+  overflow: hidden;
 }
 .wrapper:before,
 .wrapper:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .wrapper:after {
   clear: both;
 }
-/* Header */
-body > .header {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  z-index: 1030;
-}
-/* Define 2 column template */
-.right-side,
-.left-side {
+.layout-boxed .wrapper {
+  max-width: 1250px;
+  margin: 0 auto;
   min-height: 100%;
-  display: block;
+  box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
+  position: relative;
 }
-/*right side - contins main content*/
-.right-side {
-  background-color: #f9f9f9;
-  margin-left: 220px;
+.layout-boxed {
+  background: url('../img/boxed-bg.jpg') repeat fixed;
 }
-/*left side - contains sidebar*/
-.left-side {
-  position: absolute;
-  width: 220px;
-  top: 0;
+/*
+ * Content Wrapper - contins main content
+ * ```.right-side has been deprecated as of v2.0.0 in favor of .content-wrapper  ```
+ */
+.content-wrapper,
+.right-side,
+.main-footer {
+  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -moz-transition: -moz-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -o-transition: -o-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  transition: transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -webkit-transition: margin-left 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -o-transition: margin-left 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  transition: margin-left 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  margin-left: 230px;
+  z-index: 820;
+}
+.layout-top-nav .content-wrapper,
+.layout-top-nav .right-side,
+.layout-top-nav .main-footer {
+  margin-left: 0;
 }
-@media screen and (min-width: 992px) {
-  .left-side {
-    top: 50px;
-  }
-  /*Right side strech mode*/
-  .right-side.strech {
+@media (max-width: 767px) {
+  .content-wrapper,
+  .right-side,
+  .main-footer {
     margin-left: 0;
   }
-  .right-side.strech > .content-header {
-    margin-top: 0px;
-  }
-  /* Left side collapse */
-  .left-side.collapse-left {
-    left: -220px;
-  }
 }
-/*Give content full width on xs screens*/
-@media screen and (max-width: 992px) {
-  .right-side {
+@media (min-width: 768px) {
+  .sidebar-collapse .content-wrapper,
+  .sidebar-collapse .right-side,
+  .sidebar-collapse .main-footer {
     margin-left: 0;
   }
 }
-/*
-    By default the layout is not fixed but if you add the class .fixed to the body element
-    the sidebar and the navbar will automatically become poisitioned fixed
-*/
-body.fixed > .header,
-body.fixed .left-side,
-body.fixed .navbar {
+@media (max-width: 767px) {
+  .sidebar-open .content-wrapper,
+  .sidebar-open .right-side,
+  .sidebar-open .main-footer {
+    -webkit-transform: translate(230px, 0);
+    -ms-transform: translate(230px, 0);
+    -o-transform: translate(230px, 0);
+    transform: translate(230px, 0);
+  }
+}
+.content-wrapper,
+.right-side {
+  min-height: 100%;
+  background-color: #ecf0f5;
+  z-index: 800;
+}
+.main-footer {
+  background: #fff;
+  padding: 15px;
+  color: #444;
+  border-top: 1px solid #eee;
+}
+/* Fixed layout */
+.fixed .main-header,
+.fixed .main-sidebar,
+.fixed .left-side {
   position: fixed;
 }
-body.fixed > .header {
+.fixed .main-header {
   top: 0;
   right: 0;
   left: 0;
 }
-body.fixed .navbar {
-  left: 0;
-  right: 0;
+.fixed .content-wrapper,
+.fixed .right-side {
+  padding-top: 50px;
+}
+@media (max-width: 767px) {
+  .fixed .content-wrapper,
+  .fixed .right-side {
+    padding-top: 100px;
+  }
 }
-body.fixed .wrapper {
-  margin-top: 50px;
+.fixed.layout-boxed .wrapper {
+  max-width: 100%;
 }
 /* Content */
 .content {
-  padding: 20px 15px;
-  background: #f9f9f9;
-  overflow: auto;
+  min-height: 250px;
+  padding: 15px;
+  margin-right: auto;
+  margin-left: auto;
+  padding-left: 15px;
+  padding-right: 15px;
 }
-/* Utility */
 /* H1 - H6 font */
 h1,
 h2,
@@ -126,706 +155,481 @@ h6,
 .h6 {
   font-family: 'Source Sans Pro', sans-serif;
 }
-/* All images should be responsive */
-img {
-  max-width: 100% !important;
+/* General Links */
+a {
+  color: #3c8dbc;
 }
-.sort-highlight {
-  background: #f4f4f4;
-  border: 1px dashed #ddd;
-  margin-bottom: 10px;
+a:hover,
+a:active,
+a:focus {
+  outline: none;
+  text-decoration: none;
+  color: #72afd2;
 }
-/* 10px padding and margins */
-.pad {
-  padding: 10px;
+/* Page Header */
+.page-header {
+  margin: 10px 0 20px 0;
+  font-size: 22px;
 }
-.margin {
-  margin: 10px;
+.page-header > small {
+  color: #666;
+  display: block;
+  margin-top: 5px;
 }
-/* Display inline */
-.inline {
-  display: inline;
-  width: auto;
+/*
+ * Component: Main Header
+ * ----------------------
+ */
+.main-header {
+  position: relative;
+  max-height: 100px;
+  z-index: 1030;
 }
-/* Background colors */
-.bg-red,
-.bg-yellow,
-.bg-aqua,
-.bg-blue,
-.bg-light-blue,
-.bg-green,
-.bg-navy,
-.bg-teal,
-.bg-olive,
-.bg-lime,
-.bg-orange,
-.bg-fuchsia,
-.bg-purple,
-.bg-maroon,
-.bg-black {
-  color: #f9f9f9 !important;
+.main-header > .navbar {
+  margin-bottom: 0;
+  margin-left: 230px;
+  border: none;
+  min-height: 50px;
+  border-radius: 0;
 }
-.bg-gray {
-  background-color: #eaeaec !important;
+.layout-top-nav .main-header > .navbar {
+  margin-left: 0!important;
 }
-.bg-black {
-  background-color: #222222 !important;
+.main-header #navbar-search-input {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: transparent;
 }
-.bg-red {
-  background-color: #f56954 !important;
+.main-header #navbar-search-input:focus,
+.main-header #navbar-search-input:active {
+  border-color: rgba(0, 0, 0, 0.1) !important;
+  background: rgba(255, 255, 255, 0.9);
 }
-.bg-yellow {
-  background-color: #f39c12 !important;
+.main-header #navbar-search-input::-moz-placeholder {
+  color: #ccc;
+  opacity: 1;
 }
-.bg-aqua {
-  background-color: #00c0ef !important;
+.main-header #navbar-search-input:-ms-input-placeholder {
+  color: #ccc;
 }
-.bg-blue {
-  background-color: #0073b7 !important;
+.main-header #navbar-search-input::-webkit-input-placeholder {
+  color: #ccc;
 }
-.bg-light-blue {
-  background-color: #3c8dbc !important;
+.main-header .navbar-custom-menu,
+.main-header .navbar-right {
+  margin-right: 5px;
+  float: right;
 }
-.bg-green {
-  background-color: #00a65a !important;
+@media (max-width: 991px) {
+  .main-header .navbar-custom-menu a,
+  .main-header .navbar-right a {
+    color: inherit;
+    background: transparent;
+  }
 }
-.bg-navy {
-  background-color: #001f3f !important;
+@media (max-width: 767px) {
+  .main-header .navbar-right {
+    float: none;
+  }
+  .navbar-collapse .main-header .navbar-right {
+    margin: 7.5px -15px;
+  }
+  .main-header .navbar-right > li {
+    color: inherit;
+    border: 0;
+  }
 }
-.bg-teal {
-  background-color: #39cccc !important;
+.main-header .sidebar-toggle {
+  float: left;
+  background-color: transparent;
+  background-image: none;
+  padding: 15px 15px;
+  font-family: fontAwesome;
 }
-.bg-olive {
-  background-color: #3d9970 !important;
+.main-header .sidebar-toggle:before {
+  content: "\f0c9";
 }
-.bg-lime {
-  background-color: #01ff70 !important;
+.main-header .sidebar-toggle:hover {
+  color: #fff;
 }
-.bg-orange {
-  background-color: #ff851b !important;
+.main-header .sidebar-toggle .icon-bar {
+  display: none;
 }
-.bg-fuchsia {
-  background-color: #f012be !important;
+.main-header .navbar .nav > li.user > a > .fa,
+.main-header .navbar .nav > li.user > a > .glyphicon,
+.main-header .navbar .nav > li.user > a > .ion {
+  margin-right: 5px;
 }
-.bg-purple {
-  background-color: #932ab6 !important;
+.main-header .navbar .nav > li > a > .label {
+  position: absolute;
+  top: 9px;
+  right: 7px;
+  text-align: center;
+  font-size: 9px;
+  padding: 2px 3px;
+  line-height: .9;
 }
-.bg-maroon {
-  background-color: #85144b !important;
+.main-header .logo {
+  display: block;
+  float: left;
+  height: 50px;
+  font-size: 20px;
+  line-height: 50px;
+  text-align: center;
+  width: 230px;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  padding: 0 15px;
+  font-weight: 300;
 }
-/* Text colors */
-.text-red {
-  color: #f56954 !important;
+.main-header .navbar-brand {
+  color: #fff;
 }
-.text-yellow {
-  color: #f39c12 !important;
+.content-header {
+  position: relative;
+  padding: 15px 15px 0 15px;
 }
-.text-aqua {
-  color: #00c0ef !important;
+.content-header > h1 {
+  margin: 0;
+  font-size: 24px;
 }
-.text-blue {
-  color: #0073b7 !important;
+.content-header > h1 > small {
+  font-size: 15px;
+  display: inline-block;
+  padding-left: 4px;
+  font-weight: 300;
 }
-.text-black {
-  color: #222222 !important;
+.content-header > .breadcrumb {
+  float: right;
+  background: transparent;
+  margin-top: 0px;
+  margin-bottom: 0;
+  font-size: 12px;
+  padding: 7px 5px;
+  position: absolute;
+  top: 15px;
+  right: 10px;
+  border-radius: 2px;
 }
-.text-light-blue {
-  color: #3c8dbc !important;
+.content-header > .breadcrumb > li > a {
+  color: #444;
+  text-decoration: none;
+  display: inline-block;
 }
-.text-green {
-  color: #00a65a !important;
+.content-header > .breadcrumb > li > a > .fa,
+.content-header > .breadcrumb > li > a > .glyphicon,
+.content-header > .breadcrumb > li > a > .ion {
+  margin-right: 5px;
 }
-.text-navy {
-  color: #001f3f !important;
+.content-header > .breadcrumb > li + li:before {
+  content: '>\00a0';
 }
-.text-teal {
-  color: #39cccc !important;
+@media (max-width: 991px) {
+  .content-header > .breadcrumb {
+    position: relative;
+    margin-top: 5px;
+    top: 0;
+    right: 0;
+    float: none;
+    background: #d2d6de;
+    padding-left: 10px;
+  }
+  .content-header > .breadcrumb li:before {
+    color: #97a0b3;
+  }
 }
-.text-olive {
-  color: #3d9970 !important;
+.navbar-toggle {
+  color: #fff;
+  border: 0;
+  margin: 0;
+  padding: 15px 15px;
 }
-.text-lime {
-  color: #01ff70 !important;
+@media (max-width: 991px) {
+  .navbar-custom-menu .navbar-nav > li {
+    float: left;
+  }
+  .navbar-custom-menu .navbar-nav {
+    margin: 0;
+    float: left;
+  }
+  .navbar-custom-menu .navbar-nav > li > a {
+    padding-top: 15px;
+    padding-bottom: 15px;
+    line-height: 20px;
+  }
 }
-.text-orange {
-  color: #ff851b !important;
+@media (max-width: 767px) {
+  .main-header {
+    position: relative;
+  }
+  .main-header .logo,
+  .main-header .navbar {
+    width: 100%;
+    float: none;
+    position: relative!important;
+  }
+  .main-header .navbar {
+    margin: 0;
+  }
+  .main-header .navbar-custom-menu {
+    float: right;
+  }
+  .main-sidebar,
+  .left-side {
+    padding-top: 100px!important;
+  }
 }
-.text-fuchsia {
-  color: #f012be !important;
+/*
+ * Component: Sidebar
+ * ------------------
+ */
+.main-sidebar,
+.left-side {
+  position: absolute;
+  top: 0;
+  left: 0;
+  padding-top: 50px;
+  min-height: 100%;
+  width: 230px;
+  z-index: 810;
+  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -moz-transition: -moz-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  -o-transition: -o-transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
+  transition: transform 0.3s cubic-bezier(0.32, 1.25, 0.375, 1.15);
 }
-.text-purple {
-  color: #932ab6 !important;
+@media (max-width: 767px) {
+  .main-sidebar,
+  .left-side {
+    -webkit-transform: translate(-230px, 0);
+    -ms-transform: translate(-230px, 0);
+    -o-transform: translate(-230px, 0);
+    transform: translate(-230px, 0);
+  }
 }
-.text-maroon {
-  color: #85144b !important;
+@media (min-width: 768px) {
+  .sidebar-collapse .main-sidebar,
+  .sidebar-collapse .left-side {
+    -webkit-transform: translate(-230px, 0);
+    -ms-transform: translate(-230px, 0);
+    -o-transform: translate(-230px, 0);
+    transform: translate(-230px, 0);
+  }
 }
-/*Hide elements by display none only*/
-.hide {
-  display: none !important;
+@media (max-width: 767px) {
+  .sidebar-open .main-sidebar,
+  .sidebar-open .left-side {
+    -webkit-transform: translate(0, 0);
+    -ms-transform: translate(0, 0);
+    -o-transform: translate(0, 0);
+    transform: translate(0, 0);
+  }
 }
-/* Remove borders */
-.no-border {
-  border: 0px !important;
+.sidebar {
+  padding-bottom: 10px;
 }
-/* Remove padding */
-.no-padding {
-  padding: 0px !important;
+.fixed .sidebar {
+  overflow: auto;
+  height: 100%;
 }
-/* Remove margins */
-.no-margin {
-  margin: 0px !important;
+.sidebar-form input:focus {
+  border-color: transparent!important;
 }
-/* Remove box shadow */
-.no-shadow {
-  box-shadow: none!important;
+.user-panel {
+  padding: 10px;
 }
-/* Don't display when printing */
-@media print {
-  .no-print {
-    display: none;
-  }
-  .left-side,
-  .header,
-  .content-header {
-    display: none;
-  }
-  .right-side {
-    margin: 0;
-  }
+.user-panel:before,
+.user-panel:after {
+  content: " ";
+  display: table;
 }
-/* Remove border radius */
-.flat {
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
+.user-panel:after {
+  clear: both;
 }
-/* Change the color of the striped tables */
-.table-striped > tbody > tr:nth-child(odd) > td,
-.table-striped > tbody > tr:nth-child(odd) > th {
-  background-color: #f3f4f5;
+.user-panel > .image > img {
+  width: 45px;
+  height: 45px;
 }
-.table.no-border,
-.table.no-border td,
-.table.no-border th {
-  border: 0;
+.user-panel > .info {
+  font-weight: 600;
+  padding: 5px 5px 5px 15px;
+  font-size: 14px;
+  line-height: 1;
 }
-/* .text-center in tables */
-table.text-center,
-table.text-center td,
-table.text-center th {
-  text-align: center;
+.user-panel > .info > p {
+  margin-bottom: 9px;
 }
-.table.align th {
-  text-align: left;
+.user-panel > .info > a {
+  text-decoration: none;
+  padding-right: 5px;
+  margin-top: 3px;
+  font-size: 11px;
+  font-weight: normal;
 }
-.table.align td {
-  text-align: right;
+.user-panel > .info > a > .fa,
+.user-panel > .info > a > .ion,
+.user-panel > .info > a > .glyphicon {
+  margin-right: 3px;
 }
-.text-bold,
-.text-bold.table td,
-.text-bold.table th {
-  font-weight: 700;
+.sidebar-menu {
+  list-style: none;
+  margin: 0;
+  padding: 0;
 }
-.border-radius-none {
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
+.sidebar-menu > li {
+  position: relative;
+  margin: 0;
+  padding: 0;
 }
-/* _fix for sparkline tooltip */
-.jqstooltip {
-  padding: 5px!important;
-  width: auto!important;
-  height: auto!important;
+.sidebar-menu > li > a {
+  padding: 12px 5px 12px 15px;
+  display: block;
 }
-/*
-Gradient Background colors
-*/
-.bg-teal-gradient {
-  background: #39cccc !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #39cccc), color-stop(1, #7adddd)) !important;
-  background: -ms-linear-gradient(bottom, #39cccc, #7adddd) !important;
-  background: -moz-linear-gradient(center bottom, #39cccc 0%, #7adddd 100%) !important;
-  background: -o-linear-gradient(#7adddd, #39cccc) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#7adddd', endColorstr='#39cccc', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu > li > a > .fa,
+.sidebar-menu > li > a > .glyphicon,
+.sidebar-menu > li > a > .ion {
+  width: 20px;
 }
-.bg-light-blue-gradient {
-  background: #3c8dbc !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #3c8dbc), color-stop(1, #67a8ce)) !important;
-  background: -ms-linear-gradient(bottom, #3c8dbc, #67a8ce) !important;
-  background: -moz-linear-gradient(center bottom, #3c8dbc 0%, #67a8ce 100%) !important;
-  background: -o-linear-gradient(#67a8ce, #3c8dbc) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#67a8ce', endColorstr='#3c8dbc', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu > li .label,
+.sidebar-menu > li .badge {
+  margin-top: 3px;
+  margin-right: 5px;
 }
-.bg-blue-gradient {
-  background: #0073b7 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #0073b7), color-stop(1, #0089db)) !important;
-  background: -ms-linear-gradient(bottom, #0073b7, #0089db) !important;
-  background: -moz-linear-gradient(center bottom, #0073b7 0%, #0089db 100%) !important;
-  background: -o-linear-gradient(#0089db, #0073b7) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0089db', endColorstr='#0073b7', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu li.header {
+  padding: 10px 25px 10px 15px;
+  font-size: 12px;
 }
-.bg-aqua-gradient {
-  background: #00c0ef !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #00c0ef), color-stop(1, #14d1ff)) !important;
-  background: -ms-linear-gradient(bottom, #00c0ef, #14d1ff) !important;
-  background: -moz-linear-gradient(center bottom, #00c0ef 0%, #14d1ff 100%) !important;
-  background: -o-linear-gradient(#14d1ff, #00c0ef) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#14d1ff', endColorstr='#00c0ef', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu li > a > .fa-angle-left {
+  width: auto;
+  height: auto;
+  padding: 0;
+  margin-right: 10px;
+  margin-top: 3px;
 }
-.bg-yellow-gradient {
-  background: #f39c12 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #f39c12), color-stop(1, #f7bc60)) !important;
-  background: -ms-linear-gradient(bottom, #f39c12, #f7bc60) !important;
-  background: -moz-linear-gradient(center bottom, #f39c12 0%, #f7bc60 100%) !important;
-  background: -o-linear-gradient(#f7bc60, #f39c12) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7bc60', endColorstr='#f39c12', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu li.active > a > .fa-angle-left {
+  -webkit-transform: rotate(-90deg);
+  -ms-transform: rotate(-90deg);
+  -o-transform: rotate(-90deg);
+  transform: rotate(-90deg);
 }
-.bg-purple-gradient {
-  background: #932ab6 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #932ab6), color-stop(1, #b959d9)) !important;
-  background: -ms-linear-gradient(bottom, #932ab6, #b959d9) !important;
-  background: -moz-linear-gradient(center bottom, #932ab6 0%, #b959d9 100%) !important;
-  background: -o-linear-gradient(#b959d9, #932ab6) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b959d9', endColorstr='#932ab6', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu li.active > .treeview-menu {
+  display: block;
 }
-.bg-green-gradient {
-  background: #00a65a !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #00a65a), color-stop(1, #00ca6d)) !important;
-  background: -ms-linear-gradient(bottom, #00a65a, #00ca6d) !important;
-  background: -moz-linear-gradient(center bottom, #00a65a 0%, #00ca6d 100%) !important;
-  background: -o-linear-gradient(#00ca6d, #00a65a) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ca6d', endColorstr='#00a65a', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu .treeview-menu {
+  display: none;
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  padding-left: 5px;
 }
-.bg-red-gradient {
-  background: #f56954 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #f56954), color-stop(1, #f89384)) !important;
-  background: -ms-linear-gradient(bottom, #f56954, #f89384) !important;
-  background: -moz-linear-gradient(center bottom, #f56954 0%, #f89384 100%) !important;
-  background: -o-linear-gradient(#f89384, #f56954) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f89384', endColorstr='#f56954', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu .treeview-menu .treeview-menu {
+  padding-left: 20px;
 }
-.bg-black-gradient {
-  background: #222222 !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #222222), color-stop(1, #3c3c3c)) !important;
-  background: -ms-linear-gradient(bottom, #222222, #3c3c3c) !important;
-  background: -moz-linear-gradient(center bottom, #222222 0%, #3c3c3c 100%) !important;
-  background: -o-linear-gradient(#3c3c3c, #222222) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3c3c3c', endColorstr='#222222', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu .treeview-menu > li {
+  margin: 0;
 }
-.bg-maroon-gradient {
-  background: #85144b !important;
-  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #85144b), color-stop(1, #b11b64)) !important;
-  background: -ms-linear-gradient(bottom, #85144b, #b11b64) !important;
-  background: -moz-linear-gradient(center bottom, #85144b 0%, #b11b64 100%) !important;
-  background: -o-linear-gradient(#b11b64, #85144b) !important;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b11b64', endColorstr='#85144b', GradientType=0) !important;
-  color: #fff;
+.sidebar-menu .treeview-menu > li > a {
+  padding: 5px 5px 5px 15px;
+  display: block;
+  font-size: 14px;
 }
-.connectedSortable {
-  min-height: 100px;
+.sidebar-menu .treeview-menu > li > a > .fa,
+.sidebar-menu .treeview-menu > li > a > .glyphicon,
+.sidebar-menu .treeview-menu > li > a > .ion {
+  width: 20px;
 }
-/*---------------------------------------------------
-    LESS Elements 0.9
-  ---------------------------------------------------
-    A set of useful LESS mixins
-    More info at: http://lesselements.com
-  ---------------------------------------------------*/
-/*
-    Components: navbar, logo and content header
--------------------------------------------------
-*/
-body > .header {
-  position: relative;
-  max-height: 100px;
-  z-index: 1030;
+.sidebar-menu .treeview-menu > li > a > .fa-angle-left,
+.sidebar-menu .treeview-menu > li > a > .fa-angle-down {
+  width: auto;
 }
-body > .header .navbar {
-  height: 50px;
-  margin-bottom: 0;
-  margin-left: 220px;
+/*
+ * Component: Dropdown menus
+ * -------------------------
+ */
+/*Dropdowns in general*/
+.dropdown-menu {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-color: #eee;
 }
-body > .header .navbar .sidebar-toggle {
-  float: left;
-  padding: 9px 5px;
-  margin-top: 8px;
-  margin-right: 0;
-  margin-bottom: 8px;
-  margin-left: 5px;
-  background-color: transparent;
-  background-image: none;
-  border: 1px solid transparent;
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
-  border-radius: 0 !important;
+.dropdown-menu > li > a {
+  color: #777;
 }
-body > .header .navbar .sidebar-toggle:hover .icon-bar {
-  background: #f6f6f6;
+.dropdown-menu > li > a > .glyphicon,
+.dropdown-menu > li > a > .fa,
+.dropdown-menu > li > a > .ion {
+  margin-right: 10px;
 }
-body > .header .navbar .sidebar-toggle .icon-bar {
-  display: block;
-  width: 22px;
-  height: 2px;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
+.dropdown-menu > li > a:hover {
+  background-color: #e1e3e9;
+  color: #333;
 }
-body > .header .navbar .sidebar-toggle .icon-bar + .icon-bar {
-  margin-top: 4px;
+.dropdown-menu > .divider {
+  background-color: #eee;
 }
-body > .header .navbar .nav > li.user > a {
-  font-weight: bold;
+/*
+    Navbar custom dropdown menu
+------------------------------------
+*/
+.navbar-nav > .notifications-menu,
+.navbar-nav > .messages-menu,
+.navbar-nav > .tasks-menu {
+  position: relative;
 }
-body > .header .navbar .nav > li.user > a > .fa,
-body > .header .navbar .nav > li.user > a > .glyphicon,
-body > .header .navbar .nav > li.user > a > .ion {
-  margin-right: 5px;
+.navbar-nav > .notifications-menu > .dropdown-menu,
+.navbar-nav > .messages-menu > .dropdown-menu,
+.navbar-nav > .tasks-menu > .dropdown-menu {
+  width: 280px;
+  padding: 0 0 0 0!important;
+  margin: 0!important;
+  top: 100%;
 }
-body > .header .navbar .nav > li > a > .label {
-  -webkit-border-radius: 50%;
-  -moz-border-radius: 50%;
-  border-radius: 50%;
-  position: absolute;
-  top: 7px;
-  right: 2px;
-  font-size: 10px;
-  font-weight: normal;
-  width: 15px;
-  height: 15px;
-  line-height: 1.0em;
-  text-align: center;
-  padding: 2px;
+.navbar-nav > .notifications-menu > .dropdown-menu > li,
+.navbar-nav > .messages-menu > .dropdown-menu > li,
+.navbar-nav > .tasks-menu > .dropdown-menu > li {
+  position: relative;
 }
-body > .header .navbar .nav > li > a:hover > .label {
-  top: 3px;
+.navbar-nav > .notifications-menu > .dropdown-menu > li.header,
+.navbar-nav > .messages-menu > .dropdown-menu > li.header,
+.navbar-nav > .tasks-menu > .dropdown-menu > li.header {
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  background-color: #ffffff;
+  padding: 7px 10px;
+  border-bottom: 1px solid #f4f4f4;
+  color: #444444;
+  font-size: 14px;
 }
-body > .header .logo {
-  float: left;
-  font-size: 20px;
-  line-height: 50px;
+.navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a,
+.navbar-nav > .messages-menu > .dropdown-menu > li.footer > a,
+.navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a {
+  border-top-left-radius: 0px;
+  border-top-right-radius: 0px;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+  font-size: 12px;
+  background-color: #fff;
+  padding: 7px 10px;
+  border-bottom: 1px solid #eeeeee;
+  color: #444!important;
   text-align: center;
-  padding: 0 10px;
-  width: 220px;
-  font-family: 'Kaushan Script', cursive;
-  font-weight: 500;
-  height: 50px;
-  display: block;
 }
-body > .header .logo .icon {
-  margin-right: 10px;
+@media (max-width: 991px) {
+  .navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a,
+  .navbar-nav > .messages-menu > .dropdown-menu > li.footer > a,
+  .navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a {
+    background: #fff!important;
+    color: #444!important;
+  }
 }
-.right-side > .content-header {
-  position: relative;
-  padding: 15px 15px 10px 20px;
-}
-.right-side > .content-header > h1 {
-  margin: 0;
-  font-size: 24px;
-}
-.right-side > .content-header > h1 > small {
-  font-size: 15px;
-  display: inline-block;
-  padding-left: 4px;
-  font-weight: 300;
-}
-.right-side > .content-header > .breadcrumb {
-  float: right;
-  background: transparent;
-  margin-top: 0px;
-  margin-bottom: 0;
-  font-size: 12px;
-  padding: 7px 5px;
-  position: absolute;
-  top: 15px;
-  right: 10px;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
-  border-radius: 2px;
-}
-.right-side > .content-header > .breadcrumb > li > a {
-  color: #444;
-  text-decoration: none;
-}
-.right-side > .content-header > .breadcrumb > li > a > .fa,
-.right-side > .content-header > .breadcrumb > li > a > .glyphicon,
-.right-side > .content-header > .breadcrumb > li > a > .ion {
-  margin-right: 5px;
-}
-.right-side > .content-header > .breadcrumb > li + li:before {
-  content: '>\00a0';
-}
-@media screen and (max-width: 767px) {
-  .right-side > .content-header > .breadcrumb {
-    position: relative;
-    margin-top: 5px;
-    top: 0;
-    right: 0;
-    float: none;
-    background: #efefef;
-  }
-}
-
-@media screen and (max-width: 560px) {
-  body > .header {
-    position: relative;
-  }
-  body > .header .logo,
-  body > .header .navbar {
-    width: 100%;
-    float: none;
-    position: relative!important;
-  }
-  body > .header .navbar {
-    margin: 0;
-  }
-  body.fixed > .header {
-    position: fixed;
-  }
-  body.fixed > .wrapper,
-  body.fixed .sidebar-offcanvas {
-    margin-top: 100px!important;
-  }
-}
-/*
-    Component: Sidebar
---------------------------
-*/
-.sidebar {
-  margin-bottom: 5px;
-}
-.sidebar .sidebar-form input:focus {
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  border-color: transparent!important;
-}
-.sidebar .sidebar-menu {
-  list-style: none;
-  margin: 0;
-  padding: 0;
-}
-.sidebar .sidebar-menu > li {
-  margin: 0;
-  padding: 0;
-}
-.sidebar .sidebar-menu > li > a {
-  padding: 12px 5px 12px 15px;
-  display: block;
-}
-.sidebar .sidebar-menu > li > a > .fa,
-.sidebar .sidebar-menu > li > a > .glyphicon,
-.sidebar .sidebar-menu > li > a > .ion {
-  width: 20px;
-}
-.sidebar .sidebar-menu .treeview-menu {
-  display: none;
-  list-style: none;
-  padding: 0;
-  margin: 0;
-}
-.sidebar .sidebar-menu .treeview-menu > li {
-  margin: 0;
-}
-.sidebar .sidebar-menu .treeview-menu > li > a {
-  padding: 5px 5px 5px 15px;
-  display: block;
-  font-size: 14px;
-  margin: 0px 0px;
-}
-.sidebar .sidebar-menu .treeview-menu > li > a > .fa,
-.sidebar .sidebar-menu .treeview-menu > li > a > .glyphicon,
-.sidebar .sidebar-menu .treeview-menu > li > a > .ion {
-  width: 20px;
-}
-.user-panel {
-  padding: 10px;
-}
-.user-panel:before,
-.user-panel:after {
-  display: table;
-  content: " ";
-}
-.user-panel:after {
-  clear: both;
-}
-.user-panel > .image > img {
-  width: 45px;
-  height: 45px;
-}
-.user-panel > .info {
-  font-weight: 600;
-  padding: 5px 5px 5px 15px;
-  font-size: 14px;
-  line-height: 1;
-}
-.user-panel > .info > p {
-  margin-bottom: 9px;
-}
-.user-panel > .info > a {
-  text-decoration: none;
-  padding-right: 5px;
-  margin-top: 3px;
-  font-size: 11px;
-  font-weight: normal;
-}
-.user-panel > .info > a > .fa,
-.user-panel > .info > a > .ion,
-.user-panel > .info > a > .glyphicon {
-  margin-right: 3px;
-}
-/*
- * Off Canvas
- * --------------------------------------------------
- *  Gives us the push menu effect
- */
-@media screen and (max-width: 992px) {
-  .relative {
-    position: relative;
-  }
-  .row-offcanvas-right .sidebar-offcanvas {
-    right: -220px;
-  }
-  .row-offcanvas-left .sidebar-offcanvas {
-    left: -220px;
-  }
-  .row-offcanvas-right.active {
-    right: 220px;
-  }
-  .row-offcanvas-left.active {
-    left: 220px;
-  }
-  .sidebar-offcanvas {
-    left: 0;
-  }
-  body.fixed .sidebar-offcanvas {
-    margin-top: 50px;
-    left: -220px;
-  }
-  body.fixed .row-offcanvas-left.active .navbar {
-    left: 220px !important;
-    right: 0;
-  }
-  body.fixed .row-offcanvas-left.active .sidebar-offcanvas {
-    left: 0px;
-  }
-}
-/* 
-    Dropdown menus
-----------------------------
-*/
-/*Dropdowns in general*/
-.dropdown-menu {
-  -webkit-box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  -moz-box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
-  z-index: 2300;
-}
-.dropdown-menu > li > a > .glyphicon,
-.dropdown-menu > li > a > .fa,
-.dropdown-menu > li > a > .ion {
-  margin-right: 10px;
-}
-.dropdown-menu > li > a:hover {
-  background-color: #3c8dbc;
-  color: #f9f9f9;
-}
-/*Drodown in navbars*/
-.skin-blue .navbar .dropdown-menu > li > a {
-  color: #444444;
-}
-/*
-    Navbar custom dropdown menu
-------------------------------------
-*/
-.navbar-nav > .notifications-menu > .dropdown-menu,
-.navbar-nav > .messages-menu > .dropdown-menu,
-.navbar-nav > .tasks-menu > .dropdown-menu {
-  width: 280px;
-  padding: 0 0 0 0!important;
-  margin: 0!important;
-  top: 100%;
-  border: 1px solid #dfdfdf;
-  -webkit-border-radius: 4px !important;
-  -moz-border-radius: 4px !important;
-  border-radius: 4px !important;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li.header,
-.navbar-nav > .messages-menu > .dropdown-menu > li.header,
-.navbar-nav > .tasks-menu > .dropdown-menu > li.header {
-  -webkit-border-top-left-radius: 4px;
-  -webkit-border-top-right-radius: 4px;
-  -webkit-border-bottom-right-radius: 0;
-  -webkit-border-bottom-left-radius: 0;
-  -moz-border-radius-topleft: 4px;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-bottomright: 0;
-  -moz-border-radius-bottomleft: 0;
-  border-top-left-radius: 4px;
-  border-top-right-radius: 4px;
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0;
-  background-color: #ffffff;
-  padding: 7px 10px;
-  border-bottom: 1px solid #f4f4f4;
-  color: #444444;
-  font-size: 14px;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li.header:after,
-.navbar-nav > .messages-menu > .dropdown-menu > li.header:after,
-.navbar-nav > .tasks-menu > .dropdown-menu > li.header:after {
-  bottom: 100%;
-  left: 92%;
-  border: solid transparent;
-  content: " ";
-  height: 0;
-  width: 0;
-  position: absolute;
-  pointer-events: none;
-  border-color: rgba(255, 255, 255, 0);
-  border-bottom-color: #ffffff;
-  border-width: 7px;
-  margin-left: -7px;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a,
-.navbar-nav > .messages-menu > .dropdown-menu > li.footer > a,
-.navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a {
-  -webkit-border-top-left-radius: 0px;
-  -webkit-border-top-right-radius: 0px;
-  -webkit-border-bottom-right-radius: 4px;
-  -webkit-border-bottom-left-radius: 4px;
-  -moz-border-radius-topleft: 0px;
-  -moz-border-radius-topright: 0px;
-  -moz-border-radius-bottomright: 4px;
-  -moz-border-radius-bottomleft: 4px;
-  border-top-left-radius: 0px;
-  border-top-right-radius: 0px;
-  border-bottom-right-radius: 4px;
-  border-bottom-left-radius: 4px;
-  font-size: 12px;
-  background-color: #f4f4f4;
-  padding: 7px 10px;
-  border-bottom: 1px solid #eeeeee;
-  color: #444444;
-  text-align: center;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a:hover,
-.navbar-nav > .messages-menu > .dropdown-menu > li.footer > a:hover,
-.navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a:hover {
-  background: #f4f4f4;
-  text-decoration: none;
-  font-weight: normal;
+.navbar-nav > .notifications-menu > .dropdown-menu > li.footer > a:hover,
+.navbar-nav > .messages-menu > .dropdown-menu > li.footer > a:hover,
+.navbar-nav > .tasks-menu > .dropdown-menu > li.footer > a:hover {
+  text-decoration: none;
+  font-weight: normal;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu,
 .navbar-nav > .tasks-menu > .dropdown-menu > li .menu {
+  max-height: 200px;
   margin: 0;
   padding: 0;
   list-style: none;
@@ -842,71 +646,43 @@ body > .header .logo .icon {
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a:hover,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:hover,
 .navbar-nav > .tasks-menu > .dropdown-menu > li .menu > li > a:hover {
-  background: #f6f6f6;
+  background: #f4f4f4;
   text-decoration: none;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a {
-  font-size: 12px;
   color: #444444;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  padding: 10px;
 }
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon,
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa,
 .navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion {
-  font-size: 20px;
-  width: 50px;
-  text-align: center;
-  padding: 15px 0px;
-  margin-right: 5px;
-  /* Default background and font colors */
-  background: #00c0ef;
-  color: #f9f9f9;
-  /* Fallback for browsers that doesn't support rgba */
-  color: rgba(255, 255, 255, 0.7);
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.danger,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.danger,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.danger {
-  background: #f56954;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.warning,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.warning,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.warning {
-  background: #f39c12;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.success,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.success,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.success {
-  background: #00a65a;
-}
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .glyphicon.info,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .fa.info,
-.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a > .ion.info {
-  background: #00c0ef;
+  width: 20px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a {
   margin: 0px;
-  line-height: 20px;
-  padding: 10px 5px 10px 5px;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
+  padding: 10px 10px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > div > img {
   margin: auto 10px auto auto;
   width: 40px;
   height: 40px;
-  border: 1px solid #dddddd;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > h4 {
   padding: 0;
   margin: 0 0 0 45px;
   color: #444444;
   font-size: 15px;
+  position: relative;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > h4 > small {
   color: #999999;
   font-size: 10px;
-  float: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a > p {
   margin: 0 0 0 45px;
@@ -915,8 +691,8 @@ body > .header .logo .icon {
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:before,
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a:after {
   clear: both;
@@ -935,180 +711,196 @@ body > .header .logo .icon {
   margin: 0;
 }
 .navbar-nav > .user-menu > .dropdown-menu {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
   padding: 1px 0 0 0;
   border-top-width: 0;
   width: 280px;
 }
-.navbar-nav > .user-menu > .dropdown-menu:after {
-  bottom: 100%;
-  right: 10px;
-  border: solid transparent;
-  content: " ";
-  height: 0;
-  width: 0;
-  position: absolute;
-  pointer-events: none;
-  border-color: rgba(255, 255, 255, 0);
-  border-bottom-color: #ffffff;
-  border-width: 10px;
-  margin-left: -10px;
+.navbar-nav > .user-menu > .dropdown-menu,
+.navbar-nav > .user-menu > .dropdown-menu > .user-body {
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header {
   height: 175px;
   padding: 10px;
-  background: #3c8dbc;
   text-align: center;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > img {
   z-index: 5;
   height: 90px;
   width: 90px;
-  border: 8px solid;
+  border: 3px solid;
   border-color: transparent;
   border-color: rgba(255, 255, 255, 0.2);
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p {
   z-index: 5;
-  color: #f9f9f9;
+  color: #fff;
   color: rgba(255, 255, 255, 0.8);
   font-size: 17px;
-  text-shadow: 2px 2px 3px #333333;
   margin-top: 10px;
 }
 .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p > small {
   display: block;
   font-size: 12px;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body {
+.navbar-nav > .user-menu > .dropdown-menu > .user-body {
   padding: 15px;
   border-bottom: 1px solid #f4f4f4;
   border-top: 1px solid #dddddd;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:before,
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:after {
-  display: table;
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:before,
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:after {
   content: " ";
+  display: table;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body:after {
+.navbar-nav > .user-menu > .dropdown-menu > .user-body:after {
   clear: both;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-body > div > a {
-  color: #0073b7;
+.navbar-nav > .user-menu > .dropdown-menu > .user-body a {
+  color: #444 !important;
+}
+@media (max-width: 991px) {
+  .navbar-nav > .user-menu > .dropdown-menu > .user-body a {
+    background: #fff !important;
+    color: #444 !important;
+  }
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer {
   background-color: #f9f9f9;
   padding: 10px;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:before,
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:after {
-  display: table;
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:before,
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:after {
   content: " ";
+  display: table;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer:after {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer:after {
   clear: both;
 }
-.navbar-nav > .user-menu > .dropdown-menu > li.user-footer .btn-default {
+.navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default {
   color: #666666;
 }
-/* Add fade animation to dropdown menus */
-.open > .dropdown-menu {
-  animation-name: fadeAnimation;
-  animation-duration: .7s;
-  animation-iteration-count: 1;
-  animation-timing-function: ease;
-  animation-fill-mode: forwards;
-  -webkit-animation-name: fadeAnimation;
-  -webkit-animation-duration: .7s;
-  -webkit-animation-iteration-count: 1;
-  -webkit-animation-timing-function: ease;
-  -webkit-animation-fill-mode: forwards;
-  -moz-animation-name: fadeAnimation;
-  -moz-animation-duration: .7s;
-  -moz-animation-iteration-count: 1;
-  -moz-animation-timing-function: ease;
-  -moz-animation-fill-mode: forwards;
-}
-@keyframes fadeAnimation {
-  from {
+.navbar-nav > .user-menu .user-image {
+  float: left;
+  width: 25px;
+  height: 25px;
+  border-radius: 50%;
+  margin-right: 10px;
+  margin-top: -2px;
+}
+@media (max-width: 767px) {
+  .navbar-nav > .user-menu .user-image {
+    float: none;
+    margin-right: 0;
+    margin-top: -8px;
+    line-height: 10px;
+  }
+}
+/* Add fade animation to dropdown menus by appending
+ the class .animated-dropdown-menu to the .dropdown-menu ul (or ol)*/
+.open:not(.dropup) > .animated-dropdown-menu {
+  backface-visibility: visible !important;
+  -webkit-animation: flipInX 0.7s both;
+  -o-animation: flipInX 0.7s both;
+  animation: flipInX 0.7s both;
+}
+@keyframes flipInX {
+  0% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transition-timing-function: ease-in;
     opacity: 0;
-    top: 120%;
   }
-  to {
+  40% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transition-timing-function: ease-in;
+  }
+  60% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
     opacity: 1;
-    top: 100%;
+  }
+  80% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+  }
+  100% {
+    transform: perspective(400px);
   }
 }
-@-webkit-keyframes fadeAnimation {
-  from {
+@-webkit-keyframes flipInX {
+  0% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transition-timing-function: ease-in;
     opacity: 0;
-    top: 120%;
   }
-  to {
-    opacity: 1;
-    top: 100%;
+  40% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transition-timing-function: ease-in;
   }
-}
-/* Fix dropdown menu for small screens to display correctly on small screens */
-@media screen and (max-width: 767px) {
-  .navbar-nav > .notifications-menu > .dropdown-menu,
-  .navbar-nav > .user-menu > .dropdown-menu,
-  .navbar-nav > .tasks-menu > .dropdown-menu,
-  .navbar-nav > .messages-menu > .dropdown-menu {
-    position: absolute;
-    top: 100%;
-    right: 0;
-    left: auto;
-    border-right: 1px solid #dddddd;
-    border-bottom: 1px solid #dddddd;
-    border-left: 1px solid #dddddd;
-    background: #ffffff;
+  60% {
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    opacity: 1;
   }
-}
-/* Fix menu positions on xs screens to appear correctly and fully */
-@media screen and (max-width: 480px) {
-  .navbar-nav > .notifications-menu > .dropdown-menu > li.header,
-  .navbar-nav > .tasks-menu > .dropdown-menu > li.header,
-  .navbar-nav > .messages-menu > .dropdown-menu > li.header {
-    /* Remove arrow from the top */
+  80% {
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
   }
-  .navbar-nav > .notifications-menu > .dropdown-menu > li.header:after,
-  .navbar-nav > .tasks-menu > .dropdown-menu > li.header:after,
-  .navbar-nav > .messages-menu > .dropdown-menu > li.header:after {
-    border-width: 0px!important;
+  100% {
+    transform: perspective(400px);
   }
-  .navbar-nav > .tasks-menu > .dropdown-menu {
-    position: absolute;
-    right: -120px;
-    left: auto;
+}
+/* Fix dropdown menu in navbars */
+.navbar-custom-menu > .navbar-nav > li {
+  position: relative;
+}
+.navbar-custom-menu > .navbar-nav > li > .dropdown-menu {
+  position: absolute;
+  right: 0;
+  left: auto;
+}
+@media (max-width: 991px) {
+  .navbar-custom-menu > .navbar-nav {
+    float: right;
   }
-  .navbar-nav > .notifications-menu > .dropdown-menu {
-    position: absolute;
-    right: -170px;
-    left: auto;
+  .navbar-custom-menu > .navbar-nav > li {
+    position: static;
   }
-  .navbar-nav > .messages-menu > .dropdown-menu {
+  .navbar-custom-menu > .navbar-nav > li > .dropdown-menu {
     position: absolute;
-    right: -210px;
+    right: 5%;
     left: auto;
+    border: 1px solid #ddd;
+    background: #fff;
   }
 }
-/* 
-   All form elements including input, select, textarea etc.
------------------------------------------------------------------
-*/
+/*
+ * Component: Form
+ * ---------------
+ */
 .form-control {
-  -webkit-border-radius: 0px !important;
-  -moz-border-radius: 0px !important;
   border-radius: 0px !important;
   box-shadow: none;
+  border-color: #d2d6de;
 }
 .form-control:focus {
   border-color: #3c8dbc !important;
   box-shadow: none;
 }
+.form-control::-moz-placeholder {
+  color: #bbb;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #bbb;
+}
+.form-control::-webkit-input-placeholder {
+  color: #bbb;
+}
+.form-control:not(select) {
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
+}
 .form-group.has-success label {
   color: #00a65a;
 }
@@ -1124,38 +916,72 @@ body > .header .logo .icon {
   box-shadow: none;
 }
 .form-group.has-error label {
-  color: #f56954;
+  color: #dd4b39;
 }
 .form-group.has-error .form-control {
-  border-color: #f56954 !important;
+  border-color: #dd4b39 !important;
   box-shadow: none;
 }
 /* Input group */
 .input-group .input-group-addon {
-  border-radius: 0;
-  background-color: #f4f4f4;
+  border-radius: 0px;
+  border-color: #d2d6de;
+  background-color: #fff;
 }
 /* button groups */
 .btn-group-vertical .btn.btn-flat:first-of-type,
 .btn-group-vertical .btn.btn-flat:last-of-type {
   border-radius: 0;
 }
-/* Checkbox and radio inputs */
-.checkbox,
-.radio {
+.icheck > label {
   padding-left: 0;
 }
-/* 
-    Compenent: Progress bars
---------------------------------
-*/
+/*
+ * Component: Progress Bar
+ * -----------------------
+ */
+.progress,
+.progress > .progress-bar {
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+.progress,
+.progress > .progress-bar,
+.progress .progress-bar,
+.progress > .progress-bar .progress-bar {
+  border-radius: 1px;
+}
 /* size variation */
-.progress.sm {
+.progress.sm,
+.progress-sm {
   height: 10px;
 }
-.progress.xs {
+.progress.sm,
+.progress-sm,
+.progress.sm .progress-bar,
+.progress-sm .progress-bar {
+  border-radius: 1px;
+}
+.progress.xs,
+.progress-xs {
   height: 7px;
 }
+.progress.xs,
+.progress-xs,
+.progress.xs .progress-bar,
+.progress-xs .progress-bar {
+  border-radius: 1px;
+}
+.progress.xxs,
+.progress-xxs {
+  height: 3px;
+}
+.progress.xxs,
+.progress-xxs,
+.progress.xxs .progress-bar,
+.progress-xxs .progress-bar {
+  border-radius: 1px;
+}
 /* Vertical bars */
 .progress.vertical {
   position: relative;
@@ -1169,12 +995,24 @@ body > .header .logo .icon {
   position: absolute;
   bottom: 0;
 }
-.progress.vertical.sm {
+.progress.vertical.sm,
+.progress.vertical.progress-sm {
   width: 20px;
 }
-.progress.vertical.xs {
+.progress.vertical.xs,
+.progress.vertical.progress-xs {
   width: 10px;
 }
+.progress.vertical.xxs,
+.progress.vertical.progress-xxs {
+  width: 3px;
+}
+.progress-group .progress-text {
+  font-weight: 600;
+}
+.progress-group .progress-number {
+  float: right;
+}
 /* Remove margins from progress bars when put in a table */
 .table tr > td .progress {
   margin: 0;
@@ -1185,9 +1023,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-light-blue,
 .progress-striped .progress-bar-primary {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-green,
@@ -1196,9 +1033,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-green,
 .progress-striped .progress-bar-success {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-aqua,
@@ -1207,9 +1043,8 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-aqua,
 .progress-striped .progress-bar-info {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-yellow,
@@ -1218,32 +1053,30 @@ body > .header .logo .icon {
 }
 .progress-striped .progress-bar-yellow,
 .progress-striped .progress-bar-warning {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-red,
 .progress-bar-danger {
-  background-color: #f56954;
+  background-color: #dd4b39;
 }
 .progress-striped .progress-bar-red,
 .progress-striped .progress-bar-danger {
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 /*
-    Component: Small boxes
-*/
+ * Component: Small Box
+ * --------------------
+ */
 .small-box {
+  border-radius: 2px;
   position: relative;
   display: block;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
-  border-radius: 2px;
-  margin-bottom: 15px;
+  margin-bottom: 20px;
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
 }
 .small-box > .inner {
   padding: 10px;
@@ -1284,10 +1117,12 @@ body > .header .logo .icon {
   z-index: 5px;
 }
 .small-box .icon {
+  -webkit-transition: all 0.3s linear;
+  -o-transition: all 0.3s linear;
+  transition: all 0.3s linear;
   position: absolute;
-  top: auto;
-  bottom: 5px;
-  right: 5px;
+  top: -10px;
+  right: 10px;
   z-index: 0;
   font-size: 90px;
   color: rgba(0, 0, 0, 0.15);
@@ -1297,39 +1132,9 @@ body > .header .logo .icon {
   color: #f9f9f9;
 }
 .small-box:hover .icon {
-  animation-name: tansformAnimation;
-  animation-duration: .5s;
-  animation-iteration-count: 1;
-  animation-timing-function: ease;
-  animation-fill-mode: forwards;
-  -webkit-animation-name: tansformAnimation;
-  -webkit-animation-duration: .5s;
-  -webkit-animation-iteration-count: 1;
-  -webkit-animation-timing-function: ease;
-  -webkit-animation-fill-mode: forwards;
-  -moz-animation-name: tansformAnimation;
-  -moz-animation-duration: .5s;
-  -moz-animation-iteration-count: 1;
-  -moz-animation-timing-function: ease;
-  -moz-animation-fill-mode: forwards;
-}
-@keyframes tansformAnimation {
-  from {
-    font-size: 90px;
-  }
-  to {
-    font-size: 100px;
-  }
+  font-size: 95px;
 }
-@-webkit-keyframes tansformAnimation {
-  from {
-    font-size: 90px;
-  }
-  to {
-    font-size: 100px;
-  }
-}
-@media screen and (max-width: 480px) {
+@media (max-width: 767px) {
   .small-box {
     text-align: center;
   }
@@ -1341,19 +1146,17 @@ body > .header .logo .icon {
   }
 }
 /*
-    component: Boxes
--------------------------
-*/
+ * Component: Box
+ * --------------
+ */
 .box {
   position: relative;
+  border-radius: 3px;
   background: #ffffff;
-  border-top: 2px solid #c1c1c1;
+  border-top: 3px solid #d2d6de;
   margin-bottom: 20px;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
   width: 100%;
-  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
 }
 .box.box-primary {
   border-top-color: #3c8dbc;
@@ -1362,7 +1165,7 @@ body > .header .logo .icon {
   border-top-color: #00c0ef;
 }
 .box.box-danger {
-  border-top-color: #f56954;
+  border-top-color: #dd4b39;
 }
 .box.box-warning {
   border-top-color: #f39c12;
@@ -1370,201 +1173,116 @@ body > .header .logo .icon {
 .box.box-success {
   border-top-color: #00a65a;
 }
-.box.height-control .box-body {
-  max-height: 300px;
-  overflow: auto;
-}
-.box .box-header {
-  position: relative;
-  -webkit-border-top-left-radius: 3px;
-  -webkit-border-top-right-radius: 3px;
-  -webkit-border-bottom-right-radius: 0;
-  -webkit-border-bottom-left-radius: 0;
-  -moz-border-radius-topleft: 3px;
-  -moz-border-radius-topright: 3px;
-  -moz-border-radius-bottomright: 0;
-  -moz-border-radius-bottomleft: 0;
-  border-top-left-radius: 3px;
-  border-top-right-radius: 3px;
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0;
-  border-bottom: 0px solid #f4f4f4;
-  color: #444;
-}
-.box .box-header:before,
-.box .box-header:after {
-  display: table;
-  content: " ";
+.box.box-default {
+  border-top-color: #d2d6de;
 }
-.box .box-header:after {
-  clear: both;
+.box.collapsed-box .box-body,
+.box.collapsed-box .box-footer {
+  display: none;
 }
-.box .box-header > .fa,
-.box .box-header > .glyphicon,
-.box .box-header > .ion,
-.box .box-header .box-title {
-  display: inline-block;
-  padding: 10px 10px 10px 10px;
+.box .nav-stacked > li {
+  border-bottom: 1px solid #f4f4f4;
   margin: 0;
-  font-size: 20px;
-  font-weight: 400;
-  float: left;
-  cursor: default;
-}
-.box .box-header a {
-  color: #444;
-}
-.box .box-header > .box-tools {
-  padding: 5px 10px 5px 5px;
-}
-.box .box-body {
-  padding: 10px;
-  -webkit-border-top-left-radius: 0;
-  -webkit-border-top-right-radius: 0;
-  -webkit-border-bottom-right-radius: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  border-top-left-radius: 0;
-  border-top-right-radius: 0;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
-}
-.box .box-body > table,
-.box .box-body > .table {
-  margin-bottom: 0;
-}
-.box .box-body.chart-responsive {
-  width: 100%;
-  overflow: hidden;
-}
-.box .box-body > .chart {
-  position: relative;
-  overflow: hidden;
-  width: 100%;
-}
-.box .box-body > .chart svg,
-.box .box-body > .chart canvas {
-  width: 100%!important;
-}
-.box .box-body .fc {
-  margin-top: 5px;
-}
-.box .box-body .fc-header-title h2 {
-  font-size: 15px;
-  line-height: 1.6em;
-  color: #666;
-  margin-left: 10px;
-}
-.box .box-body .fc-header-right {
-  padding-right: 10px;
-}
-.box .box-body .fc-header-left {
-  padding-left: 10px;
 }
-.box .box-body .fc-widget-header {
-  background: #fafafa;
-  box-shadow: inset 0px -3px 1px rgba(0, 0, 0, 0.02);
+.box .nav-stacked > li:last-of-type {
+  border-bottom: none;
 }
-.box .box-body .fc-grid {
-  width: 100%;
-  border: 0;
+.box.height-control .box-body {
+  max-height: 300px;
+  overflow: auto;
 }
-.box .box-body .fc-widget-header:first-of-type,
-.box .box-body .fc-widget-content:first-of-type {
-  border-left: 0;
-  border-right: 0;
+.box .border-right {
+  border-right: 1px solid #f4f4f4;
 }
-.box .box-body .fc-widget-header:last-of-type,
-.box .box-body .fc-widget-content:last-of-type {
-  border-right: 0;
+.box .border-left {
+  border-left: 1px solid #f4f4f4;
 }
-.box .box-body .table {
-  margin-bottom: 0;
+.box.box-solid {
+  border-top: 0px;
 }
-.box .box-body .full-width-chart {
-  margin: -19px;
+.box.box-solid > .box-header .btn.btn-default {
+  background: transparent;
 }
-.box .box-body.no-padding .full-width-chart {
-  margin: -9px;
+.box.box-solid > .box-header .btn:hover,
+.box.box-solid > .box-header a:hover {
+  background: rgba(0, 0, 0, 0.1) !important;
 }
-.box .box-footer {
-  border-top: 1px solid #f4f4f4;
-  -webkit-border-top-left-radius: 0;
-  -webkit-border-top-right-radius: 0;
-  -webkit-border-bottom-right-radius: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  border-top-left-radius: 0;
-  border-top-right-radius: 0;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
-  padding: 10px;
-  background-color: #ffffff;
+.box.box-solid.box-default {
+  border: 1px solid #d2d6de;
 }
-.box.box-solid {
-  border-top: 0px;
+.box.box-solid.box-default > .box-header {
+  color: #444444;
+  background: #d2d6de;
+  background-color: #d2d6de;
 }
-.box.box-solid > .box-header {
-  padding-bottom: 0px!important;
+.box.box-solid.box-default > .box-header a,
+.box.box-solid.box-default > .box-header .btn {
+  color: #444444;
 }
-.box.box-solid > .box-header .btn.btn-default {
-  background: transparent;
+.box.box-solid.box-primary {
+  border: 1px solid #3c8dbc;
 }
 .box.box-solid.box-primary > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #3c8dbc;
   background-color: #3c8dbc;
 }
-.box.box-solid.box-primary > .box-header a {
-  color: #444;
+.box.box-solid.box-primary > .box-header a,
+.box.box-solid.box-primary > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-info {
+  border: 1px solid #00c0ef;
 }
 .box.box-solid.box-info > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #00c0ef;
   background-color: #00c0ef;
 }
-.box.box-solid.box-info > .box-header a {
-  color: #444;
+.box.box-solid.box-info > .box-header a,
+.box.box-solid.box-info > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-danger {
+  border: 1px solid #dd4b39;
 }
 .box.box-solid.box-danger > .box-header {
-  color: #fff;
-  background: #f56954;
-  background-color: #f56954;
+  color: #ffffff;
+  background: #dd4b39;
+  background-color: #dd4b39;
 }
-.box.box-solid.box-danger > .box-header a {
-  color: #444;
+.box.box-solid.box-danger > .box-header a,
+.box.box-solid.box-danger > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-warning {
+  border: 1px solid #f39c12;
 }
 .box.box-solid.box-warning > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #f39c12;
   background-color: #f39c12;
 }
-.box.box-solid.box-warning > .box-header a {
-  color: #444;
+.box.box-solid.box-warning > .box-header a,
+.box.box-solid.box-warning > .box-header .btn {
+  color: #ffffff;
+}
+.box.box-solid.box-success {
+  border: 1px solid #00a65a;
 }
 .box.box-solid.box-success > .box-header {
-  color: #fff;
+  color: #ffffff;
   background: #00a65a;
   background-color: #00a65a;
 }
-.box.box-solid.box-success > .box-header a {
-  color: #444;
+.box.box-solid.box-success > .box-header a,
+.box.box-solid.box-success > .box-header .btn {
+  color: #ffffff;
 }
 .box.box-solid > .box-header > .box-tools .btn {
   border: 0;
   box-shadow: none;
 }
-.box.box-solid.collapsed-box .box-header {
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
 .box.box-solid[class*='bg'] > .box-header {
   color: #fff;
 }
@@ -1578,168 +1296,364 @@ body > .header .logo .icon {
   font-size: 12px;
   margin-bottom: 0.3em;
 }
-.box .todo-list {
-  margin: 0;
-  padding: 0px 0px;
-  list-style: none;
+.box > .overlay,
+.box > .loading-img {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
 }
-.box .todo-list > li {
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
-  border-radius: 2px;
-  padding: 10px;
-  background: #f3f4f5;
-  margin-bottom: 2px;
-  border-left: 2px solid #e6e7e8;
-  color: #444;
+.box .overlay {
+  z-index: 1010;
+  background: rgba(255, 255, 255, 0.7);
+  border-radius: 3px;
 }
-.box .todo-list > li:last-of-type {
-  margin-bottom: 0;
+.box .overlay > .fa {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin-left: -15px;
+  margin-top: -15px;
+  color: #000;
+  font-size: 30px;
 }
-.box .todo-list > li.danger {
-  border-left-color: #f56954;
+.box .overlay.dark {
+  background: rgba(0, 0, 0, 0.5);
 }
-.box .todo-list > li.warning {
-  border-left-color: #f39c12;
+.box-header {
+  color: #444;
+  display: block;
+  padding: 10px;
+  position: relative;
 }
-.box .todo-list > li.info {
-  border-left-color: #00c0ef;
+.box-header:before,
+.box-header:after {
+  content: " ";
+  display: table;
 }
-.box .todo-list > li.success {
-  border-left-color: #00a65a;
+.box-header:after {
+  clear: both;
 }
-.box .todo-list > li.primary {
-  border-left-color: #3c8dbc;
+.box-header.with-border {
+  border-bottom: 1px solid #f4f4f4;
 }
-.box .todo-list > li > input[type='checkbox'] {
-  margin: 0 10px 0 5px;
+.collapsed-box .box-header.with-border {
+  border-bottom: none;
 }
-.box .todo-list > li .text {
+.box-header > .fa,
+.box-header > .glyphicon,
+.box-header > .ion,
+.box-header .box-title {
   display: inline-block;
-  margin-left: 5px;
-  font-weight: 600;
-}
-.box .todo-list > li .label {
-  margin-left: 10px;
-  font-size: 9px;
-}
-.box .todo-list > li .tools {
-  display: none;
-  float: right;
-  color: #f56954;
+  font-size: 18px;
+  margin: 0;
+  line-height: 1;
 }
-.box .todo-list > li .tools > .fa,
-.box .todo-list > li .tools > .glyphicon,
-.box .todo-list > li .tools > .ion {
+.box-header > .fa,
+.box-header > .glyphicon,
+.box-header > .ion {
   margin-right: 5px;
-  cursor: pointer;
 }
-.box .todo-list > li:hover .tools {
-  display: inline-block;
+.box-header > .box-tools {
+  position: absolute;
+  right: 10px;
+  top: 5px;
 }
-.box .todo-list > li.done {
-  color: #999;
+.box-header > .box-tools [data-toggle="tooltip"] {
+  position: relative;
 }
-.box .todo-list > li.done .text {
-  text-decoration: line-through;
-  font-weight: 500;
+.box-header > .box-tools.pull-right .dropdown-menu {
+  right: 0;
+  left: auto;
 }
-.box .todo-list > li.done .label {
-  background: #eaeaec !important;
+.btn-box-tool {
+  padding: 5px;
+  font-size: 12px;
+  background: transparent;
+  box-shadow: none!important;
+  color: #97a0b3;
 }
-.box .todo-list .handle {
-  display: inline-block;
-  cursor: move;
-  margin: 0 5px;
+.open .btn-box-tool,
+.btn-box-tool:hover {
+  color: #606c84;
 }
-.box .chat {
-  padding: 5px 20px 5px 10px;
+.btn-box-tool:active {
+  outline: none!important;
 }
-.box .chat .item {
-  margin-bottom: 10px;
+.box-body {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+  padding: 10px;
 }
-.box .chat .item:before,
-.box .chat .item:after {
-  display: table;
-  content: " ";
+.no-header .box-body {
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
 }
-.box .chat .item:after {
-  clear: both;
+.box-body > .table {
+  margin-bottom: 0;
 }
-.box .chat .item > img {
-  width: 40px;
-  height: 40px;
-  border: 2px solid transparent;
-  -webkit-border-radius: 50% !important;
-  -moz-border-radius: 50% !important;
-  border-radius: 50% !important;
+.box-body > .chart {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
 }
-.box .chat .item > img.online {
-  border: 2px solid #00a65a;
+.box-body > .chart svg,
+.box-body > .chart canvas {
+  width: 100%!important;
 }
-.box .chat .item > img.offline {
-  border: 2px solid #f56954;
+.box-body .fc {
+  margin-top: 5px;
 }
-.box .chat .item > .message {
-  margin-left: 55px;
+.box-body .full-width-chart {
+  margin: -19px;
+}
+.box-body.no-padding .full-width-chart {
+  margin: -9px;
+}
+.box-body .box-pane {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 3px;
+}
+.box-body .box-pane-right {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 0;
+}
+.box-footer {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+  border-top: 1px solid #f4f4f4;
+  padding: 10px;
+  background-color: #ffffff;
+}
+.chart-legend {
+  margin: 10px 0;
+}
+@media (max-width: 991px) {
+  .chart-legend > li {
+    float: left;
+    margin-right: 10px;
+  }
+}
+/* Widget: TODO LIST */
+.todo-list {
+  margin: 0;
+  padding: 0px 0px;
+  list-style: none;
+  overflow: auto;
+}
+.todo-list > li {
+  border-radius: 2px;
+  padding: 10px;
+  background: #f4f4f4;
+  margin-bottom: 2px;
+  border-left: 2px solid #e6e7e8;
+  color: #444;
+}
+.todo-list > li:last-of-type {
+  margin-bottom: 0;
+}
+.todo-list > li.danger {
+  border-left-color: #dd4b39;
+}
+.todo-list > li.warning {
+  border-left-color: #f39c12;
+}
+.todo-list > li.info {
+  border-left-color: #00c0ef;
+}
+.todo-list > li.success {
+  border-left-color: #00a65a;
+}
+.todo-list > li.primary {
+  border-left-color: #3c8dbc;
+}
+.todo-list > li > input[type='checkbox'] {
+  margin: 0 10px 0 5px;
+}
+.todo-list > li .text {
+  display: inline-block;
+  margin-left: 5px;
+  font-weight: 600;
+}
+.todo-list > li .label {
+  margin-left: 10px;
+  font-size: 9px;
+}
+.todo-list > li .tools {
+  display: none;
+  float: right;
+  color: #dd4b39;
+}
+.todo-list > li .tools > .fa,
+.todo-list > li .tools > .glyphicon,
+.todo-list > li .tools > .ion {
+  margin-right: 5px;
+  cursor: pointer;
+}
+.todo-list > li:hover .tools {
+  display: inline-block;
+}
+.todo-list > li.done {
+  color: #999;
+}
+.todo-list > li.done .text {
+  text-decoration: line-through;
+  font-weight: 500;
+}
+.todo-list > li.done .label {
+  background: #d2d6de !important;
+}
+.todo-list .handle {
+  display: inline-block;
+  cursor: move;
+  margin: 0 5px;
+}
+/* Chat widget (DEPRECATED - this will be removed in the next major release. Use Direct Chat instead)*/
+.chat {
+  padding: 5px 20px 5px 10px;
+}
+.chat .item {
+  margin-bottom: 10px;
+}
+.chat .item:before,
+.chat .item:after {
+  content: " ";
+  display: table;
+}
+.chat .item:after {
+  clear: both;
+}
+.chat .item > img {
+  width: 40px;
+  height: 40px;
+  border: 2px solid transparent;
+  border-radius: 50% !important;
+}
+.chat .item > img.online {
+  border: 2px solid #00a65a;
+}
+.chat .item > img.offline {
+  border: 2px solid #dd4b39;
+}
+.chat .item > .message {
+  margin-left: 55px;
   margin-top: -40px;
 }
-.box .chat .item > .message > .name {
+.chat .item > .message > .name {
   display: block;
   font-weight: 600;
 }
-.box .chat .item > .attachment {
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
+.chat .item > .attachment {
   border-radius: 3px;
-  background: #f0f0f0;
+  background: #f4f4f4;
   margin-left: 65px;
   margin-right: 15px;
   padding: 10px;
 }
-.box .chat .item > .attachment > h4 {
+.chat .item > .attachment > h4 {
   margin: 0 0 5px 0;
   font-weight: 600;
   font-size: 14px;
 }
-.box .chat .item > .attachment > p,
-.box .chat .item > .attachment > .filename {
+.chat .item > .attachment > p,
+.chat .item > .attachment > .filename {
   font-weight: 600;
   font-size: 13px;
   font-style: italic;
   margin: 0;
 }
-.box .chat .item > .attachment:before,
-.box .chat .item > .attachment:after {
-  display: table;
+.chat .item > .attachment:before,
+.chat .item > .attachment:after {
   content: " ";
+  display: table;
 }
-.box .chat .item > .attachment:after {
+.chat .item > .attachment:after {
   clear: both;
 }
-.box > .overlay,
-.box > .loading-img {
-  position: absolute;
-  top: 0;
-  left: 0;
+.box-input {
+  max-width: 200px;
+}
+/*
+ * Component: Info Box
+ * -------------------
+ */
+.info-box {
+  display: block;
+  min-height: 90px;
+  background: #fff;
   width: 100%;
-  height: 100%;
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-radius: 2px;
+  margin-bottom: 15px;
 }
-.box > .overlay {
-  z-index: 1010;
-  background: rgba(255, 255, 255, 0.7);
+.info-box small {
+  font-size: 14px;
 }
-.box > .overlay.dark {
-  background: rgba(0, 0, 0, 0.5);
+.info-box .progress {
+  background: rgba(0, 0, 0, 0.2);
+  margin: 5px -10px 5px -10px;
+  height: 2px;
 }
-.box > .loading-img {
-  z-index: 1020;
-  background: transparent url('../img/ajax-loader1.gif') 50% 50% no-repeat;
+.info-box .progress,
+.info-box .progress .progress-bar {
+  border-radius: 0;
+}
+.info-box .progress .progress-bar {
+  background: #fff;
+}
+.info-box-icon {
+  border-top-left-radius: 2px;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 2px;
+  display: block;
+  float: left;
+  height: 90px;
+  width: 90px;
+  text-align: center;
+  font-size: 45px;
+  line-height: 90px;
+  background: rgba(0, 0, 0, 0.2);
+}
+.info-box-content {
+  padding: 5px 10px;
+  margin-left: 90px;
+}
+.info-box-number {
+  display: block;
+  font-weight: bold;
+  font-size: 18px;
+}
+.progress-description,
+.info-box-text {
+  display: block;
+  font-size: 14px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.info-box-text {
+  text-transform: uppercase;
+}
+.info-box-more {
+  display: block;
+}
+.progress-description {
+  margin: 0;
 }
 /*
-Component: timeline
---------------------
-*/
+ * Component: Timeline
+ * -------------------
+ */
 .timeline {
   position: relative;
   margin: 0 0 30px 0;
@@ -1751,13 +1665,10 @@ Component: timeline
   position: absolute;
   top: 0px;
   bottom: 0;
-  width: 5px;
+  width: 4px;
   background: #ddd;
-  left: 30px;
-  border: 1px solid #eee;
+  left: 31px;
   margin: 0;
-  -webkit-border-radius: 2px;
-  -moz-border-radius: 2px;
   border-radius: 2px;
 }
 .timeline > li {
@@ -1767,33 +1678,35 @@ Component: timeline
 }
 .timeline > li:before,
 .timeline > li:after {
-  display: table;
   content: " ";
+  display: table;
 }
 .timeline > li:after {
   clear: both;
 }
 .timeline > li > .timeline-item {
-  margin-top: 10px;
-  border: 0px solid #dfdfdf;
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-radius: 3px;
+  margin-top: 0px;
   background: #fff;
-  color: #555;
+  color: #444;
   margin-left: 60px;
   margin-right: 15px;
-  padding: 5px;
+  padding: 0;
   position: relative;
-  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
 }
 .timeline > li > .timeline-item > .time {
   color: #999;
   float: right;
-  margin: 2px 0 0 0;
+  padding: 10px;
+  font-size: 12px;
 }
 .timeline > li > .timeline-item > .timeline-header {
   margin: 0;
   color: #555;
   border-bottom: 1px solid #f4f4f4;
-  padding: 5px;
+  padding: 10px;
   font-size: 16px;
   line-height: 1.1;
 }
@@ -1809,310 +1722,302 @@ Component: timeline
   padding: 5px;
   display: inline-block;
   background-color: #fff;
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
   border-radius: 4px;
 }
 .timeline > li > .fa,
 .timeline > li > .glyphicon,
 .timeline > li > .ion {
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
   width: 30px;
   height: 30px;
   font-size: 15px;
   line-height: 30px;
   position: absolute;
   color: #666;
-  background: #eee;
+  background: #d2d6de;
   border-radius: 50%;
   text-align: center;
   left: 18px;
   top: 0;
 }
 /*
-    Component: Buttons
--------------------------
-*/
+ * Component: Button
+ * -----------------
+ */
 .btn {
-  font-weight: 500;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
   border-radius: 3px;
+  -webkit-box-shadow: none;
+  box-shadow: none;
   border: 1px solid transparent;
-  -webkit-box-shadow: inset 0px -2px 0px 0px rgba(0, 0, 0, 0.09);
-  -moz-box-shadow: inset 0px -2px 0px 0px rgba(0, 0, 0, 0.09);
-  box-shadow: inset 0px -1px 0px 0px rgba(0, 0, 0, 0.09);
 }
-.btn.btn-default {
-  background-color: #fafafa;
-  color: #666;
-  border-color: #ddd;
-  border-bottom-color: #ddd;
+.btn.uppercase {
+  text-transform: uppercase;
+}
+.btn.btn-flat {
+  border-radius: 0;
+  -webkit-box-shadow: none;
+  -moz-box-shadow: none;
+  box-shadow: none;
+  border-width: 1px;
+}
+.btn:active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn:focus {
+  outline: none;
+}
+.btn.btn-file {
+  position: relative;
+  overflow: hidden;
+}
+.btn.btn-file > input[type='file'] {
+  position: absolute;
+  top: 0;
+  right: 0;
+  min-width: 100%;
+  min-height: 100%;
+  font-size: 100px;
+  text-align: right;
+  opacity: 0;
+  filter: alpha(opacity=0);
+  outline: none;
+  background: white;
+  cursor: inherit;
+  display: block;
 }
-.btn.btn-default:hover,
-.btn.btn-default:active,
-.btn.btn-default.hover {
-  background-color: #f4f4f4!important;
+.btn-default {
+  background-color: #f4f4f4;
+  color: #444;
+  border-color: #ddd;
 }
-.btn.btn-default.btn-flat {
-  border-bottom-color: #d9dadc;
+.btn-default:hover,
+.btn-default:active,
+.btn-default.hover {
+  background-color: #e7e7e7 !important;
 }
-.btn.btn-primary {
+.btn-primary {
   background-color: #3c8dbc;
   border-color: #367fa9;
 }
-.btn.btn-primary:hover,
-.btn.btn-primary:active,
-.btn.btn-primary.hover {
+.btn-primary:hover,
+.btn-primary:active,
+.btn-primary.hover {
   background-color: #367fa9;
 }
-.btn.btn-success {
+.btn-success {
   background-color: #00a65a;
   border-color: #008d4c;
 }
-.btn.btn-success:hover,
-.btn.btn-success:active,
-.btn.btn-success.hover {
+.btn-success:hover,
+.btn-success:active,
+.btn-success.hover {
   background-color: #008d4c;
 }
-.btn.btn-info {
+.btn-info {
   background-color: #00c0ef;
   border-color: #00acd6;
 }
-.btn.btn-info:hover,
-.btn.btn-info:active,
-.btn.btn-info.hover {
+.btn-info:hover,
+.btn-info:active,
+.btn-info.hover {
   background-color: #00acd6;
 }
-.btn.btn-danger {
-  background-color: #f56954;
-  border-color: #f4543c;
+.btn-danger {
+  background-color: #dd4b39;
+  border-color: #d73925;
 }
-.btn.btn-danger:hover,
-.btn.btn-danger:active,
-.btn.btn-danger.hover {
-  background-color: #f4543c;
+.btn-danger:hover,
+.btn-danger:active,
+.btn-danger.hover {
+  background-color: #d73925;
 }
-.btn.btn-warning {
+.btn-warning {
   background-color: #f39c12;
   border-color: #e08e0b;
 }
-.btn.btn-warning:hover,
-.btn.btn-warning:active,
-.btn.btn-warning.hover {
+.btn-warning:hover,
+.btn-warning:active,
+.btn-warning.hover {
   background-color: #e08e0b;
 }
-.btn.btn-flat {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  border-width: 1px;
-}
-.btn:active {
-  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-  -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+.btn-outline {
+  border: 1px solid #fff;
+  background: transparent;
+  color: #fff;
 }
-.btn:focus {
-  outline: none;
+.btn-outline:hover,
+.btn-outline:focus,
+.btn-outline:active {
+  color: rgba(255, 255, 255, 0.7);
+  border-color: rgba(255, 255, 255, 0.7);
 }
-.btn.btn-file {
-  position: relative;
-  width: 120px;
-  height: 35px;
-  overflow: hidden;
+.btn-link {
+  -webkit-box-shadow: none;
+  box-shadow: none;
 }
-.btn.btn-file > input[type='file'] {
-  display: block !important;
-  width: 100% !important;
-  height: 35px !important;
-  opacity: 0 !important;
-  position: absolute;
-  top: -10px;
-  cursor: pointer;
+.btn[class*='bg-']:hover {
+  -webkit-box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.2);
+  box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.2);
 }
-.btn.btn-app {
+.btn-app {
+  border-radius: 3px;
   position: relative;
   padding: 15px 5px;
   margin: 0 0 10px 10px;
   min-width: 80px;
   height: 60px;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
   text-align: center;
   color: #666;
   border: 1px solid #ddd;
-  background-color: #fafafa;
+  background-color: #f4f4f4;
   font-size: 12px;
 }
-.btn.btn-app > .fa,
-.btn.btn-app > .glyphicon,
-.btn.btn-app > .ion {
+.btn-app > .fa,
+.btn-app > .glyphicon,
+.btn-app > .ion {
   font-size: 20px;
   display: block;
 }
-.btn.btn-app:hover {
+.btn-app:hover {
   background: #f4f4f4;
   color: #444;
   border-color: #aaa;
 }
-.btn.btn-app:active,
-.btn.btn-app:focus {
+.btn-app:active,
+.btn-app:focus {
   -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
   -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
   box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
 }
-.btn.btn-app > .badge {
+.btn-app > .badge {
   position: absolute;
   top: -3px;
   right: -10px;
   font-size: 10px;
   font-weight: 400;
 }
-.btn.btn-social-old {
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  opacity: 0.9;
-  padding: 0;
+/*
+ * Component: Callout
+ * ------------------
+ */
+.callout {
+  border-radius: 3px;
+  margin: 0 0 20px 0;
+  padding: 15px 30px 15px 15px;
+  border-left: 5px solid #eee;
 }
-.btn.btn-social-old > .fa {
-  padding: 10px 0;
-  width: 40px;
+.callout a {
+  color: #fff;
+  text-decoration: underline;
 }
-.btn.btn-social-old > .fa + span {
-  border-left: 1px solid rgba(255, 255, 255, 0.3);
+.callout a:hover {
+  color: #eee;
 }
-.btn.btn-social-old span {
-  padding: 10px;
+.callout h4 {
+  margin-top: 0;
+  font-weight: 600;
 }
-.btn.btn-social-old:hover {
-  opacity: 1;
-}
-.btn.btn-circle {
-  width: 30px;
-  height: 30px;
-  line-height: 30px;
-  padding: 0;
-  -webkit-border-radius: 50%;
-  -moz-border-radius: 50%;
-  border-radius: 50%;
-}
-/* 
-    Component: callout
-------------------------
-*/
-.callout {
-  margin: 0 0 20px 0;
-  padding: 15px 30px 15px 15px;
-  border-left: 5px solid #eee;
-}
-.callout h4 {
-  margin-top: 0;
-}
-.callout p:last-child {
-  margin-bottom: 0;
+.callout p:last-child {
+  margin-bottom: 0;
 }
 .callout code,
 .callout .highlight {
   background-color: #fff;
 }
 .callout.callout-danger {
-  background-color: #fcf2f2;
-  border-color: #dFb5b4;
+  border-color: #c23321;
 }
 .callout.callout-warning {
-  background-color: #fefbed;
-  border-color: #f1e7bc;
+  border-color: #c87f0a;
 }
 .callout.callout-info {
-  background-color: #f0f7fd;
-  border-color: #d0e3f0;
+  border-color: #0097bc;
 }
-.callout.callout-danger h4 {
-  color: #B94A48;
+.callout.callout-success {
+  border-color: #00733e;
 }
-.callout.callout-warning h4 {
-  color: #C09853;
+/*
+ * Component: alert
+ * ----------------
+ */
+.alert {
+  border-radius: 3px;
 }
-.callout.callout-info h4 {
-  color: #3A87AD;
+.alert h4 {
+  font-weight: 600;
 }
-/* 
-    Component: alert
-------------------------
-*/
-.alert {
-  padding-left: 30px;
-  margin-left: 15px;
-  position: relative;
+.alert .icon {
+  margin-right: 10px;
 }
-.alert > .fa,
-.alert > .glyphicon {
-  position: absolute;
-  left: -15px;
-  top: -15px;
-  width: 35px;
-  height: 35px;
-  -webkit-border-radius: 50%;
-  -moz-border-radius: 50%;
-  border-radius: 50%;
-  line-height: 35px;
-  text-align: center;
-  background: inherit;
-  border: inherit;
+.alert .close {
+  color: #000;
+  opacity: 0.2;
+  filter: alpha(opacity=20);
+}
+.alert .close:hover {
+  opacity: 0.5;
+  filter: alpha(opacity=50);
+}
+.alert a {
+  color: #fff;
+  text-decoration: underline;
+}
+.alert-success {
+  border-color: #008d4c;
+}
+.alert-danger,
+.alert-error {
+  border-color: #d73925;
+}
+.alert-warning {
+  border-color: #e08e0b;
+}
+.alert-info {
+  border-color: #00acd6;
 }
 /*
-    Component: Navs
-*/
+ * Component: Nav
+ * --------------
+ */
 /* NAV PILLS */
-.nav.nav-pills > li > a {
-  border-top: 3px solid transparent;
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
+.nav-pills > li > a {
   border-radius: 0;
+  border-top: 3px solid transparent;
   color: #444;
 }
-.nav.nav-pills > li > a > .fa,
-.nav.nav-pills > li > a > .glyphicon,
-.nav.nav-pills > li > a > .ion {
+.nav-pills > li > a > .fa,
+.nav-pills > li > a > .glyphicon,
+.nav-pills > li > a > .ion {
   margin-right: 5px;
 }
-.nav.nav-pills > li.active > a,
-.nav.nav-pills > li.active > a:hover {
-  background-color: #f6f6f6;
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover {
+  background-color: #f4f4f4;
   border-top-color: #3c8dbc;
   color: #444;
 }
-.nav.nav-pills > li.active > a {
+.nav-pills > li.active > a {
   font-weight: 600;
 }
-.nav.nav-pills > li > a:hover {
+.nav-pills > li > a:hover {
   background-color: #f6f6f6;
 }
-.nav.nav-pills.nav-stacked > li > a {
+/* NAV STACKED */
+.nav-stacked > li > a {
+  border-radius: 0;
   border-top: 0;
   border-left: 3px solid transparent;
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  border-radius: 0;
   color: #444;
 }
-.nav.nav-pills.nav-stacked > li.active > a,
-.nav.nav-pills.nav-stacked > li.active > a:hover {
-  background-color: #f6f6f6;
+.nav-stacked > li.active > a,
+.nav-stacked > li.active > a:hover {
+  background-color: #f4f4f4;
+  border-top: 0;
   border-left-color: #3c8dbc;
   color: #444;
 }
-.nav.nav-pills.nav-stacked > li.header {
+.nav-stacked > li.header {
   border-bottom: 1px solid #ddd;
   color: #777;
   margin-bottom: 10px;
@@ -2123,11 +2028,14 @@ Component: timeline
 .nav-tabs-custom {
   margin-bottom: 20px;
   background: #fff;
-  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+  border-radius: 3px;
 }
 .nav-tabs-custom > .nav-tabs {
   margin: 0;
   border-bottom-color: #f4f4f4;
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
 }
 .nav-tabs-custom > .nav-tabs > li {
   border-top: 3px solid transparent;
@@ -2135,8 +2043,6 @@ Component: timeline
   margin-right: 5px;
 }
 .nav-tabs-custom > .nav-tabs > li > a {
-  -webkit-border-radius: 0 !important;
-  -moz-border-radius: 0 !important;
   border-radius: 0 !important;
 }
 .nav-tabs-custom > .nav-tabs > li > a,
@@ -2162,7 +2068,7 @@ Component: timeline
   border-right-color: #f4f4f4;
 }
 .nav-tabs-custom > .nav-tabs > li:first-of-type {
-  margin-left: 0px;
+  margin-left: 0;
 }
 .nav-tabs-custom > .nav-tabs > li:first-of-type.active > a {
   border-left-width: 0;
@@ -2174,28 +2080,28 @@ Component: timeline
   float: right;
 }
 .nav-tabs-custom > .nav-tabs.pull-right > li:first-of-type {
-  margin-right: 0px;
+  margin-right: 0;
 }
 .nav-tabs-custom > .nav-tabs.pull-right > li:first-of-type.active > a {
   border-left-width: 1px;
-  border-right-width: 0px;
+  border-right-width: 0;
 }
 .nav-tabs-custom > .nav-tabs > li.header {
-  font-weight: 400;
   line-height: 35px;
   padding: 0 10px;
   font-size: 20px;
   color: #444;
-  cursor: default;
 }
 .nav-tabs-custom > .nav-tabs > li.header > .fa,
 .nav-tabs-custom > .nav-tabs > li.header > .glyphicon,
 .nav-tabs-custom > .nav-tabs > li.header > .ion {
-  margin-right: 

<TRUNCATED>


[16/52] [abbrv] incubator-kylin git commit: reset default call-out style in new adminLte version

Posted by ma...@apache.org.
reset default call-out style in new adminLte version


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

Branch: refs/heads/0.8.0
Commit: e6b0715de2ed85a996bfb592d110d13d47febe91
Parents: fb405eb
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 17 17:52:31 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:49 2015 +0800

----------------------------------------------------------------------
 webapp/app/index.html          | 22 ++++++++++++++++++++--
 webapp/app/less/component.less | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/e6b0715d/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index c8698ac..8c6bb2d 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -184,11 +184,11 @@
 <!--template-->
 <!-- static template for cube save/update result notification -->
 <script type="text/ng-template" id="cubeResultError.html">
-    <div class="callout callout-danger">
+    <div class="callout">
         <h4>Error Message</h4>
         <p>{{text}}</p>
     </div>
-    <div class="callout callout-info">
+    <div class="callout callout-danger">
         <h4>Cube Schema</h4>
         <pre>{{schema}}</pre>
     </div>
@@ -200,6 +200,24 @@
     </div>
 </script>
 
+<!--template-->
+<!-- static template for cube save/update result notification -->
+<script type="text/ng-template" id=" modelResultError.html">
+    <div class="callout callout-info">
+        <h4>Error Message</h4>
+        <p>{{text}}</p>
+    </div>
+    <div class="callout callout-danger">
+        <h4>Model Schema</h4>
+        <pre>{{schema}}</pre>
+    </div>
+</script>
+
+<script type="text/ng-template" id="modelResultSuccess.html">
+    <div class="callout callout-info">
+        <p>{{text}}</p>
+    </div>
+</script>
 
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/e6b0715d/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 18a0cd2..0289bc4 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -861,3 +861,35 @@ span.input-icon {
   -moz-box-shadow: 0 0 8px rgba(82, 168, 236, .6);
   box-shadow: 0 0 8px rgba(82, 168, 236, .6)
 }
+
+
+//override callout info in AdinLTE.css
+.callout {
+   margin: 0 0 20px 0 !important;
+   padding: 15px 30px 15px 15px !important;
+   border-left: 5px solid #eee !important;
+   color: black !important;
+ }
+
+.callout.callout-info {
+  background-color: #f0f7fd !important;
+  border-color: #d0e3f0 !important;
+  color: black !important;
+}
+
+.callout.callout-danger {
+  background-color: #fcf2f2  !important;
+  border-color: #dFb5b4  !important;
+  color: black !important;
+}
+
+ul.messenger-theme-ice .messenger-message{
+  color:#666667 !important;
+}
+.messenger-message.alert{
+  background-color: #f6f6f6 !important;
+}
+
+.model-dimension-edit .chosen-container{
+  width:100% !important;
+}


[20/52] [abbrv] incubator-kylin git commit: add model service&controller backend

Posted by ma...@apache.org.
add model service&controller backend


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

Branch: refs/heads/0.8.0
Commit: 286e52036ff0aec8fa2118561eac7a21eac755b0
Parents: be5b810
Author: jiazhong <ji...@ebay.com>
Authored: Thu Mar 12 17:49:27 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:49 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/metadata/MetadataManager.java  |  11 +-
 .../kylin/rest/controller/CubeController.java   |  69 +--------
 .../kylin/rest/controller/ModelController.java  | 149 +++++++++++++++----
 .../rest/controller/ModelDescController.java    |  61 ++++++++
 .../apache/kylin/rest/request/CubeRequest.java  |  29 +---
 .../apache/kylin/rest/request/ModelRequest.java | 109 ++++++++++++++
 .../apache/kylin/rest/service/ModelService.java | 118 +++++++++++++++
 .../rest/controller/CubeControllerTest.java     |   7 -
 8 files changed, 420 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index b5a3e96..9d489e2 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -22,11 +22,7 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -286,6 +282,11 @@ public class MetadataManager {
         return dataModelDescMap.get(name);
     }
 
+    public List<DataModelDesc> getModels() {
+        return new ArrayList<DataModelDesc>(dataModelDescMap.values());
+    }
+
+
     private void reloadAllDataModel() throws IOException {
         ResourceStore store = getStore();
         logger.debug("Reloading DataModel from folder " + store.getReadableResourcePath(ResourceStore.DATA_MODEL_DESC_RESOURCE_ROOT));

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
index 231c834..d4cef18 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -122,7 +122,6 @@ public class CubeController extends BasicController {
      * @param cubeName
      * @param notifyList
      * @throws IOException
-     * @throws CubeIntegrityException
      */
     @RequestMapping(value = "/{cubeName}/notify_list", method = {RequestMethod.PUT})
     @ResponseBody
@@ -283,7 +282,7 @@ public class CubeController extends BasicController {
     }
 
     /**
-     * Get available table list of the input database
+     *save cubeDesc
      *
      * @return Table metadata array
      * @throws IOException
@@ -292,26 +291,6 @@ public class CubeController extends BasicController {
     @ResponseBody
     @Metered(name = "saveCube")
     public CubeRequest saveCubeDesc(@RequestBody CubeRequest cubeRequest) {
-        //Update Model 
-        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        DataModelDesc modelDesc = deserializeDataModelDesc(cubeRequest);
-        if (modelDesc == null || StringUtils.isEmpty(modelDesc.getName())) {
-            return cubeRequest;
-        }
-
-        try {
-            DataModelDesc existingModel = metaManager.getDataModelDesc(modelDesc.getName());
-            if (existingModel == null) {
-                metaManager.createDataModelDesc(modelDesc);
-            } else {
-                modelDesc.setLastModified(existingModel.getLastModified());
-                metaManager.updateDataModelDesc(modelDesc);
-            }
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
 
         CubeDesc desc = deserializeCubeDesc(cubeRequest);
         if (desc == null) {
@@ -339,7 +318,7 @@ public class CubeController extends BasicController {
     }
 
     /**
-     * Get available table list of the input database
+     * update CubDesc
      *
      * @return Table metadata array
      * @throws JsonProcessingException
@@ -350,30 +329,6 @@ public class CubeController extends BasicController {
     @Metered(name = "updateCube")
     public CubeRequest updateCubeDesc(@RequestBody CubeRequest cubeRequest) throws JsonProcessingException {
 
-        //Update Model 
-        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        DataModelDesc modelDesc = deserializeDataModelDesc(cubeRequest);
-        if (modelDesc == null) {
-            return cubeRequest;
-        }
-        try {
-
-            DataModelDesc existingModel = metaManager.getDataModelDesc(modelDesc.getName());
-            if (existingModel == null) {
-                metaManager.createDataModelDesc(modelDesc);
-            } else {
-
-                //ignore overwriting conflict checking before splict MODEL & CUBE
-                modelDesc.setLastModified(existingModel.getLastModified());
-                metaManager.updateDataModelDesc(modelDesc);
-            }
-
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-
         //update cube
         CubeDesc desc = deserializeCubeDesc(cubeRequest);
 
@@ -413,7 +368,7 @@ public class CubeController extends BasicController {
     }
 
     /**
-     * Get available table list of the input database
+     *get Hbase Info
      *
      * @return true
      * @throws IOException
@@ -474,23 +429,7 @@ public class CubeController extends BasicController {
         return desc;
     }
 
-    private DataModelDesc deserializeDataModelDesc(CubeRequest cubeRequest) {
-        DataModelDesc desc = null;
-        try {
-            logger.debug("Saving MODEL " + cubeRequest.getModelDescData());
-            desc = JsonUtil.readValue(cubeRequest.getModelDescData(), DataModelDesc.class);
-        } catch (JsonParseException e) {
-            logger.error("The data model definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data model definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
+
 
     /**
      * @return

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 2499f59..97a5d32 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -18,50 +18,143 @@
 
 package org.apache.kylin.rest.controller;
 
-import java.io.IOException;
-
-import org.apache.kylin.rest.service.CubeService;
+import com.codahale.metrics.annotation.Metered;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.ModelRequest;
+import org.apache.kylin.rest.service.ModelService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
 
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.DataModelDesc;
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
 
 /**
+ * ModelController is defined as Restful API entrance for UI.
+ *
  * @author jiazhong
- * 
  */
 @Controller
-@RequestMapping(value = "/model")
-public class ModelController {
+@RequestMapping(value = "/models")
+public class ModelController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(ModelController.class);
 
     @Autowired
-    private CubeService cubeService;
+    private ModelService modelService;
+
+    @RequestMapping(value = "", method = {RequestMethod.GET})
+    @ResponseBody
+    @Metered(name = "listModels")
+    public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam("limit") Integer limit, @RequestParam("offset") Integer offset) {
+        return modelService.getModels(modelName, projectName, (null == limit) ? 20 : limit, offset);
+    }
+
+    @RequestMapping(value = "/{modelName}", method = {RequestMethod.DELETE})
+    @ResponseBody
+    @Metered(name = "deleteModel")
+    public void deleteModel(@PathVariable String modelName) {
+
+    }
 
     /**
-     * Get detail information of the "Cube ID"
-     * 
-     * @param cubeDescName
-     *            Cube ID
-     * @return
-     * @throws IOException
+     *
+     * create model
+     * @throws java.io.IOException
      */
-    @RequestMapping(value = "/{model_name}", method = { RequestMethod.GET })
+    @RequestMapping(value = "", method = {RequestMethod.POST})
     @ResponseBody
-    public DataModelDesc getModel(@PathVariable String model_name) {
-        MetadataManager metaManager= MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        DataModelDesc modeDesc = metaManager.getDataModelDesc(model_name);
-        return modeDesc;
-            
+    @Metered(name = "saveModel")
+    public ModelRequest saveModelDesc(@RequestBody ModelRequest modelRequest) {
+        //Update Model
+        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
+        if (modelDesc == null || StringUtils.isEmpty(modelDesc.getName())) {
+            return modelRequest;
+        }
+        if (StringUtils.isEmpty(modelDesc.getName())) {
+            logger.info("Model name should not be empty.");
+            throw new BadRequestException("Model name should not be empty.");
+        }
+
+        try {
+            modelDesc.setUuid(UUID.randomUUID().toString());
+            String projectName = (null == modelRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : modelRequest.getProject();
+
+            modelService.createModelDesc(projectName, modelDesc);
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        modelRequest.setUuid(modelDesc.getUuid());
+        modelRequest.setSuccessful(true);
+        return modelRequest;
+    }
+
+    @RequestMapping(value = "", method = {RequestMethod.PUT})
+    @ResponseBody
+    @Metered(name = "updateModel")
+    public ModelRequest updateModelDesc(@RequestBody ModelRequest modelRequest) throws JsonProcessingException {
+
+        //Update Model
+        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
+        if (modelDesc == null) {
+            return modelRequest;
+        }
+
+        try {
+            modelService.updateModelAndDesc(modelDesc,modelRequest.getProject());
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        String descData = JsonUtil.writeValueAsIndentString(modelDesc);
+        modelRequest.setModelDescData(descData);
+
+        return modelRequest;
     }
 
-    public void setCubeService(CubeService cubeService) {
-        this.cubeService = cubeService;
+
+
+    private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
+        DataModelDesc desc = null;
+        try {
+            logger.debug("Saving MODEL " + modelRequest.getModelDescData());
+            desc = JsonUtil.readValue(modelRequest.getModelDescData(), DataModelDesc.class);
+        } catch (JsonParseException e) {
+            logger.error("The data model definition is not valid.", e);
+            updateRequest(modelRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data model definition is not valid.", e);
+            updateRequest(modelRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
     }
 
+    private void updateRequest(ModelRequest request, boolean success, String message) {
+        request.setModelDescData("");
+        request.setSuccessful(success);
+        request.setMessage(message);
+    }
+    public void setModelService(ModelService modelService) {
+        this.modelService = modelService;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
new file mode 100644
index 0000000..fda7927
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
@@ -0,0 +1,61 @@
+/*
+ * 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.controller;
+
+import java.io.IOException;
+
+import org.apache.kylin.rest.service.CubeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.DataModelDesc;
+
+/**
+ * @author jiazhong
+ * 
+ */
+@Controller
+@RequestMapping(value = "/model")
+public class ModelDescController extends BasicController{
+
+
+    /**
+     * Get detail information of the "Model ID"
+     * 
+     * @param modelDescName
+     *            Model ID
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{model_name}", method = { RequestMethod.GET })
+    @ResponseBody
+    public DataModelDesc getModel(@PathVariable String model_name) {
+        MetadataManager metaManager= MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        DataModelDesc modeDesc = metaManager.getDataModelDesc(model_name);
+        return modeDesc;
+            
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
index ab6f8f4..6c4eecb 100644
--- a/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
+++ b/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
@@ -23,10 +23,8 @@ public class CubeRequest {
     private String uuid;
     private String cubeName;
     private String cubeDescData;
-    private String modelDescData;
     private boolean successful;
     private String message;
-    private String cubeDescName;
     private String project;
 
     public String getUuid() {
@@ -38,21 +36,6 @@ public class CubeRequest {
     }
 
     /**
-     * @return the cubeDescName
-     */
-    public String getCubeDescName() {
-        return cubeDescName;
-    }
-
-    /**
-     * @param cubeDescName
-     *            the cubeDescName to set
-     */
-    public void setCubeDescName(String cubeDescName) {
-        this.cubeDescName = cubeDescName;
-    }
-
-    /**
      * @return the message
      */
     public String getMessage() {
@@ -85,10 +68,9 @@ public class CubeRequest {
     public CubeRequest() {
     }
 
-    public CubeRequest(long id, String cubeName, String cubeDescData,String modelDescData) {
+    public CubeRequest( String cubeName, String cubeDescData) {
         this.cubeName = cubeName;
         this.cubeDescData = cubeDescData;
-        this.modelDescData = modelDescData;
     }
 
     public String getCubeDescData() {
@@ -98,16 +80,7 @@ public class CubeRequest {
     public void setCubeDescData(String cubeDescData) {
         this.cubeDescData = cubeDescData;
     }
-    
-    
-    
-    public String getModelDescData() {
-        return modelDescData;
-    }
 
-    public void setModelDescData(String modelDescData) {
-        this.modelDescData = modelDescData;
-    }
 
     /**
      * @return the cubeDescName

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java b/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
new file mode 100644
index 0000000..15b62cf
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
@@ -0,0 +1,109 @@
+/*
+ * 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 ModelRequest {
+
+    private String uuid;
+    private String modelName;
+    private String modelDescData;
+    private boolean successful;
+    private String message;
+    private String project;
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @param message
+     *            the message to set
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    /**
+     * @return the status
+     */
+    public boolean getSuccessful() {
+        return successful;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setSuccessful(boolean status) {
+        this.successful = status;
+    }
+
+    public ModelRequest() {
+    }
+
+    public ModelRequest(String modelName, String modelDescData) {
+        this.modelName = modelName;
+        this.modelDescData = modelDescData;
+    }
+
+    
+    
+    public String getModelDescData() {
+        return modelDescData;
+    }
+
+    public void setModelDescData(String modelDescData) {
+        this.modelDescData = modelDescData;
+    }
+
+    /**
+     * @return the modelName
+     */
+    public String getModelName() {
+        return modelName;
+    }
+
+    /**
+     * @param modelName
+     *            the cubeName to set
+     */
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
new file mode 100644
index 0000000..ddf2594
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -0,0 +1,118 @@
+/*
+ * 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.service;
+
+
+import org.apache.kylin.job.exception.JobException;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author jiazhong
+ */
+@Component("modelMgmtService")
+public class ModelService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ModelService.class);
+
+    @Autowired
+    private AccessService accessService;
+
+    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
+    public List<DataModelDesc> listAllModels(final String modelName, final String projectName) {
+        List<DataModelDesc> models = null;
+        ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
+
+        if (null == project) {
+            models = getMetadataManager().getModels();
+        } else {
+            //TO-DO
+//            models = listAllModels(projectName);
+        }
+
+        List<DataModelDesc> filterModels = new ArrayList();
+        for (DataModelDesc modelDesc : models) {
+            boolean isModelMatch = (null == modelName) || modelDesc.getName().toLowerCase().contains(modelName.toLowerCase());
+
+            if (isModelMatch) {
+                filterModels.add(modelDesc);
+            }
+        }
+
+        return filterModels;
+    }
+
+    public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) {
+        int climit = (null == limit) ? 30 : limit;
+        int coffset = (null == offset) ? 0 : offset;
+
+        List<DataModelDesc> modelDescs;
+        modelDescs = listAllModels(modelName, projectName);
+
+        if (modelDescs.size() <= coffset) {
+            return Collections.emptyList();
+        }
+
+        if ((modelDescs.size() - coffset) < climit) {
+            return modelDescs.subList(coffset, modelDescs.size());
+        }
+
+        return modelDescs.subList(coffset, coffset + climit);
+    }
+
+
+    public DataModelDesc createModelDesc(String projectName, DataModelDesc desc) throws IOException {
+        if (getMetadataManager().getDataModelDesc(desc.getName()) != null) {
+            throw new InternalErrorException("The model named " + desc.getName() + " already exists");
+        }
+        DataModelDesc createdDesc = null;
+        createdDesc = getMetadataManager().createDataModelDesc(desc);
+//        ProjectInstance project = getProjectManager().getProject(projectName);
+//        accessService.inherit(createdDesc, project);
+        return createdDesc;
+    }
+
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#model, 'ADMINISTRATION') or hasPermission(#model, 'MANAGEMENT')")
+    public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
+        DataModelDesc existingModel = getMetadataManager().getDataModelDesc(desc.getName());
+        if (existingModel == null) {
+            getMetadataManager().createDataModelDesc(desc);
+        } else {
+            getMetadataManager().updateDataModelDesc(desc);
+        }
+        return desc;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/286e5203/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
index 336eae5..52c2d77 100644
--- a/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/controller/CubeControllerTest.java
@@ -43,7 +43,6 @@ public class CubeControllerTest extends ServiceTestBase {
 
     private CubeController cubeController;
     private CubeDescController cubeDescController;
-    private ModelController modelController;
 
     @Autowired
     CubeService cubeService;
@@ -60,8 +59,6 @@ public class CubeControllerTest extends ServiceTestBase {
         cubeDescController = new CubeDescController();
         cubeDescController.setCubeService(cubeService);
 
-        modelController = new ModelController();
-        modelController.setCubeService(cubeService);
     }
 
     @Test
@@ -104,13 +101,9 @@ public class CubeControllerTest extends ServiceTestBase {
 
         CubeRequest cubeRequest = new CubeRequest();
         cubeRequest.setCubeDescData(cubeDescWriter.toString());
-        cubeRequest.setModelDescData(modelDescWriter.toString());
         cubeRequest = cubeController.saveCubeDesc(cubeRequest);
 
 
-        DataModelDesc model = modelController.getModel(newModelName);
-        Assert.assertNotNull(model);
-
         List<String> notifyList = Lists.newArrayList();
         notifyList.add("john@example.com");
         cubeController.updateNotifyList(newCubeName, notifyList);


[46/52] [abbrv] incubator-kylin git commit: KYLIN-675

Posted by ma...@apache.org.
KYLIN-675


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

Branch: refs/heads/0.8.0
Commit: a35133a69a1e69e0dfde56ce28b55ac151b726fd
Parents: d9e2d04
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 10 14:44:13 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:39:11 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cube.js      | 4 ++--
 webapp/app/js/controllers/modelEdit.js | 4 ++--
 webapp/app/js/controllers/query.js     | 1 +
 webapp/app/partials/query/query.html   | 2 +-
 4 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a35133a6/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 8e184d1..55c54f0 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -357,8 +357,8 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
 });
 
 
-var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube,metaModel, buildType,SweetAlert,loadingRequest) {
-    $scope.cube = cube;
+var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube,metaModel, buildType,SweetAlert,loadingRequest,cubesManager) {
+    $scope.cubesManager = cubesManager;
     $scope.metaModel={
         model:metaModel.model
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a35133a6/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index c483752..22a9f23 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -117,7 +117,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
             modelsManager.selectedModel.partition_desc.partition_date_start=null;
         }
         $scope.state.project = modelsManager.selectedModel.project;
-        var _model = angular.copy($scope.model);
+        var _model = angular.copy(modelsManager.selectedModel);
         delete _model.project;
         $scope.state.modelSchema = angular.toJson(_model, true);
 
@@ -220,7 +220,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         if(modelsManager.selectedModel.partition_desc.partition_date_start==0){
             modelsManager.selectedModel.partition_desc.partition_date_start = null;
         }
-        if($scope.model&&(modelsManager.selectedModel.partition_desc.partition_date_start||modelsManager.selectedModel.partition_desc.partition_date_start==0))
+        if(modelsManager.selectedModel&&(modelsManager.selectedModel.partition_desc.partition_date_start||modelsManager.selectedModel.partition_desc.partition_date_start==0))
         {
             modelsManager.selectedModel.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a35133a6/webapp/app/js/controllers/query.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/query.js b/webapp/app/js/controllers/query.js
index 10be251..4cf699f 100644
--- a/webapp/app/js/controllers/query.js
+++ b/webapp/app/js/controllers/query.js
@@ -354,6 +354,7 @@ KylinApp
 
         $scope.refreshCurQuery = function () {
             $scope.curQuery = this.query;
+
         }
 
         $scope.showSavePanel = function () {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a35133a6/webapp/app/partials/query/query.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/query/query.html b/webapp/app/partials/query/query.html
index d34dbc7..7947788 100644
--- a/webapp/app/partials/query/query.html
+++ b/webapp/app/partials/query/query.html
@@ -193,7 +193,7 @@
                         class="{{(query==curQuery)? 'active':''}}">
                         <span>
                             <button class="btn {{(query==curQuery)?'active':''}} btn-default btn-xs" style="width: 50px"
-                                    ng-click="refreshCurQuery()">
+                                    ng-click="refreshCurQuery();$event.stopPropagation();">
                                 {{$index+1}}
                                 <span ng-if="query.status=='failed'">
                                     <i style="color: #f0ad4e" class="fa fa-exclamation-triangle"></i>


[15/52] [abbrv] incubator-kylin git commit: move project to header and update AdminLTE css to v2.0.4

Posted by ma...@apache.org.
move project to header and update AdminLTE css to v2.0.4


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

Branch: refs/heads/0.8.0
Commit: 603fe3fcec98dc75e8878f7dd2f24df6677bd953
Parents: 4b50834
Author: jiazhong <ji...@ebay.com>
Authored: Wed Mar 11 18:44:14 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:34:17 2015 +0800

----------------------------------------------------------------------
 webapp/app/css/AdminLTE.css                     | 4600 ++++++++++--------
 webapp/app/less/component.less                  |   24 +-
 webapp/app/partials/cubes/cube_json_edit.html   |   15 -
 webapp/app/partials/cubes/cubes.html            |    8 -
 webapp/app/partials/header.html                 |   20 +-
 webapp/app/partials/jobs/jobs.html              |   15 +-
 webapp/app/partials/query/query.html            |    9 -
 webapp/app/partials/tables/source_metadata.html |    8 -
 8 files changed, 2618 insertions(+), 2081 deletions(-)
----------------------------------------------------------------------



[45/52] [abbrv] incubator-kylin git commit: use modelsManager

Posted by ma...@apache.org.
use modelsManager


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

Branch: refs/heads/0.8.0
Commit: d9e2d046d8bd72a0fd56f6bbf8806c9215dd9035
Parents: 0088884
Author: jiazhong <ji...@ebay.com>
Authored: Wed Apr 8 17:27:04 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:33 2015 +0800

----------------------------------------------------------------------
 webapp/app/index.html                           |   3 +-
 webapp/app/js/controllers/cube.js               |  15 +-
 webapp/app/js/controllers/cubeAdvanceSetting.js |   5 +-
 webapp/app/js/controllers/cubeDimensions.js     |   9 +-
 webapp/app/js/controllers/cubeEdit.js           |  66 +++----
 webapp/app/js/controllers/cubeModel.js          |  15 +-
 webapp/app/js/controllers/cubeSchema.js         |  21 +--
 webapp/app/js/controllers/modelDimensions.js    |  15 +-
 webapp/app/js/controllers/modelEdit.js          |  36 ++--
 webapp/app/js/controllers/modelSchema.js        |  14 +-
 webapp/app/js/controllers/models.js             | 101 +++--------
 webapp/app/js/model/cubesManager.js             |   4 +
 webapp/app/js/model/modelList.js                |  91 ----------
 webapp/app/js/model/modelsManager.js            | 178 +++++++++++++++++++
 .../cubeDesigner/advanced_settings.html         |  18 +-
 .../app/partials/cubeDesigner/dimensions.html   |   4 +-
 webapp/app/partials/cubeDesigner/info.html      |  16 +-
 webapp/app/partials/cubeDesigner/measures.html  |   6 +-
 webapp/app/partials/cubeDesigner/overview.html  |   8 +-
 webapp/app/partials/cubes/cube_detail.html      |  98 +++++-----
 webapp/app/partials/jobs/job_merge.html         |  16 +-
 webapp/app/partials/jobs/job_refresh.html       |  12 +-
 webapp/app/partials/jobs/job_submit.html        |  11 +-
 .../modelDesigner/conditions_settings.html      |  28 +--
 .../app/partials/modelDesigner/data_model.html  |  18 +-
 .../modelDesigner/model_dimensions.html         |  12 +-
 .../app/partials/modelDesigner/model_info.html  |   8 +-
 .../partials/modelDesigner/model_measures.html  |   8 +-
 webapp/app/partials/models/model_detail.html    |  38 ++--
 webapp/app/partials/models/model_schema.html    |   8 +-
 webapp/app/partials/models/models.html          |   4 +-
 webapp/app/partials/models/models_tree.html     |   4 +-
 32 files changed, 477 insertions(+), 413 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 19ced08..8845499 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -145,9 +145,10 @@
 <script src="js/model/tableModel.js"></script>
 <script src="js/model/cubeListModel.js"></script>
 <script src="js/model/jobListModel.js"></script>
+<script src="js/model/cubesManager.js"></script>
 
 <!--New GUI-->
-<script src="js/model/modelList.js"></script>
+<script src="js/model/modelsManager.js"></script>
 
 <script src="js/controllers/page.js"></script>
 <script src="js/controllers/index.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index f31742a..8e184d1 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,10 +18,13 @@
 
 'use strict';
 
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert,loadingRequest,ModelList,$modal) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert,loadingRequest,modelsManager,$modal,cubesManager) {
     $scope.newAccess = null;
     $scope.state = {jsonEdit: false};
 
+    $scope.modelsManager = modelsManager;
+    $scope.cubesManager = cubesManager;
+
     $scope.buildGraph = function (cube) {
        GraphService.buildTree(cube);
     };
@@ -242,7 +245,9 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
     };
 
     $scope.startJobSubmit = function (cube) {
-        $scope.metaModel.model = ModelList.getModelByCube(cube.name);
+        $scope.metaModel={
+            model:modelsManager.getModelByCube(cube.name)
+        }
         if ($scope.metaModel.model.name) {
             if ($scope.metaModel.model.partition_desc.partition_date_column) {
                 $modal.open({
@@ -306,6 +311,9 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
     };
 
     $scope.startRefresh = function (cube) {
+        $scope.metaModel={
+            model:modelsManager.getModelByCube(cube.name)
+        };
             $modal.open({
                 templateUrl: 'jobRefresh.html',
                 controller: jobSubmitCtrl,
@@ -325,6 +333,9 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
     };
 
     $scope.startMerge = function (cube) {
+        $scope.metaModel={
+            model:modelsManager.getModelByCube(cube.name)
+        };
             $modal.open({
                 templateUrl: 'jobMerge.html',
                 controller: jobSubmitCtrl,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cubeAdvanceSetting.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeAdvanceSetting.js b/webapp/app/js/controllers/cubeAdvanceSetting.js
index c9558d8..c29f513 100644
--- a/webapp/app/js/controllers/cubeAdvanceSetting.js
+++ b/webapp/app/js/controllers/cubeAdvanceSetting.js
@@ -18,10 +18,11 @@
 
 'use strict';
 
-KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
+KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,MetaModel,cubesManager) {
+    $scope.cubesManager = cubesManager;
 
     //convert some undefined or null value
-    angular.forEach($scope.cubeMetaFrame.rowkey.rowkey_columns,function(rowkey){
+    angular.forEach(cubesManager.cubeMetaFrame.rowkey.rowkey_columns,function(rowkey){
             if(!rowkey.dictionary){
                 rowkey.dictionary = "false";
             }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index 35b66ab..8608bfc 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -18,8 +18,9 @@
 
 'use strict';
 
-KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
+KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel,cubesManager) {
 
+    $scope.cubeManager = cubesManager;
     // Available columns list derived from cube data model.
     $scope.availableColumns = {};
 
@@ -114,7 +115,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
 
     // Check column status: selected or disabled based on current cube dimensions.
     $scope.initColumnStatus = function () {
-        angular.forEach($scope.cubeMetaFrame.dimensions, function (dim) {
+        angular.forEach(cubesManager.cubeMetaFrame.dimensions, function (dim) {
             var cols = dimCols(dim);
 
             angular.forEach(cols, function (colName) {
@@ -189,7 +190,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         return types;
     };
 
-    var dimList = $scope.cubeMetaFrame.dimensions;
+    var dimList = cubesManager.cubeMetaFrame.dimensions;
 
     // Open add/edit dimension modal.
     $scope.openDimModal = function (dimType) {
@@ -417,7 +418,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
     // Check whether there is column conflicts.
     $scope.dimConflicts = [];
 
-    $scope.$watch('cubeMetaFrame.dimensions', function (newVal, oldVal) {
+    $scope.$watch('cubesManager.cubeMetaFrame.dimensions', function (newVal, oldVal) {
         if (!newVal || !newVal.length) {
             return;
         }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 98fc9a3..94ea27b 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -19,7 +19,7 @@
 'use strict';
 
 
-KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService,ModelList) {
+KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService,modelsManager,cubesManager) {
     $scope.cubeConfig = cubeConfig;
 
     // when add cube will transfer model Name
@@ -115,28 +115,30 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     if ($scope.isEdit = !!$routeParams.cubeName) {
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
-                $scope.cubeMetaFrame = detail[0];
+                cubesManager.cubeMetaFrame = detail[0];
+                cubesManager.cubeMetaFrame = detail[0];
                 $scope.metaModel = {};
 
                 //get model from API when page refresh
-                if(!ModelList.getModels().length){
-                    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (_model) {
+                if(!modelsManager.getModels().length){
+                    ModelDescService.get({model_name: cubesManager.cubeMetaFrame.model_name}, function (_model) {
                         $scope.metaModel.model = _model;
                     });
                 }
-                $scope.metaModel.model=ModelList.getModel($scope.cubeMetaFrame.model_name);
+                $scope.metaModel.model=modelsManager.getModel(cubesManager.cubeMetaFrame.model_name);
 
-                $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
+                $scope.state.cubeSchema = angular.toJson(cubesManager.cubeMetaFrame, true);
             }
         });
 
     } else {
-        $scope.cubeMetaFrame = CubeDescModel.createNew();
+//        cubesManager.cubeMetaFrame = CubeDescModel.createNew();
+        cubesManager.cubeMetaFrame = CubeDescModel.createNew();
         $scope.metaModel ={
-            model : ModelList.getModel(modelName)
+            model : modelsManager.getModel(modelName)
         }
-        $scope.cubeMetaFrame.model_name = modelName;
-        $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
+        cubesManager.cubeMetaFrame.model_name = modelName;
+        $scope.state.cubeSchema = angular.toJson(cubesManager.cubeMetaFrame, true);
     }
 
 
@@ -161,18 +163,18 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         }
         //use cubedesc name as model name
         if($scope.metaModel.model.name===""||angular.isUndefined($scope.metaModel.model.name)){
-            $scope.metaModel.model.name = $scope.cubeMetaFrame.name;
+            $scope.metaModel.model.name = cubesManager.cubeMetaFrame.name;
         }
 
         //set model ref for cubeDesc
-        if($scope.cubeMetaFrame.model_name===""||angular.isUndefined($scope.cubeMetaFrame.model_name)){
-            $scope.cubeMetaFrame.model_name = $scope.cubeMetaFrame.name;
+        if(cubesManager.cubeMetaFrame.model_name===""||angular.isUndefined(cubesManager.cubeMetaFrame.model_name)){
+            cubesManager.cubeMetaFrame.model_name = cubesManager.cubeMetaFrame.name;
         }
 
-        $scope.state.project = $scope.cubeMetaFrame.project;
-//        delete $scope.cubeMetaFrame.project;
+        $scope.state.project = cubesManager.cubeMetaFrame.project;
+//        delete cubesManager.cubeMetaFrame.project;
 
-        $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
+        $scope.state.cubeSchema = angular.toJson(cubesManager.cubeMetaFrame, true);
     };
 
     $scope.cubeResultTmpl = function (notification) {
@@ -210,7 +212,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
                         } else {
                             $scope.saveCubeRollBack();
-                            $scope.cubeMetaFrame.project = $scope.state.project;
+                            cubesManager.cubeMetaFrame.project = $scope.state.project;
                                 var message =request.message;
                                 var msg = !!(message) ? message : 'Failed to take action.';
                                 MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.cubeSchema}), 'error', {}, true, 'top_center');
@@ -237,7 +239,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':'Created the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
                         } else {
                             $scope.saveCubeRollBack();
-                            $scope.cubeMetaFrame.project = $scope.state.project;
+                            cubesManager.cubeMetaFrame.project = $scope.state.project;
                             var message =request.message;
                             var msg = !!(message) ? message : 'Failed to take action.';
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.cubeSchema}), 'error', {}, true, 'top_center');
@@ -277,7 +279,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     $scope.updateMandatory = function(rowkey_column){
         if(!rowkey_column.mandatory){
-            angular.forEach($scope.cubeMetaFrame.rowkey.aggregation_groups, function (group, index) {
+            angular.forEach(cubesManager.cubeMetaFrame.rowkey.aggregation_groups, function (group, index) {
                    var index = group.indexOf(rowkey_column.column);
                    if(index>-1){
                        group.splice(index,1);
@@ -291,7 +293,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         var tmpRowKeyColumns = [];
         var tmpAggregationItems = [];//put all aggregation item
         var hierarchyItemArray = [];//put all hierarchy items
-        angular.forEach($scope.cubeMetaFrame.dimensions, function (dimension, index) {
+        angular.forEach(cubesManager.cubeMetaFrame.dimensions, function (dimension, index) {
 
            //derived column
             if(dimension.derived&&dimension.derived.length){
@@ -361,7 +363,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
 
         //rm mandatory column from aggregation item
-        angular.forEach($scope.cubeMetaFrame.rowkey.rowkey_columns,function(value,index){
+        angular.forEach(cubesManager.cubeMetaFrame.rowkey.rowkey_columns,function(value,index){
                 if(value.mandatory){
                     tmpAggregationItems = _.filter(tmpAggregationItems,function(item){
                            return item!=value.column;
@@ -369,16 +371,16 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                 }
         });
 
-        var rowkeyColumns = $scope.cubeMetaFrame.rowkey.rowkey_columns;
+        var rowkeyColumns = cubesManager.cubeMetaFrame.rowkey.rowkey_columns;
         var newRowKeyColumns = sortSharedData(rowkeyColumns,tmpRowKeyColumns);
         var increasedColumns = increasedColumn(rowkeyColumns,tmpRowKeyColumns);
         newRowKeyColumns = newRowKeyColumns.concat(increasedColumns);
 
         //! here get the latest rowkey_columns
-        $scope.cubeMetaFrame.rowkey.rowkey_columns = newRowKeyColumns;
+        cubesManager.cubeMetaFrame.rowkey.rowkey_columns = newRowKeyColumns;
 
         if($scope.cubeMode==="editExistCube") {
-            var aggregationGroups = $scope.cubeMetaFrame.rowkey.aggregation_groups;
+            var aggregationGroups = cubesManager.cubeMetaFrame.rowkey.aggregation_groups;
             // rm unused item from group,will only rm when [edit] dimension
             angular.forEach(aggregationGroups, function (group, index) {
                 if (group) {
@@ -410,7 +412,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         if($scope.cubeMode==="addNewCube"){
 
           if(!tmpAggregationItems.length) {
-              $scope.cubeMetaFrame.rowkey.aggregation_groups=[];
+              cubesManager.cubeMetaFrame.rowkey.aggregation_groups=[];
               return;
           }
 
@@ -426,7 +428,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
           //hierarchyItems
           var increasedDataGroups = sliceGroupItemToGroups(unHierarchyItems);
           if(!hierarchyItemArray.length){
-              $scope.cubeMetaFrame.rowkey.aggregation_groups = increasedDataGroups;
+              cubesManager.cubeMetaFrame.rowkey.aggregation_groups = increasedDataGroups;
               return;
           };
 
@@ -474,7 +476,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
               }
           }
             //! here get the latest aggregation groups,only effect when add newCube
-            $scope.cubeMetaFrame.rowkey.aggregation_groups = increasedDataGroups;
+            cubesManager.cubeMetaFrame.rowkey.aggregation_groups = increasedDataGroups;
         }
     }
 
@@ -554,10 +556,10 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     // ~ private methods
     function generateColumnFamily() {
-        $scope.cubeMetaFrame.hbase_mapping.column_family = [];
+        cubesManager.cubeMetaFrame.hbase_mapping.column_family = [];
         var colFamily = ColFamily();
         var normalMeasures = [], distinctCountMeasures=[];
-        angular.forEach($scope.cubeMetaFrame.measures, function (measure, index) {
+        angular.forEach(cubesManager.cubeMetaFrame.measures, function (measure, index) {
             if(measure.function.expression === 'COUNT_DISTINCT'){
                 distinctCountMeasures.push(measure);
             }else{
@@ -569,7 +571,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             angular.forEach(normalMeasures, function(normalM, index){
                 nmcf.columns[0].measure_refs.push(normalM.name);
             });
-            $scope.cubeMetaFrame.hbase_mapping.column_family.push(nmcf);
+            cubesManager.cubeMetaFrame.hbase_mapping.column_family.push(nmcf);
         }
 
         if (distinctCountMeasures.length > 0){
@@ -577,7 +579,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             angular.forEach(distinctCountMeasures, function(dcm, index){
                 dccf.columns[0].measure_refs.push(dcm.name);
             });
-            $scope.cubeMetaFrame.hbase_mapping.column_family.push(dccf);
+            cubesManager.cubeMetaFrame.hbase_mapping.column_family.push(dccf);
         }
     }
 
@@ -601,7 +603,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
     });
 
     $scope.$on('DimensionsEdited', function (event) {
-        if ($scope.cubeMetaFrame) {
+        if (cubesManager.cubeMetaFrame) {
             reGenerateRowKey();
         }
     });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index cbd7978..dd7991d 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,8 +18,9 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel,ModelService,loadingRequest) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log,TableModel,ModelService,loadingRequest,modelsManager) {
 
+    $scope.modelsManager = modelsManager;
 
     $scope.buildGraph = function (model) {
 //        var newModel = jQuery.extend(true, {}, model);
@@ -71,7 +72,7 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
 
     $scope.newLookup = Lookup();
 
-    var lookupList = $scope.model.lookups;
+    var lookupList = modelsManager.selectedModel.lookups;
 
     $scope.openLookupModal = function () {
         var modalInstance = $modal.open({
@@ -134,7 +135,7 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
     };
 
         $scope.removeLookup = function (lookup) {
-            var dimExist = _.some($scope.model.dimensions,function(item,index){
+            var dimExist = _.some(modelsManager.selectedModel.dimensions,function(item,index){
                 return item.table===lookup.table;
             });
             if(dimExist) {
@@ -148,9 +149,9 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
                     closeOnConfirm: true
                 }, function (isConfirm) {
                     if (isConfirm) {
-                        for (var i = $scope.model.dimensions.length - 1; i >= 0; i--) {
-                            if ($scope.model.dimensions[i].table === lookup.table) {
-                                $scope.model.dimensions.splice(i, 1);
+                        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);
@@ -195,7 +196,7 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaMod
             }
 
             //column type validate
-            var fact_table = $scope.model.fact_table;
+            var fact_table = modelsManager.selectedModel.fact_table;
             var lookup_table = $scope.newLookup.table;
 
             for(var i = 0;i<$scope.newLookup.join.primary_key.length;i++){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 327dc25..89ee492 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -18,8 +18,9 @@
 
 'use strict';
 
-KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService,SweetAlert) {
+KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService,SweetAlert,cubesManager) {
 
+    $scope.cubesManager = cubesManager;
     $scope.projects = [];
     $scope.newDimension = null;
     $scope.newMeasure = null;
@@ -42,7 +43,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         $scope.state = {mode: "view"};
     }
 
-    $scope.$watch('cubeMetaFrame', function (newValue, oldValue) {
+    $scope.$watch('cubesManager.cubeMetaFrame', function (newValue, oldValue) {
         if(!newValue){
             return;
         }
@@ -66,8 +67,8 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.saveNewMeasure = function () {
-        if ($scope.cubeMetaFrame.measures.indexOf($scope.newMeasure) === -1) {
-            $scope.cubeMetaFrame.measures.push($scope.newMeasure);
+        if (cubesManager.cubeMetaFrame.measures.indexOf($scope.newMeasure) === -1) {
+            cubesManager.cubeMetaFrame.measures.push($scope.newMeasure);
         }
         $scope.newMeasure = null;
     };
@@ -103,7 +104,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     }
 
     $scope.addNewRowkeyColumn = function () {
-        $scope.cubeMetaFrame.rowkey.rowkey_columns.push({
+        cubesManager.cubeMetaFrame.rowkey.rowkey_columns.push({
             "column": "",
             "length": 0,
             "dictionary": "true",
@@ -112,7 +113,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.addNewAggregationGroup = function () {
-        $scope.cubeMetaFrame.rowkey.aggregation_groups.push([]);
+        cubesManager.cubeMetaFrame.rowkey.aggregation_groups.push([]);
     };
 
     $scope.refreshAggregationGroup = function (list, index, aggregation_groups) {
@@ -212,7 +213,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
 
     $scope.check_cube_dimension = function(){
         var errors = [];
-        if(!$scope.cubeMetaFrame.dimensions.length){
+        if(!cubesManager.cubeMetaFrame.dimensions.length){
             errors.push("Dimension can't be null");
         }
         var errorInfo = "";
@@ -228,7 +229,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.check_cube_measure = function(){
-        var _measures = $scope.cubeMetaFrame.measures;
+        var _measures = cubesManager.cubeMetaFrame.measures;
         var errors = [];
         if(!_measures||!_measures.length){
             errors.push("Please define your metrics.");
@@ -260,7 +261,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     $scope.check_cube_setting = function(){
         var errors = [];
 
-        angular.forEach($scope.cubeMetaFrame.rowkey.aggregation_groups,function(group){
+        angular.forEach(cubesManager.cubeMetaFrame.rowkey.aggregation_groups,function(group){
             if(!group.length){
                 errors.push("Each aggregation group can't be empty.");
             }
@@ -304,7 +305,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
                     TableModel.aceSrcTbLoaded();
                 }
 
-                $scope.cubeMetaFrame.project = projName;
+                cubesManager.cubeMetaFrame.project = projName;
             }
 
             angular.forEach($scope.projects, function (project, index) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/modelDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDimensions.js b/webapp/app/js/controllers/modelDimensions.js
index c89e6a6..41acd24 100644
--- a/webapp/app/js/controllers/modelDimensions.js
+++ b/webapp/app/js/controllers/modelDimensions.js
@@ -18,7 +18,8 @@
 
 'use strict';
 
-KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel) {
+KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel,modelsManager) {
+    $scope.modelsManager = modelsManager;
 
     // Available columns list derived from cube data model.
     $scope.availableColumns = {};
@@ -32,24 +33,24 @@ KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel) {
 
     // Dump available columns plus column table name, whether is from lookup table.
     $scope.initColumns = function () {
-        var factTable = $scope.model.fact_table;
+        var factTable = modelsManager.selectedModel.fact_table;
 
-        $scope.availableTables.push($scope.model.fact_table);
-        var lookups = $scope.model.lookups;
+        $scope.availableTables.push(modelsManager.selectedModel.fact_table);
+        var lookups = modelsManager.selectedModel.lookups;
         for (var j = 0; j < lookups.length; j++) {
             $scope.availableTables.push(lookups[j].table);
         }
 
 //        init dimension only when dimen
-//        if(!$scope.model.dimensions.length){
+//        if(!modelsManager.selectedModel.dimensions.length){
 
             for(var i = 0;i<$scope.availableTables.length;i++){
-                var tableInUse = _.some($scope.model.dimensions,function(item){
+                var tableInUse = _.some(modelsManager.selectedModel.dimensions,function(item){
                     return item.table == $scope.availableTables[i];
                 });
 
                 if(!tableInUse){
-                    $scope.model.dimensions.push(new Dimension($scope.availableTables[i]));
+                    modelsManager.selectedModel.dimensions.push(new Dimension($scope.availableTables[i]));
                 }
             }
 //        }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index dc9b87a..c483752 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) {
+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) {
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
@@ -29,6 +29,8 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         $location.path("/models");
     }
 
+    $scope.modelsManager = modelsManager;
+
     $scope.cubeConfig = cubeConfig;
 
     $scope.getPartitonColumns = function(tableName){
@@ -74,11 +76,11 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         var modelName = $routeParams.modelName;
         ModelDescService.get({model_name: modelName}, function (model) {
                     if (model) {
-                        $scope.model = model;
-                        $scope.model.project = ProjectModel.getProjectByCubeModel(modelName);
+                        modelsManager.selectedModel = model;
+                        modelsManager.selectedModel.project = ProjectModel.getProjectByCubeModel(modelName);
 
                         if(!ProjectModel.getSelectedProject()){
-                            ProjectModel.setSelectedProject($scope.model.project);
+                            ProjectModel.setSelectedProject(modelsManager.selectedModel.project);
                             TableModel.aceSrcTbLoaded();
                         }
 
@@ -95,26 +97,26 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
     } else {
         MetaModel.initModel();
-        $scope.model = MetaModel.getMetaModel();
-        $scope.model.project = ProjectModel.getSelectedProject();
+        modelsManager.selectedModel = MetaModel.getMetaModel();
+        modelsManager.selectedModel.project = ProjectModel.getSelectedProject();
     }
 
 
     $scope.prepareModel = function () {
         // generate column family
 
-        if ($scope.model.partition_desc.partition_date_column!=null&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
-            var dateStart = new Date($scope.model.partition_desc.partition_date_start);
+        if (modelsManager.selectedModel.partition_desc.partition_date_column!=null&&(modelsManager.selectedModel.partition_desc.partition_date_start|modelsManager.selectedModel.partition_desc.partition_date_start==0)) {
+            var dateStart = new Date(modelsManager.selectedModel.partition_desc.partition_date_start);
             dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
             //switch selected time to utc timestamp
-            $scope.model.partition_desc.partition_date_start = new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
+            modelsManager.selectedModel.partition_desc.partition_date_start = new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
 
 
         }
-        if($scope.model.partition_desc.partition_date_column==null){
-            $scope.model.partition_desc.partition_date_start=null;
+        if(modelsManager.selectedModel.partition_desc.partition_date_column==null){
+            modelsManager.selectedModel.partition_desc.partition_date_start=null;
         }
-        $scope.state.project = $scope.model.project;
+        $scope.state.project = modelsManager.selectedModel.project;
         var _model = angular.copy($scope.model);
         delete _model.project;
         $scope.state.modelSchema = angular.toJson(_model, true);
@@ -215,17 +217,17 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
 //    reverse the date
     $scope.saveModelRollBack = function (){
-        if($scope.model.partition_desc.partition_date_start==0){
-            $scope.model.partition_desc.partition_date_start = null;
+        if(modelsManager.selectedModel.partition_desc.partition_date_start==0){
+            modelsManager.selectedModel.partition_desc.partition_date_start = null;
         }
-        if($scope.model&&($scope.model.partition_desc.partition_date_start||$scope.model.partition_desc.partition_date_start==0))
+        if($scope.model&&(modelsManager.selectedModel.partition_desc.partition_date_start||modelsManager.selectedModel.partition_desc.partition_date_start==0))
         {
-            $scope.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+            modelsManager.selectedModel.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
         }
     };
 
     $scope.removeTableDimensions = function(tableIndex){
-        $scope.model.dimensions.splice(tableIndex,1);
+        modelsManager.selectedModel.dimensions.splice(tableIndex,1);
     }
 
     $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 17a3b06..a2126e8 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -18,9 +18,9 @@
 
 'use strict';
 
-KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,$log,SweetAlert) {
+KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,$log,SweetAlert,modelsManager) {
 
-    $log.info($scope.model);
+    $scope.modelsManager = modelsManager;
 
     $scope.projects = [];
     $scope.newDimension = null;
@@ -135,7 +135,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
      */
     $scope.check_data_model = function(){
         var errors = [];
-//        if(!$scope.model.lookups.length){
+//        if(!modelsManager.selectedModel.lookups.length){
 //            errors.push("No lookup table defined");
 //        }
         var errorInfo = "";
@@ -158,10 +158,10 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     $scope.check_model_dimensions = function(){
 
         var errors = [];
-        if(!$scope.model.dimensions.length){
+        if(!modelsManager.selectedModel.dimensions.length){
             errors.push("No dimensions defined.");
         }
-        angular.forEach($scope.model.dimensions,function(_dimension){
+        angular.forEach(modelsManager.selectedModel.dimensions,function(_dimension){
             if(!_dimension.columns||!_dimension.columns.length){
             errors.push("No dimension columns defined for Table["+_dimension.table+"]");
             }
@@ -186,7 +186,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     $scope.check_model_measure = function(){
 
         var errors = [];
-        if(!$scope.model.metrics||!$scope.model.metrics.length){
+        if(!modelsManager.selectedModel.metrics||!modelsManager.selectedModel.metrics.length){
             errors.push("Please define your metrics.");
         }
         var errorInfo = "";
@@ -203,7 +203,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     };
     $scope.check_model_setting = function(){
         var errors = [];
-        if($scope.model.partition_desc.partition_date_column!=null&& $scope.model.partition_desc.partition_date_start==null){
+        if(modelsManager.selectedModel.partition_desc.partition_date_column!=null&& modelsManager.selectedModel.partition_desc.partition_date_start==null){
             errors.push("Please indicate start date when partition date column selected.");
         }
         var errorInfo = "";

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 557be9c..be7d827 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -18,11 +18,9 @@
 
 'use strict';
 
-KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window,$modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
-        //selected model
-        $scope.model = {};
+KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window,$modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,modelsManager,cubesManager) {
+
         //tree data
-        $scope.models_treedata=[];
 
         $scope.cubeSelected = false;
         $scope.cube = {};
@@ -33,9 +31,10 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
             $scope.showModels = showModel;
         }
 
-        $scope.modelList = ModelList;
+        $scope.modelsManager = modelsManager;
+        $scope.cubesManager = cubesManager;
         $scope.modelConfig = modelConfig;
-        ModelList.removeAll();
+        modelsManager.removeAll();
         $scope.loading = false;
         $scope.action = {};
         $scope.window = 0.68 * $window.innerHeight;
@@ -52,8 +51,6 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 defer.resolve([]);
                 return defer.promise;
             }
-//            offset = (!!offset) ? offset : null;
-//            limit = (!!limit) ? limit : null;
 
             var queryParam = {};
             if ($scope.listParams.modelName) {
@@ -63,7 +60,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
             $scope.loading = true;
 
-             ModelList.list(queryParam).then(function(resp){
+             modelsManager.list(queryParam).then(function(resp){
                 $scope.loading = false;
                 defer.resolve(resp);
             },function(resp){
@@ -74,80 +71,38 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
             return  defer.promise;
         };
 
+        //add ref for selectedModel
+//        $scope.model = modelsManager.selectedModel;
+//        $scope.cubeSelected = modelsManager.cubeSelected;
+//        $scope.cube = modelsManager.selectedCube;
+//        $scope.cubeMetaFrame =modelsManager.cubeDetail;
+//        $scope.cube={detail: modelsManager.cubeDetail};
+//        $scope.metaModel = {model:modelsManager.curModel};
+
         $scope.init = function(){
-            $scope.list().then(function(resp){
-                $scope.models_treedata = [];
-                angular.forEach(ModelList.models,function(model){
-                    var _model = {
-                        label:model.name,
-                        noLeaf:true,
-                        data:model,
-                        onSelect:function(branch){
-                         // set selected model
-                            $scope.model=branch.data;
-                            $scope.cubeSelected = false;
-                        }
-                    };
-                    var _children = [];
-                    angular.forEach(model.cubes,function(cube){
-                        _children.push(
-                            {
-                                label:cube.name,
-                                data:cube,
-                                onSelect:function(branch){
-                                    $log.info("cube selected:"+branch.data.name);
-                                    $scope.cubeSelected = true;
-//                                    $scope.cubeMetaFrame = branch.data;
-                                    $scope.cube = branch.data;
-                                    $scope.listAccess(cube, 'CubeInstance');
-
-                                    CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
-                                        if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
-                                            //cubeMetaFrame for cube view and edit
-                                            $scope.cubeMetaFrame = detail[0];
-                                            //for show detail info
-                                            $scope.cube.detail = detail[0];
-                                            //add model info
-                                            $scope.metaModel ={
-                                                model : ModelList.getModelByCube(cube.name)
-                                            }
-                                        }else{
-                                            SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
-                                        }
-                                    }, function (e) {
-                                        if(e.data&& e.data.exception){
-                                            var message =e.data.exception;
-                                            var msg = !!(message) ? message : 'Failed to take action.';
-                                            SweetAlert.swal('Oops...', msg, 'error');
-                                        }else{
-                                            SweetAlert.swal('Oops...', "Failed to take action.", 'error');
-                                        }
-                                    });
-
-
-
-                                    // set selecte model
-                                }
-                            }
-                        );
-                    });
-                    if(_children.length){
-                         _model.children = _children;
-                    }
-                    $scope.models_treedata.push(_model);
-                });
-                $scope.models_treedata = _.sortBy($scope.models_treedata, function (i) { return i.label.toLowerCase(); });
 
+            var queryParam = {};
+            if ($scope.listParams.modelName) {
+                queryParam.modelName = $scope.listParams.modelName;
+            }
+            queryParam.projectName = $scope.projectModel.selectedProject;
+
+            modelsManager.generatorTreeData(queryParam).then(function(resp){
+//                $scope.models_treedata = resp;
             });
+
         };
 
         $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
-                ModelList.removeAll();
+                modelsManager.removeAll();
                 //init selected model
-                $scope.model = {};
+//                $scope.model = {};
+                modelsManager.selectedModel;
                 $scope.init();
+
         });
 
+
     $scope.status = {
         isopen: true
     };

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/model/cubesManager.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/cubesManager.js b/webapp/app/js/model/cubesManager.js
index 6ba303f..f8e9cd8 100644
--- a/webapp/app/js/model/cubesManager.js
+++ b/webapp/app/js/model/cubesManager.js
@@ -19,4 +19,8 @@
 // TODO add cubes manager
 KylinApp.service('cubesManager',function(){
 
+    this.currentCube = {};
+
+    this.cubeMetaFrame={};
+
 })

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
deleted file mode 100644
index 388cabc..0000000
--- a/webapp/app/js/model/modelList.js
+++ /dev/null
@@ -1,91 +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.
-*/
-
-KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel,$log){
-    var _this = this;
-    this.models=[];
-
-    this.list = function(queryParam){
-
-        var defer = $q.defer();
-        var cubeDetail = [];
-        var modelPermission = [];
-        ModelService.list(queryParam, function (_models) {
-
-            angular.forEach(_models, function (model, index) {
-                $log.info("Add model permission info");
-                modelPermission.push(
-                AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
-                    model.accessEntities = accessEntities;
-                }).$promise
-                )
-                $log.info("Add cube info to model ,not detail info");
-                cubeDetail.push(
-//                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
-                    CubeService.list({modelName:model.name}, function (_cubes) {
-                    model.cubes = _cubes;
-                    }).$promise
-                );
-
-                model.project = ProjectModel.getProjectByCubeModel(model.name);
-            });
-            $q.all(cubeDetail,modelPermission).then(
-                function(result){
-                    _models = _.filter(_models,function(models){return models.name!=undefined});
-                    _this.models = _this.models.concat(_models);
-                    defer.resolve(_this.models);
-                }
-            );
-        },function(){
-            defer.reject("Failed to load models");
-        });
-        return defer.promise;
-
-    };
-
-
-    this.removemodels = function(models){
-        var modelsIndex = _this.models.indexOf(models);
-        if (modelsIndex > -1) {
-            _this.models.splice(modelsIndex, 1);
-        }
-    }
-
-    this.getModel = function(modelName){
-      return  _.find(_this.models,function(unit){
-            return unit.name == modelName;
-        })
-    }
-
-    this.getModels = function(){
-        return _this.models;
-    }
-
-    this.getModelByCube = function(cubeName){
-        return  _.find(_this.models,function(model){
-            return _.some(model.cubes,function(_cube){
-                return _cube.name == cubeName;
-            });
-        })
-    }
-
-    this.removeAll = function(){
-        _this.models = [];
-    };
-
-});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/js/model/modelsManager.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelsManager.js b/webapp/app/js/model/modelsManager.js
new file mode 100644
index 0000000..71b77a4
--- /dev/null
+++ b/webapp/app/js/model/modelsManager.js
@@ -0,0 +1,178 @@
+/*
+ * 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.
+*/
+
+KylinApp.service('modelsManager',function(ModelService,CubeService,$q,AccessService,ProjectModel,$log,CubeDescService,SweetAlert,cubesManager){
+    var _this = this;
+    this.models=[];
+    this.modelTreeData = [];
+    this.selectedModel={};
+    this.cubeModel={};
+    this.cubeSelected = false;
+
+    //list models and complemete cube,access info
+    this.list = function(queryParam){
+
+        var defer = $q.defer();
+        var cubeDetail = [];
+        var modelPermission = [];
+        ModelService.list(queryParam, function (_models) {
+
+            angular.forEach(_models, function (model, index) {
+                $log.info("Add model permission info");
+                modelPermission.push(
+                AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
+                    model.accessEntities = accessEntities;
+                }).$promise
+                )
+                $log.info("Add cube info to model ,not detail info");
+                cubeDetail.push(
+//                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+                    CubeService.list({modelName:model.name}, function (_cubes) {
+                    model.cubes = _cubes;
+                    }).$promise
+                );
+
+                model.project = ProjectModel.getProjectByCubeModel(model.name);
+            });
+            $q.all(cubeDetail,modelPermission).then(
+                function(result){
+                    _models = _.filter(_models,function(models){return models.name!=undefined});
+                    _this.models = _this.models.concat(_models);
+                    defer.resolve(_this.models);
+                }
+            );
+        },function(){
+            defer.reject("Failed to load models");
+        });
+        return defer.promise;
+
+    };
+
+    //generator tree data info
+    this.generatorTreeData = function(queryParam){
+        var defer = $q.defer();
+        _this.list(queryParam).then(function(resp){
+            _this.modelTreeData = [];
+            angular.forEach(_this.models,function(model){
+                var _model = {
+                    label:model.name,
+                    noLeaf:true,
+                    data:model,
+                    onSelect:function(branch){
+                        // set selected model
+                        _this.selectedModel = branch.data;
+                        _this.cubeSelected = false;
+                    }
+                };
+                var _children = [];
+                angular.forEach(model.cubes,function(cube){
+                    _children.push(
+                        {
+                            label:cube.name,
+                            data:cube,
+                            onSelect:function(branch){
+                                $log.info("cube selected:"+branch.data.name);
+                                _this.cubeSelected = true;
+//                                    $scope.cubeMetaFrame = branch.data;
+//                                _this.selectedCube = branch.data;
+                                cubesManager.currentCube = branch.data;
+                                _this.listAccess(cubesManager.currentCube, 'CubeInstance');
+
+                                CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
+                                    if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
+                                        //cubeMetaFrame for cube view and edit
+//                                        $scope.cubeMetaFrame = detail[0];
+                                        //for show detail info
+//                                        $scope.cube.detail = detail[0];
+                                        //add model info
+                                        cubesManager.currentCube.detail = detail[0];
+                                        cubesManager.cubeMetaFrame = detail[0];
+                                        _this.cubeModel = _this.getModelByCube(cubesManager.currentCube.name);
+                                    }else{
+                                        SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
+                                    }
+                                }, function (e) {
+                                    if(e.data&& e.data.exception){
+                                        var message =e.data.exception;
+                                        var msg = !!(message) ? message : 'Failed to take action.';
+                                        SweetAlert.swal('Oops...', msg, 'error');
+                                    }else{
+                                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                                    }
+                                });
+                                // set selecte model
+                            }
+                        }
+                    );
+                });
+                if(_children.length){
+                    _model.children = _children;
+                }
+                _this.modelTreeData.push(_model);
+            });
+            _this.modelTreeData = _.sortBy(_this.modelTreeData, function (i) { return i.label.toLowerCase(); });
+            defer.resolve(_this.modelTreeData);
+        });
+        return defer.promise;
+    };
+
+
+    this.removemodels = function(models){
+        var modelsIndex = _this.models.indexOf(models);
+        if (modelsIndex > -1) {
+            _this.models.splice(modelsIndex, 1);
+        }
+    }
+
+    this.getModel = function(modelName){
+      return  _.find(_this.models,function(unit){
+            return unit.name == modelName;
+        })
+    }
+
+    this.getModels = function(){
+        return _this.models;
+    }
+
+    this.getModelByCube = function(cubeName){
+        return  _.find(_this.models,function(model){
+            return _.some(model.cubes,function(_cube){
+                return _cube.name == cubeName;
+            });
+        })
+    }
+
+    this.removeAll = function(){
+        _this.models = [];
+    };
+
+    this.listAccess = function (entity, type) {
+        var defer = $q.defer();
+
+        entity.accessLoading = true;
+        AccessService.list({type: type, uuid: entity.uuid}, function (accessEntities) {
+            entity.accessLoading = false;
+            entity.accessEntities = accessEntities;
+            defer.resolve();
+        });
+
+        return defer.promise;
+    };
+
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/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 ba2e20d..e841a1d 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -22,7 +22,7 @@
         <div class="form-group">
             <h4 style="margin-left:42px">Aggregation Groups</h4>
             <table style="margin-left:42px; width:92%"
-                   ng-if="cubeMetaFrame.rowkey.aggregation_groups.length > 0"
+                   ng-if="cubesManager.cubeMetaFrame.rowkey.aggregation_groups.length > 0"
                    class="table table-hover list">
                 <tr class="row">
                     <th class="col-xs-1">ID</th>
@@ -30,7 +30,7 @@
                     <th ng-if="state.mode=='edit'" class="col-xs-1"></th>
                 </tr>
 
-                <tr ng-repeat="aggregation_groups in cubeMetaFrame.rowkey.aggregation_groups" class="row">
+                <tr ng-repeat="aggregation_groups in cubesManager.cubeMetaFrame.rowkey.aggregation_groups" class="row">
                     <td class="col-xs-1">
                         <!-- ID -->
                         <b>{{($index + 1)}}</b>
@@ -39,15 +39,15 @@
                         <!-- Dimensions -->
                         <select ng-if="state.mode=='edit'" style="width: 100%"
                                 ng-model="aggregation_groups"  chosen multiple
-                                ng-change="refreshAggregationGroup(cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
-                                ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubeMetaFrame.rowkey.rowkey_columns">
+                                ng-change="refreshAggregationGroup(cubesManager.cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
+                                ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubesManager.cubeMetaFrame.rowkey.rowkey_columns">
                             <option value=""></option>
                         </select>
                         <p ng-if="state.mode=='view'" style="word-wrap: break-word; word-break: normal;max-width: 1000px ">{{aggregation_groups}}</p>
                     </td>
                     <td ng-if="state.mode=='edit'" class="col-xs-1">
                         <button class="btn btn-xs btn-info"
-                                ng-click="removeElement(cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
+                                ng-click="removeElement(cubesManager.cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
                                 class="fa fa-minus"></i>
                         </button>
                     </td>
@@ -65,7 +65,7 @@
         <div class="form-group">
             <h4 style="margin-left:42px">Rowkeys</h4>
             <table style="margin-left:42px; width:92%"
-                   ng-if="cubeMetaFrame.rowkey.rowkey_columns.length > 0"
+                   ng-if="cubesManager.cubeMetaFrame.rowkey.rowkey_columns.length > 0"
                    class="table table-hover list"
                     >
                <thead>
@@ -79,9 +79,9 @@
                     </tr>
                </thead>
 
-                <tbody ui-sortable="state.mode=='edit'" ng-model="cubeMetaFrame.rowkey.rowkey_columns">
+                <tbody ui-sortable="state.mode=='edit'" ng-model="cubesManager.cubeMetaFrame.rowkey.rowkey_columns">
 
-                    <tr  ng-repeat="rowkey_column in cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
+                    <tr  ng-repeat="rowkey_column in cubesManager.cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
 
                         <td>
                             <!-- ID -->
@@ -134,7 +134,7 @@
 
                         <td ng-if="state.mode=='edit'">
                             <button class="btn btn-xs btn-info"
-                                    ng-click="removeElement(cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
+                                    ng-click="removeElement(cubesManager.cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
                                     class="fa fa-minus"></i>
                             </button>
                         </td>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 94ce1fd..c2da223 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -47,7 +47,7 @@
                 </span>
             </div>
         </div>
-        <table class="table table-striped table-hover" ng-if="cubeMetaFrame.dimensions.length > 0">
+        <table class="table table-striped table-hover" ng-if="cubesManager.cubeMetaFrame.dimensions.length > 0">
             <thead>
                 <tr>
                     <th>ID</th>
@@ -59,7 +59,7 @@
                 </tr>
             </thead>
             <tbody class="cube-dimension">
-                <tr ng-repeat="dimension in cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
+                <tr ng-repeat="dimension in cubesManager.cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
                     <!--ID -->
                     <td>
                         <b>{{dimension.id = ($index + 1)}}</b>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index 1833818..7fda22a 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -29,12 +29,12 @@
                         <input disabled ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/"
-                               ng-model="cubeMetaFrame.model_name"/>
+                               ng-model="cubesManager.cubeMetaFrame.model_name"/>
                         <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is required.</small>
                         <small class="help-block" ng-show="!forms.cube_info_form.model_name.$error.required&&forms.cube_info_form.model_name.$invalid && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is invalid.</small>
 
                         <span ng-if="state.mode=='view'">
-                            {{cubeMetaFrame.model_name}}
+                            {{cubesManager.cubeMetaFrame.model_name}}
                         </span>
                     </div>
                 </div>
@@ -48,13 +48,13 @@
                     </label>
                     <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.cube_name.$sbumitted)}">
                         <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
-                               ng-model="cubeMetaFrame.name" required
+                               ng-model="cubesManager.cubeMetaFrame.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
                         <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is required.</small>
                         <small class="help-block" ng-show="!forms.cube_info_form.cube_name.$error.required&&forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is invalid.</small>
 
-                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
+                        <span ng-if="state.mode=='view'">{{cubesManager.cubeMetaFrame.name}}</span>
                     </div>
                 </div>
             </div>
@@ -67,8 +67,8 @@
                     </label>
                     <div class="col-xs-12 col-sm-6">
                         <input type="text" class="form-control" placeholder="Comma Separated"
-                               ng-model="cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
-                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.notify_list}}</span>
+                               ng-model="cubesManager.cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
+                        <span ng-if="state.mode=='view'">{{cubesManager.cubeMetaFrame.notify_list}}</span>
                     </div>
                 </div>
             </div>
@@ -81,8 +81,8 @@
                     </label>
                     <div class="col-xs-12 col-sm-6">
                         <textarea ng-if="state.mode=='edit'" class="form-control box-default"
-                            name="comment" id="comment" ng-model="cubeMetaFrame.description"></textarea>
-                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.description}}</span>
+                            name="comment" id="comment" ng-model="cubesManager.cubeMetaFrame.description"></textarea>
+                        <span ng-if="state.mode=='view'">{{cubesManager.cubeMetaFrame.description}}</span>
                     </div>
                 </div>
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index c426e95..c45ae8e 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -18,7 +18,7 @@
 
 <!-- Measures Summary -->
 <ng-form name="forms.cube_measure_form">
-    <div class="dataTables_wrapper form-inline no-footer" ng-if="cubeMetaFrame.measures.length > 0">
+    <div class="dataTables_wrapper form-inline no-footer" ng-if="cubesManager.cubeMetaFrame.measures.length > 0">
             <div class="row">
                 <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
                     <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
@@ -38,7 +38,7 @@
                     </tr>
                 </thead>
                 <tbody>
-                    <tr ng-repeat="measure in cubeMetaFrame.measures | filter: state.measureFilter track by $index">
+                    <tr ng-repeat="measure in cubesManager.cubeMetaFrame.measures | filter: state.measureFilter track by $index">
                         <td>
                             <!--ID -->
                             <b>{{measure.id = ($index + 1)}}</b>
@@ -69,7 +69,7 @@
                                 <i class="fa fa-pencil"></i>
                             </button>
                             <!--Remove Button -->
-                            <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
+                            <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubesManager.cubeMetaFrame.measures, measure)">
                                 <i class="fa fa-trash-o"></i>
                             </button>
                         </td>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/cubeDesigner/overview.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/overview.html b/webapp/app/partials/cubeDesigner/overview.html
index 4bf14ff..28f02c3 100644
--- a/webapp/app/partials/cubeDesigner/overview.html
+++ b/webapp/app/partials/cubeDesigner/overview.html
@@ -29,7 +29,7 @@
                     <!--Cube Name-->
                     <tr>
                         <th>Cube Name</th>
-                        <td class="tb-breakword">{{cubeMetaFrame.name}}</td>
+                        <td class="tb-breakword">{{cubesManager.cubeMetaFrame.name}}</td>
                     </tr>
                     <!--Fact Table-->
                     <tr>
@@ -46,12 +46,12 @@
                     <!--Dimensions-->
                     <tr>
                         <th>Dimensions</th>
-                        <td>{{cubeMetaFrame.dimensions.length}}</td>
+                        <td>{{cubesManager.cubeMetaFrame.dimensions.length}}</td>
                     </tr>
                     <!--Measures-->
                     <tr>
                         <th>Measures</th>
-                        <td>{{cubeMetaFrame.measures.length}}</td>
+                        <td>{{cubesManager.cubeMetaFrame.measures.length}}</td>
                     </tr>
                 </tbody>
             </table>
@@ -68,7 +68,7 @@
             </div>
             <div class="box-body">
                 <p class="muted">
-                    {{cubeMetaFrame.description}}
+                    {{cubesManager.cubeMetaFrame.description}}
                 </p>
             </div>
         </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 93084e3..ae1ed5b 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -18,120 +18,120 @@
 
 <div ng-controller="CubeCtrl" class="nav-tabs-custom" style="margin-top:40px;">
     <ul class="nav nav-tabs">
-        <li class="{{(!cube.visiblePage || cube.visiblePage=='metadata')? 'active':''}}">
-            <a href="" ng-click="cube.visiblePage='metadata'">Grid</a>
+        <li class="{{(!cubesManager.currentCube.visiblePage || cubesManager.currentCube.visiblePage=='metadata')? 'active':''}}">
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='metadata'">Grid</a>
         </li>
-        <!--<li class="{{cube.visiblePage=='graph'? 'active':''}}">-->
-            <!--<a href="" ng-click="cube.visiblePage='graph';buildGraph(cube);">Visualization</a>-->
+        <!--<li class="{{cubesManager.currentCube.visiblePage=='graph'? 'active':''}}">-->
+            <!--<a href="" ng-click="cubesManager.currentCube.visiblePage='graph';buildGraph(cubesManager.currentCube);">Visualization</a>-->
         <!--</li>-->
-        <li class="{{cube.visiblePage=='sql'? 'active':''}}">
-            <a href="" ng-click="cube.visiblePage='sql';getCubeSql(cube)">SQL</a>
+        <li class="{{cubesManager.currentCube.visiblePage=='sql'? 'active':''}}">
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='sql';getCubeSql(cubesManager.currentCube)">SQL</a>
         </li>
-        <li class="{{cube.visiblePage=='json'? 'active':''}}"
-            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
-            <a href="" ng-click="cube.visiblePage='json';">JSON(Cube)</a>
+        <li class="{{cubesManager.currentCube.visiblePage=='json'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cubesManager.currentCube, 16) && !newAccess">
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='json';">JSON(Cube)</a>
         </li>
-      <!--<li class="{{cube.visiblePage=='json_model'? 'active':''}}"-->
+      <!--<li class="{{cubesManager.currentCube.visiblePage=='json_model'? 'active':''}}"-->
           <!--ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">-->
-        <!--<a href="" ng-click="cube.visiblePage='json_model';">JSON(Model)</a>-->
+        <!--<a href="" ng-click="cubesManager.currentCube.visiblePage='json_model';">JSON(Model)</a>-->
       <!--</li>-->
-        <li class="{{cube.visiblePage=='access'? 'active':''}}">
-            <a href="" ng-click="cube.visiblePage='access';listAccess(cube, 'CubeInstance');">Access</a>
+        <li class="{{cubesManager.currentCube.visiblePage=='access'? 'active':''}}">
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='access';listAccess(cubesManager.currentCube, 'CubeInstance');">Access</a>
         </li>
-        <li class="{{cube.visiblePage=='notification'? 'active':''}}"
-            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
-            <a href="" ng-click="cube.visiblePage='notification';getNotifyListString(cube);">Notification</a>
+        <li class="{{cubesManager.currentCube.visiblePage=='notification'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cubesManager.currentCube, 16) && !newAccess">
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='notification';getNotifyListString(cubesManager.currentCube);">Notification</a>
         </li>
-        <li class="{{cube.visiblePage=='hbase'? 'active':''}}"
+        <li class="{{cubesManager.currentCube.visiblePage=='hbase'? 'active':''}}"
             ng-if="userService.hasRole('ROLE_ADMIN')">
-            <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">HBase</a>
+            <a href="" ng-click="cubesManager.currentCube.visiblePage='hbase';getHbaseInfo(cubesManager.currentCube)">HBase</a>
         </li>
-        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cubesManager.currentCube, 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-cubes">Action</i> <span class="caret"></span>
             </a>
             <ul class="dropdown-menu">
-                <li ng-if="cube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">
-                    <a ng-click="dropCube(cube)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li>
-                <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))">
-                    <a href="cubes/edit/{{cube.name}}">Edit</a></li>
-                <li><a ng-click="startJobSubmit(cube);">Build</a></li>
-                <li><a ng-click="startRefresh(cube)">Refresh</a></li>
-                <li><a ng-click="startMerge(cube)">Merge</a></li>
-                <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li>
-                <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li>
-                <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li>
+                <li ng-if="cubesManager.currentCube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">
+                    <a ng-click="dropCube(cubesManager.currentCube)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li>
+                <li ng-if="cubesManager.currentCube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cubesManager.currentCube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))">
+                    <a href="cubes/edit/{{cubesManager.currentCube.name}}">Edit</a></li>
+                <li><a ng-click="startJobSubmit(cubesManager.currentCube);">Build</a></li>
+                <li><a ng-click="startRefresh(cubesManager.currentCube)">Refresh</a></li>
+                <li><a ng-click="startMerge(cubesManager.currentCube)">Merge</a></li>
+                <li ng-if="cubesManager.currentCube.status!='DISABLED'"><a ng-click="disable(cubesManager.currentCube)">Disable</a></li>
+                <li ng-if="cubesManager.currentCube.status=='DISABLED'"><a ng-click="enable(cubesManager.currentCube)">Enable</a></li>
+                <li ng-if="cubesManager.currentCube.status=='DISABLED'"><a ng-click="purge(cubesManager.currentCube)">Purge</a></li>
             </ul>
         </li>
 
     </ul>
 
-    <div class="cube-detail" ng-if="!cube.visiblePage || cube.visiblePage=='metadata'">
+    <div class="cube-detail" ng-if="!cubesManager.currentCube.visiblePage || cubesManager.currentCube.visiblePage=='metadata'">
         <div ng-include="'partials/cubes/cube_schema.html'" ng-controller="CubeSchemaCtrl"
-             ng-init="state={mode:'view', cubeName:cube.name}"></div>
+             ng-init="state={mode:'view', cubeName:cubesManager.currentCube.name}"></div>
     </div>
 
-    <div ng-show="cube.visiblePage=='sql'" class="cube-detail">
-        <div ng-if="cube.sql">
-            <pre style="background-color: white;border: 0px">{{cube.sql}}</pre>
+    <div ng-show="cubesManager.currentCube.visiblePage=='sql'" class="cube-detail">
+        <div ng-if="cubesManager.currentCube.sql">
+            <pre style="background-color: white;border: 0px">{{cubesManager.currentCube.sql}}</pre>
         </div>
 
-        <div ng-if="!cube.sql">
+        <div ng-if="!cubesManager.currentCube.sql">
             <span calss="text-info">No SQL GENERATED.</span>
         </div>
     </div>
 
-    <div ng-show="cube.visiblePage=='json'" class="cube-detail">
+    <div ng-show="cubesManager.currentCube.visiblePage=='json'" class="cube-detail">
         <pre ng-if="!state.jsonEdit"
-             style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.detail), true)}}</pre>
+             style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cubesManager.currentCube.detail), true)}}</pre>
     </div>
 
-    <!--<div ng-show="cube.visiblePage=='json_model'" class="cube-detail">-->
+    <!--<div ng-show="cubesManager.currentCube.visiblePage=='json_model'" class="cube-detail">-->
           <!--<pre ng-if="!state.jsonEdit"-->
                <!--style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>-->
     <!--</div>-->
-    <!--<div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">-->
+    <!--<div ng-show="cubesManager.currentCube.visiblePage=='graph'" id="cube_graph_{{cubesManager.currentCube.name}}" class="cube-detail cube_graph">-->
     <!--</div>-->
 
-    <div class="cube-detail" ng-if="cube.visiblePage=='access'">
+    <div class="cube-detail" ng-if="cubesManager.currentCube.visiblePage=='access'">
         <div class="row">
             <div class="col-xs-1"></div>
             <div class="col-xs-10">
-                <div ng-include src="'partials/common/access.html'" ng-init="entity=cube;type='CubeInstance';"></div>
+                <div ng-include src="'partials/common/access.html'" ng-init="entity=cubesManager.currentCube;type='CubeInstance';"></div>
             </div>
             <div class="col-xs-1"></div>
         </div>
     </div>
 
-    <div class="cube-detail" ng-show="cube.visiblePage=='notification'">
+    <div class="cube-detail" ng-show="cubesManager.currentCube.visiblePage=='notification'">
         <div style="margin: 15px;">
             <form>
                 <h5>Notification List(Common Separated)</h5>
                 <div class="form-group">
-                    <input ng-model="cube.notifyListString" class="form-control" placeholder="Notification List..." />
+                    <input ng-model="cubesManager.currentCube.notifyListString" class="form-control" placeholder="Notification List..." />
                 </div>
                 <div class="form-group">
-                    <button class="btn btn-primary btn-sm" ng-click="updateNotifyList(cube)">Save</button>
+                    <button class="btn btn-primary btn-sm" ng-click="updateNotifyList(cubesManager.currentCube)">Save</button>
                 </div>
                 <div class="space-4"></div>
             </form>
         </div>
     </div>
 
-    <div class="cube-detail" ng-show="cube.visiblePage=='hbase'">
+    <div class="cube-detail" ng-show="cubesManager.currentCube.visiblePage=='hbase'">
         <div style="margin: 15px;">
-            <div ng-repeat="table in cube.hbase">
+            <div ng-repeat="table in cubesManager.currentCube.hbase">
                 <h5><b>HTable:</b> {{table.tableName}}</h5>
                 <ul>
                     <li>Region Count: <span class="red">{{table.regionCount}}</span></li>
                     <li>Size: <span class="red">{{table.tableSize | bytes:2}}</span></li>
                 </ul>
             </div>
-            <div ng-if="cube.hbase">
+            <div ng-if="cubesManager.currentCube.hbase">
                 <div class="hr hr8 hr-double hr-dotted"></div>
-                <h5><b>Total Size:</b> <span class="red">{{cube.totalSize | bytes:2}}</span></h5>
+                <h5><b>Total Size:</b> <span class="red">{{cubesManager.currentCube.totalSize | bytes:2}}</span></h5>
             </div>
-            <div ng-if="cube.hbase.length == 0">
+            <div ng-if="cubesManager.currentCube.hbase.length == 0">
                 <h5>No HBase Info.</h5>
             </div>
         </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/jobs/job_merge.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/job_merge.html b/webapp/app/partials/jobs/job_merge.html
index c55b280..35f88fe 100644
--- a/webapp/app/partials/jobs/job_merge.html
+++ b/webapp/app/partials/jobs/job_merge.html
@@ -24,11 +24,11 @@
         <div ng-if="metaModel.model.partition_desc.partition_date_column" class="row">
             <div class="col-md-2"></div>
             <div class="col-md-8">
-                <div ng-if="!!!(cube.segments) || cube.segments.length < 2">
+                <div ng-if="!!!(cubesManager.currentCube.segments) || cubesManager.currentCube.segments.length < 2">
                     <span class="text-info">NO SEGMENT TO MERGE.</span>
                 </div>
-                <div ng-if="cube.segments.length >= 2" class="row">
-                    <table class="table table-striped list" ng-if="(cube.segments|filter: {status: 'NEW'}).length == 0">
+                <div ng-if="cubesManager.currentCube.segments.length >= 2" class="row">
+                    <table class="table table-striped list" ng-if="(cubesManager.currentCube.segments|filter: {status: 'NEW'}).length == 0">
                         <tbody>
                         <tr>
                             <td>PARTITION DATE COLUMN</td>
@@ -38,8 +38,8 @@
                             <td>MERGE START SEGMENT</td>
                             <td>
                                 <select ng-model="mergeStartSeg"
-                                        ng-init="mergeStartSeg=cube.segments[0];mergeStartSelected(mergeStartSeg)"
-                                        ng-options="segment as segment.name for segment in cube.segments"
+                                        ng-init="mergeStartSeg=cubesManager.currentCube.segments[0];mergeStartSelected(mergeStartSeg)"
+                                        ng-options="segment as segment.name for segment in cubesManager.currentCube.segments"
                                         ng-change="mergeStartSelected(mergeStartSeg)">
                                 </select>
                             </td>
@@ -48,8 +48,8 @@
                             <td>MERGE END SEGMENT</td>
                             <td>
                                 <select ng-model="mergeEndSeg"
-                                        ng-init="mergeEndSeg=cube.segments[cube.segments.length-1];mergeEndSelected(mergeEndSeg)"
-                                        ng-options="segment as segment.name for segment in cube.segments"
+                                        ng-init="mergeEndSeg=cubesManager.currentCube.segments[cubesManager.currentCube.segments.length-1];mergeEndSelected(mergeEndSeg)"
+                                        ng-options="segment as segment.name for segment in cubesManager.currentCube.segments"
                                         ng-change="mergeEndSelected(mergeEndSeg)">
                                 </select>
                             </td>
@@ -103,7 +103,7 @@
                         </tbody>
                     </table>
 
-                    <div ng-if="(cube.segments|filter: {status: 'NEW'}).length > 0">
+                    <div ng-if="(cubesManager.currentCube.segments|filter: {status: 'NEW'}).length > 0">
                         <span class="text-warning">There exists a build request of this cube, the job may be running or error. If you need a new build, please wait for its complete or discard it.</span>
                     </div>
                 </div>


[51/52] [abbrv] incubator-kylin git commit: Kylin-675 Sub-Task-1

Posted by ma...@apache.org.
Kylin-675 Sub-Task-1


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

Branch: refs/heads/0.8.0
Commit: 10dc6a20153241439e4619ec026bde2d6d1a3501
Parents: be3899c
Author: jiazhong <ji...@ebay.com>
Authored: Mon Apr 20 13:35:51 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:40:22 2015 +0800

----------------------------------------------------------------------
 .../test_case_data/sandbox/kylin.properties     | 196 +++++++++----------
 1 file changed, 98 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/10dc6a20/examples/test_case_data/sandbox/kylin.properties
----------------------------------------------------------------------
diff --git a/examples/test_case_data/sandbox/kylin.properties b/examples/test_case_data/sandbox/kylin.properties
index 596e811..f211137 100644
--- a/examples/test_case_data/sandbox/kylin.properties
+++ b/examples/test_case_data/sandbox/kylin.properties
@@ -1,98 +1,98 @@
-## Config for Kylin Engine ##
-
-# List of web servers in use, this enables one web server instance to sync up with other servers.
-kylin.rest.servers=localhost:7070
-
-# The metadata store in hbase
-kylin.metadata.url=kylin_metadata@hbase
-
-# The storage for final cube file in hbase
-kylin.storage.url=hbase
-
-# Temp folder in hdfs
-kylin.hdfs.working.dir=/tmp
-
-kylin.job.mapreduce.default.reduce.input.mb=500
-
-# If true, job engine will not assume that hadoop CLI reside on the same server as it self
-# you will have to specify kylin.job.remote.cli.hostname, kylin.job.remote.cli.username and kylin.job.remote.cli.password
-kylin.job.run.as.remote.cmd=false
-
-# Only necessary when kylin.job.run.as.remote.cmd=true
-kylin.job.remote.cli.hostname=
-
-# Only necessary when kylin.job.run.as.remote.cmd=true
-kylin.job.remote.cli.username=
-
-# Only necessary when kylin.job.run.as.remote.cmd=true
-kylin.job.remote.cli.password=
-
-# Used by test cases to prepare synthetic data for sample cube
-kylin.job.remote.cli.working.dir=/tmp/kylin
-
-# Max count of concurrent jobs running
-kylin.job.concurrent.max.limit=10
-
-# Whether calculate cube in mem in each mapper;
-kylin.job.cubing.inMem=true
-
-#the percentage of the sampling, default 25%
-kylin.job.cubing.inMem.sampling.percent=25
-
-# The cut size for hbase region, in GB.
-# E.g, for cube whose capacity be marked as "SMALL", split region per 5GB by default
-kylin.job.hbase.region.cut.small=5
-kylin.job.hbase.region.cut.medium=10
-kylin.job.hbase.region.cut.large=50
-
-# Time interval to check hadoop job status
-kylin.job.yarn.app.rest.check.interval.seconds=10
-
-## Config for Restful APP ##
-# database connection settings:
-ldap.server=
-ldap.username=
-ldap.password=
-ldap.user.searchBase=
-ldap.user.searchPattern=
-ldap.user.groupSearchBase=
-ldap.service.searchBase=OU=
-ldap.service.searchPattern=
-ldap.service.groupSearchBase=
-acl.adminRole=
-acl.defaultRole=
-ganglia.group=
-ganglia.port=8664
-
-## Config for mail service
-
-# If true, will send email notification;
-mail.enabled=false
-mail.host=
-mail.username=
-mail.password=
-mail.sender=
-
-###########################config info for web#######################
-
-#help info ,format{name|displayName|link} ,optional
-kylin.web.help.length=4
-kylin.web.help.0=start|Getting Started|
-kylin.web.help.1=odbc|ODBC Driver|
-kylin.web.help.2=tableau|Tableau Guide|
-kylin.web.help.3=onboard|Cube Design Tutorial|
-#hadoop url link ,optional
-kylin.web.hadoop=
-#job diagnostic url link ,optional
-kylin.web.diagnostic=
-#contact mail on web page ,optional
-kylin.web.contact_mail=
-
-###########################config info for front#######################
-
-#env DEV|QA|PROD
-deploy.env=DEV
-
-###########################config info for sandbox#######################
-kylin.sandbox=true
-
+## Config for Kylin Engine ##
+
+# List of web servers in use, this enables one web server instance to sync up with other servers.
+kylin.rest.servers=localhost:7070
+
+# The metadata store in hbase
+kylin.metadata.url=kylin_metadata@hbase
+
+# The storage for final cube file in hbase
+kylin.storage.url=hbase
+
+# Temp folder in hdfs
+kylin.hdfs.working.dir=/tmp
+
+kylin.job.mapreduce.default.reduce.input.mb=500
+
+# If true, job engine will not assume that hadoop CLI reside on the same server as it self
+# you will have to specify kylin.job.remote.cli.hostname, kylin.job.remote.cli.username and kylin.job.remote.cli.password
+kylin.job.run.as.remote.cmd=false
+
+# Only necessary when kylin.job.run.as.remote.cmd=true
+kylin.job.remote.cli.hostname=
+
+# Only necessary when kylin.job.run.as.remote.cmd=true
+kylin.job.remote.cli.username=
+
+# Only necessary when kylin.job.run.as.remote.cmd=true
+kylin.job.remote.cli.password=
+
+# Used by test cases to prepare synthetic data for sample cube
+kylin.job.remote.cli.working.dir=/tmp/kylin
+
+# Max count of concurrent jobs running
+kylin.job.concurrent.max.limit=10
+
+# Whether calculate cube in mem in each mapper;
+kylin.job.cubing.inMem=true
+
+#the percentage of the sampling, default 25%
+kylin.job.cubing.inMem.sampling.percent=25
+
+# The cut size for hbase region, in GB.
+# E.g, for cube whose capacity be marked as "SMALL", split region per 5GB by default
+kylin.job.hbase.region.cut.small=5
+kylin.job.hbase.region.cut.medium=10
+kylin.job.hbase.region.cut.large=50
+
+# Time interval to check hadoop job status
+kylin.job.yarn.app.rest.check.interval.seconds=10
+
+## Config for Restful APP ##
+# database connection settings:
+ldap.server=
+ldap.username=
+ldap.password=
+ldap.user.searchBase=
+ldap.user.searchPattern=
+ldap.user.groupSearchBase=
+ldap.service.searchBase=OU=
+ldap.service.searchPattern=
+ldap.service.groupSearchBase=
+acl.adminRole=
+acl.defaultRole=
+ganglia.group=
+ganglia.port=8664
+
+## Config for mail service
+
+# If true, will send email notification;
+mail.enabled=false
+mail.host=
+mail.username=
+mail.password=
+mail.sender=
+
+###########################config info for web#######################
+
+#help info ,format{name|displayName|link} ,optional
+kylin.web.help.length=4
+kylin.web.help.0=start|Getting Started|
+kylin.web.help.1=odbc|ODBC Driver|
+kylin.web.help.2=tableau|Tableau Guide|
+kylin.web.help.3=onboard|Cube Design Tutorial|
+#hadoop url link ,optional
+kylin.web.hadoop=
+#job diagnostic url link ,optional
+kylin.web.diagnostic=
+#contact mail on web page ,optional
+kylin.web.contact_mail=
+
+###########################config info for front#######################
+
+#env DEV|QA|PROD
+deploy.env=DEV
+
+###########################config info for sandbox#######################
+kylin.sandbox=true
+


[13/52] [abbrv] incubator-kylin git commit: move project to header and update AdminLTE css to v2.0.4

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 4caf964..18a0cd2 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -838,4 +838,26 @@ span.input-icon {
 .cube-dimension .dl-horizontal{
   margin-top: 0px !important;
   margin-bottom: 0px !important;
-}
\ No newline at end of file
+}
+
+//style choosen for bootstrap3
+.chosen-container-single .chosen-single {
+  height: 30px;
+  border-radius: 3px;
+  border: 1px solid #CCCCCC;
+}
+.chosen-container-single .chosen-single span {
+  padding-top: 2px;
+}
+.chosen-container-single .chosen-single div b {
+  margin-top: 2px;
+}
+.chosen-container-active .chosen-single,
+.chosen-container-active.chosen-with-drop .chosen-single {
+  border-color: #ccc;
+  border-color: rgba(82, 168, 236, .8);
+  outline: 0;
+  outline: thin dotted \9;
+  -moz-box-shadow: 0 0 8px rgba(82, 168, 236, .6);
+  box-shadow: 0 0 8px rgba(82, 168, 236, .6)
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/cubes/cube_json_edit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_json_edit.html b/webapp/app/partials/cubes/cube_json_edit.html
index 461aabd..56baa3e 100644
--- a/webapp/app/partials/cubes/cube_json_edit.html
+++ b/webapp/app/partials/cubes/cube_json_edit.html
@@ -23,21 +23,6 @@
         </div>
         <div class="col-xs-9">
             <form role="form" name="cube_form" novalidate>
-                <div class="row">
-                    <div class="col-xs-12">
-                        <form class="navbar-form navbar-left" style="margin-top: 0px !important;" ng-if="userService.isAuthorized()">
-                            <div class="form-group">
-                                <span><b>Project: </b></span>
-                                <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                                        ng-options="project as project for project in projectModel.projects"
-                                        style="width: 150px"
-                                        class="chosen-select">
-                                    <option  ng-if="userService.hasRole('ROLE_ADMIN')"  selected value=""> -- Choose Project -- </option>
-                                </select>
-                            </div>
-                        </form>
-                    </div>
-                </div>
                 <section style="padding-bottom: 20px">
                     <div style="height: 620px; font-size: 14px;" ui-ace="{
                                       useWrapMode : true,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/cubes/cubes.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html
index 0a9676a..9e6976f 100644
--- a/webapp/app/partials/cubes/cubes.html
+++ b/webapp/app/partials/cubes/cubes.html
@@ -21,14 +21,6 @@
     <div class="col-xs-3">
         <form ng-if="userService.isAuthorized()">
             <div class="form-group">
-                <span><b>Project: </b></span>
-                <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                        ng-options="project as project for project in projectModel.projects"
-                        style="width: 150px"
-                        data-placeholder="select a project"
-                        class="chosen-select">
-                    <option ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null" value=""> -- Select All -- </option>
-                </select>
                 <!--Project-->
                 <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
                 <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index 937f56c..18a9b66 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -31,20 +31,26 @@
 
             <div class="navbar-collapse collapse" collapse="isCollapsed">
                 <ul class="nav navbar-nav">
+                    <li class="project-cntnr"  style="padding:7px 15px;background-color:#2e8965;" ng-if="userService.isAuthorized()">
+                        <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
+                                ng-options="project as project for project in projectModel.projects"
+                                style="width: 150px"
+                                data-placeholder="select a project"
+                                class="chosen-select">
+                            <option ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null"  value=""> -- Choose Project -- </option>
+                        </select>
+                    </li>
                     <li class="{{activeTab=='query'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="query">Query</a>
+                        <a href="query">Insight</a>
                     </li>
                     <li class="{{activeTab=='cubes'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="cubes">Cubes</a>
+                        <a href="cubes">Model</a>
                     </li>
                     <li class="{{activeTab=='jobs'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="jobs">Jobs</a>
+                        <a href="jobs">Monitor</a>
                     </li>
                     <li class="{{activeTab=='sourceMeta'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="sourceMeta">Tables</a>
-                    </li>
-                    <li class="{{activeTab=='admin'?'purple':'green'}}" ng-if="userService.hasRole('ROLE_ADMIN')">
-                        <a href="admin">Admin</a>
+                        <a href="sourceMeta">System</a>
                     </li>
                 </ul>
                 <ul class="nav navbar-nav navbar-right">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/jobs/jobs.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/jobs.html b/webapp/app/partials/jobs/jobs.html
index aba9ce6..3b2ee04 100644
--- a/webapp/app/partials/jobs/jobs.html
+++ b/webapp/app/partials/jobs/jobs.html
@@ -21,15 +21,6 @@
     <div class="col-xs-3">
         <form ng-if="userService.isAuthorized()">
             <div class="form-group">
-                <span><b>Project: </b></span>
-                <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                        ng-options="project as project for project in projectModel.projects"
-                        style="width: 150px"
-                        data-placeholder="select a project"
-                        class="chosen-select">
-                    <option ng-if="userService.hasRole('ROLE_ADMIN')"  ng-selected="projectModel.selectedProject==null"  value=""> -- Select All -- </option>
-                </select>
-                <!--Project-->
                 <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
                 <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
                     <i class="fa fa-plus"></i>
@@ -38,14 +29,12 @@
         </form>
     </div>
     <!--Cube Name: -->
-    <div class="col-xs-3">
-        <form ng-submit="jobList.removeAll();reload()" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search"><b>Cube Name:</b>
+        <form class="pull-right" ng-submit="jobList.removeAll();reload()" style="display: inline" >
+            <span class="input-icon input-icon-right nav-search"><b>Job Name:</b>
                 <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="cubeName" />
                 <i class="ace-icon fa fa-search blue" ng-click="jobList.removeAll();reload()"></i>
             </span>
         </form>
-    </div>
 </div>
 
 <!--Jobs Table-->

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/query/query.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/query/query.html b/webapp/app/partials/query/query.html
index 25dcf9f..d34dbc7 100644
--- a/webapp/app/partials/query/query.html
+++ b/webapp/app/partials/query/query.html
@@ -20,15 +20,6 @@
     <!--Project-->
     <form class="navbar-form navbar-left" style="margin-top: 0px !important;" ng-if="userService.isAuthorized()">
         <div class="form-group">
-            <span><b>Project: </b></span>
-            <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                    ng-options="project as project for project in projectModel.projects"
-                    style="width: 150px"
-                    data-placeholder="select a project"
-                    class="chosen-select">
-                <option ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null"  value=""> -- Choose Project -- </option>
-            </select>
-            <!--Project-->
             <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
             <a class="btn btn-xs btn-primary" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'" style="width: 29px" tooltip="Add Project" ng-click="toCreateProj()">
                 <i class="fa fa-plus"></i>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/603fe3fc/webapp/app/partials/tables/source_metadata.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_metadata.html b/webapp/app/partials/tables/source_metadata.html
index 62b4d0f..d7b5a1e 100755
--- a/webapp/app/partials/tables/source_metadata.html
+++ b/webapp/app/partials/tables/source_metadata.html
@@ -20,14 +20,6 @@
     <!--Project-->
     <form class="navbar-form navbar-left" style="margin-top: 0px !important;" ng-if="userService.isAuthorized()">
         <div class="form-group">
-            <span><b>Project: </b></span>
-            <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
-                    ng-options="project as project for project in projectModel.projects"
-                    style="width: 150px"
-                    data-placeholder="select a project"
-                    class="chosen-select">
-                <option  ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null"  value=""> -- Choose Project -- </option>
-            </select>
             <!--Project-->
             <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
             <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'" tooltip="Add Project" ng-click="toCreateProj()">


[04/52] [abbrv] incubator-kylin git commit: KYLIN-766

Posted by ma...@apache.org.
KYLIN-766


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

Branch: refs/heads/0.8.0
Commit: 69240574c874a830ea406edeab881a38b3e32040
Parents: fc056fd
Author: qianhao.zhou <qi...@ebay.com>
Authored: Thu May 14 16:38:09 2015 +0800
Committer: qianhao.zhou <qi...@ebay.com>
Committed: Thu May 14 16:38:09 2015 +0800

----------------------------------------------------------------------
 .../serializer/BigDecimalSerializer.java        | 20 ++++++--
 .../serializer/BigDecimalSerializerTest.java    | 52 ++++++++++++++++++++
 2 files changed, 67 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/69240574/metadata/src/main/java/org/apache/kylin/metadata/serializer/BigDecimalSerializer.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/serializer/BigDecimalSerializer.java b/metadata/src/main/java/org/apache/kylin/metadata/serializer/BigDecimalSerializer.java
index 671d249..cf146fb 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/serializer/BigDecimalSerializer.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/serializer/BigDecimalSerializer.java
@@ -18,19 +18,23 @@
 
 package org.apache.kylin.metadata.serializer;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.BytesUtil;
 import org.apache.kylin.metadata.model.DataType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 
 /**
  * @author yangli9
  * 
  */
 public class BigDecimalSerializer extends DataTypeSerializer<BigDecimal> {
+
+    private static final Logger logger = LoggerFactory.getLogger(BigDecimalSerializer.class);
     
     final DataType type;
     final int maxLength;
@@ -43,9 +47,14 @@ public class BigDecimalSerializer extends DataTypeSerializer<BigDecimal> {
 
     @Override
     public void serialize(BigDecimal value, ByteBuffer out) {
+        if (value.scale() > type.getScale()) {
+            logger.warn("value's scale has exceeded the " + type.getScale() +", cut it off, to ensure encoded value do not exceed maxLength " + maxLength);
+            value = value.setScale(type.getScale(), BigDecimal.ROUND_HALF_EVEN);
+        }
         byte[] bytes = value.unscaledValue().toByteArray();
-        if (bytes.length + 2 > maxLength)
+        if (bytes.length + 2 > maxLength) {
             throw new IllegalArgumentException("'" + value + "' exceeds the expected length for type " + type);
+        }
 
         BytesUtil.writeVInt(value.scale(), out);
         BytesUtil.writeVInt(bytes.length, out);
@@ -89,4 +98,5 @@ public class BigDecimalSerializer extends DataTypeSerializer<BigDecimal> {
         else
             return new BigDecimal(Bytes.toString(value));
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/69240574/metadata/src/test/java/org/apache/kylin/metadata/serializer/BigDecimalSerializerTest.java
----------------------------------------------------------------------
diff --git a/metadata/src/test/java/org/apache/kylin/metadata/serializer/BigDecimalSerializerTest.java b/metadata/src/test/java/org/apache/kylin/metadata/serializer/BigDecimalSerializerTest.java
new file mode 100644
index 0000000..e7b7916
--- /dev/null
+++ b/metadata/src/test/java/org/apache/kylin/metadata/serializer/BigDecimalSerializerTest.java
@@ -0,0 +1,52 @@
+package org.apache.kylin.metadata.serializer;
+
+import org.apache.kylin.metadata.model.DataType;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class BigDecimalSerializerTest {
+
+    private static BigDecimalSerializer bigDecimalSerializer;
+
+    @BeforeClass
+    public static void beforeClass() {
+        bigDecimalSerializer = new BigDecimalSerializer(DataType.getInstance("decimal"));
+    }
+
+    @Test
+    public void testNormal() {
+        BigDecimal input = new BigDecimal("1234.1234");
+        ByteBuffer buffer = ByteBuffer.allocate(256);
+        buffer.mark();
+        bigDecimalSerializer.serialize(input, buffer);
+        buffer.reset();
+        BigDecimal output = bigDecimalSerializer.deserialize(buffer);
+        assertEquals(input, output);
+    }
+
+    @Test
+    public void testScaleOutOfRange() {
+        BigDecimal input = new BigDecimal("1234.1234567890");
+        ByteBuffer buffer = ByteBuffer.allocate(256);
+        buffer.mark();
+        bigDecimalSerializer.serialize(input, buffer);
+        buffer.reset();
+        BigDecimal output = bigDecimalSerializer.deserialize(buffer);
+        assertEquals(input.setScale(bigDecimalSerializer.type.getScale(), BigDecimal.ROUND_HALF_EVEN), output);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testOutOfPrecision() {
+        BigDecimal input = new BigDecimal("66855344214907231736.4924");
+        ByteBuffer buffer = ByteBuffer.allocate(256);
+        bigDecimalSerializer.serialize(input, buffer);
+    }
+
+}


[38/52] [abbrv] incubator-kylin git commit: add step check

Posted by ma...@apache.org.
add step check


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

Branch: refs/heads/0.8.0
Commit: 725598fbc8ad41c29a9c5d09a0424ef7200ba499
Parents: 5926d46
Author: jiazhong <ji...@ebay.com>
Authored: Fri Mar 27 18:05:01 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/modelSchema.js        |  18 +-
 webapp/app/less/app.less                        |   2 +-
 webapp/app/less/component.less                  |   5 +
 .../app/partials/modelDesigner/model_info.html  |  92 +++++----
 webapp/app/partials/models/model_schema.html    |   4 +-
 webapp/app/partials/tables/source_metadata.html | 194 -------------------
 6 files changed, 75 insertions(+), 240 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index b2b7ba7..4d7b6c1 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -28,13 +28,15 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
 
     $scope.wizardSteps = [
-        {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false},
-        {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false},
-        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false},
-        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false},
-        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false}
+        {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false,form:'model_info_form'},
+        {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false,form:null},
+        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:null},
+        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:null},
+        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:null}
     ];
 
+    $scope.formStepMap =[{}]
+
     $scope.curStep = $scope.wizardSteps[0];
 
 
@@ -93,7 +95,11 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         }
     };
 
-    $scope.goToStep = function(stepIndex){
+    $scope.goToStep = function(stepIndex,form){
+        if(form){
+            console.log($scope[form]);
+            console.log(document.querySelector("form"));
+        }
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index c829ca1..9c629d0 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -365,7 +365,7 @@ pre {
 }
 
 input.ng-invalid-required {
-  border: 2px solid lightblue;
+  border: 1px solid #dd4b39;
 }
 
 input.ng-invalid-required:after {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 4ab31e5..ee28e84 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -963,4 +963,9 @@ Angular 1.2.0 Animation
 
 .abn-tree i.indented{
   font-size:14px !important;
+}
+
+//form validate
+.has-feedback{
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index 92c1ef0..ca7e231 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -19,49 +19,52 @@
 <div class="row">
     <div class="col-xs-8">
         <!--Project-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right">
-                    <a ng-if="state.mode=='edit'" href="projects">
-                        <b>Project</b>
-                    </a>
-                    <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="model.project"/>
-                    <span ng-if="state.mode=='view'">
-                        {{model.project}}
-                    </span>
+        <ng-form name="model_info_form" novalidate>
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-3 control-label no-padding-right">
+                        <a ng-if="state.mode=='edit'" href="projects">
+                            <b>Project</b>
+                        </a>
+                        <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
+                    </label>
+                    <div class="col-xs-6" ng-class="model_info_form.project_name.$invalid?'has-error':model_info_form.project_name.$dirty?'has-success':''">
+                         <!--edit-->
+                        <input ng-if="state.mode=='edit'" required name="project_name" type="text" class="form-control"
+                               ng-model="model.project"/>
+                        <small class="help-block" ng-show="model_info_form.project_name.$error.required">The project is required</small>
+
+                        <!--view-->
+                        <span ng-if="state.mode=='view'">
+                            {{model.project}}
+                        </span>
+                    </div>
                 </div>
             </div>
-        </div>
 
-        <!--Model Name-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Model Name</b>
-                </label>
+            <!--Model Name-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Model Name</b>
+                    </label>
 
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
-                           ng-model="model.name" required
-                           placeholder="You can use letters, numbers, and '_'"
-                           ng-maxlength=100 ng-pattern="/^\w+$/" />
-                    <span ng-if="state.mode=='view'">{{model.name}}</span>
-                </div>
-                <div class="col-xs-12 col-sm-3">
-                    <div class="text-warning" ng-if="design_form.model_name.$error.required  && design_form.model_name.$dirty">
-                        Model name is required.
-                    </div>
-                    <div class="text-warning" ng-if="design_form.model_name.$invalid && design_form.model_name.$dirty && !design_form.model_name.$error.required">
-                        Model name is invalid.
+                    <div class="col-xs-12 col-sm-6" ng-class="model_info_form.model_name.$invalid?'has-error':model_info_form.model_name.$dirty?'has-success':''">
+
+                        <!-- edit -->
+                        <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
+                               ng-model="model.name" required
+                               placeholder="You can use letters, numbers, and '_'"
+                               ng-maxlength=100 ng-pattern="/^\w+$/" />
+                        <small class="help-block" ng-show="model_info_form.model_name.$error.required  && model_info_form.model_name.$dirty">Model name is required.</small>
+                        <small class="help-block" ng-show="model_info_form.model_name.$invalid && model_info_form.model_name.$dirty && !model_info_form.model_name.$error.required"> Model name is invalid.</small>
+
+
+                        <span ng-if="state.mode=='view'">{{model.name}}</span>
                     </div>
                 </div>
             </div>
-        </div>
-
+        </ng-form>
     </div>
 
     <!--Tips-->
@@ -83,3 +86,20 @@
         </div>
     </div>
 </div>
+
+<div class="row" ng-hide="true">
+    <div class="col-xs-8">
+    <div class="box box-danger">
+        <div class="box-header with-border">
+            <i class="fa fa-warning"></i>
+            <h3 class="box-title">Warning!</h3>
+        </div>
+        <div class="box-body callout callout-warning">
+            <ol>
+                <li>Project can't be empty</li>
+                <li>Model Name can't be empty</li>
+            </ol>
+        </div><!-- /.box-body -->
+    </div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 67adf69..ac607e6 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -22,14 +22,13 @@
         <h4 class="box-title text-info">Model Designer</h4>
     </div>
     <div class="box-body">
-        <ng-form name="design_form" ng-submit="">
             <!-- Add a mock button to avoid auto submit-->
             <button ng-click="" ng-show="false"></button>
             <div>
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
                         class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
-                        <span style="cursor:pointer;" ng-click="goToStep($index)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span style="cursor:pointer;" ng-click="goToStep($index,curStep.form)" class="step">{{step.step = ($index + 1)}}</span>
                         <span class="title">{{step.title}}</span>
                      </li>
                 </ul>
@@ -64,7 +63,6 @@
                     </div>
                 </div>
             </div>
-        </ng-form>
     </div>
 </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/725598fb/webapp/app/partials/tables/source_metadata.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_metadata.html b/webapp/app/partials/tables/source_metadata.html
deleted file mode 100755
index 8e39c95..0000000
--- a/webapp/app/partials/tables/source_metadata.html
+++ /dev/null
@@ -1,194 +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.
--->
-
-<div class="page-header" style="height: 50px;">
-    <!--Project-->
-    <form class="navbar-form navbar-left" style="margin-top: 0px !important;" ng-if="userService.isAuthorized()">
-        <div class="form-group">
-            <!--Project-->
-            <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
-            <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'" tooltip="Add Project" ng-click="toCreateProj()">
-                <i class="fa fa-plus"></i>
-            </a>
-
-        </div>
-    </form>
-</div>
-
-<div class="row" ng-controller="SourceMetaCtrl">
-    <!--table_tree-->
-    <div class="col-xs-3">
-        <div ng-include src="'partials/tables/source_table_tree.html'"></div>
-    </div>
-    <!--Tab-->
-    <div class="col-xs-9">
-        <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
-        <div class="tabbable nav-tabs-custom">
-            <ul class="nav nav-tabs">
-                <li class="active">
-                    <a data-toggle="tab" href="#column">Columns</a>
-                </li>
-                <li>
-                    <a data-toggle="tab" href="#schema">Extend Information</a>
-                </li>
-            </ul>
-            <div class="tab-content">
-                <!--Schema-->
-                <div id="schema" class="tab-pane">
-                    <div ng-if="tableModel.selectedSrcTable.uuid" class="table-responsive">
-                        <table class="table">
-                            <tbody>
-                                <tr>
-                                    <th style="width:20%">NAME</th>
-                                    <td>{{ tableModel.selectedSrcTable.name}}</td>
-                                </tr>
-                                <tr>
-                                    <th>Hive DATABASE</th>
-                                    <td>{{tableModel.selectedSrcTable.database}}</td>
-                                </tr>
-                                <tr>
-                                    <th>SNAPSHOT TIME</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.lastUpdateTime | utcToConfigTimeZone}}</td>
-                                </tr>
-                                <tr>
-                                    <th>LOCATION</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.location}}</td>
-                                </tr>
-                                <tr>
-                                    <th>INPUT FORMAT</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.inputformat}}</td>
-                                </tr>
-                                <tr>
-                                    <th>OUTPUT FORMAT</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.outputformat}}</td>
-                                </tr>
-                                <tr>
-                                    <th>OWNER</th>
-                                    <td><a href="mailto:{{tableModel.selectedSrcTable.exd.owner}}">{{tableModel.selectedSrcTable.exd.owner}}</a></td>
-                                </tr>
-                                <tr>
-                                    <th>TOTAL FILE NUMBER</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.totalNumberFiles}}</td>
-                                </tr>
-                                <tr>
-                                    <th>TOTAL FILE SIZE</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.totalFileSize}}</td>
-                                </tr>
-                                <tr>
-                                    <th>PARTITIONED</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.partitioned}}</td>
-                                </tr>
-                                <tr>
-                                    <th>PARTITION COLUMNS</th>
-                                    <td>{{tableModel.selectedSrcTable.exd.partitionColumns}}</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                    </div>
-                </div>
-                <!--Columns-->
-                <div id="column" class="tab-pane active">
-                    <div class="profile-user-info">
-                        <div>
-                            <label class="table-header-text">Columns</label>
-                            <span class="input-icon form-search nav-search pull-right">
-                                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="columnName"/>
-                                <i class="ace-icon fa fa-search nav-search-icon"></i>
-                            </span>
-                        </div>
-                        <div class="space-6"></div>
-                        <div ng-if="(tableModel.selectedSrcTable.columns | filter: columnName).length>0">
-                            <table class="table table-hover table-striped list">
-                                <thead>
-                                <tr style="cursor: pointer">
-                                    <th ng-repeat="theaditem in tableConfig.theaditems"
-                                        ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
-                                        {{theaditem.name}}
-                                        <i ng-if="state.reverseColumn!= theaditem.attr"
-                                           class="fa fa-unsorted"></i>
-                                        <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
-                                           class="fa fa-sort-asc"></i>
-                                        <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
-                                           class="fa fa-sort-desc"></i>
-                                    </th>
-                                </tr>
-                                </thead>
-
-                                <tr ng-repeat="column in tableModel.selectedSrcTable.columns | filter: columnName | orderObjectBy:state.filterAttr:state.filterReverse">
-                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
-                                        {{ column.id}}
-                                    </td>
-                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
-                                        {{ column.name}}
-                                    </td>
-                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
-                                        {{ column.datatype}}
-                                    </td>
-                                    <td style="{{(tableModel.selectedSrcTable.selectedSrcColumn.id == column.id)? 'background-color:#EBF9FE':''}}">
-                                        <!--{{ tableModel.selectedSrcTable.cardinality[column.name]}}-->
-                                        {{column.cardinality}}
-                                    </td>
-                                </tr>
-                            </table>
-                        </div>
-                        <div ng-if="(tableModel.selectedSrcTable.columns | filter: columnName).length == 0" no-result
-                             text="No Matched Table Column."></div>
-                        <div ng-if="!!!tableModel.selectedSrcTable.uuid">
-                            <div no-result text="No Table Selected."></div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-
-
-    <!--show load hive table tip when no models list-->
-    <div ng-show="!models_treedata.length" style="margin-top:40px;">
-        <div class="box box-primary">
-            <div class="box-header with-border">
-                <h3 class="box-title">No tables</h3>
-            </div>
-            <div class="box-body">
-                <p>
-                    <a href="models/add" ng-if="userService.hasRole('ROLE_MODELER')">Click here to load your hive table</a>
-                </p>
-            </div><!-- /.box-body -->
-        </div>
-    </div>
-
-
-
-    <script type="text/ng-template" id="addHiveTable.html">
-        <div class="modal-header">
-            <h4>Load Hive Table Metadata</h4>
-        </div>
-        <div class="modal-body">
-            <span><strong>Project: </strong>{{ $parent.projectName!=null?$parent.projectName:'NULL'}}</span>
-            <label for="tables"> Table Names:(Seperate with comma)</label>
-            <textarea ng-model="$parent.tableNames" class="form-control" id="tables"
-                      placeholder="table1,table2  By default,system will choose 'Default' as database,you can specify database like this 'database.table'"></textarea>
-        </div>
-        <div class="modal-footer">
-            <button class="btn btn-primary" ng-click="add()">Sync</button>
-            <button class="btn btn-primary" ng-click="cancel()">Cancel</button>
-        </div>
-    </script>
-</div>
-
-<div ng-include="'partials/projects/project_create.html'"></div>


[48/52] [abbrv] incubator-kylin git commit: KYLIN-683

Posted by ma...@apache.org.
KYLIN-683


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

Branch: refs/heads/0.8.0
Commit: 5fc9d9b86aea716004720041fd224b29fd4b00eb
Parents: 570d5a8
Author: jiazhong <ji...@ebay.com>
Authored: Tue Apr 14 14:25:08 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:39:12 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/rest/model/Performance.java    |  7 ++++++
 .../kylin/rest/service/PerformanceService.java  |  7 ++++++
 .../kylin/rest/util/PerformanceMonitorTask.java |  7 ++++++
 webapp/app/js/controllers/cubeSchema.js         | 24 ++++++++++++++++++--
 webapp/app/partials/cubeDesigner/measures.html  |  1 +
 5 files changed, 44 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5fc9d9b8/server/src/main/java/org/apache/kylin/rest/model/Performance.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/Performance.java b/server/src/main/java/org/apache/kylin/rest/model/Performance.java
new file mode 100644
index 0000000..33071b2
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/model/Performance.java
@@ -0,0 +1,7 @@
+package org.apache.kylin.rest.model;
+
+/**
+ * Created by jiazhong on 2015/4/13.
+ */
+public class Performance {
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5fc9d9b8/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java b/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
new file mode 100644
index 0000000..cfae02a
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
@@ -0,0 +1,7 @@
+package org.apache.kylin.rest.service;
+
+/**
+ * Created by jiazhong on 2015/4/13.
+ */
+public class PerformanceService {
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5fc9d9b8/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java b/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
new file mode 100644
index 0000000..1f777b0
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
@@ -0,0 +1,7 @@
+package org.apache.kylin.rest.util;
+
+/**
+ * Created by jiazhong on 2015/4/13.
+ */
+public class PerformanceMonitorTask {
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5fc9d9b8/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 89ee492..cc8390d 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -75,18 +75,38 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
 
     //map right return type for param
     $scope.measureReturnTypeUpdate = function(){
-        if($scope.newMeasure.function.expression!=="COUNT_DISTINCT"){
+        if($scope.newMeasure.function.parameter.type=="constant"&&$scope.newMeasure.function.expression!=="COUNT_DISTINCT"){
+            switch($scope.newMeasure.function.expression){
+                case "SUM":
+                case "COUNT":
+                    $scope.newMeasure.function.returntype = "bigint";
+                    break;
+                default:
+                    $scope.newMeasure.function.returntype = "";
+                    break;
+            }
+        }
+        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(colType==""||!colType){
+                $scope.newMeasure.function.returntype = "";
+                return;
+            }
+
 
             switch($scope.newMeasure.function.expression){
                 case "SUM":
                     if(colType==="smallint"||colType==="int"||colType==="bigint"){
                         $scope.newMeasure.function.returntype= 'bigint';
                     }else{
-                        $scope.newMeasure.function.returntype= 'decimal';
+                        if(colType.indexOf('decimal')!=-1){
+                            $scope.newMeasure.function.returntype= colType;
+                        }else{
+                            $scope.newMeasure.function.returntype= 'decimal';
+                        }
                     }
                     break;
                 case "MIN":

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5fc9d9b8/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index c45ae8e..47e2d1f 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -128,6 +128,7 @@
                                 <select class="form-control" ng-if="newMeasure.function.expression != 'COUNT'"
                                     ng-init="newMeasure.function.parameter.type=(!!newMeasure.function.parameter.type)?newMeasure.function.parameter.type: 'column' "
                                     chosen ng-model="newMeasure.function.parameter.type" required
+                                    ng-change="measureReturnTypeUpdate();"
                                     ng-options="mpt as mpt for mpt in cubeConfig.measureParamType">
                                     <option value=""></option>
                                 </select>


[50/52] [abbrv] incubator-kylin git commit: KYLIN-197

Posted by ma...@apache.org.
KYLIN-197


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

Branch: refs/heads/0.8.0
Commit: be3899c3ccbd913146b3e42cf301d31a26df7f61
Parents: 5fc9d9b
Author: jiazhong <ji...@ebay.com>
Authored: Tue Apr 14 16:55:58 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:39:30 2015 +0800

----------------------------------------------------------------------
 .../rest/controller/PerformanceController.java  |  20 ++++
 .../kylin/rest/filter/RequestLoggingFilter.java |  30 +++++
 .../apache/kylin/rest/model/Performance.java    | 120 +++++++++++++++++++
 .../kylin/rest/service/PerformanceService.java  |  10 ++
 .../kylin/rest/util/PerformanceMonitorTask.java |  20 ++++
 .../src/main/resources/applicationContext.xml   |   3 +
 server/src/main/resources/log4j.properties      |  10 ++
 server/src/main/webapp/WEB-INF/web.xml          |  29 ++++-
 8 files changed, 241 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java b/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
new file mode 100644
index 0000000..1735165
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/controller/PerformanceController.java
@@ -0,0 +1,20 @@
+package org.apache.kylin.rest.controller;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Created by jiazhong on 2015/4/13.
+ */
+
+@Controller
+@RequestMapping(value = "/performance")
+public class PerformanceController extends BasicController {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/java/org/apache/kylin/rest/filter/RequestLoggingFilter.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/filter/RequestLoggingFilter.java b/server/src/main/java/org/apache/kylin/rest/filter/RequestLoggingFilter.java
new file mode 100644
index 0000000..d58287d
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/filter/RequestLoggingFilter.java
@@ -0,0 +1,30 @@
+package org.apache.kylin.rest.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.AbstractRequestLoggingFilter;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Created by jiazhong on 2015/4/14.
+ */
+public class RequestLoggingFilter extends AbstractRequestLoggingFilter {
+
+    private static final Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class);
+
+    @Override
+    protected void beforeRequest(HttpServletRequest request, String message) {
+//        String user = SecurityContextHolder.getContext().getAuthentication().getName();
+//        logger.info("USER:"+user+"requestURI:"+request.getRequestURI());
+    }
+
+    @Override
+    protected void afterRequest(HttpServletRequest request, String message)
+    {
+        logger.info(message);
+//        logger.info("["+"uri="+request.getRequestURI()+",user="+request.getRemoteUser()+request.get);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/java/org/apache/kylin/rest/model/Performance.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/Performance.java b/server/src/main/java/org/apache/kylin/rest/model/Performance.java
index 33071b2..35d843a 100644
--- a/server/src/main/java/org/apache/kylin/rest/model/Performance.java
+++ b/server/src/main/java/org/apache/kylin/rest/model/Performance.java
@@ -4,4 +4,124 @@ package org.apache.kylin.rest.model;
  * Created by jiazhong on 2015/4/13.
  */
 public class Performance {
+
+    public int query_total;
+
+    public double query_qps;
+
+    public double query_latency;
+
+    public int job_total;
+
+    public double job_average;
+
+    public int job_mr_waiting;
+
+    public int cube_total;
+
+    public int cube_active;
+
+    public double cube_storage;
+
+    public int source_total;
+
+    public int source_records;
+
+    public double source_storage;
+
+    public int getQuery_total() {
+        return query_total;
+    }
+
+    public void setQuery_total(int query_total) {
+        this.query_total = query_total;
+    }
+
+    public double getQuery_qps() {
+        return query_qps;
+    }
+
+    public void setQuery_qps(double query_qps) {
+        this.query_qps = query_qps;
+    }
+
+    public double getQuery_latency() {
+        return query_latency;
+    }
+
+    public void setQuery_latency(double query_latency) {
+        this.query_latency = query_latency;
+    }
+
+    public int getJob_total() {
+        return job_total;
+    }
+
+    public void setJob_total(int job_total) {
+        this.job_total = job_total;
+    }
+
+    public double getJob_average() {
+        return job_average;
+    }
+
+    public void setJob_average(double job_average) {
+        this.job_average = job_average;
+    }
+
+    public int getJob_mr_waiting() {
+        return job_mr_waiting;
+    }
+
+    public void setJob_mr_waiting(int job_mr_waiting) {
+        this.job_mr_waiting = job_mr_waiting;
+    }
+
+    public int getCube_total() {
+        return cube_total;
+    }
+
+    public void setCube_total(int cube_total) {
+        this.cube_total = cube_total;
+    }
+
+    public int getCube_active() {
+        return cube_active;
+    }
+
+    public void setCube_active(int cube_active) {
+        this.cube_active = cube_active;
+    }
+
+    public double getCube_storage() {
+        return cube_storage;
+    }
+
+    public void setCube_storage(double cube_storage) {
+        this.cube_storage = cube_storage;
+    }
+
+    public int getSource_total() {
+        return source_total;
+    }
+
+    public void setSource_total(int source_total) {
+        this.source_total = source_total;
+    }
+
+    public int getSource_records() {
+        return source_records;
+    }
+
+    public void setSource_records(int source_records) {
+        this.source_records = source_records;
+    }
+
+    public double getSource_storage() {
+        return source_storage;
+    }
+
+    public void setSource_storage(double source_storage) {
+        this.source_storage = source_storage;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java b/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
index cfae02a..2de7e5c 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/PerformanceService.java
@@ -1,7 +1,17 @@
 package org.apache.kylin.rest.service;
 
+import org.springframework.stereotype.Component;
+
 /**
  * Created by jiazhong on 2015/4/13.
  */
+
+@Component("performanceService")
 public class PerformanceService {
+
+
+    public void parseQueryInfo(){
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java b/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
index 1f777b0..146bee7 100644
--- a/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
+++ b/server/src/main/java/org/apache/kylin/rest/util/PerformanceMonitorTask.java
@@ -1,7 +1,27 @@
 package org.apache.kylin.rest.util;
 
+import org.apache.kylin.rest.service.PerformanceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
 /**
  * Created by jiazhong on 2015/4/13.
  */
+
 public class PerformanceMonitorTask {
+
+    @Autowired
+    private PerformanceService performanceService;
+    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+    @Scheduled(fixedRate = 3600000)
+    public void reportCurrentTime() {
+        System.out.println("The time is now " + dateFormat.format(new Date()));
+    }
+
+
+    public void setPerformanceService(PerformanceService performanceService) {this.performanceService = performanceService;}
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/resources/applicationContext.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/applicationContext.xml b/server/src/main/resources/applicationContext.xml
index 75c69df..9d3594c 100644
--- a/server/src/main/resources/applicationContext.xml
+++ b/server/src/main/resources/applicationContext.xml
@@ -109,6 +109,9 @@
 	</bean>
 	<!-- Rest service binding -->
 
+	<task:annotation-driven />
+	<bean id="performanceMonitorTask" class="org.apache.kylin.rest.util.PerformanceMonitorTask"></bean>
+
 	<!-- Cache Config -->
 	<cache:annotation-driven />
 	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/server/src/main/resources/log4j.properties b/server/src/main/resources/log4j.properties
index c52992d..fc06073 100644
--- a/server/src/main/resources/log4j.properties
+++ b/server/src/main/resources/log4j.properties
@@ -9,6 +9,13 @@ log4j.appender.file.File=${catalina.home}/logs/kylin.log
 log4j.appender.file.layout.ConversionPattern=[%t]:[%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%l] - %m%n
 log4j.appender.file.Append=true
 
+
+log4j.appender.request=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.request.layout=org.apache.log4j.PatternLayout
+log4j.appender.request.File=${catalina.home}/logs/kylin_request.log
+log4j.appender.request.layout.ConversionPattern=[%t]:[%d{yyyy-MM-dd HH:mm:ss,SSS}][%p][%l] - %m%n
+log4j.appender.request.Append=true
+
 log4j.appender.query=org.apache.log4j.DailyRollingFileAppender
 log4j.appender.query.layout=org.apache.log4j.PatternLayout
 log4j.appender.query.File=${catalina.home}/logs/kylin_query.log
@@ -36,3 +43,6 @@ log4j.logger.org.apache.kylin.storage=DEBUG, query
 log4j.logger.org.apache.kylin.rest.controller.JobController=DEBUG, job
 log4j.logger.org.apache.kylin.rest.service.JobService=DEBUG, job
 log4j.logger.org.apache.kylin.job=DEBUG, job
+
+#api config
+log4j.logger.org.apache.kylin.rest.filter.RequestLoggingFilter=DEBUG, request
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/be3899c3/server/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index 61874ed..e6b4c82 100644
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -92,7 +92,34 @@
 	    <filter-name>instrumentedFilter</filter-name>
 	    <url-pattern>/*</url-pattern>
 	</filter-mapping>
-	
+
+    <!--request log filter-->
+    <filter>
+        <filter-name>requestLoggingFilter</filter-name>
+        <filter-class>org.apache.kylin.rest.filter.RequestLoggingFilter</filter-class>
+        <init-param>
+            <param-name>includeClientInfo</param-name>
+            <param-value>true</param-value>
+        </init-param>
+        <init-param>
+            <param-name>includePayload</param-name>
+            <param-value>true</param-value>
+        </init-param>
+        <init-param>
+            <param-name>maxPayloadLength</param-name>
+            <param-value>10240</param-value>
+        </init-param>
+        <init-param>
+            <param-name>includeQueryString</param-name>
+            <param-value>true</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>requestLoggingFilter</filter-name>
+        <servlet-name>kylin</servlet-name>
+    </filter-mapping>
+
     <servlet>
         <servlet-name>kylin</servlet-name>
         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>


[10/52] [abbrv] incubator-kylin git commit: KYLIN-702 make default block size to 64M for hive flat table.

Posted by ma...@apache.org.
KYLIN-702 make default block size to 64M for hive flat table.


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

Branch: refs/heads/0.8.0
Commit: 4cf65f070bc9ddb05bba1414fcc67b1a991e64c7
Parents: 60d94fa
Author: Shao Feng, Shi <sh...@ebay.com>
Authored: Fri May 15 10:36:57 2015 +0800
Committer: Shao Feng, Shi <sh...@ebay.com>
Committed: Fri May 15 10:37:14 2015 +0800

----------------------------------------------------------------------
 conf/kylin_hive_conf.xml | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4cf65f07/conf/kylin_hive_conf.xml
----------------------------------------------------------------------
diff --git a/conf/kylin_hive_conf.xml b/conf/kylin_hive_conf.xml
index d990175..8bd2c10 100644
--- a/conf/kylin_hive_conf.xml
+++ b/conf/kylin_hive_conf.xml
@@ -7,6 +7,12 @@
     </property>
 
     <property>
+        <name>dfs.block.size</name>
+        <value>67108864</value>
+        <description>Block size</description>
+    </property>
+
+    <property>
         <name>hive.exec.compress.output</name>
         <value>true</value>
         <description>enable compress</description>
@@ -47,8 +53,13 @@
         <description>Enable hive file merge on map-reduce job</description>
     </property>
     <property>
+        <name>mapred.output.compression.type</name>
+        <value>BLOCK</value>
+        <description>The compression type to use for job outputs</description>
+    </property>
+    <property>
         <name>hive.merge.size.per.task</name>
-        <value>64000000</value>
+        <value>256000000</value>
         <description>Size for the merged file</description>
     </property>
 </configuration>
\ No newline at end of file


[02/52] [abbrv] incubator-kylin git commit: KYLIN-763 remove author information

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java b/job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java
index a83b87c..5ab97c9 100644
--- a/job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java
+++ b/job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job;
 import org.apache.kylin.job.execution.AbstractExecutable;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public abstract class BaseTestExecutable extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java b/job/src/test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java
index 0582de3..dc42dc5 100644
--- a/job/src/test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java
+++ b/job/src/test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java
@@ -76,7 +76,6 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
 /**
- * Created by qianzhou on 3/9/15.
  *
  * This class is going to be deleted
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java b/job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java
index 48f7a82..65faad7 100644
--- a/job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java
+++ b/job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java
@@ -80,7 +80,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.collect.Lists;
 
 /**
- * Created by qianzhou on 3/9/15.
  */
 public class BuildIIWithStreamTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/DataGenTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/DataGenTest.java b/job/src/test/java/org/apache/kylin/job/DataGenTest.java
index 7b10a22..7161f59 100644
--- a/job/src/test/java/org/apache/kylin/job/DataGenTest.java
+++ b/job/src/test/java/org/apache/kylin/job/DataGenTest.java
@@ -42,7 +42,6 @@ import java.util.Map;
 import static org.junit.Assert.assertTrue;
 
 /**
- * Created by honma on 6/19/14.
  */
 public class DataGenTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java b/job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java
index 10d08ba..ac4828e 100644
--- a/job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java
+++ b/job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 12/22/14.
  */
 public class ErrorTestExecutable extends BaseTestExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java b/job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java
index 18173d2..e18cc0d 100644
--- a/job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java
+++ b/job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 12/22/14.
  */
 public class FailedTestExecutable extends BaseTestExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java b/job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java
index 74b8891..6aaeaa2 100644
--- a/job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java
+++ b/job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java
@@ -49,7 +49,6 @@ import java.io.File;
 import java.io.IOException;
 
 /**
- * Created by qianzhou on 3/6/15.
  */
 public class IIStreamBuilderTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java b/job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java
index 641d031..b4f6a98 100644
--- a/job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java
+++ b/job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 12/31/14.
  */
 public class SelfStopExecutable extends BaseTestExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java b/job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java
index 861531f..1421f10 100644
--- a/job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java
+++ b/job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 12/22/14.
  */
 public class SucceedTestExecutable extends BaseTestExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java b/job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java
index d9a1860..44ba8f4 100644
--- a/job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java
+++ b/job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java
@@ -24,7 +24,6 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 /**
- * Created by honma on 5/29/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class ColumnConfig {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/dataGen/FactTableGenerator.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/dataGen/FactTableGenerator.java b/job/src/test/java/org/apache/kylin/job/dataGen/FactTableGenerator.java
index 7cafea6..5827946 100644
--- a/job/src/test/java/org/apache/kylin/job/dataGen/FactTableGenerator.java
+++ b/job/src/test/java/org/apache/kylin/job/dataGen/FactTableGenerator.java
@@ -36,7 +36,6 @@ import java.text.SimpleDateFormat;
 import java.util.*;
 
 /**
- * Created by hongbin on 5/20/14.
  */
 public class FactTableGenerator {
     CubeInstance cube = null;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java b/job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java
index b51ddf7..9412944 100644
--- a/job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java
+++ b/job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java
@@ -30,7 +30,6 @@ import com.fasterxml.jackson.databind.JsonMappingException;
 import org.apache.kylin.common.util.JsonUtil;
 
 /**
- * Created by honma on 5/29/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class GenConfig {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java b/job/src/test/java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java
index bf915e6..c303ebf 100644
--- a/job/src/test/java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java
+++ b/job/src/test/java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java
@@ -19,7 +19,6 @@ import java.util.Map;
 import java.util.Random;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/5/15.
  */
 public class StreamingDataGenerator {
     private static final Logger logger = LoggerFactory.getLogger(StreamingDataGenerator.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java b/job/src/test/java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java
index f321fc3..386d858 100644
--- a/job/src/test/java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java
+++ b/job/src/test/java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java
@@ -34,7 +34,6 @@ import java.util.BitSet;
 import java.util.List;
 
 /**
- * Created by shaoshi on 5/12/15.
  */
 public class CubeSamplingTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java b/job/src/test/java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java
index 1dc5c44..3232a80 100644
--- a/job/src/test/java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java
+++ b/job/src/test/java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java
@@ -27,7 +27,6 @@ import org.apache.hadoop.hbase.client.Put;
 import org.apache.kylin.common.util.Bytes;
 
 /**
- * Created by hongbin on 5/15/14.
  */
 public class TestHbaseClient {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java b/job/src/test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java
index 03a84fb..3b4a6af 100644
--- a/job/src/test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java
+++ b/job/src/test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java
@@ -32,7 +32,6 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.util.LocalFileMetadataTestCase;
 
 /**
- * Created by honma on 8/20/14.
  */
 public class HdfsOpsTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/hadoop/invertedindex/IITest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/hadoop/invertedindex/IITest.java b/job/src/test/java/org/apache/kylin/job/hadoop/invertedindex/IITest.java
index ecc3c23..7a88420 100644
--- a/job/src/test/java/org/apache/kylin/job/hadoop/invertedindex/IITest.java
+++ b/job/src/test/java/org/apache/kylin/job/hadoop/invertedindex/IITest.java
@@ -54,7 +54,6 @@ import java.io.IOException;
 import java.util.*;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/26/15.
  */
 public class IITest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java b/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
index 9da0f73..f47e152 100644
--- a/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
+++ b/job/src/test/java/org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java
@@ -32,7 +32,6 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 
 /**
- * Created by qianzhou on 12/26/14.
  */
 public abstract class BaseSchedulerTest extends HBaseMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java b/job/src/test/java/org/apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java
index a0ec671..22afb1d 100644
--- a/job/src/test/java/org/apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java
+++ b/job/src/test/java/org/apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java
@@ -31,7 +31,6 @@ import org.apache.kylin.job.execution.DefaultChainedExecutable;
 import org.apache.kylin.job.execution.ExecutableState;
 
 /**
- * Created by qianzhou on 12/19/14.
  */
 public class DefaultSchedulerTest extends BaseSchedulerTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/manager/ExecutableManagerTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/manager/ExecutableManagerTest.java b/job/src/test/java/org/apache/kylin/job/manager/ExecutableManagerTest.java
index 11af88e..1d28fc8 100644
--- a/job/src/test/java/org/apache/kylin/job/manager/ExecutableManagerTest.java
+++ b/job/src/test/java/org/apache/kylin/job/manager/ExecutableManagerTest.java
@@ -37,7 +37,6 @@ import java.util.List;
 import static org.junit.Assert.*;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public class ExecutableManagerTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java
----------------------------------------------------------------------
diff --git a/job/src/test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java b/job/src/test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java
index 9587e89..95e4b7f 100644
--- a/job/src/test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java
+++ b/job/src/test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java
@@ -19,7 +19,6 @@ import org.junit.Ignore;
 import org.junit.Test;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/6/15.
  */
 @Ignore
 public class HBaseRowDigestTest extends HBaseMetadataTestCase {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/filter/DateConditionModifier.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/filter/DateConditionModifier.java b/metadata/src/main/java/org/apache/kylin/metadata/filter/DateConditionModifier.java
index 74e2d71..8d5c10c 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/filter/DateConditionModifier.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/filter/DateConditionModifier.java
@@ -11,7 +11,6 @@ import java.util.List;
 import java.util.Set;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 public class DateConditionModifier implements TupleFilterSerializer.Decorator {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/filter/TsConditionEraser.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/filter/TsConditionEraser.java b/metadata/src/main/java/org/apache/kylin/metadata/filter/TsConditionEraser.java
index 5a7ee40..96ff81c 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/filter/TsConditionEraser.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/filter/TsConditionEraser.java
@@ -6,7 +6,6 @@ import org.apache.kylin.metadata.model.TblColRef;
 import java.util.IdentityHashMap;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 public class TsConditionEraser implements TupleFilterSerializer.Decorator {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java b/metadata/src/main/java/org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java
index 138940f..49cd327 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java
@@ -6,7 +6,6 @@ import org.apache.kylin.common.hll.HyperLogLogPlusCounter;
 import org.apache.kylin.metadata.model.DataType;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/10/15.
  */
 public class FixedHLLCodec extends FixedLenMeasureCodec<HyperLogLogPlusCounter> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
index 7f26482..73e71b6 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
@@ -25,7 +25,6 @@ import org.apache.kylin.common.util.StringUtil;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/26/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class DimensionDesc {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
index abf87b7..e1ab0af 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
@@ -21,7 +21,6 @@ package org.apache.kylin.metadata.model;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/30/14.
  */
 public interface IJoinedFlatTableDesc {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java b/metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
index 1b931a0..9dbe63e 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
@@ -21,7 +21,6 @@ package org.apache.kylin.metadata.model;
 import org.apache.kylin.metadata.model.TblColRef;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/30/14.
  */
 public class IntermediateColumnDesc {
     private String id;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/project/RealizationEntry.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/RealizationEntry.java b/metadata/src/main/java/org/apache/kylin/metadata/project/RealizationEntry.java
index cfbe6a3..910d242 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/RealizationEntry.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/RealizationEntry.java
@@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import org.apache.kylin.metadata.realization.RealizationType;
 
 /**
- * Created by qianzhou on 12/5/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class RealizationEntry {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealizationConstants.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealizationConstants.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealizationConstants.java
index c38f5da..3a07cc6 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealizationConstants.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/IRealizationConstants.java
@@ -1,7 +1,6 @@
 package org.apache.kylin.metadata.realization;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/5/15.
  */
 public class IRealizationConstants {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java
index 2c7ba42..618dff5 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationRegistry.java
@@ -34,7 +34,6 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/18/14.
  */
 public class RealizationRegistry {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationType.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationType.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationType.java
index 1b5dbc5..3fcfe63 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationType.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/RealizationType.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.metadata.realization;
 
 /**
- * Created by qianzhou on 12/8/14.
  */
 
 //TODO: change to String for plugin

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigest.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigest.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigest.java
index f31aa97..7811858 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigest.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigest.java
@@ -26,7 +26,6 @@ import org.apache.kylin.metadata.model.JoinDesc;
 import org.apache.kylin.metadata.model.TblColRef;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/8/15.
  */
 public class SQLDigest {
     public String factTable;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigestUtil.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigestUtil.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigestUtil.java
index 695ac8f..19b9ee7 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigestUtil.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/SQLDigestUtil.java
@@ -10,7 +10,6 @@ import com.google.common.collect.BoundType;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/14/15.
  */
 public class SQLDigestUtil {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/realization/StreamSQLDigest.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/realization/StreamSQLDigest.java b/metadata/src/main/java/org/apache/kylin/metadata/realization/StreamSQLDigest.java
index 3a1d41a..4fd9f17 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/realization/StreamSQLDigest.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/realization/StreamSQLDigest.java
@@ -8,7 +8,6 @@ import org.apache.kylin.metadata.filter.TupleFilterSerializer;
 import org.apache.kylin.metadata.model.TblColRef;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  *
  * A encapsulation of {@link SQLDigest},
  * This class makes {@link SQLDigest} being able to compare with other {@link SQLDigest}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
index 7803d0d..b87c633 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/CompoundTupleIterator.java
@@ -10,7 +10,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/14/15.
  */
 public class CompoundTupleIterator implements ITupleIterator {
     private static final Logger logger = LoggerFactory.getLogger(CompoundTupleIterator.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
index bbad038..ebdcb5d 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java
@@ -5,7 +5,6 @@ import java.util.Iterator;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/14/15.
  *
  */
 public class SimpleTupleIterator implements ITupleIterator {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
index 9a6a2be..556fca6 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java
@@ -7,7 +7,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/15/15.
  *
  * Like "tee" command in linux, it effectively duplicates the underlying
  * ITupleIterator's results

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/test/java/org/apache/kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java
----------------------------------------------------------------------
diff --git a/metadata/src/test/java/org/apache/kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java b/metadata/src/test/java/org/apache/kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java
index b0e2b5a..bb30c1e 100644
--- a/metadata/src/test/java/org/apache/kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java
+++ b/metadata/src/test/java/org/apache/kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java
@@ -4,7 +4,6 @@ import org.apache.kylin.metadata.model.DataType;
 import org.junit.Test;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/4/15.
  */
 public class FixedPointLongCodecTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/metadata/src/test/java/org/apache/kylin/metadata/model/TableDescTest.java
----------------------------------------------------------------------
diff --git a/metadata/src/test/java/org/apache/kylin/metadata/model/TableDescTest.java b/metadata/src/test/java/org/apache/kylin/metadata/model/TableDescTest.java
index 78895c8..3a69e5c 100644
--- a/metadata/src/test/java/org/apache/kylin/metadata/model/TableDescTest.java
+++ b/metadata/src/test/java/org/apache/kylin/metadata/model/TableDescTest.java
@@ -20,7 +20,6 @@ package org.apache.kylin.metadata.model;
 
 
 /**
- * Created by qianzhou on 12/3/14.
  */
 public class TableDescTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/main/java/org/apache/kylin/query/routing/RoutingRule.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/routing/RoutingRule.java b/query/src/main/java/org/apache/kylin/query/routing/RoutingRule.java
index ff717a2..a24bc4e 100644
--- a/query/src/main/java/org/apache/kylin/query/routing/RoutingRule.java
+++ b/query/src/main/java/org/apache/kylin/query/routing/RoutingRule.java
@@ -31,7 +31,6 @@ import org.apache.kylin.metadata.realization.RealizationType;
 import org.apache.kylin.query.relnode.OLAPContext;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public abstract class RoutingRule {
     private static final Logger logger = LoggerFactory.getLogger(QueryRouter.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/AdjustForWeaklyMatchedRealization.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/AdjustForWeaklyMatchedRealization.java b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/AdjustForWeaklyMatchedRealization.java
index 3f3a5d9..eba309a 100644
--- a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/AdjustForWeaklyMatchedRealization.java
+++ b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/AdjustForWeaklyMatchedRealization.java
@@ -37,7 +37,6 @@ import java.util.Iterator;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public class AdjustForWeaklyMatchedRealization extends RoutingRule {
     private static final Logger logger = LoggerFactory.getLogger(AdjustForWeaklyMatchedRealization.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationPriorityRule.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationPriorityRule.java b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationPriorityRule.java
index 96fafde..4389263 100644
--- a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationPriorityRule.java
+++ b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationPriorityRule.java
@@ -27,7 +27,6 @@ import org.apache.kylin.query.relnode.OLAPContext;
 import org.apache.kylin.query.routing.RoutingRule;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public class RealizationPriorityRule extends RoutingRule {
     static Map<RealizationType, Integer> priorities = Maps.newHashMap();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationSortRule.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationSortRule.java b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationSortRule.java
index ed8644f..f9a250e 100644
--- a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationSortRule.java
+++ b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RealizationSortRule.java
@@ -28,7 +28,6 @@ import java.util.Comparator;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public class RealizationSortRule extends RoutingRule {
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RemoveUncapableRealizationsRule.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RemoveUncapableRealizationsRule.java b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RemoveUncapableRealizationsRule.java
index fc68ddd..c710ff1 100644
--- a/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RemoveUncapableRealizationsRule.java
+++ b/query/src/main/java/org/apache/kylin/query/routing/RoutingRules/RemoveUncapableRealizationsRule.java
@@ -26,7 +26,6 @@ import org.apache.kylin.query.relnode.OLAPContext;
 import org.apache.kylin.query.routing.RoutingRule;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public class RemoveUncapableRealizationsRule extends RoutingRule {
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/test/java/org/apache/kylin/query/test/CombinationTest.java
----------------------------------------------------------------------
diff --git a/query/src/test/java/org/apache/kylin/query/test/CombinationTest.java b/query/src/test/java/org/apache/kylin/query/test/CombinationTest.java
index 7a3128b..9e8e92b 100644
--- a/query/src/test/java/org/apache/kylin/query/test/CombinationTest.java
+++ b/query/src/test/java/org/apache/kylin/query/test/CombinationTest.java
@@ -29,7 +29,6 @@ import java.util.Arrays;
 import java.util.Collection;
 
 /**
- * Created by honma on 7/2/14.
  */
 @RunWith(Parameterized.class)
 public class CombinationTest extends KylinQueryTest {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java
----------------------------------------------------------------------
diff --git a/query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java b/query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java
index 37fc4f3..185b22e 100644
--- a/query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java
+++ b/query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java
@@ -32,7 +32,6 @@ import java.util.Collection;
 import java.util.Map;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/2/15.
  */
 @RunWith(Parameterized.class)
 public class IIQueryTest extends KylinQueryTest {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/test/java/org/apache/kylin/query/test/KylinTestBase.java
----------------------------------------------------------------------
diff --git a/query/src/test/java/org/apache/kylin/query/test/KylinTestBase.java b/query/src/test/java/org/apache/kylin/query/test/KylinTestBase.java
index 89fb01d..0f5c1ec 100644
--- a/query/src/test/java/org/apache/kylin/query/test/KylinTestBase.java
+++ b/query/src/test/java/org/apache/kylin/query/test/KylinTestBase.java
@@ -41,7 +41,6 @@ import java.util.*;
 import java.util.logging.LogManager;
 
 /**
- * Created by hongbin on 2/18/14.
  */
 public class KylinTestBase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/query/src/test/java/org/apache/kylin/query/test/RealizationRegistryTest.java
----------------------------------------------------------------------
diff --git a/query/src/test/java/org/apache/kylin/query/test/RealizationRegistryTest.java b/query/src/test/java/org/apache/kylin/query/test/RealizationRegistryTest.java
index dc814ea..c1789db 100644
--- a/query/src/test/java/org/apache/kylin/query/test/RealizationRegistryTest.java
+++ b/query/src/test/java/org/apache/kylin/query/test/RealizationRegistryTest.java
@@ -32,7 +32,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 /**
- * Created by qianzhou on 1/26/15.
  */
 public class RealizationRegistryTest extends LocalFileMetadataTestCase {
     @Before

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java b/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
index bcf5ad5..7ffea38 100644
--- a/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
+++ b/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
@@ -21,7 +21,6 @@ package org.apache.kylin.rest.model;
 import java.io.Serializable;
 
 /**
- * Created by lukhan on 2/27/14.
  */
 public class ColumnMeta implements Serializable {
     private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java b/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
index 269fbab..00b01db 100644
--- a/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
+++ b/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.rest.model;
 
 /**
- * Created by lukhan on 2/27/14.
  */
 public class SelectedColumnMeta {
     public SelectedColumnMeta(boolean isAutoIncrement, boolean isCaseSensitive, boolean isSearchable, boolean isCurrency, int isNullalbe, boolean isSigned, int displaySize, String label, String name, String schemaName, String catelogName, String tableName, int precision, int scale, int columnType, String columnTypeName, boolean isReadOnly, boolean isWritable, boolean isDefinitelyWritable) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java b/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
index 36f7aa1..485e745 100644
--- a/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
+++ b/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Created by lukhan on 2/27/14.
  */
 public class TableMeta implements Serializable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
index 075fa52..71cd1c4 100644
--- a/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
+++ b/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.rest.request;
 
 /**
- * Created by honma on 8/7/14.
  */
 public class CreateProjectRequest {
     private String name;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java b/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
index 9ec9c1d..66e8ec0 100644
--- a/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
+++ b/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.rest.request;
 
 /**
- * Created by honma on 7/10/14.
  */
 public class MetaRequest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java b/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
index 3819de6..29ba162 100644
--- a/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
+++ b/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.rest.request;
 
 /**
- * Created by honma on 8/7/14.
  */
 public class UpdateProjectRequest {
     private String formerProjectName;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java b/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
index e104897..6ce8b83 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 import java.util.List;
 
 /**
- * Created by qianzhou on 1/19/15.
  */
 @Component("cacheService")
 public class CacheService extends BasicService {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java b/server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java
index 2b1de23..2eff08f 100644
--- a/server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java
+++ b/server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java
@@ -13,7 +13,6 @@ import java.util.List;
 import java.util.Properties;
 
 /**
- * Created by shaoshi on 2/5/15.
  */
 public class JDBCDriverTest extends HBaseMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/test/java/org/apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java b/server/src/test/java/org/apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java
index 2c7e068..ed63183 100644
--- a/server/src/test/java/org/apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java
+++ b/server/src/test/java/org/apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java
@@ -28,7 +28,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * Created by qianzhou on 1/16/15.
  */
 public class BroadcasterReceiveServlet extends HttpServlet {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/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 7bcaba8..467b7cd 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
@@ -35,7 +35,6 @@ import org.apache.kylin.metadata.project.ProjectInstance;
 import org.apache.kylin.metadata.project.ProjectManager;
 
 /**
- * Created by honma on 8/7/14.
  */
 public class ProjectControllerTest extends ServiceTestBase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
index 00f521b..64a71c4 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/CacheServiceTest.java
@@ -49,7 +49,6 @@ import java.util.concurrent.atomic.AtomicLong;
 import static org.junit.Assert.*;
 
 /**
- * Created by qianzhou on 1/16/15.
  */
 
 public class CacheServiceTest extends LocalFileMetadataTestCase {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
index 3e31898..068619e 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java
@@ -42,7 +42,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 public class CacheFledgedStorageEngine implements IStorageEngine {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java b/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
index 18a0e02..9b4caa5 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/StorageLayerCache.java
@@ -1,7 +1,6 @@
 package org.apache.kylin.storage.cache;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/11/15.
  */
 public interface StorageLayerCache {
     boolean isCacheEnabled();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
index 52405d8..5e58822 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
@@ -19,7 +19,6 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 
 public class StreamSQLResult {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java b/storage/src/main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java
index 9b7550f..4ca8e78 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java
@@ -21,7 +21,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Created by shaoshi on 3/23/15.
  * This implementation uses Dictionary to encode and decode the table; If a column doesn't have dictionary, will check
  * its data type to serialize/deserialize it;
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/GTComboStore.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/GTComboStore.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/GTComboStore.java
index a6476ca..f07b516 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/GTComboStore.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/GTComboStore.java
@@ -10,7 +10,6 @@ import java.io.IOException;
 import java.util.BitSet;
 
 /**
- * Created by qianzhou on 5/6/15.
  */
 public class GTComboStore implements IGTStore {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java
index 5c0c436..d8edf45 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java
@@ -5,7 +5,6 @@ import org.apache.kylin.common.util.ByteArray;
 import java.util.BitSet;
 
 /**
- * Created by qianzhou on 5/6/15.
  */
 public final class ScanKey {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/FileSystem.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/FileSystem.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/FileSystem.java
index bebc1a2..db245fd 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/FileSystem.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/FileSystem.java
@@ -4,7 +4,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
- * Created by qianzhou on 5/4/15.
  */
 interface FileSystem {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java
index fec0d13..25d66f0 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java
@@ -16,7 +16,6 @@ import java.util.BitSet;
 import java.util.UUID;
 
 /**
- * Created by qianzhou on 5/4/15.
  */
 public class GTDiskStore implements IGTStore {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/HadoopFileSystem.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/HadoopFileSystem.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/HadoopFileSystem.java
index 7a6450d..9546db7 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/HadoopFileSystem.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/HadoopFileSystem.java
@@ -10,7 +10,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
- * Created by qianzhou on 5/6/15.
  */
 class HadoopFileSystem implements FileSystem {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java
index d512552..0d07f3b 100644
--- a/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java
+++ b/storage/src/main/java/org/apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java
@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
 import java.io.*;
 
 /**
- * Created by qianzhou on 5/4/15.
  */
 class LocalFileSystem implements FileSystem {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java
index 20deaeb..ae62959 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java
@@ -9,7 +9,6 @@ import org.apache.kylin.cube.kv.RowConstants;
 import com.google.common.collect.Lists;
 
 /**
- * Created by qianzhou on 4/20/15.
  */
 public class AggrKey implements Comparable<AggrKey> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggregationCache.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggregationCache.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggregationCache.java
index f951409..4274b9d 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggregationCache.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/AggregationCache.java
@@ -25,7 +25,6 @@ import org.apache.kylin.metadata.measure.MeasureAggregator;
 import com.google.common.collect.Maps;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 11/27/14.
  */
 @SuppressWarnings("rawtypes")
 public abstract class AggregationCache {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/CoprocessorConstants.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/CoprocessorConstants.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/CoprocessorConstants.java
index 7efb283..6e69827 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/CoprocessorConstants.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/CoprocessorConstants.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.storage.hbase.coprocessor;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 11/26/14.
  */
 public class CoprocessorConstants {
     public static final int SERIALIZE_BUFFER_SIZE = 65536;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/FilterDecorator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/FilterDecorator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/FilterDecorator.java
index 73bfd25..7729e8c 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/FilterDecorator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/FilterDecorator.java
@@ -13,7 +13,6 @@ import java.util.Collection;
 import java.util.Set;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/3/15.
  */
 @SuppressWarnings("unchecked")
 public class FilterDecorator implements TupleFilterSerializer.Decorator {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/ClearTextDictionary.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/ClearTextDictionary.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/ClearTextDictionary.java
index e93bf17..e9a3780 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/ClearTextDictionary.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/ClearTextDictionary.java
@@ -45,7 +45,6 @@ import org.apache.kylin.storage.hbase.coprocessor.CoprocessorRowType;
 import java.util.Map;
 
 /**
- * Created by qianzhou on 3/17/15.
  */
 public class ClearTextDictionary implements IDictionaryAware {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationCache.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationCache.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationCache.java
index ac6fa70..3ab3934 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationCache.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationCache.java
@@ -26,7 +26,6 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 11/27/14.
  */
 public class EndpointAggregationCache extends AggregationCache {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
index 6a7c14a..d9ede57 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java
@@ -58,7 +58,6 @@ import java.io.IOException;
 import java.util.*;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/2/14.
  */
 public class EndpointTupleIterator implements ITupleIterator {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java
index 4c1c568..5952a1f 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java
@@ -33,7 +33,6 @@ import java.util.List;
 import java.util.NoSuchElementException;
 
 /**
- * Created by honma on 11/10/14.
  */
 public class HbaseServerKVIterator implements Iterable<IIRow>, Closeable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java
index af8d917..429e060 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java
@@ -64,7 +64,6 @@ import com.google.protobuf.Service;
 import it.uniroma3.mat.extendedset.intset.ConciseSet;
 
 /**
- * Created by honma on 11/7/14.
  */
 public class IIEndpoint extends IIProtos.RowsService implements Coprocessor, CoprocessorService {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIResponseAdapter.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIResponseAdapter.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIResponseAdapter.java
index eb3eef3..8675de1 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIResponseAdapter.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/IIResponseAdapter.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.storage.hbase.coprocessor.endpoint;
 
 /**
- * Created by honma on 11/10/14.
  */
 public class IIResponseAdapter {
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java
index 45de6fe..0848a5c 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java
@@ -9,7 +9,6 @@ import org.apache.kylin.storage.hbase.coprocessor.CoprocessorRowType;
 import java.util.Map;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/3/15.
  */
 public class LocalDictionary implements IDictionaryAware {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java
index 0691560..09327eb 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java
@@ -26,7 +26,6 @@ import org.apache.kylin.storage.hbase.coprocessor.CoprocessorRowType;
 import it.uniroma3.mat.extendedset.intset.ConciseSet;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 11/24/14.
  * <p/>
  * an adapter
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
index f16e40c..18155c6 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractor.java
@@ -10,7 +10,6 @@ import org.apache.kylin.common.util.DateFormat;
 import com.google.common.collect.Range;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/8/15.
  */
 public class TsConditionExtractor {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
index 0350489..beb86c5 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridInstance.java
@@ -18,7 +18,6 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import java.util.List;
 
 /**
- * Created by shaoshi on 2/13/15.
  */
 
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java
index 7e4621c..df3fae3 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridManager.java
@@ -18,7 +18,6 @@ import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Created by shaoshi on 2/13/15.
  */
 public class HybridManager implements IRealizationProvider {
     public static final Serializer<HybridInstance> HYBRID_SERIALIZER = new JsonSerializer<HybridInstance>(HybridInstance.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
index 96b6ad0..87ff26b 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
@@ -21,7 +21,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Ranges;
 
 /**
- * Created by shaoshi on 2/13/15.
  */
 public class HybridStorageEngine implements IStorageEngine {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java b/storage/src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java
index d390415..2ac2445 100644
--- a/storage/src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java
+++ b/storage/src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java
@@ -3,7 +3,6 @@ package org.apache.kylin.storage.util;
 import net.sf.ehcache.pool.sizeof.ReflectionSizeOf;
 
 /**
- * Created by qianzhou on 5/11/15.
  */
 public final class SizeOfUtil {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
index fd34224..e86771d 100644
--- a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
@@ -15,7 +15,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 public class EhcacheTest {
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/filter/DateConditionModifierTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/filter/DateConditionModifierTest.java b/storage/src/test/java/org/apache/kylin/storage/filter/DateConditionModifierTest.java
index 29cf7b1..669289e 100644
--- a/storage/src/test/java/org/apache/kylin/storage/filter/DateConditionModifierTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/filter/DateConditionModifierTest.java
@@ -9,7 +9,6 @@ import org.junit.Assert;
 import org.junit.Test;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/7/15.
  */
 public class DateConditionModifierTest extends FilterBaseTest {
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/filter/TsConditionEraserTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/filter/TsConditionEraserTest.java b/storage/src/test/java/org/apache/kylin/storage/filter/TsConditionEraserTest.java
index c1fff70..59b1af0 100644
--- a/storage/src/test/java/org/apache/kylin/storage/filter/TsConditionEraserTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/filter/TsConditionEraserTest.java
@@ -20,7 +20,6 @@ import org.junit.Test;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/13/15.
  */
 public class TsConditionEraserTest extends LocalFileMetadataTestCase {
     IIInstance ii;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationTest.java b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationTest.java
index ae0a9bf..3217f1c 100644
--- a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/EndpointAggregationTest.java
@@ -43,7 +43,6 @@ import org.junit.Test;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 11/27/14.
  *
  * ii test
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java
index 4369b26..df1c26b 100644
--- a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 import static org.junit.Assert.assertEquals;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/3/14.
  */
 public class TableRecordInfoTest extends LocalFileMetadataTestCase {
     IIInstance ii;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractorTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractorTest.java b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractorTest.java
index 99ce8b9..7a04ee6 100644
--- a/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractorTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/hbase/coprocessor/endpoint/TsConditionExtractorTest.java
@@ -38,7 +38,6 @@ import org.junit.Test;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) 
  *
  * ii test
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/storage/src/test/java/org/apache/kylin/storage/hybrid/HybridManagerTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/hybrid/HybridManagerTest.java b/storage/src/test/java/org/apache/kylin/storage/hybrid/HybridManagerTest.java
index 775ef9d..3ad7ca6 100644
--- a/storage/src/test/java/org/apache/kylin/storage/hybrid/HybridManagerTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/hybrid/HybridManagerTest.java
@@ -11,7 +11,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 /**
- * Created by shaoshi on 2/13/15.
  */
 public class HybridManagerTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/BrokerConfig.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/BrokerConfig.java b/streaming/src/main/java/org/apache/kylin/streaming/BrokerConfig.java
index f229202..f1104e1 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/BrokerConfig.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/BrokerConfig.java
@@ -38,7 +38,6 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class BrokerConfig {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/JsonStreamParser.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/JsonStreamParser.java b/streaming/src/main/java/org/apache/kylin/streaming/JsonStreamParser.java
index d229647..7d730b7 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/JsonStreamParser.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/JsonStreamParser.java
@@ -50,7 +50,6 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public final class JsonStreamParser implements StreamParser {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/KafkaConfig.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/KafkaConfig.java b/streaming/src/main/java/org/apache/kylin/streaming/KafkaConfig.java
index 77dff2b..9949c96 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/KafkaConfig.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/KafkaConfig.java
@@ -48,7 +48,6 @@ import java.io.*;
 import java.util.List;
 
 /**
- * Created by qianzhou on 3/2/15.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class KafkaConfig extends RootPersistentEntity {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/KafkaConsumer.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/KafkaConsumer.java b/streaming/src/main/java/org/apache/kylin/streaming/KafkaConsumer.java
index 715eefe..70d37ef 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/KafkaConsumer.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/KafkaConsumer.java
@@ -49,7 +49,6 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Created by qianzhou on 2/15/15.
  */
 public class KafkaConsumer implements Runnable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/KafkaRequester.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/KafkaRequester.java b/streaming/src/main/java/org/apache/kylin/streaming/KafkaRequester.java
index 62f82a2..02e2759 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/KafkaRequester.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/KafkaRequester.java
@@ -54,7 +54,6 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
 
 /**
- * Created by qianzhou on 2/15/15.
  */
 public final class KafkaRequester {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/StreamBuilder.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/StreamBuilder.java b/streaming/src/main/java/org/apache/kylin/streaming/StreamBuilder.java
index 4f5f0f5..67cb109 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/StreamBuilder.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/StreamBuilder.java
@@ -43,7 +43,6 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Created by qianzhou on 2/17/15.
  */
 public abstract class StreamBuilder implements Runnable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/StreamMessage.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/StreamMessage.java b/streaming/src/main/java/org/apache/kylin/streaming/StreamMessage.java
index 4747b7d..6229aa5 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/StreamMessage.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/StreamMessage.java
@@ -35,7 +35,6 @@
 package org.apache.kylin.streaming;
 
 /**
- * Created by qianzhou on 2/15/15.
  */
 public class StreamMessage {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/StreamParser.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/StreamParser.java b/streaming/src/main/java/org/apache/kylin/streaming/StreamParser.java
index afbfff0..304e252 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/StreamParser.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/StreamParser.java
@@ -37,7 +37,6 @@ package org.apache.kylin.streaming;
 import java.util.List;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public interface StreamParser {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/StreamingManager.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/StreamingManager.java b/streaming/src/main/java/org/apache/kylin/streaming/StreamingManager.java
index d3a7c70..46c34fa 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/StreamingManager.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/StreamingManager.java
@@ -44,7 +44,6 @@ import java.io.*;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public class StreamingManager {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/StringStreamParser.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/StringStreamParser.java b/streaming/src/main/java/org/apache/kylin/streaming/StringStreamParser.java
index 8f99eb5..14e1b45 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/StringStreamParser.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/StringStreamParser.java
@@ -39,7 +39,6 @@ import java.util.List;
 import com.google.common.collect.Lists;
 
 /**
- * Created by qianzhou on 3/25/15.
  */
 public final class StringStreamParser implements StreamParser {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java b/streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java
index b93d589..4338b18 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java
@@ -40,7 +40,6 @@ import java.util.List;
 /**
  * The topic metadata should be invariant, otherwise will cause re-initialization of the Consumer
  *
- * Created by qianzhou on 2/15/15.
  */
 public class TopicMeta {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java b/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java
index 7c1d435..755b490 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java
@@ -57,7 +57,6 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Created by qianzhou on 3/3/15.
  */
 public class IIStreamBuilder extends StreamBuilder {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/SliceBuilder.java
----------------------------------------------------------------------
diff --git a/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/SliceBuilder.java b/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/SliceBuilder.java
index 7ca374f..b6769a9 100644
--- a/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/SliceBuilder.java
+++ b/streaming/src/main/java/org/apache/kylin/streaming/invertedindex/SliceBuilder.java
@@ -52,7 +52,6 @@ import javax.annotation.Nullable;
 import java.util.List;
 
 /**
- * Created by qianzhou on 3/27/15.
  */
 public final class SliceBuilder {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java b/streaming/src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java
index 3919335..30b7588 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java
@@ -41,7 +41,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 
 /**
- * Created by qianzhou on 2/16/15.
  */
 public abstract class KafkaBaseTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/KafkaConsumerTest.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/KafkaConsumerTest.java b/streaming/src/test/java/org/apache/kylin/streaming/KafkaConsumerTest.java
index cb32030..c782dae 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/KafkaConsumerTest.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/KafkaConsumerTest.java
@@ -50,7 +50,6 @@ import java.util.concurrent.Executors;
 import static org.junit.Assert.assertTrue;
 
 /**
- * Created by qianzhou on 2/16/15.
  */
 public class KafkaConsumerTest extends KafkaBaseTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/KafkaRequesterTest.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/KafkaRequesterTest.java b/streaming/src/test/java/org/apache/kylin/streaming/KafkaRequesterTest.java
index fb6ed84..9d99825 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/KafkaRequesterTest.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/KafkaRequesterTest.java
@@ -43,7 +43,6 @@ import org.junit.Test;
 import static org.junit.Assert.*;
 
 /**
- * Created by qianzhou on 2/16/15.
  */
 public class KafkaRequesterTest extends KafkaBaseTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/streaming/src/test/java/org/apache/kylin/streaming/OneOffStreamProducer.java
----------------------------------------------------------------------
diff --git a/streaming/src/test/java/org/apache/kylin/streaming/OneOffStreamProducer.java b/streaming/src/test/java/org/apache/kylin/streaming/OneOffStreamProducer.java
index dcd9642..c17a3fc 100644
--- a/streaming/src/test/java/org/apache/kylin/streaming/OneOffStreamProducer.java
+++ b/streaming/src/test/java/org/apache/kylin/streaming/OneOffStreamProducer.java
@@ -53,7 +53,6 @@ import java.io.IOException;
 import java.util.Properties;
 
 /**
- * Created by qianzhou on 2/16/15.
  */
 public class OneOffStreamProducer {
 



[07/52] [abbrv] incubator-kylin git commit: KYLIN-759 split ICachableStorageEngine and IStorageEngine

Posted by ma...@apache.org.
KYLIN-759 split ICachableStorageEngine and IStorageEngine


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

Branch: refs/heads/0.8.0
Commit: ac515a76e83b1da529b3e990f94867994983cc24
Parents: 0e42b2d
Author: honma <ho...@ebay.com>
Authored: Thu May 14 14:39:03 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Thu May 14 20:22:04 2015 +0800

----------------------------------------------------------------------
 .../kylin/storage/ICachableStorageEngine.java   | 30 +++++++++++++++++++-
 .../apache/kylin/storage/IStorageEngine.java    | 21 --------------
 .../kylin/storage/StorageEngineFactory.java     |  6 ++--
 .../AbstractCacheFledgedStorageEngine.java      |  8 ++++--
 .../cache/CacheFledgedDynamicStorageEngine.java | 18 +++---------
 .../cache/CacheFledgedStaticStorageEngine.java  | 22 +++++---------
 .../kylin/storage/cube/CubeStorageEngine.java   | 11 +++++--
 .../kylin/storage/hbase/CubeStorageEngine.java  | 12 ++++++--
 .../hbase/InvertedIndexStorageEngine.java       | 11 +++++--
 .../storage/hybrid/HybridStorageEngine.java     | 11 -------
 .../kylin/storage/test/DynamicCacheTest.java    |  9 ++++--
 .../kylin/storage/test/StaticCacheTest.java     |  9 ++++--
 12 files changed, 90 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
index eadef09..e38350a 100644
--- a/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/ICachableStorageEngine.java
@@ -1,7 +1,35 @@
 package org.apache.kylin.storage;
 
+import com.google.common.collect.Range;
+
 /**
  * Created by Hongbin Ma(Binmahone) on 5/14/15.
  */
-public interface ICachableStorageEngine extends IStorageEngine{
+public interface ICachableStorageEngine extends IStorageEngine {
+    /**
+     *
+     * being dynamic => getVolatilePeriod() return not null
+     * being dynamic => partition column of its realization not null
+     *
+     * @return true for static storage like cubes
+     *          false for dynamic storage like II
+     */
+    boolean isDynamic();
+
+    /**
+     * volatile period is the period of time in which the returned data is not stable
+     * e.g. inverted index's last several minutes' data is dynamic as time goes by.
+     * data in this period cannot be cached
+     *
+     * This method should not be called before ITupleIterator.close() is called
+     *
+     * @return null if the underlying storage guarantees the data is static
+     */
+    Range<Long> getVolatilePeriod();
+
+    /**
+     * get the uuid for the realization assigned to this storage engine
+     * @return
+     */
+    String getStorageUUID();
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
index d6b777a..46a94ca 100644
--- a/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/IStorageEngine.java
@@ -22,8 +22,6 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
 import org.apache.kylin.storage.tuple.TupleInfo;
 
-import com.google.common.collect.Range;
-
 /**
  * 
  * @author xjiang
@@ -33,25 +31,6 @@ public interface IStorageEngine {
 
     ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo);
 
-    /**
-     *
-     * being dynamic => getVolatilePeriod() return not null
-     * being dynamic => partition column of its realization not null
-     *
-     * @return true for static storage like cubes
-     *          false for dynamic storage like II
-     */
-    boolean isDynamic();
 
-    /**
-     * volatile period is the period of time in which the returned data is not stable
-     * e.g. inverted index's last several minutes' data is dynamic as time goes by.
-     * data in this period cannot be cached
-     *
-     * This method should not be called before ITupleIterator.close() is called
-     *
-     * @return null if the underlying storage guarantees the data is static
-     */
-    Range<Long> getVolatilePeriod();
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java b/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
index 29a53fd..0d720ab 100644
--- a/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
+++ b/storage/src/main/java/org/apache/kylin/storage/StorageEngineFactory.java
@@ -45,14 +45,14 @@ public class StorageEngineFactory {
     public static IStorageEngine getStorageEngine(IRealization realization) {
 
         if (realization.getType() == RealizationType.INVERTED_INDEX) {
-            IStorageEngine ret = new InvertedIndexStorageEngine((IIInstance) realization);
+            ICachableStorageEngine ret = new InvertedIndexStorageEngine((IIInstance) realization);
             if (allowStorageLayerCache) {
                 return wrapWithCache(ret, realization);
             } else {
                 return ret;
             }
         } else if (realization.getType() == RealizationType.CUBE) {
-            IStorageEngine ret = new CubeStorageEngine((CubeInstance) realization);
+            ICachableStorageEngine ret = new CubeStorageEngine((CubeInstance) realization);
             if (allowStorageLayerCache) {
                 return wrapWithCache(ret, realization);
             } else {
@@ -63,7 +63,7 @@ public class StorageEngineFactory {
         }
     }
 
-    private static IStorageEngine wrapWithCache(IStorageEngine underlyingStorageEngine, IRealization realization) {
+    private static IStorageEngine wrapWithCache(ICachableStorageEngine underlyingStorageEngine, IRealization realization) {
         if (underlyingStorageEngine.isDynamic()) {
             return new CacheFledgedDynamicStorageEngine(underlyingStorageEngine, getPartitionCol(realization));
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
index d8e2fc0..09f0026 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/AbstractCacheFledgedStorageEngine.java
@@ -8,6 +8,8 @@ import net.sf.ehcache.config.PersistenceConfiguration;
 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
 
 import org.apache.kylin.metadata.realization.StreamSQLDigest;
+import org.apache.kylin.metadata.tuple.TeeTupleItrListener;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.IStorageEngine;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -15,15 +17,15 @@ import org.slf4j.LoggerFactory;
 /**
  * Created by Hongbin Ma(Binmahone) on 5/13/15.
  */
-public abstract class AbstractCacheFledgedStorageEngine {
+public abstract class AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
     private static final Logger logger = LoggerFactory.getLogger(AbstractCacheFledgedStorageEngine.class);
     protected static CacheManager cacheManager = CacheManager.create();
 
-    protected final IStorageEngine underlyingStorage;
+    protected final ICachableStorageEngine underlyingStorage;
     protected StreamSQLDigest streamSQLDigest;
     protected boolean queryCacheExists;
 
-    public AbstractCacheFledgedStorageEngine(IStorageEngine underlyingStorage) {
+    public AbstractCacheFledgedStorageEngine(ICachableStorageEngine underlyingStorage) {
         this.underlyingStorage = underlyingStorage;
         this.queryCacheExists = false;
         this.makeCacheIfNecessary(underlyingStorage.getClass().getName());

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
index 65672ae..0a4fd2a 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedDynamicStorageEngine.java
@@ -12,7 +12,7 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.realization.SQLDigestUtil;
 import org.apache.kylin.metadata.realization.StreamSQLDigest;
 import org.apache.kylin.metadata.tuple.*;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.coprocessor.endpoint.TsConditionExtractor;
 import org.apache.kylin.storage.tuple.TupleInfo;
@@ -24,14 +24,14 @@ import java.util.List;
 /**
  * Created by Hongbin Ma(Binmahone) on 5/11/15.
  */
-public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
+public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorageEngine {
     private static final Logger logger = LoggerFactory.getLogger(CacheFledgedDynamicStorageEngine.class);
 
     private final TblColRef partitionColRef;
 
     private Range<Long> ts;
 
-    public CacheFledgedDynamicStorageEngine(IStorageEngine underlyingStorage, TblColRef partitionColRef) {
+    public CacheFledgedDynamicStorageEngine(ICachableStorageEngine underlyingStorage, TblColRef partitionColRef) {
         super(underlyingStorage);
         this.partitionColRef = partitionColRef;
 
@@ -117,17 +117,7 @@ public class CacheFledgedDynamicStorageEngine extends AbstractCacheFledgedStorag
         }
     }
 
-    @Override
-    public Range<Long> getVolatilePeriod() {
-        return underlyingStorage.getVolatilePeriod();
-    }
-
-    @Override
-    public boolean isDynamic() {
-        return true;
-    }
-
-    @Override
+   @Override
     public void notify(List<ITuple> duplicated) {
         Range<Long> cacheExclude = this.underlyingStorage.getVolatilePeriod();
         if (cacheExclude != null) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
index 860dea2..a309c24 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/CacheFledgedStaticStorageEngine.java
@@ -1,13 +1,15 @@
 package org.apache.kylin.storage.cache;
 
-import com.google.common.collect.Range;
 import com.google.common.collect.Ranges;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.Element;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.realization.StreamSQLDigest;
-import org.apache.kylin.metadata.tuple.*;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.metadata.tuple.ITuple;
+import org.apache.kylin.metadata.tuple.ITupleIterator;
+import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
+import org.apache.kylin.metadata.tuple.TeeTupleIterator;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.tuple.TupleInfo;
 import org.slf4j.Logger;
@@ -18,10 +20,10 @@ import java.util.List;
 /**
  * Created by Hongbin Ma(Binmahone) on 5/11/15.
  */
-public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorageEngine implements IStorageEngine, TeeTupleItrListener {
+public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorageEngine  {
     private static final Logger logger = LoggerFactory.getLogger(CacheFledgedStaticStorageEngine.class);
 
-    public CacheFledgedStaticStorageEngine(IStorageEngine underlyingStorage) {
+    public CacheFledgedStaticStorageEngine(ICachableStorageEngine underlyingStorage) {
         super(underlyingStorage);
     }
 
@@ -62,16 +64,6 @@ public class CacheFledgedStaticStorageEngine extends AbstractCacheFledgedStorage
     }
 
     @Override
-    public Range<Long> getVolatilePeriod() {
-        return underlyingStorage.getVolatilePeriod();
-    }
-
-    @Override
-    public boolean isDynamic() {
-        return false;
-    }
-
-    @Override
     public void notify(List<ITuple> duplicated) {
         StreamSQLResult newCacheEntry = new StreamSQLResult(duplicated, Ranges.<Long> all(), null);
         cacheManager.getCache(this.underlyingStorage.getClass().getName()).put(new Element(streamSQLDigest, newCacheEntry));

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
index a353f49..5fbcf98 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cube/CubeStorageEngine.java
@@ -21,7 +21,7 @@ import org.apache.kylin.metadata.model.SegmentStatusEnum;
 import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.DerivedFilterTranslator;
 import org.apache.kylin.storage.tuple.TupleInfo;
@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
 
 import java.util.*;
 
-public class CubeStorageEngine implements IStorageEngine {
+public class CubeStorageEngine implements ICachableStorageEngine {
 
     private static final Logger logger = LoggerFactory.getLogger(CubeStorageEngine.class);
 
@@ -38,10 +38,12 @@ public class CubeStorageEngine implements IStorageEngine {
 
     private final CubeInstance cubeInstance;
     private final CubeDesc cubeDesc;
+    private final String uuid;
 
     public CubeStorageEngine(CubeInstance cube) {
         this.cubeInstance = cube;
         this.cubeDesc = cube.getDescriptor();
+        this.uuid = cube.getUuid();
     }
 
     @Override
@@ -99,6 +101,11 @@ public class CubeStorageEngine implements IStorageEngine {
     }
 
     @Override
+    public String getStorageUUID() {
+        return this.uuid;
+    }
+
+    @Override
     public boolean isDynamic() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
index 699cc41..94c1dcc 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java
@@ -47,7 +47,7 @@ import org.apache.kylin.metadata.model.SegmentStatusEnum;
 import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.coprocessor.observer.ObserverEnabler;
 import org.apache.kylin.storage.tuple.TupleInfo;
@@ -59,7 +59,7 @@ import java.util.*;
 /**
  * @author xjiang, yangli9
  */
-public class CubeStorageEngine implements IStorageEngine {
+public class CubeStorageEngine implements ICachableStorageEngine {
 
     private static final Logger logger = LoggerFactory.getLogger(CubeStorageEngine.class);
 
@@ -68,10 +68,12 @@ public class CubeStorageEngine implements IStorageEngine {
 
     private final CubeInstance cubeInstance;
     private final CubeDesc cubeDesc;
+    private final String uuid;
 
     public CubeStorageEngine(CubeInstance cube) {
         this.cubeInstance = cube;
         this.cubeDesc = cube.getDescriptor();
+        this.uuid = cube.getUuid();
     }
 
     @Override
@@ -138,6 +140,12 @@ public class CubeStorageEngine implements IStorageEngine {
     }
 
     @Override
+    public String getStorageUUID() {
+        return this.uuid;
+    }
+
+
+    @Override
     public boolean isDynamic() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
index c94222e..de85190 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hbase/InvertedIndexStorageEngine.java
@@ -25,7 +25,7 @@ import org.apache.kylin.invertedindex.IIInstance;
 import org.apache.kylin.invertedindex.IISegment;
 import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.hbase.coprocessor.endpoint.EndpointTupleIterator;
 import org.apache.kylin.storage.tuple.TupleInfo;
@@ -37,15 +37,17 @@ import java.util.ArrayList;
 /**
  * @author yangli9
  */
-public class InvertedIndexStorageEngine implements IStorageEngine {
+public class InvertedIndexStorageEngine implements ICachableStorageEngine {
 
     private static Logger logger = LoggerFactory.getLogger(InvertedIndexStorageEngine.class);
 
     private IISegment seg;
+    private String uuid;
     private EndpointTupleIterator dataIterator;
 
     public InvertedIndexStorageEngine(IIInstance ii) {
         this.seg = ii.getFirstSegment();
+        this.uuid = ii.getUuid();
     }
 
     @Override
@@ -70,6 +72,11 @@ public class InvertedIndexStorageEngine implements IStorageEngine {
     }
 
     @Override
+    public String getStorageUUID() {
+        return this.uuid;
+    }
+
+    @Override
     public boolean isDynamic() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
index f9cea05..b7219b5 100644
--- a/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
+++ b/storage/src/main/java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java
@@ -2,10 +2,8 @@ package org.apache.kylin.storage.hybrid;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Range;
 import com.google.common.collect.Ranges;
 import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.RangeUtil;
 import org.apache.kylin.metadata.MetadataManager;
 import org.apache.kylin.metadata.model.DataModelDesc;
 import org.apache.kylin.metadata.model.TblColRef;
@@ -64,15 +62,6 @@ public class HybridStorageEngine implements IStorageEngine {
         return new CompoundTupleIterator(Lists.newArrayList(historicalDataIterator, realtimeDataIterator));
     }
 
-    @Override
-    public Range<Long> getVolatilePeriod() {
-        return RangeUtil.merge(historicalStorageEngine.getVolatilePeriod(), realtimeStorageEngine.getVolatilePeriod());
-    }
-
-    @Override
-    public boolean isDynamic() {
-        return true;
-    }
 
     private MetadataManager getMetadataManager() {
         return MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java b/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
index 0d962cb..3b587f1 100644
--- a/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/test/DynamicCacheTest.java
@@ -12,7 +12,7 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITuple;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
 import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.cache.CacheFledgedDynamicStorageEngine;
 import org.apache.kylin.storage.hbase.coprocessor.endpoint.TsConditionExtractor;
@@ -88,7 +88,7 @@ public class DynamicCacheTest {
         final AtomicInteger underlyingSEHitCount = new AtomicInteger(0);
         final List<Integer> returnedRowPerSearch = Lists.newArrayList();
 
-        CacheFledgedDynamicStorageEngine dynamicCache = new CacheFledgedDynamicStorageEngine(new IStorageEngine() {
+        CacheFledgedDynamicStorageEngine dynamicCache = new CacheFledgedDynamicStorageEngine(new ICachableStorageEngine() {
             @Override
             public ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo) {
                 Range<Long> tsRagneInQuery = TsConditionExtractor.extractTsCondition(partitionCol, sqlDigest.filter);
@@ -114,6 +114,11 @@ public class DynamicCacheTest {
             public Range<Long> getVolatilePeriod() {
                 return Ranges.greaterThan(DateFormat.stringToMillis("2011-02-01"));
             }
+
+            @Override
+            public String getStorageUUID() {
+                return "111ca32a-a33e-4b69-12aa-0bb8b1f8c191";
+            }
         }, partitionCol);
 
         sqlDigest.filter = StorageMockUtils.buildTs2010Filter(groups.get(0));

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/ac515a76/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java b/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
index 9b69830..0133214 100644
--- a/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/test/StaticCacheTest.java
@@ -10,7 +10,7 @@ import org.apache.kylin.metadata.realization.SQLDigest;
 import org.apache.kylin.metadata.tuple.ITuple;
 import org.apache.kylin.metadata.tuple.ITupleIterator;
 import org.apache.kylin.metadata.tuple.SimpleTupleIterator;
-import org.apache.kylin.storage.IStorageEngine;
+import org.apache.kylin.storage.ICachableStorageEngine;
 import org.apache.kylin.storage.StorageContext;
 import org.apache.kylin.storage.cache.CacheFledgedStaticStorageEngine;
 import org.apache.kylin.storage.tuple.Tuple;
@@ -45,7 +45,7 @@ public class StaticCacheTest {
 
         final AtomicInteger underlyingSEHitCount = new AtomicInteger(0);
 
-        CacheFledgedStaticStorageEngine cacheFledgedStaticStorageEngine = new CacheFledgedStaticStorageEngine(new IStorageEngine() {
+        CacheFledgedStaticStorageEngine cacheFledgedStaticStorageEngine = new CacheFledgedStaticStorageEngine(new ICachableStorageEngine() {
             @Override
             public ITupleIterator search(StorageContext context, SQLDigest sqlDigest, TupleInfo returnTupleInfo) {
                 underlyingSEHitCount.incrementAndGet();
@@ -61,6 +61,11 @@ public class StaticCacheTest {
             public Range<Long> getVolatilePeriod() {
                 return null;
             }
+
+            @Override
+            public String getStorageUUID() {
+                return "111ca32a-a33e-4b69-12aa-0bb8b1f8c092";
+            }
         });
 
         ITupleIterator firstIterator = cacheFledgedStaticStorageEngine.search(context, sqlDigest, tupleInfo);


[05/52] [abbrv] incubator-kylin git commit: KYLIN-759 clean log setttings

Posted by ma...@apache.org.
KYLIN-759 clean log setttings


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

Branch: refs/heads/0.8.0
Commit: 60d94fa55bfed1876dbbecb821aa5323c5cbffb4
Parents: 9179235
Author: honma <ho...@ebay.com>
Authored: Thu May 14 20:17:41 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Thu May 14 20:22:04 2015 +0800

----------------------------------------------------------------------
 .../kylin/storage/cache/StreamSQLResult.java    |  1 -
 .../apache/kylin/storage/cache/EhcacheTest.java | 10 +++-
 streaming/src/test/resources/log4j.xml          | 51 --------------------
 3 files changed, 9 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/60d94fa5/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
----------------------------------------------------------------------
diff --git a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
index 924044b..57dbd67 100644
--- a/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
+++ b/storage/src/main/java/org/apache/kylin/storage/cache/StreamSQLResult.java
@@ -17,7 +17,6 @@ import java.util.NavigableMap;
 
 /**
  */
-
 public class StreamSQLResult {
     private Range<Long> timeCovered;
     private NavigableMap<Long, List<ITuple>> sortedRows;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/60d94fa5/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
----------------------------------------------------------------------
diff --git a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
index fe390de..2751196 100644
--- a/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
+++ b/storage/src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java
@@ -1,5 +1,6 @@
 package org.apache.kylin.storage.cache;
 
+import com.google.common.collect.Lists;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.CacheManager;
 import net.sf.ehcache.Element;
@@ -7,9 +8,10 @@ import net.sf.ehcache.config.CacheConfiguration;
 import net.sf.ehcache.config.Configuration;
 import net.sf.ehcache.config.PersistenceConfiguration;
 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
-
 import org.junit.Test;
 
+import java.util.List;
+
 /**
  */
 public class EhcacheTest {
@@ -36,6 +38,12 @@ public class EhcacheTest {
         System.out.println("runtime used memory: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024 + "M");
         byte[] blob = new byte[(1024 * 40 * 1024)];//400M
 
+        List<String> manyObjects = Lists.newArrayList();
+        for (int i = 0; i < 10000; i++) {
+            manyObjects.add(new String("" + i));
+        }
+        testCache.put(new Element("0", manyObjects));
+
         testCache.put(new Element("1", blob));
         System.out.println(testCache.get("1") == null);
         System.out.println(testCache.getSize());

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/60d94fa5/streaming/src/test/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/streaming/src/test/resources/log4j.xml b/streaming/src/test/resources/log4j.xml
deleted file mode 100644
index a0afa96..0000000
--- a/streaming/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  ~ /*
-  ~
-  ~ * 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.
-  ~
-  ~ */
-  -->
-
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration debug="true"
-                     xmlns:log4j='http://jakarta.apache.org/log4j/'>
-
-    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
-        <layout class="org.apache.log4j.PatternLayout">
-            <param name="ConversionPattern" value="%d{dd MMM yyyy HH:mm:ss} %5p %c{1} - %m%n"/>
-        </layout>
-    </appender>
-
-    <root>
-        <level value="INFO"/>
-        <appender-ref ref="consoleAppender"/>
-    </root>
-
-</log4j:configuration>
\ No newline at end of file


[44/52] [abbrv] incubator-kylin git commit: use modelsManager

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/jobs/job_refresh.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/job_refresh.html b/webapp/app/partials/jobs/job_refresh.html
index 89705e0..6113a12 100644
--- a/webapp/app/partials/jobs/job_refresh.html
+++ b/webapp/app/partials/jobs/job_refresh.html
@@ -24,11 +24,11 @@
         <div ng-if="metaModel.model.partition_desc.partition_date_column" class="row">
             <div class="col-md-2"></div>
             <div class="col-md-8">
-                <div ng-if="!!!(cube.segments) || cube.segments.length == 0">
+                <div ng-if="!!!(cubesManager.currentCube.segments) || cubesManager.currentCube.segments.length == 0">
                     <span class="text-info">No Segment to refresh.</span>
                 </div>
-                <div ng-if="cube.segments.length > 0" class="row">
-                    <table class="table table-striped list" ng-if="(cube.segments|filter: {status: 'NEW'}).length == 0">
+                <div ng-if="cubesManager.currentCube.segments.length > 0" class="row">
+                    <table class="table table-striped list" ng-if="(cubesManager.currentCube.segments|filter: {status: 'NEW'}).length == 0">
                         <tbody>
                         <tr>
                             <td>PARTITION DATE COLUMN</td>
@@ -38,8 +38,8 @@
                             <td>MERGE START SEGMENT</td>
                             <td>
                                 <select ng-model="selectedSegment"
-                                        ng-init="selectedSegment=cube.segments[0];segmentSelected(selectedSegment);"
-                                        ng-options="segment as segment.name for segment in cube.segments"
+                                        ng-init="selectedSegment=cubesManager.currentCube.segments[0];segmentSelected(selectedSegment);"
+                                        ng-options="segment as segment.name for segment in cubesManager.currentCube.segments"
                                         ng-change="segmentSelected(selectedSegment)">
                                 </select>
                             </td>
@@ -70,7 +70,7 @@
                         </tbody>
                     </table>
 
-                    <div ng-if="(cube.segments|filter: {status: 'NEW'}).length > 0">
+                    <div ng-if="(cubesManager.currentCube.segments|filter: {status: 'NEW'}).length > 0">
                         <span class="text-warning">There exists a build request of this cube, the job may be running or error. If you need a new build, please wait for its complete or discard it.</span>
                     </div>
                 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/jobs/job_submit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/job_submit.html b/webapp/app/partials/jobs/job_submit.html
index 7887680..0876ed8 100644
--- a/webapp/app/partials/jobs/job_submit.html
+++ b/webapp/app/partials/jobs/job_submit.html
@@ -19,7 +19,6 @@
 <script type="text/ng-template" id="jobSubmit.html">
     <div class="modal-header">
         <h4 tooltip="submit">CUBE BUILD CONFIRM</h4>
-        <span>{{metaModel.model.partition_desc.partition_date_column}}</span>
     </div>
     <div class="modal-body" style="background-color: white">
         <div ng-if="metaModel.model.partition_desc.partition_date_column" class="row">
@@ -27,7 +26,7 @@
             <div class="col-md-8">
                 <div class="row">
                     <table class="table table-striped list"
-                           ng-if="(cube.segments | filter: {status: 'NEW'}).length == 0">
+                           ng-if="(cubesManager.currentCube.segments | filter: {status: 'NEW'}).length == 0">
                         <tbody>
                         <tr>
                             <td>PARTITION DATE COLUMN</td>
@@ -37,15 +36,15 @@
                             <td>Start Date (Include)</td>
                             <td>
                                 <!--no need convert UTC again-->
-                                <div ng-if="cube.segments.length == 0">
+                                <div ng-if="cubesManager.currentCube.segments.length == 0">
                                     {{jobBuildRequest.startTime =
                                     (!!metaModel.model.partition_desc.partition_date_start)?metaModel.model.partition_desc.partition_date_start:0
                                     | reverseToGMT0 }}
                                 </div>
-                                <div ng-if="cube.segments.length > 0">
+                                <div ng-if="cubesManager.currentCube.segments.length > 0">
                                     <!--no need to convert-->
                                     <div ng-if="metaModel.model.partition_desc.partition_type=='APPEND'">
-                                        {{ jobBuildRequest.startTime = cube.segments[cube.segments.length-1].date_range_end| reverseToGMT0 }}
+                                        {{ jobBuildRequest.startTime = cubesManager.currentCube.segments[cubesManager.currentCube.segments.length-1].date_range_end| reverseToGMT0 }}
                                     </div>
                                     <!--<div ng-if="metaModel.model.partition_desc.cube_partition_type=='UPDATE_INSERT'">-->
                                         <!--&lt;!&ndash;<datepicker ng-model="jobBuildRequest.startTime" show-weeks="true"&ndash;&gt;-->
@@ -68,7 +67,7 @@
                         </tbody>
                     </table>
 
-                    <div ng-if="(cube.segments|filter: {status: 'NEW'}).length > 0">
+                    <div ng-if="(cubesManager.currentCube.segments|filter: {status: 'NEW'}).length > 0">
                         <span class="text-warning">There exists a build request of this cube, the job may be running or error. If you need a new build, please wait for its complete or discard it.</span>
                     </div>
                 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/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 b104309..d066930 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -27,11 +27,11 @@
                 <div class="col-xs-12 col-sm-6">
                     <select class="form-control"
                         ng-if="state.mode=='edit'"
-                        chosen ng-model="model.partition_desc.partition_type"
+                        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'">{{model.partition_desc.partition_type}}</span>
+                    <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.partition_desc.partition_type}}</span>
                 </div>
             </div>
         </div>
@@ -43,16 +43,16 @@
                 <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="model.partition_desc.partition_date_column"
+                            ng-model="modelsManager.selectedModel.partition_desc.partition_date_column"
                             ng-if="state.mode=='edit'"
                             data-placement=""
-                            ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
+                            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>
                     </select>
                     <small class="help-block text-red" ng-show="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</small>
 
                     <span ng-if="state.mode=='view'">
-                        {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
+                        {{!!(modelsManager.selectedModel.partition_desc.partition_date_column)?modelsManager.selectedModel.partition_desc.partition_date_column: ''}}</span>
                 </div>
             </div>
         </div>
@@ -61,14 +61,14 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
-                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null?'has-error':''">
+                <div class="col-xs-12 col-sm-6" ng-class="modelsManager.selectedModel.partition_desc.partition_date_column!=null&& modelsManager.selectedModel.partition_desc.partition_date_start==null?'has-error':''">
                   <!--edit model will convert in MetaModel.converDateToGMT-->
                     <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
-                           ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
+                           ng-model="modelsManager.selectedModel.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
                            placeholder="Click to choose start date..." is-open="opened" />
-                    <small class="help-block" ng-show="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null">Please input start date when partition date column selected.</small>
+                    <small class="help-block" ng-show="modelsManager.selectedModel.partition_desc.partition_date_column!=null&& modelsManager.selectedModel.partition_desc.partition_date_start==null">Please input start date when partition date column selected.</small>
                   <!--vier model will convert use filter-->
-                    <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
+                    <span ng-if="state.mode=='view'&&modelsManager.selectedModel.partition_desc.partition_date_column">{{(modelsManager.selectedModel.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
                 </div>
             </div>
         </div>
@@ -79,11 +79,11 @@
                   <div class="col-xs-12 col-sm-6">
                       <select class="form-control"
                               ng-if="state.mode=='edit'"
-                              chosen ng-model="model.capacity"
+                              chosen ng-model="modelsManager.selectedModel.capacity"
                               ng-options="ddt as ddt for ddt in cubeConfig.cubeCapacities">
                           <option value=""></option>
                       </select>
-                      <span ng-if="state.mode=='view'">{{model.capacity}}</span>
+                      <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.capacity}}</span>
                   </div>
               </div>
           </div>
@@ -103,16 +103,16 @@
                                   style="height:150px"
                                   class="form-control box-default"
                                   placeholder="Please input WHERE clause without typing 'WHERE'"
-                                  ng-model="model.filter_condition">
+                                  ng-model="modelsManager.selectedModel.filter_condition">
                         </textarea>
                     </div>
 
                     <!--view mode-->
                     <div class="form-group row" ng-if="state.mode=='view'"
                          style="font-family:'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro'">
-                        <div ng-if="model.filter_condition" class="col-md-11 col-md-offset-1">
+                        <div ng-if="modelsManager.selectedModel.filter_condition" class="col-md-11 col-md-offset-1">
                             <p style="color: #930f80;"><b>WHERE</b></p>
-                            <span>{{model.filter_condition}}</span>
+                            <span>{{modelsManager.selectedModel.filter_condition}}</span>
                         </div>
                     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/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 5f31201..076bc49 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -27,9 +27,9 @@
             </label>
             <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.innerform.typeahead.$invalid && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$sbumitted)}">
                 <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
-                           title="name" model="model.fact_table" required="true"></typeahead>
+                           title="name" model="modelsManager.selectedModel.fact_table" required="true"></typeahead>
                 <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.$sbumitted)">The fact table is required</small>
-                <span ng-if="state.mode=='view'">{{model.fact_table}}</span>
+                <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.fact_table}}</span>
             </div>
         </div>
     </div>
@@ -38,22 +38,22 @@
     <div class="dataTables_wrapper form-inline no-footer">
         <div class="row">
             <div class="col-xs-6" ng-if="state.mode=='edit'">
-                <button type="button" class="btn btn-primary" ng-disabled="!model.fact_table.length"
+                <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
                 </button>
             </div>
             <div class="col-xs-6" ng-if="state.mode!='edit'">
-                <b>{{model.lookups.length ? 'Lookup Tables' : 'No Lookup Tables'}}</b>
+                <b>{{modelsManager.selectedModel.lookups.length ? 'Lookup Tables' : 'No Lookup 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="model.lookups.length">
+                <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;" ng-if="modelsManager.selectedModel.lookups.length">
                     <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="lookupState.filter"/>
                     <i class="ace-icon fa fa-search nav-search-icon"></i>
                 </span>
             </div>
         </div>
-        <table class="table table-striped table-hover" ng-if="model.lookups.length">
+        <table class="table table-striped table-hover" ng-if="modelsManager.selectedModel.lookups.length">
             <thead>
             <tr>
                 <th>ID</th>
@@ -64,7 +64,7 @@
             </tr>
             </thead>
             <tbody>
-            <tr ng-repeat="lookup in model.lookups | filter:lookupState.filter track by $index">
+            <tr ng-repeat="lookup in modelsManager.selectedModel.lookups | filter:lookupState.filter track by $index">
                 <td>
                     <b>{{$index + 1}}</b>
                 </td>
@@ -80,7 +80,7 @@
                 <td>
                     <ul class="list-unstyled">
                         <li ng-repeat="pk in lookup.join.primary_key track by $index">
-                            <code>{{lookup.table + '.' + pk}} = {{model.fact_table + '.' + lookup.join.foreign_key[$index]}}</code>
+                            <code>{{lookup.table + '.' + pk}} = {{modelsManager.selectedModel.fact_table + '.' + lookup.join.foreign_key[$index]}}</code>
                         </li>
                     </ul>
                 </td>
@@ -147,7 +147,7 @@
                                         <b>=</b>
                                         <select style="width: 45%" chosen data-placeholder="Fact Table Column"
                                                 ng-model="newLookup.join.foreign_key[$index]"
-                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(model.fact_table)" >
+                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(modelsManager.selectedModel.fact_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/incubator-kylin/blob/d9e2d046/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 e7fe07e..e17557a 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -21,7 +21,7 @@
    <ng-form name="forms.model_dimensions_form" novalidate>
     <!-- Dimensions Summary -->
     <div class="dataTables_wrapper form-inline no-footer">
-        <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
+        <div class="row"  ng-if="state.mode=='view'&&modelsManager.selectedModel.dimensions.length > 0">
             <div class="col-xs-6">
                 <b>Dimensions</b>
             </div>
@@ -35,7 +35,7 @@
 
          <!-- VIEW MODE -->
         <div class="row">
-            <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
+            <table class="table table-striped table-hover" ng-if="state.mode=='view'&&modelsManager.selectedModel.dimensions.length > 0">
                 <thead>
                     <tr>
                         <th>ID</th>
@@ -44,7 +44,7 @@
                     </tr>
                 </thead>
                 <tbody class="cube-dimension">
-                    <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                    <tr ng-repeat="dimension in modelsManager.selectedModel.dimensions | filter:dimState.filter track by $index">
                         <!--ID -->
                         <td>
                             <b>{{dimension.id = ($index + 1)}}</b>
@@ -64,7 +64,7 @@
         <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
             <h4 style="margin-left:42px">Dimensions</h4>
             <table style="margin-left:42px; width:92%"
-                   ng-if="model.dimensions.length > 0"
+                   ng-if="modelsManager.selectedModel.dimensions.length > 0"
                    class="table table-hover list">
                 <tr class="row">
                     <th class="col-xs-1">ID</th>
@@ -72,7 +72,7 @@
                     <th class="col-xs-9">Columns</th>
                 </tr>
 
-                <tr ng-repeat="dimension in model.dimensions" class="row">
+                <tr ng-repeat="dimension in modelsManager.selectedModel.dimensions" class="row">
                     <td class="col-xs-1">
                         <!-- ID -->
                         <b>{{($index + 1)}}</b>
@@ -83,7 +83,7 @@
                     <td class="col-xs-9">
                         <!-- Dimensions -->
                         <select ng-if="state.mode=='edit'" style="width: 100%"
-                                ng-model="model.dimensions[$index].columns" chosen multiple
+                                ng-model="modelsManager.selectedModel.dimensions[$index].columns" chosen multiple
                                 ng-change=""
                                 ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
                             <option value=""></option>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index d300806..18fac09 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -32,14 +32,14 @@
 
                         <!-- edit -->
                         <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
-                               ng-model="model.name" required
+                               ng-model="modelsManager.selectedModel.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
                         <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is required.</small>
                         <small class="help-block" ng-show="!forms.model_info_form.model_name.$error.required&&forms.model_info_form.model_name.$invalid && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is invalid.</small>
 
 
-                        <span ng-if="state.mode=='view'">{{model.name}}</span>
+                        <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.name}}</span>
                     </div>
                 </div>
             </div>
@@ -52,8 +52,8 @@
                     </label>
                     <div class="col-xs-12 col-sm-6">
                         <textarea ng-if="state.mode=='edit'" class="form-control box-default"
-                                  name="comment" id="comment" ng-model="model.description"></textarea>
-                        <span ng-if="state.mode=='view'">{{model.description}}</span>
+                                  name="comment" id="comment" ng-model="modelsManager.selectedModel.description"></textarea>
+                        <span ng-if="state.mode=='view'">{{modelsManager.selectedModel.description}}</span>
                     </div>
                 </div>
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/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 f324788..039132d 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -20,7 +20,7 @@
 <ng-form name="forms.model_measure_form" novalidate>
 <div class="dataTables_wrapper form-inline no-footer">
 
-    <table ng-if="state.mode=='view'&&model.metrics.length > 0" class="table table-striped table-hover">
+    <table ng-if="state.mode=='view'&&modelsManager.selectedModel.metrics.length > 0" class="table table-striped table-hover">
         <thead>
             <tr>
                 <th>ID</th>
@@ -28,7 +28,7 @@
             </tr>
         </thead>
         <tbody>
-            <tr ng-repeat="measure in model.metrics track by $index">
+            <tr ng-repeat="measure in modelsManager.selectedModel.metrics track by $index">
                 <td>
                     <!--ID -->
                     <b>{{$index + 1}}</b>
@@ -43,9 +43,9 @@
     <div  ng-if="state.mode=='edit'" class="form-group" style="width: 100%">
         <h3 class="box-title">Select your measures</h3>
         <select style="width: 100%"
-                ng-model="model.metrics"  chosen multiple
+                ng-model="modelsManager.selectedModel.metrics"  chosen multiple
                 ng-change=""
-                ng-options="measure.name as measure.name for measure in getColumnsByTable(model.fact_table)">
+                ng-options="measure.name as measure.name for measure in getColumnsByTable(modelsManager.selectedModel.fact_table)">
             <option value=""></option>
         </select>
     </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/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 dd8b23c..7752ba6 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -18,46 +18,46 @@
 
 <!--show detail when exist models-->
 <div ng-controller="CubeModelCtrl" class="nav-tabs-custom" style="margin-top:40px;">
-    <ul ng-show="model.name" class="nav nav-tabs">
-        <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
-            <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
+    <ul ng-show="modelsManager.selectedModel.name" class="nav nav-tabs">
+        <li class="{{(!modelsManager.selectedModel.visiblePage || modelsManager.selectedModel.visiblePage=='metadata')? 'active':''}}">
+            <a href="" ng-click="modelsManager.selectedModel.visiblePage='metadata'">Grid</a>
         </li>
-        <li class="{{model.visiblePage=='graph'? 'active':''}}">
-            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);$event.stopPropagation();">Visualization</a>
+        <li class="{{modelsManager.selectedModel.visiblePage=='graph'? 'active':''}}">
+            <a href="" ng-click="modelsManager.selectedModel.visiblePage='graph';buildGraph(modelsManager.selectedModel);$event.stopPropagation();">Visualization</a>
         </li>
-        <li class="{{model.visiblePage=='json_model'? 'active':''}}"
-            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
-            <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
+        <li class="{{modelsManager.selectedModel.visiblePage=='json_model'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(modelsManager.selectedModel, 16) && !newAccess">
+            <a href="" ng-click="modelsManager.selectedModel.visiblePage='json_model';">JSON</a>
         </li>
-        <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+        <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(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <a href="models/edit/{{model.name}}" data-widget="collapse">Edit</a>
+                <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(model)">Drop</a>
+                    <a ng-click="dropModel(modelsManager.selectedModel)">Drop</a>
                 </li>
                 <li role="presentation" class="divider"></li>
-                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <a href="cubes/add/{{model.name}}" data-widget="collapse">Create Cube</a>
+                <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="!model.visiblePage || model.visiblePage=='metadata'">
+    <div class="model-detail" ng-if="!modelsManager.selectedModel.visiblePage || modelsManager.selectedModel.visiblePage=='metadata'">
         <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
-             ng-init="state={mode:'view', modelName:model.name}">
+             ng-init="state={mode:'view', modelName:modelsManager.selectedModel.name}">
         </div>
     </div>
-    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="model-detail model_graph">
+    <div ng-show="modelsManager.selectedModel.visiblePage=='graph'" id="model_graph_{{modelsManager.selectedModel.name}}" class="model-detail model_graph">
     </div>
-    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
+    <div ng-show="modelsManager.selectedModel.visiblePage=='json_model'" class="model-detail">
           <pre ng-if="!state.jsonEdit"
-               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>
+               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(modelsManager.selectedModel), true)}}</pre>
     </div>
 
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index b94cecb..c7da5f2 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -17,13 +17,11 @@
 -->
 
 <!--hide when view model and no model selected-->
-<div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
+<div class="box box-primary model-design box-2px" ng-init="model" ng-hide="state.mode=='view'&&!modelsManager.selectedModel.name">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
     </div>
     <div class="box-body">
-            <!-- Add a mock button to avoid auto submit-->
-            <button ng-click="" ng-show="false"></button>
             <div>
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
@@ -66,7 +64,7 @@
 </div>
 
 <!--show create model tip when no models list-->
-<div ng-show="state.mode=='view'&&!models_treedata.length" style="margin-top:40px;">
+<div ng-show="state.mode=='view'&&!modelsManager.modelTreeData.length" style="margin-top:40px;">
     <div class="box box-primary">
         <div class="box-header with-border">
             <i class="fa fa-bullhorn"></i>
@@ -81,7 +79,7 @@
 </div>
 
 <!--show select model tip when models not empty and no model selected-->
-<div ng-show="state.mode=='view'&&!!models_treedata.length&&!model.name" style="margin-top:40px;">
+<div ng-show="state.mode=='view'&&!!modelsManager.modelTreeData.length&&!modelsManager.selectedModel.name" style="margin-top:40px;">
     <div class="box box-primary">
         <div class="box-header with-border">
             <i class="fa fa-bullhorn"></i>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 2d3e79f..dbcda0a 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -40,10 +40,10 @@
             </tab>
         </tabset>
     </div>
-    <div  ng-if="showModels&&!cubeSelected"  class="col-xs-9 models-main">
+    <div  ng-if="showModels&&!modelsManager.cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/models/model_detail.html'"></div>
     </div>
-    <div  ng-if="showModels&&cubeSelected"  class="col-xs-9 models-main">
+    <div  ng-if="showModels&&modelsManager.cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/cubes/cube_detail.html'"></div>
     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/d9e2d046/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 4ed21f6..21128ce 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -33,7 +33,7 @@
     <!--tree-->
     <div style="width:100%; height:{{window}}px; overflow:auto;">
         <abn-tree
-                tree-data         = "models_treedata"
+                tree-data         = "modelsManager.modelTreeData"
                 tree-control      = "my_tree"
                 icon-leaf         = "fa fa-cubes"
                 icon-expand       = "fa fa-star"
@@ -41,6 +41,6 @@
                 expand-level      = "2"
                 initial-selection = "">
             </abn-tree>
-        <div no-result ng-if="models_treedata.length==0"></div>
+        <div no-result ng-if="modelsManager.modelTreeData.length==0"></div>
     </div>
 </div>


[18/52] [abbrv] incubator-kylin git commit: show models list page

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/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
new file mode 100644
index 0000000..9067807
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -0,0 +1,354 @@
+<!--
+* 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.
+-->
+
+<div ng-controller="ModelDimensionsCtrl">
+
+<!-- Dimensions Summary -->
+<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">
+                    <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="!model.fact_table.length"
+                    ng-click="openAutoGenModal()">
+                <i class="fa fa-building-o"></i> Auto Generator
+            </button>
+        </div>
+        <div class="col-xs-6" ng-if="state.mode!='edit'">
+            <b>Dimensions</b>
+        </div>
+        <div class="col-xs-6">
+            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                <i class="ace-icon fa fa-search nav-search-icon"></i>
+            </span>
+        </div>
+    </div>
+    <table class="table table-striped table-hover" ng-if="model.dimensions.length > 0">
+        <thead>
+            <tr>
+                <th>ID</th>
+                <th>Name</th>
+                <th>Table Name</th>
+                <th>Type</th>
+                <th></th>
+                <th ng-if="state.mode=='edit'">Actions</th>
+            </tr>
+        </thead>
+        <tbody class="cube-dimension">
+            <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                <!--ID -->
+                <td>
+                    <b>{{dimension.id = ($index + 1)}}</b>
+                </td>
+                <!--Name -->
+                <td>
+                    <span>{{dimension.name}}</span>
+                </td>
+                <!--Table Name -->
+                <td>
+                    <span tooltip="{{dimension.table == model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                </td>
+                <!--Type-->
+                <td>
+                    <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+                </td>
+                <!--Columns-->
+                <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>
+                        </div>
+                    </div>
+                </td>
+                <td ng-if="state.mode=='edit'">
+                    <!--edit button-->
+                    <button class="btn btn-xs btn-info"
+                            ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
+                    </button>
+                    <!-- remove button-->
+                    <button class="btn btn-xs btn-danger"
+                            ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+                    </button>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+<div class="space-16"></div>
+<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
+    <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
+    <div class="row" ng-repeat="c in dimConflicts">
+        <div class="col-xs-3">
+            <code>{{c.table}}.{{c.column}}</code>
+        </div>
+        <div class="col-xs-3">
+            <ul class="list-unstyled">
+                <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+<!-- Edit Dimension Form -->
+<script type="text/ng-template" id="addEditDimension.html">
+    <div class="modal-header">
+        <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
+            <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
+        </h4>
+    </div>
+    <div class="modal-body">
+        <ng-form name="edit_dim_form">
+        <div class="row">
+            <div class="col-xs-8">
+                <!--Name-->
+                <div class="form-group">
+                    <div class="row">
+                        <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                        <div class="col-xs-12 col-sm-6">
+                            <input type="text" placeholder="Name.." class="form-control" name="dim_name"
+                                   tooltip="dimension name.." tooltip-trigger="focus"
+                                   ng-model="newDimension.name" required />
+                        </div>
+                        <div class="col-xs-12 col-sm-3">
+                            <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
+                                The Dimension Name is required.
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Table Name: derived dimension only allows lookup tables-->
+                <div class="form-group">
+                    <div class="row">
+                        <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)">
+                                <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">
+                                <option value=""></option>
+                            </select>
+                        </div>
+                        <div class="col-xs-12 col-sm-3">
+                            <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
+                                Derived dimension only comes from lookup table.
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Normal Dimension: choose one column-->
+                <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
+                    <div class="row">
+                        <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[0]" ng-options="column.name as column.name for column in getColumnsByTable(newDimension.table)">
+                                <option value=""></option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Hierarchy Dimension-->
+                <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
+                    <div class="row">
+                        <div class="col-sm-6 col-sm-offset-3">
+                            <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
+                                 ng-model="newDimension.column" class="hierarchy-container">
+                                <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
+                                    <div class="row">
+                                        <div class="col-xs-2">
+                                            <span class="badge">{{$index + 1}}</span>
+                                        </div>
+                                        <div class="col-xs-8">
+                                            <select chosen style="width: 100%"
+                                                    data-placeholder="Dimension Hierarchy Column"
+                                                    ng-model="newDimension.column[$index]"
+                                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(newDimension.table)" >
+                                                <option value="">-- Select Column --</option>
+                                            </select>
+                                        </div>
+                                        <div class="col-xs-2">
+                                            <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                    ng-click="newDimension.column.splice($index, 1);">
+                                                <i class="fa fa-trash-o"></i>
+                                            </button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+
+                            <div class="space-8"></div>
+
+                            <div class="row">
+                                <div class="col-xs-4">
+                                    <button class="btn btn-xs btn-info"
+                                            ng-click="newDimension.column.push('');">
+                                        <i class="fa fa-plus"></i> New Hierarchy</button>
+                                </div>
+                                <div class="col-xs-8">
+                                    <p class="help-block">Drag level into the order you prefer.</p>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <!--Derived Dimension-->
+                <div ng-if="dimType.indexOf('derived') >= 0">
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col-sm-6 col-sm-offset-3">
+                                <div ng-repeat="derived in newDimension.derived track by $index">
+                                    <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 getColumnsByTable(newDimension.table)" >
+                                            <option value=""></option>
+                                        </select>
+                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                ng-click="newDimension.derived.splice($index, 1);">
+                                            <i class="fa fa-trash-o"></i>
+                                        </button>
+                                        <div class="space-4"></div>
+                                    </div>
+                                </div>
+                                <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
+                                    <i class="fa fa-plus"></i> New Derived</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Tips</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>Type in any input box for auto suggestion</li>
+                                    <li>Pick up Fact Table from Star Schema Tables first</li>
+                                    <li>Data Type should match with Hive Table's Data Type</li>
+                                    <li>Join Type have to be same as will be used in query</li>
+                                    <li>Using Hierarchy to inherit one dimension another</li>
+                                    <li>Using Derived for One-One relationship between columns, like ID and Name</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        </ng-form>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
+        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+    </div>
+</script>
+
+
+<script type="text/ng-template" id="autoGenDimension.html">
+    <div class="modal-header">
+        <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
+    </div>
+    <div class="modal-body">
+        <div class="row">
+            <div class="col-xs-8">
+                <div class="box box-solid">
+                    <div class="box-header"><h4>Columns</h4></div>
+                    <div class="box-body">
+                        <ul class="list-unstyled columns-region">
+                            <li ng-repeat="table in availableTables track by $index">
+                                <h5 class="table-name-underline">
+                                    <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
+                                </h5>
+                                <ul class="list-unstyled">
+                                    <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
+                                        <label>
+                                            <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
+                                                   ng-disabled="selectedColumns[table][col.name].disabled">
+                                            {{col.name}}
+                                        </label>
+                                    </li>
+                                </ul>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Auto Generate Rules</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>Column is disabled once there is already a dimension referred this column.</li>
+                                    <li>In fact table: one normal dimension will be auto generated per column.</li>
+                                    <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
+        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+    </div>
+</script>
+
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/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
new file mode 100644
index 0000000..88b7baf
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -0,0 +1,185 @@
+<!--
+* 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.
+-->
+
+<!-- Measures Summary -->
+<div class="dataTables_wrapper form-inline no-footer" ng-if="model.metrics.length > 0">
+    <div class="row">
+        <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
+            <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
+            <i class="ace-icon fa fa-search nav-search-icon"></i>
+        </span>
+    </div>
+    <table class="table table-striped table-hover">
+        <thead>
+            <tr>
+                <th>ID</th>
+                <th>Column</th>
+                <th ng-if="state.mode=='edit'">Actions</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr ng-repeat="measure in model.metrics track by $index">
+                <td>
+                    <!--ID -->
+                    <b>{{$index + 1}}</b>
+                </td>
+                <td>
+                    <!--Name -->
+                    <span tooltip="measure name..">{{measure}}</span>
+                </td>
+                <td ng-if="state.mode=='edit'">
+                    <!--Edit Button -->
+                    <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
+                        <i class="fa fa-pencil"></i>
+                    </button>
+                    <!--Remove Button -->
+                    <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
+                        <i class="fa fa-trash-o"></i>
+                    </button>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+<!--Add Measures Button-->
+<div class="form-group">
+    <button class="btn btn-sm btn-info" ng-click="addNewMeasure()" ng-show="state.mode=='edit' && !newMeasure">
+        <i class="fa fa-plus"></i> Measure
+    </button>
+</div>
+
+<!--Edit Measure-->
+<ng-form name="edit_mes_form">
+<div class="box box-solid" ng-if="newMeasure">
+    <div class="box-header">
+        <h4 class="box-title text-info">Edit Measure</h4>
+    </div>
+    <div class="box-body">
+        <div class="row">
+            <div class="col-xs-8">
+                    <!--Name-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <input type="text" placeholder="Name.." class="form-control"
+                                    tooltip="measure name.." tooltip-trigger="focus"
+                                    ng-model="newMeasure.name" required />
+                            </div>
+                        </div>
+                    </div>
+                    <!--Expression-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Expression</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control"
+                                    ng-init="newMeasure.function.expression = (!!newMeasure.function.expression)?newMeasure.function.expression:cubeConfig.dftSelections.measureExpression" chosen ng-model="newMeasure.function.expression" required
+                                    ng-change="measureReturnTypeUpdate();"
+                                    ng-options="me as me for me in cubeConfig.measureExpressions">
+                                    <option value=""></option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Param Type-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Type</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control" ng-if="newMeasure.function.expression != 'COUNT'"
+                                    ng-init="newMeasure.function.parameter.type=(!!newMeasure.function.parameter.type)?newMeasure.function.parameter.type: 'column' "
+                                    chosen ng-model="newMeasure.function.parameter.type" required
+                                    ng-options="mpt as mpt for mpt in cubeConfig.measureParamType">
+                                    <option value=""></option>
+                                </select>
+                                <span class="font-color-default"
+                                       ng-if="newMeasure.function.expression == 'COUNT'"
+                                       ng-init="newMeasure.function.parameter.type= 'constant' "><b>&nbsp;&nbsp;constant</b>
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Param Value-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Param Value</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <span class="font-color-default"
+                                    ng-if="newMeasure.function.parameter.type == 'constant'"
+                                    ng-init="newMeasure.function.parameter.value = 1"><b>&nbsp;&nbsp;1</b></span>
+                                <select class="form-control" chosen
+                                    ng-if="newMeasure.function.parameter.type == 'column'"
+                                    ng-model="newMeasure.function.parameter.value"
+                                    ng-change="measureReturnTypeUpdate();"
+                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
+                                    <option value="">-- Select a Fact Table Column --</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                    <!--Return Type-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Return Type</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control"
+                                    ng-if="newMeasure.function.expression == 'COUNT_DISTINCT'"
+                                    ng-init="newMeasure.function.returntype = (!!newMeasure.function.returntype)?newMeasure.function.returntype:cubeConfig.dftSelections.distinctDataType.value"
+                                    chosen ng-model="newMeasure.function.returntype" required
+                                    ng-options="ddt.value as ddt.name for ddt in cubeConfig.distinctDataTypes">
+                                    <option value=""></option>
+                                </select>
+                                <span class="font-color-default"
+                                      ng-if="newMeasure.function.expression != 'COUNT_DISTINCT'"
+                                     ><b>&nbsp;&nbsp;{{newMeasure.function.returntype | uppercase}}</b>
+                                </span>
+                            </div>
+                        </div>
+                    </div>
+            </div>
+
+            <!--Tips-->
+            <div class="col-xs-4">
+                <div class="box box-solid">
+                    <div class="box-header">
+                        <h4 class="box-title">Tips</h4>
+                    </div>
+                    <div class="box-body">
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <ol class="text-info">
+                                    <li>All cubes have to contain one measure for Count(1), suggest use "_Count_" as name (Has been generated automatically)</li>
+                                    <li>Only accept single column in param value with "Column" type</li>
+                                    <li>Distinct Count is approximate, please indicate Error Rate, higher accuracy degree accompanied with larger storage size and longer build time</li>
+                                </ol>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="box-footer">
+        <button class="btn btn-sm btn-info" ng-disabled="edit_mes_form.$invalid"
+                ng-click="saveNewMeasure()" ng-show="state.mode=='edit'">OK</button>
+        <button class="btn btn-link" ng-click="clearNewMeasure()">Cancel</button>
+    </div>
+</div>
+</ng-form>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/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
new file mode 100644
index 0000000..96a64c0
--- /dev/null
+++ b/webapp/app/partials/models/model_detail.html
@@ -0,0 +1,43 @@
+<!--
+* 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.
+-->
+
+<div ng-controller="CubeModelCtrl" class="nav-tabs-custom">
+    <ul class="nav nav-tabs">
+        <li class="{{(!model.visiblePage || model.visiblePage=='metadata')? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='metadata'">Grid</a>
+        </li>
+        <li class="{{model.visiblePage=='graph'? 'active':''}}">
+            <a href="" ng-click="model.visiblePage='graph';buildGraph(model);">Visualization</a>
+        </li>
+        <li class="{{model.visiblePage=='json_model'? 'active':''}}"
+            ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, 16) && !newAccess">
+            <a href="" ng-click="model.visiblePage='json_model';">JSON</a>
+        </li>
+    </ul>
+
+    <div class="model-detail" ng-if="!model.visiblePage || model.visiblePage=='metadata'">
+        <div ng-include="'partials/models/model_schema.html'" ng-controller="ModelSchemaCtrl"
+             ng-init="state={mode:'view', modelName:model.name}"></div>
+    </div>
+    <div ng-show="model.visiblePage=='json_model'" class="model-detail">
+          <pre
+               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>
+    </div>
+    <div ng-show="model.visiblePage=='graph'" id="model_graph_{{model.name}}" class="cube-detail cube_graph">
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/model_edit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_edit.html b/webapp/app/partials/models/model_edit.html
new file mode 100644
index 0000000..07c3913
--- /dev/null
+++ b/webapp/app/partials/models/model_edit.html
@@ -0,0 +1,34 @@
+<!--
+* 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.
+-->
+
+<div class="row">
+    <div class="col-xs-3">
+        <div ng-include src="'partials/tables/source_table_tree.html'" ng-controller="SourceMetaCtrl"></div>
+    </div>
+    <div class="col-xs-9">
+        <form role="form" name="cube_form" novalidate>
+            <!-- This margin in order to align with table tree in left part -->
+            <div style="margin-top: 20px;">
+                <div ng-include="'partials/cubes/cube_schema.html'" ng-controller="CubeSchemaCtrl"
+                     ng-init="state={mode:'edit', cubeName: routeParams.cubeName}">
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
new file mode 100644
index 0000000..ab9564a
--- /dev/null
+++ b/webapp/app/partials/models/model_schema.html
@@ -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.
+-->
+
+<div class="box box-primary">
+    <div class="box-header widget-header-blue widget-header-flat">
+        <h4 class="box-title text-info">Cube Designer</h4>
+    </div>
+    <div class="box-body">
+        <ng-form name="design_form" ng-submit="">
+            <!-- Add a mock button to avoid auto submit-->
+            <button ng-click="" ng-show="false"></button>
+            <div>
+                <ul class="wizard-steps">
+                    <li ng-repeat="step in wizardSteps"
+                        class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
+                        <span style="cursor:pointer;" ng-click="goToStep($index)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span class="title">{{step.title}}</span>
+                     </li>
+                </ul>
+            </div>
+            <hr/>
+            <div class="step-content pos-rel" id="step-container">
+                <div ng-include src="curStep.src"></div>
+            </div>
+            <hr/>
+            <div class="wizard-actions">
+                <div class="row">
+                    <div class="col-xs-8">
+                        <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
+                        <div>
+                            <a href="cubes" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Cubes</a>
+                        </div>
+                    </div>
+                    <div class="col-xs-4">
+                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Cube Info'">
+                            <i class="ace-icon fa fa-arrow-left"></i>
+                            Prev
+                        </button>
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
+                                ng-show="curStep.title!='Overview'">
+                            Next
+                            <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
+                        </button>
+                        <button class="btn btn-primary" ng-click="prepareCube();saveCube(design_form)" ng-disabled="design_form.$invalid"
+                                ng-if="curStep.title=='Overview' && state.mode=='edit'">
+                            Save
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </ng-form>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
new file mode 100644
index 0000000..85f7cad
--- /dev/null
+++ b/webapp/app/partials/models/models.html
@@ -0,0 +1,117 @@
+<!--
+* 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.
+-->
+
+<div class="page-header row">
+    <!--Project-->
+    <div class="col-xs-3">
+        <form ng-if="userService.isAuthorized()">
+            <div class="form-group">
+                <!--Project-->
+                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
+                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
+                    <i class="fa fa-plus"></i>
+                </a>
+            </div>
+        </form>
+    </div>
+    <!--Model Name-->
+    <div class="col-xs-3">
+        <form ng-submit="" style="display: inline" >
+            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
+                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
+                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
+            </span>
+        </form>
+    </div>
+    <div class="pull-right">
+        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
+    </div>
+</div>
+<div ng-if="!loading && modelList.models.length == 0">
+    <div no-result text="No Model."></div>
+</div>
+<loading ng-if="loading" text="Loading Models..."></loading>
+
+<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
+    <div class="row">
+        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
+    </div>
+    <table class="table table-striped table-bordered table-hover dataTable no-footer">
+        <!--Header-->
+        <thead>
+        <tr style="cursor: pointer">
+            <th ng-repeat="theaditem in modelConfig.theaditems"
+                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
+                {{theaditem.name}}
+                <i ng-if="state.reverseColumn!= theaditem.attr"
+                   class="fa fa-unsorted"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
+                   class="fa fa-sort-asc"></i>
+                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
+                   class="fa fa-sort-desc"></i>
+            </th>
+            <th>Actions</th>
+        </tr>
+        </thead>
+        <!--Body-->
+        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
+        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
+            <td>
+                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
+                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
+                {{ model.name}}
+            </td>
+            <td>
+                    {{ model.fact_table}}
+            </td>
+            <td>
+                    {{ model.last_modified | utcToConfigTimeZone}}
+            </td>
+            <td>
+                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
+                            data-toggle="dropdown" ng-click="listAccess(model, 'ModelInstance')">
+                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                    </button>
+                    <ul class="dropdown-menu" role="menu">
+                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
+                        <li ng-if="userService.hasRole('ROLE_ADMIN')">
+                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
+
+                    </ul>
+                </div>
+                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
+                    N/A
+                </span>
+            </td>
+        </tr>
+        <tr ng-show="model.showDetail">
+            <td colspan="9" style="padding: 10px 30px 10px 30px;">
+                <div ng-include src="'partials/models/model_detail.html'"></div>
+            </td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+
+<div class="row">
+    <div class="col-xs-12">
+        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 8a72f09..0b4af3f 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -103,5 +103,13 @@
             "controller": "LoginCtrl",
             "reloadOnSearch": false
         }
+    },
+    {
+        "url": "/models",
+        "params": {
+            "templateUrl": "partials/models/models.html",
+            "tab": "models",
+            "controller": "ModelsCtrl"
+        }
     }
 ]
\ No newline at end of file



[47/52] [abbrv] incubator-kylin git commit: KYLIN-667

Posted by ma...@apache.org.
KYLIN-667


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

Branch: refs/heads/0.8.0
Commit: 2dda4e1d5e3cba9139b92996e43c20da7ae71feb
Parents: a35133a
Author: jiazhong <ji...@ebay.com>
Authored: Fri Apr 10 14:46:55 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:39:11 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/query.js | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2dda4e1d/webapp/app/js/controllers/query.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/query.js b/webapp/app/js/controllers/query.js
index 4cf699f..16dffe3 100644
--- a/webapp/app/js/controllers/query.js
+++ b/webapp/app/js/controllers/query.js
@@ -354,8 +354,11 @@ KylinApp
 
         $scope.refreshCurQuery = function () {
             $scope.curQuery = this.query;
-
-        }
+            $scope.curQuery.result = {
+                isResponsePartial: false
+            };
+            $scope.query($scope.curQuery);
+        };
 
         $scope.showSavePanel = function () {
             $modal.open({


[21/52] [abbrv] incubator-kylin git commit: set tree.js for model instead cube

Posted by ma...@apache.org.
set tree.js for model  instead cube


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

Branch: refs/heads/0.8.0
Commit: afac4513f0ce58a713edf53e31aa9744a0322347
Parents: e6b0715
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 17 17:53:04 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:50 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/services/tree.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/afac4513/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index d6f346f..4b1ef2d 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('CubeGraphService', function () {
+KylinApp.service('GraphService', function () {
 
     var margin = {top: 20, right: 100, bottom: 20, left: 100},
         width = 1100 - margin.right - margin.left,


[11/52] [abbrv] incubator-kylin git commit: KYLIN-766 fix test case after-effects of BigDecimalSerializer truncating

Posted by ma...@apache.org.
KYLIN-766 fix test case after-effects of BigDecimalSerializer truncating


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

Branch: refs/heads/0.8.0
Commit: 4b5083454e9475657fc2532a1261fa861ab653df
Parents: 4cf65f0
Author: honma <ho...@ebay.com>
Authored: Fri May 15 11:13:57 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:14:04 2015 +0800

----------------------------------------------------------------------
 .../kylin/cube/kv/RowValueDecoderTest.java      | 29 +++++++++++++++-----
 .../metadata/measure/MeasureCodecTest.java      | 20 +++++++-------
 2 files changed, 32 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4b508345/cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
----------------------------------------------------------------------
diff --git a/cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java b/cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
index 3b1954b..369e6f6 100644
--- a/cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
+++ b/cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
@@ -18,12 +18,6 @@
 
 package org.apache.kylin.cube.kv;
 
-import static org.junit.Assert.*;
-
-import java.math.BigDecimal;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
 import org.apache.hadoop.io.LongWritable;
 import org.apache.kylin.common.util.LocalFileMetadataTestCase;
 import org.apache.kylin.cube.CubeManager;
@@ -37,6 +31,12 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+
 /**
  * @author George Song (ysong1)
  * 
@@ -80,7 +80,22 @@ public class RowValueDecoderTest extends LocalFileMetadataTestCase {
 
         rowValueDecoder.decode(valueBytes);
         Object[] measureValues = rowValueDecoder.getValues();
-        assertEquals("[333.1234567, 333.1111111, 333.1999999, 2]", Arrays.toString(measureValues));
+        //BigDecimal.ROUND_HALF_EVEN in BigDecimalSerializer
+        assertEquals("[333.1235, 333.1111, 333.2000, 2]", Arrays.toString(measureValues));
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testError() throws Exception {
+        CubeDesc cubeDesc = CubeManager.getInstance(getTestConfig()).getCube("test_kylin_cube_with_slr_ready").getDescriptor();
+        HBaseColumnDesc hbaseCol = cubeDesc.getHBaseMapping().getColumnFamily()[0].getColumns()[0];
+
+        MeasureCodec codec = new MeasureCodec(hbaseCol.getMeasures());
+        BigDecimal sum = new BigDecimal("11111111111111111111333.1234567");
+        BigDecimal min = new BigDecimal("333.1111111");
+        BigDecimal max = new BigDecimal("333.1999999");
+        LongWritable count = new LongWritable(2);
+        ByteBuffer buf = ByteBuffer.allocate(RowConstants.ROWVALUE_BUFFER_SIZE);
+        codec.encode(new Object[] { sum, min, max, count }, buf);
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/4b508345/cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
----------------------------------------------------------------------
diff --git a/cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java b/cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
index ddb624e..7243289 100644
--- a/cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
+++ b/cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
@@ -18,20 +18,19 @@
 
 package org.apache.kylin.metadata.measure;
 
-import static org.junit.Assert.*;
-
-import java.math.BigDecimal;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
 import org.apache.hadoop.io.DoubleWritable;
 import org.apache.hadoop.io.LongWritable;
-import org.junit.Test;
-
 import org.apache.kylin.common.hll.HyperLogLogPlusCounter;
 import org.apache.kylin.cube.kv.RowConstants;
-import org.apache.kylin.metadata.model.MeasureDesc;
 import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertTrue;
 
 /**
  * @author yangli9
@@ -46,7 +45,7 @@ public class MeasureCodecTest {
 
         DoubleWritable d = new DoubleWritable(1.0);
         LongWritable l = new LongWritable(2);
-        BigDecimal b = new BigDecimal("333.1234567");
+        BigDecimal b = new BigDecimal("333.1234");
         HyperLogLogPlusCounter hllc = new HyperLogLogPlusCounter(16);
         hllc.add("1234567");
         hllc.add("abcdefg");
@@ -62,6 +61,7 @@ public class MeasureCodecTest {
         System.out.println("size: " + buf.limit());
 
         Object copy[] = new Object[values.length];
+
         codec.decode(buf, copy);
 
         assertTrue(Arrays.equals(values, copy));


[03/52] [abbrv] incubator-kylin git commit: KYLIN-763 remove author information

Posted by ma...@apache.org.
KYLIN-763 remove author information


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

Branch: refs/heads/0.8.0
Commit: fc056fda2a276daebad9795ab3d557f225803b0c
Parents: 12bbce6
Author: qianhao.zhou <qi...@ebay.com>
Authored: Wed May 13 16:36:37 2015 +0800
Committer: qianhao.zhou <qi...@ebay.com>
Committed: Wed May 13 16:36:46 2015 +0800

----------------------------------------------------------------------
 common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java  | 1 -
 common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java | 1 -
 .../kylin/common/restclient/CaseInsensitiveStringCache.java       | 1 -
 .../org/apache/kylin/common/util/CaseInsensitiveStringMap.java    | 1 -
 .../main/java/org/apache/kylin/common/util/CompressionUtils.java  | 1 -
 .../src/main/java/org/apache/kylin/common/util/FIFOIterable.java  | 1 -
 .../src/main/java/org/apache/kylin/common/util/FIFOIterator.java  | 1 -
 .../main/java/org/apache/kylin/common/util/LogTitlePrinter.java   | 1 -
 .../src/main/java/org/apache/kylin/common/util/PartialSorter.java | 1 -
 common/src/main/java/org/apache/kylin/common/util/RangeUtil.java  | 1 -
 common/src/main/java/org/apache/kylin/common/util/SortUtil.java   | 1 -
 common/src/main/java/org/apache/kylin/common/util/SoutLogger.java | 1 -
 common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java | 1 -
 common/src/main/java/org/apache/kylin/common/util/TimeUtil.java   | 1 -
 common/src/test/java/org/apache/kylin/common/util/BasicTest.java  | 1 -
 .../src/test/java/org/apache/kylin/common/util/HbaseImporter.java | 1 -
 .../org/apache/kylin/common/util/InstallJarIntoMavenTest.java     | 1 -
 .../test/java/org/apache/kylin/common/util/PartialSorterTest.java | 1 -
 common/src/test/java/org/apache/kylin/common/util/RangeTest.java  | 1 -
 .../src/test/java/org/apache/kylin/common/util/RangeUtilTest.java | 1 -
 .../src/test/java/org/apache/kylin/common/util/TimeUtilTest.java  | 1 -
 .../main/java/org/apache/kylin/cube/CubeCapabilityChecker.java    | 1 -
 .../src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java | 1 -
 cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java    | 1 -
 .../src/main/java/org/apache/kylin/dict/DictionarySerializer.java | 1 -
 .../src/main/java/org/apache/kylin/dict/IDictionaryAware.java     | 3 +--
 .../src/main/java/org/apache/kylin/dict/TimeStrDictionary.java    | 1 -
 .../test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java   | 1 -
 .../test/java/org/apache/kylin/dict/lookup/LookupTableTest.java   | 1 -
 .../java/org/apache/kylin/invertedindex/IICapabilityChecker.java  | 1 -
 .../org/apache/kylin/invertedindex/index/BatchSliceMaker.java     | 1 -
 .../java/org/apache/kylin/invertedindex/index/RawTableRecord.java | 1 -
 .../apache/kylin/invertedindex/index/TableRecordInfoDigest.java   | 1 -
 .../apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java   | 1 -
 .../kylin/invertedindex/model/IIKeyValueCodecWithState.java       | 1 -
 .../src/main/java/org/apache/kylin/invertedindex/model/IIRow.java | 1 -
 .../java/org/apache/kylin/invertedindex/model/KeyValueCodec.java  | 1 -
 .../org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java  | 1 -
 .../kylin/invertedindex/invertedindex/IIDescManagerTest.java      | 1 -
 .../org/apache/kylin/invertedindex/invertedindex/IIDescTest.java  | 1 -
 .../apache/kylin/invertedindex/invertedindex/IIInstanceTest.java  | 1 -
 .../org/apache/kylin/invertedindex/invertedindex/LZFTest.java     | 1 -
 job/src/main/java/org/apache/kylin/job/Scheduler.java             | 1 -
 job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java | 1 -
 .../java/org/apache/kylin/job/common/HadoopShellExecutable.java   | 1 -
 job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java  | 1 -
 .../java/org/apache/kylin/job/common/MapReduceExecutable.java     | 1 -
 .../main/java/org/apache/kylin/job/common/ShellExecutable.java    | 1 -
 .../java/org/apache/kylin/job/constant/ExecutableConstants.java   | 1 -
 job/src/main/java/org/apache/kylin/job/cube/CubingJob.java        | 1 -
 job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java | 1 -
 .../org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java   | 1 -
 .../org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java   | 1 -
 job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java     | 1 -
 .../main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java    | 1 -
 job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java      | 1 -
 .../org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java    | 1 -
 .../java/org/apache/kylin/job/exception/ExecuteException.java     | 1 -
 .../apache/kylin/job/exception/IllegalStateTranferException.java  | 1 -
 .../main/java/org/apache/kylin/job/exception/LockException.java   | 1 -
 .../java/org/apache/kylin/job/exception/PersistentException.java  | 1 -
 .../java/org/apache/kylin/job/exception/SchedulerException.java   | 1 -
 .../java/org/apache/kylin/job/execution/AbstractExecutable.java   | 1 -
 .../java/org/apache/kylin/job/execution/ChainedExecutable.java    | 1 -
 .../org/apache/kylin/job/execution/DefaultChainedExecutable.java  | 1 -
 .../main/java/org/apache/kylin/job/execution/DefaultOutput.java   | 1 -
 job/src/main/java/org/apache/kylin/job/execution/Executable.java  | 1 -
 .../java/org/apache/kylin/job/execution/ExecutableContext.java    | 1 -
 .../main/java/org/apache/kylin/job/execution/ExecutableState.java | 1 -
 .../main/java/org/apache/kylin/job/execution/ExecuteResult.java   | 1 -
 job/src/main/java/org/apache/kylin/job/execution/Idempotent.java  | 1 -
 job/src/main/java/org/apache/kylin/job/execution/Output.java      | 1 -
 .../org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java    | 1 -
 .../kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java      | 1 -
 .../java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java  | 1 -
 .../java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java | 1 -
 .../org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java     | 1 -
 .../org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java    | 1 -
 .../apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java  | 1 -
 .../apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java   | 1 -
 .../java/org/apache/kylin/job/impl/threadpool/DefaultContext.java | 1 -
 .../org/apache/kylin/job/impl/threadpool/DefaultScheduler.java    | 1 -
 job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java   | 1 -
 .../java/org/apache/kylin/job/invertedindex/IIJobBuilder.java     | 1 -
 .../main/java/org/apache/kylin/job/manager/ExecutableManager.java | 1 -
 .../main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java | 1 -
 .../java/org/apache/kylin/job/streaming/StreamingBootstrap.java   | 1 -
 .../main/java/org/apache/kylin/job/streaming/StreamingCLI.java    | 1 -
 job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java  | 1 -
 .../main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java    | 1 -
 .../main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java  | 1 -
 .../main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java | 1 -
 .../java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java   | 1 -
 .../java/org/apache/kylin/job/tools/LZOSupportnessChecker.java    | 1 -
 job/src/test/java/org/apache/kylin/job/BaseTestExecutable.java    | 1 -
 .../test/java/org/apache/kylin/job/BuildCubeWithStreamTest.java   | 1 -
 job/src/test/java/org/apache/kylin/job/BuildIIWithStreamTest.java | 1 -
 job/src/test/java/org/apache/kylin/job/DataGenTest.java           | 1 -
 job/src/test/java/org/apache/kylin/job/ErrorTestExecutable.java   | 1 -
 job/src/test/java/org/apache/kylin/job/FailedTestExecutable.java  | 1 -
 job/src/test/java/org/apache/kylin/job/IIStreamBuilderTest.java   | 1 -
 job/src/test/java/org/apache/kylin/job/SelfStopExecutable.java    | 1 -
 job/src/test/java/org/apache/kylin/job/SucceedTestExecutable.java | 1 -
 job/src/test/java/org/apache/kylin/job/dataGen/ColumnConfig.java  | 1 -
 .../java/org/apache/kylin/job/dataGen/FactTableGenerator.java     | 1 -
 job/src/test/java/org/apache/kylin/job/dataGen/GenConfig.java     | 1 -
 .../java/org/apache/kylin/job/dataGen/StreamingDataGenerator.java | 1 -
 .../java/org/apache/kylin/job/hadoop/cubev2/CubeSamplingTest.java | 1 -
 .../java/org/apache/kylin/job/hadoop/hbase/TestHbaseClient.java   | 1 -
 .../test/java/org/apache/kylin/job/hadoop/hdfs/HdfsOpsTest.java   | 1 -
 .../java/org/apache/kylin/job/hadoop/invertedindex/IITest.java    | 1 -
 .../org/apache/kylin/job/impl/threadpool/BaseSchedulerTest.java   | 1 -
 .../apache/kylin/job/impl/threadpool/DefaultSchedulerTest.java    | 1 -
 .../java/org/apache/kylin/job/manager/ExecutableManagerTest.java  | 1 -
 .../test/java/org/apache/kylin/job/tools/HBaseRowDigestTest.java  | 1 -
 .../org/apache/kylin/metadata/filter/DateConditionModifier.java   | 1 -
 .../java/org/apache/kylin/metadata/filter/TsConditionEraser.java  | 1 -
 .../org/apache/kylin/metadata/measure/fixedlen/FixedHLLCodec.java | 1 -
 .../main/java/org/apache/kylin/metadata/model/DimensionDesc.java  | 1 -
 .../org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java     | 1 -
 .../org/apache/kylin/metadata/model/IntermediateColumnDesc.java   | 1 -
 .../java/org/apache/kylin/metadata/project/RealizationEntry.java  | 1 -
 .../apache/kylin/metadata/realization/IRealizationConstants.java  | 1 -
 .../apache/kylin/metadata/realization/RealizationRegistry.java    | 1 -
 .../org/apache/kylin/metadata/realization/RealizationType.java    | 1 -
 .../java/org/apache/kylin/metadata/realization/SQLDigest.java     | 1 -
 .../java/org/apache/kylin/metadata/realization/SQLDigestUtil.java | 1 -
 .../org/apache/kylin/metadata/realization/StreamSQLDigest.java    | 1 -
 .../org/apache/kylin/metadata/tuple/CompoundTupleIterator.java    | 1 -
 .../java/org/apache/kylin/metadata/tuple/SimpleTupleIterator.java | 1 -
 .../java/org/apache/kylin/metadata/tuple/TeeTupleIterator.java    | 1 -
 .../kylin/metadata/measure/fixedlen/FixedPointLongCodecTest.java  | 1 -
 .../test/java/org/apache/kylin/metadata/model/TableDescTest.java  | 1 -
 .../src/main/java/org/apache/kylin/query/routing/RoutingRule.java | 1 -
 .../routing/RoutingRules/AdjustForWeaklyMatchedRealization.java   | 1 -
 .../kylin/query/routing/RoutingRules/RealizationPriorityRule.java | 1 -
 .../kylin/query/routing/RoutingRules/RealizationSortRule.java     | 1 -
 .../routing/RoutingRules/RemoveUncapableRealizationsRule.java     | 1 -
 .../test/java/org/apache/kylin/query/test/CombinationTest.java    | 1 -
 query/src/test/java/org/apache/kylin/query/test/IIQueryTest.java  | 1 -
 .../src/test/java/org/apache/kylin/query/test/KylinTestBase.java  | 1 -
 .../java/org/apache/kylin/query/test/RealizationRegistryTest.java | 1 -
 server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java  | 1 -
 .../main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java | 1 -
 server/src/main/java/org/apache/kylin/rest/model/TableMeta.java   | 1 -
 .../java/org/apache/kylin/rest/request/CreateProjectRequest.java  | 1 -
 .../src/main/java/org/apache/kylin/rest/request/MetaRequest.java  | 1 -
 .../java/org/apache/kylin/rest/request/UpdateProjectRequest.java  | 1 -
 .../src/main/java/org/apache/kylin/rest/service/CacheService.java | 1 -
 server/src/test/java/org/apache/kylin/jdbc/JDBCDriverTest.java    | 1 -
 .../apache/kylin/rest/broadcaster/BroadcasterReceiveServlet.java  | 1 -
 .../org/apache/kylin/rest/controller/ProjectControllerTest.java   | 1 -
 .../test/java/org/apache/kylin/rest/service/CacheServiceTest.java | 1 -
 .../org/apache/kylin/storage/cache/CacheFledgedStorageEngine.java | 1 -
 .../java/org/apache/kylin/storage/cache/StorageLayerCache.java    | 1 -
 .../main/java/org/apache/kylin/storage/cache/StreamSQLResult.java | 1 -
 .../main/java/org/apache/kylin/storage/cube/CubeCodeSystem.java   | 1 -
 .../java/org/apache/kylin/storage/gridtable/GTComboStore.java     | 1 -
 .../src/main/java/org/apache/kylin/storage/gridtable/ScanKey.java | 1 -
 .../org/apache/kylin/storage/gridtable/diskstore/FileSystem.java  | 1 -
 .../org/apache/kylin/storage/gridtable/diskstore/GTDiskStore.java | 1 -
 .../kylin/storage/gridtable/diskstore/HadoopFileSystem.java       | 1 -
 .../apache/kylin/storage/gridtable/diskstore/LocalFileSystem.java | 1 -
 .../java/org/apache/kylin/storage/hbase/coprocessor/AggrKey.java  | 1 -
 .../apache/kylin/storage/hbase/coprocessor/AggregationCache.java  | 1 -
 .../kylin/storage/hbase/coprocessor/CoprocessorConstants.java     | 1 -
 .../apache/kylin/storage/hbase/coprocessor/FilterDecorator.java   | 1 -
 .../storage/hbase/coprocessor/endpoint/ClearTextDictionary.java   | 1 -
 .../hbase/coprocessor/endpoint/EndpointAggregationCache.java      | 1 -
 .../storage/hbase/coprocessor/endpoint/EndpointTupleIterator.java | 1 -
 .../storage/hbase/coprocessor/endpoint/HbaseServerKVIterator.java | 1 -
 .../kylin/storage/hbase/coprocessor/endpoint/IIEndpoint.java      | 1 -
 .../storage/hbase/coprocessor/endpoint/IIResponseAdapter.java     | 1 -
 .../kylin/storage/hbase/coprocessor/endpoint/LocalDictionary.java | 1 -
 .../storage/hbase/coprocessor/endpoint/SliceBitMapProvider.java   | 1 -
 .../storage/hbase/coprocessor/endpoint/TsConditionExtractor.java  | 1 -
 .../main/java/org/apache/kylin/storage/hybrid/HybridInstance.java | 1 -
 .../main/java/org/apache/kylin/storage/hybrid/HybridManager.java  | 1 -
 .../java/org/apache/kylin/storage/hybrid/HybridStorageEngine.java | 1 -
 .../src/main/java/org/apache/kylin/storage/util/SizeOfUtil.java   | 1 -
 .../src/test/java/org/apache/kylin/storage/cache/EhcacheTest.java | 1 -
 .../apache/kylin/storage/filter/DateConditionModifierTest.java    | 1 -
 .../org/apache/kylin/storage/filter/TsConditionEraserTest.java    | 1 -
 .../hbase/coprocessor/endpoint/EndpointAggregationTest.java       | 1 -
 .../storage/hbase/coprocessor/endpoint/TableRecordInfoTest.java   | 1 -
 .../hbase/coprocessor/endpoint/TsConditionExtractorTest.java      | 1 -
 .../java/org/apache/kylin/storage/hybrid/HybridManagerTest.java   | 1 -
 .../src/main/java/org/apache/kylin/streaming/BrokerConfig.java    | 1 -
 .../main/java/org/apache/kylin/streaming/JsonStreamParser.java    | 1 -
 .../src/main/java/org/apache/kylin/streaming/KafkaConfig.java     | 1 -
 .../src/main/java/org/apache/kylin/streaming/KafkaConsumer.java   | 1 -
 .../src/main/java/org/apache/kylin/streaming/KafkaRequester.java  | 1 -
 .../src/main/java/org/apache/kylin/streaming/StreamBuilder.java   | 1 -
 .../src/main/java/org/apache/kylin/streaming/StreamMessage.java   | 1 -
 .../src/main/java/org/apache/kylin/streaming/StreamParser.java    | 1 -
 .../main/java/org/apache/kylin/streaming/StreamingManager.java    | 1 -
 .../main/java/org/apache/kylin/streaming/StringStreamParser.java  | 1 -
 streaming/src/main/java/org/apache/kylin/streaming/TopicMeta.java | 1 -
 .../org/apache/kylin/streaming/invertedindex/IIStreamBuilder.java | 1 -
 .../org/apache/kylin/streaming/invertedindex/SliceBuilder.java    | 1 -
 .../src/test/java/org/apache/kylin/streaming/KafkaBaseTest.java   | 1 -
 .../test/java/org/apache/kylin/streaming/KafkaConsumerTest.java   | 1 -
 .../test/java/org/apache/kylin/streaming/KafkaRequesterTest.java  | 1 -
 .../java/org/apache/kylin/streaming/OneOffStreamProducer.java     | 1 -
 .../java/org/apache/kylin/streaming/StreamingManagerTest.java     | 1 -
 .../kylin/streaming/invertedindex/PrintOutStreamBuilder.java      | 1 -
 206 files changed, 1 insertion(+), 207 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java b/common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java
index a070c56..a933782 100644
--- a/common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java
+++ b/common/src/main/java/org/apache/kylin/common/mr/KylinMapper.java
@@ -24,7 +24,6 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.mapreduce.Mapper;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/19/15.
  */
 public class KylinMapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> extends Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
     protected void bindCurrentConfiguration(Configuration conf) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java b/common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java
index aba411d..bc63df7 100644
--- a/common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java
+++ b/common/src/main/java/org/apache/kylin/common/mr/KylinReducer.java
@@ -23,7 +23,6 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.mapreduce.Reducer;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/19/15.
  */
 public class KylinReducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT> extends Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
     protected void bindCurrentConfiguration(Configuration conf) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/restclient/CaseInsensitiveStringCache.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/restclient/CaseInsensitiveStringCache.java b/common/src/main/java/org/apache/kylin/common/restclient/CaseInsensitiveStringCache.java
index 14bc517..ceefc08 100644
--- a/common/src/main/java/org/apache/kylin/common/restclient/CaseInsensitiveStringCache.java
+++ b/common/src/main/java/org/apache/kylin/common/restclient/CaseInsensitiveStringCache.java
@@ -21,7 +21,6 @@ package org.apache.kylin.common.restclient;
 import java.util.concurrent.ConcurrentSkipListMap;
 
 /**
- * Created by qianzhou on 1/15/15.
  */
 public class CaseInsensitiveStringCache<V> extends SingleValueCache<String, V>{
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/CaseInsensitiveStringMap.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/CaseInsensitiveStringMap.java b/common/src/main/java/org/apache/kylin/common/util/CaseInsensitiveStringMap.java
index ee64d51..d6de581 100644
--- a/common/src/main/java/org/apache/kylin/common/util/CaseInsensitiveStringMap.java
+++ b/common/src/main/java/org/apache/kylin/common/util/CaseInsensitiveStringMap.java
@@ -24,7 +24,6 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * Created by qianzhou on 12/3/14.
  */
 public class CaseInsensitiveStringMap<T> implements Map<String, T> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/CompressionUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/CompressionUtils.java b/common/src/main/java/org/apache/kylin/common/util/CompressionUtils.java
index c6b0088..6dda7ec 100644
--- a/common/src/main/java/org/apache/kylin/common/util/CompressionUtils.java
+++ b/common/src/main/java/org/apache/kylin/common/util/CompressionUtils.java
@@ -9,7 +9,6 @@ import java.util.zip.Inflater;
 import org.slf4j.LoggerFactory;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/24/15.
  */
 public class CompressionUtils {
     private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CompressionUtils.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/FIFOIterable.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/FIFOIterable.java b/common/src/main/java/org/apache/kylin/common/util/FIFOIterable.java
index c0f7d68..4c4bc6b 100644
--- a/common/src/main/java/org/apache/kylin/common/util/FIFOIterable.java
+++ b/common/src/main/java/org/apache/kylin/common/util/FIFOIterable.java
@@ -4,7 +4,6 @@ import java.util.Iterator;
 import java.util.Queue;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/27/15.
  */
 public class FIFOIterable<T> implements Iterable<T> {
     private Queue<T> q;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/FIFOIterator.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/FIFOIterator.java b/common/src/main/java/org/apache/kylin/common/util/FIFOIterator.java
index 6751cb0..f734143 100644
--- a/common/src/main/java/org/apache/kylin/common/util/FIFOIterator.java
+++ b/common/src/main/java/org/apache/kylin/common/util/FIFOIterator.java
@@ -4,7 +4,6 @@ import java.util.Iterator;
 import java.util.Queue;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/27/15.
  *
  * Normal iterators in Collections are fail-safe,
  * i.e. adding elements to a queue will break current iterator.

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/LogTitlePrinter.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/LogTitlePrinter.java b/common/src/main/java/org/apache/kylin/common/util/LogTitlePrinter.java
index ffbc7c8..f7d3a16 100644
--- a/common/src/main/java/org/apache/kylin/common/util/LogTitlePrinter.java
+++ b/common/src/main/java/org/apache/kylin/common/util/LogTitlePrinter.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.common.util;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/27/15.
  */
 public class LogTitlePrinter {
     public static void printTitle(String title) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/PartialSorter.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/PartialSorter.java b/common/src/main/java/org/apache/kylin/common/util/PartialSorter.java
index 6d0723c..f73f525 100644
--- a/common/src/main/java/org/apache/kylin/common/util/PartialSorter.java
+++ b/common/src/main/java/org/apache/kylin/common/util/PartialSorter.java
@@ -25,7 +25,6 @@ import java.util.Comparator;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  *
  * This utility class sorts only the specified part of a list
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java b/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
index d781e17..33d6770 100644
--- a/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/RangeUtil.java
@@ -7,7 +7,6 @@ import java.util.NavigableMap;
 import com.google.common.collect.*;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/14/15.
  */
 public class RangeUtil {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/SortUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/SortUtil.java b/common/src/main/java/org/apache/kylin/common/util/SortUtil.java
index ac9f216..f0d7cdb 100644
--- a/common/src/main/java/org/apache/kylin/common/util/SortUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/SortUtil.java
@@ -6,7 +6,6 @@ import com.google.common.collect.TreeMultimap;
 import java.util.Iterator;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/5/15.
  */
 public class SortUtil {
     public static <T extends Comparable, E extends Comparable> Iterator<T> extractAndSort(Iterator<T> input, Function<T, E> extractor) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/SoutLogger.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/SoutLogger.java b/common/src/main/java/org/apache/kylin/common/util/SoutLogger.java
index 3bd9090..cfbfe5c 100644
--- a/common/src/main/java/org/apache/kylin/common/util/SoutLogger.java
+++ b/common/src/main/java/org/apache/kylin/common/util/SoutLogger.java
@@ -1,7 +1,6 @@
 package org.apache.kylin.common.util;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/6/15.
  */
 public class SoutLogger implements Logger {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java b/common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java
index 2c19665..c493424 100644
--- a/common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/ThreadUtil.java
@@ -25,7 +25,6 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/31/14.
  */
 public class ThreadUtil {
     @SuppressWarnings("unused")

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/main/java/org/apache/kylin/common/util/TimeUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/TimeUtil.java b/common/src/main/java/org/apache/kylin/common/util/TimeUtil.java
index 01fc2c1..26e3e06 100644
--- a/common/src/main/java/org/apache/kylin/common/util/TimeUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/TimeUtil.java
@@ -1,7 +1,6 @@
 package org.apache.kylin.common.util;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/4/15.
  */
 public class TimeUtil {
     private static int ONE_MINUTE_TS = 60 * 1000;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
index c259507..2f4943d 100644
--- a/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/BasicTest.java
@@ -33,7 +33,6 @@ import java.util.ArrayList;
 import java.util.Calendar;
 
 /**
-* Created by honma on 10/17/14.
 * <p/>
 * Keep this test case to test basic java functionality
 * development concept proving use

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/HbaseImporter.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/HbaseImporter.java b/common/src/test/java/org/apache/kylin/common/util/HbaseImporter.java
index e1bac24..242fa57 100644
--- a/common/src/test/java/org/apache/kylin/common/util/HbaseImporter.java
+++ b/common/src/test/java/org/apache/kylin/common/util/HbaseImporter.java
@@ -18,7 +18,6 @@ import org.apache.kylin.common.persistence.HBaseConnection;
 import com.google.common.base.Preconditions;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/6/15.
  */
 public class HbaseImporter {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/InstallJarIntoMavenTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/InstallJarIntoMavenTest.java b/common/src/test/java/org/apache/kylin/common/util/InstallJarIntoMavenTest.java
index 3ee1dd8..6dcdaf5 100644
--- a/common/src/test/java/org/apache/kylin/common/util/InstallJarIntoMavenTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/InstallJarIntoMavenTest.java
@@ -27,7 +27,6 @@ import java.util.regex.Pattern;
 import org.junit.Ignore;
 
 /**
- * Created by honma on 6/6/14.
  */
 public class InstallJarIntoMavenTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/PartialSorterTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/PartialSorterTest.java b/common/src/test/java/org/apache/kylin/common/util/PartialSorterTest.java
index 728186b..e24e7f8 100644
--- a/common/src/test/java/org/apache/kylin/common/util/PartialSorterTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/PartialSorterTest.java
@@ -25,7 +25,6 @@ import java.util.Comparator;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/5/15.
  */
 public class PartialSorterTest {
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/RangeTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/RangeTest.java b/common/src/test/java/org/apache/kylin/common/util/RangeTest.java
index 62d7b63..2a9ce40 100644
--- a/common/src/test/java/org/apache/kylin/common/util/RangeTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/RangeTest.java
@@ -8,7 +8,6 @@ import com.google.common.collect.Range;
 import com.google.common.collect.Ranges;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/14/15.
  */
 public class RangeTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/RangeUtilTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/RangeUtilTest.java b/common/src/test/java/org/apache/kylin/common/util/RangeUtilTest.java
index 1bd8403..84688aa 100644
--- a/common/src/test/java/org/apache/kylin/common/util/RangeUtilTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/RangeUtilTest.java
@@ -9,7 +9,6 @@ import java.util.NavigableMap;
 import java.util.TreeMap;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 4/20/15.
  */
 public class RangeUtilTest {
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/common/src/test/java/org/apache/kylin/common/util/TimeUtilTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/kylin/common/util/TimeUtilTest.java b/common/src/test/java/org/apache/kylin/common/util/TimeUtilTest.java
index 1442412..90a0c40 100644
--- a/common/src/test/java/org/apache/kylin/common/util/TimeUtilTest.java
+++ b/common/src/test/java/org/apache/kylin/common/util/TimeUtilTest.java
@@ -8,7 +8,6 @@ import org.junit.Assert;
 import org.junit.Test;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/4/15.
  */
 public class TimeUtilTest {
     public static long normalizeTime(long timeMillis, NormalizeUnit unit) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java b/cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
index ab585c3..52a57b0 100644
--- a/cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
+++ b/cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
@@ -33,7 +33,6 @@ import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.realization.SQLDigest;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/8/15.
  */
 public class CubeCapabilityChecker {
     private static final Logger logger = LoggerFactory.getLogger(CubeCapabilityChecker.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/cube/src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java b/cube/src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java
index dcdcfd5..f028c33 100644
--- a/cube/src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java
+++ b/cube/src/main/java/org/apache/kylin/cube/CubeDimensionDeriver.java
@@ -24,7 +24,6 @@ import java.util.Collection;
 import java.util.HashSet;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/8/15.
  *
  * the unified logic for defining a sql's dimension
  */

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java b/cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java
index 0cb77df..973998f 100644
--- a/cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java
+++ b/cube/src/main/java/org/apache/kylin/cube/model/RowKeyDesc.java
@@ -35,7 +35,6 @@ import org.apache.kylin.common.util.StringUtil;
 import org.apache.kylin.metadata.model.TblColRef;
 
 /**
- * Created by lukhan on 1/2/14.
  */
 @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
 public class RowKeyDesc {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/dictionary/src/main/java/org/apache/kylin/dict/DictionarySerializer.java
----------------------------------------------------------------------
diff --git a/dictionary/src/main/java/org/apache/kylin/dict/DictionarySerializer.java b/dictionary/src/main/java/org/apache/kylin/dict/DictionarySerializer.java
index 4b61591..a8ad2fa 100644
--- a/dictionary/src/main/java/org/apache/kylin/dict/DictionarySerializer.java
+++ b/dictionary/src/main/java/org/apache/kylin/dict/DictionarySerializer.java
@@ -6,7 +6,6 @@ import org.apache.kylin.common.util.ClassUtil;
 import java.io.*;
 
 /**
- * Created by qianzhou on 5/5/15.
  */
 public final class DictionarySerializer {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/dictionary/src/main/java/org/apache/kylin/dict/IDictionaryAware.java
----------------------------------------------------------------------
diff --git a/dictionary/src/main/java/org/apache/kylin/dict/IDictionaryAware.java b/dictionary/src/main/java/org/apache/kylin/dict/IDictionaryAware.java
index 8f3473a..1c7a009 100644
--- a/dictionary/src/main/java/org/apache/kylin/dict/IDictionaryAware.java
+++ b/dictionary/src/main/java/org/apache/kylin/dict/IDictionaryAware.java
@@ -21,8 +21,7 @@ package org.apache.kylin.dict;
 import org.apache.kylin.metadata.model.TblColRef;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/17/14.
- * 
+ *
  * Class that implement this interface has the ability to help dictionary encoding and decoding
  */
 public interface IDictionaryAware {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/dictionary/src/main/java/org/apache/kylin/dict/TimeStrDictionary.java
----------------------------------------------------------------------
diff --git a/dictionary/src/main/java/org/apache/kylin/dict/TimeStrDictionary.java b/dictionary/src/main/java/org/apache/kylin/dict/TimeStrDictionary.java
index aef26ec..fde17a8 100644
--- a/dictionary/src/main/java/org/apache/kylin/dict/TimeStrDictionary.java
+++ b/dictionary/src/main/java/org/apache/kylin/dict/TimeStrDictionary.java
@@ -5,7 +5,6 @@ import org.apache.kylin.common.util.DateFormat;
 import java.io.*;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/6/15.
  */
 public class TimeStrDictionary extends Dictionary<String> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/dictionary/src/test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java
----------------------------------------------------------------------
diff --git a/dictionary/src/test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java b/dictionary/src/test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java
index e723126..92f62fb 100644
--- a/dictionary/src/test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java
+++ b/dictionary/src/test/java/org/apache/kylin/dict/TimeStrDictionaryTests.java
@@ -8,7 +8,6 @@ import org.junit.Test;
 import java.util.Date;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/6/15.
  */
 public class TimeStrDictionaryTests {
     TimeStrDictionary dict;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/dictionary/src/test/java/org/apache/kylin/dict/lookup/LookupTableTest.java
----------------------------------------------------------------------
diff --git a/dictionary/src/test/java/org/apache/kylin/dict/lookup/LookupTableTest.java b/dictionary/src/test/java/org/apache/kylin/dict/lookup/LookupTableTest.java
index 138ae33..bb4a717 100644
--- a/dictionary/src/test/java/org/apache/kylin/dict/lookup/LookupTableTest.java
+++ b/dictionary/src/test/java/org/apache/kylin/dict/lookup/LookupTableTest.java
@@ -34,7 +34,6 @@ import java.util.List;
 import java.util.Set;
 
 /**
- * Created by shaoshi on 2/3/15.
  */
 public class LookupTableTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/IICapabilityChecker.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IICapabilityChecker.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IICapabilityChecker.java
index 5acba07..ca51492 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/IICapabilityChecker.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/IICapabilityChecker.java
@@ -31,7 +31,6 @@ import java.util.Collection;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 1/8/15.
  */
 public class IICapabilityChecker {
     private static final Logger logger = LoggerFactory.getLogger(IICapabilityChecker.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/BatchSliceMaker.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/BatchSliceMaker.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/BatchSliceMaker.java
index 2c3e593..0682d2b 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/BatchSliceMaker.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/BatchSliceMaker.java
@@ -41,7 +41,6 @@ import org.apache.kylin.invertedindex.model.IIDesc;
 import java.util.List;
 
 /**
- * Created by qianzhou on 3/20/15.
  */
 public class BatchSliceMaker {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/RawTableRecord.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/RawTableRecord.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/RawTableRecord.java
index 55104b5..b72ad26 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/RawTableRecord.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/RawTableRecord.java
@@ -28,7 +28,6 @@ import org.apache.hadoop.io.LongWritable;
 import java.util.Arrays;
 
 /**
- * Created by honma on 11/10/14.
  */
 public class RawTableRecord implements Cloneable {
     TableRecordInfoDigest digest;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/TableRecordInfoDigest.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/TableRecordInfoDigest.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/TableRecordInfoDigest.java
index d67c807..65b2a21 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/TableRecordInfoDigest.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/index/TableRecordInfoDigest.java
@@ -29,7 +29,6 @@ import java.nio.ByteBuffer;
 import java.util.Arrays;
 
 /**
- * Created by honma on 11/10/14.
  */
 public class TableRecordInfoDigest {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java
index 14934dc..b01ffa7 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIJoinedFlatTableDesc.java
@@ -28,7 +28,6 @@ import org.apache.kylin.metadata.model.TblColRef;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/30/14.
  */
 public class IIJoinedFlatTableDesc implements IJoinedFlatTableDesc {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIKeyValueCodecWithState.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIKeyValueCodecWithState.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIKeyValueCodecWithState.java
index f3431df..c6ceea9 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIKeyValueCodecWithState.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIKeyValueCodecWithState.java
@@ -12,7 +12,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/26/15.
  */
 public class IIKeyValueCodecWithState extends IIKeyValueCodec {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIRow.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIRow.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIRow.java
index 273d1e6..bf4880d 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIRow.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/IIRow.java
@@ -43,7 +43,6 @@ import org.apache.kylin.common.util.BytesUtil;
 import java.util.List;
 
 /**
- * Created by qianzhou on 3/10/15.
  */
 public final class IIRow {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/KeyValueCodec.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/KeyValueCodec.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/KeyValueCodec.java
index bbd8d61..c151beb 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/KeyValueCodec.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/model/KeyValueCodec.java
@@ -39,7 +39,6 @@ import org.apache.kylin.invertedindex.index.Slice;
 import java.util.Collection;
 
 /**
- * Created by qianzhou on 3/12/15.
  */
 public interface KeyValueCodec {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/main/java/org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/main/java/org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java b/invertedindex/src/main/java/org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java
index 45e8058..24bd0de 100644
--- a/invertedindex/src/main/java/org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java
+++ b/invertedindex/src/main/java/org/apache/kylin/invertedindex/util/IIDictionaryBuilder.java
@@ -47,7 +47,6 @@ import java.util.Collection;
 import java.util.List;
 
 /**
- * Created by qianzhou on 4/9/15.
  */
 public final class IIDictionaryBuilder {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescManagerTest.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescManagerTest.java b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescManagerTest.java
index 7089862..a13a0d1 100644
--- a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescManagerTest.java
+++ b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescManagerTest.java
@@ -30,7 +30,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 /**
- * Created by shaoshi on 1/30/15.
  */
 public class IIDescManagerTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescTest.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescTest.java b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescTest.java
index c70a207..7fc7bfa 100644
--- a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescTest.java
+++ b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIDescTest.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 
 
 /**
- * Created by shaoshi on 1/30/15.
  */
 public class IIDescTest extends LocalFileMetadataTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIInstanceTest.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIInstanceTest.java b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIInstanceTest.java
index cfdcaa0..d1df442 100644
--- a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIInstanceTest.java
+++ b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/IIInstanceTest.java
@@ -15,7 +15,6 @@ import java.io.IOException;
 import java.util.List;
 
 /**
- * Created by shaoshi on 2/5/15.
  */
 public class IIInstanceTest extends LocalFileMetadataTestCase {
     @Before

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/LZFTest.java
----------------------------------------------------------------------
diff --git a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/LZFTest.java b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/LZFTest.java
index e75dc51..1e065b9 100644
--- a/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/LZFTest.java
+++ b/invertedindex/src/test/java/org/apache/kylin/invertedindex/invertedindex/LZFTest.java
@@ -9,7 +9,6 @@ import com.ning.compress.lzf.LZFDecoder;
 import com.ning.compress.lzf.LZFEncoder;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/6/15.
  */
 public class LZFTest {
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/Scheduler.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/Scheduler.java b/job/src/main/java/org/apache/kylin/job/Scheduler.java
index 120b86f..592b274 100644
--- a/job/src/main/java/org/apache/kylin/job/Scheduler.java
+++ b/job/src/main/java/org/apache/kylin/job/Scheduler.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.exception.SchedulerException;
 import org.apache.kylin.job.execution.Executable;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public interface Scheduler<T extends Executable> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java b/job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java
index 82da8e2..29b5324 100644
--- a/job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java
+++ b/job/src/main/java/org/apache/kylin/job/cmd/BaseCommandOutput.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.cmd;
 
 /**
- * Created by qianzhou on 12/4/14.
  */
 public abstract class BaseCommandOutput implements ICommandOutput {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/common/HadoopShellExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/common/HadoopShellExecutable.java b/job/src/main/java/org/apache/kylin/job/common/HadoopShellExecutable.java
index 371e078..2da5b2a 100644
--- a/job/src/main/java/org/apache/kylin/job/common/HadoopShellExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/common/HadoopShellExecutable.java
@@ -34,7 +34,6 @@ import org.apache.kylin.job.hadoop.AbstractHadoopJob;
 import org.apache.kylin.job.execution.AbstractExecutable;
 
 /**
- * Created by qianzhou on 12/26/14.
  */
 public class HadoopShellExecutable extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java b/job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java
index 9cad096..32d6ec2 100644
--- a/job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/common/HqlExecutable.java
@@ -35,7 +35,6 @@ import org.apache.kylin.common.util.HiveClient;
 import org.apache.kylin.common.util.JsonUtil;
 
 /**
- * Created by qianzhou on 1/15/15.
  */
 public class HqlExecutable extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/common/MapReduceExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/common/MapReduceExecutable.java b/job/src/main/java/org/apache/kylin/job/common/MapReduceExecutable.java
index 10c6eba..af6cb9c 100644
--- a/job/src/main/java/org/apache/kylin/job/common/MapReduceExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/common/MapReduceExecutable.java
@@ -48,7 +48,6 @@ import org.apache.kylin.job.tools.HadoopStatusChecker;
 import com.google.common.base.Preconditions;
 
 /**
- * Created by qianzhou on 12/25/14.
  */
 public class MapReduceExecutable extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/common/ShellExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/common/ShellExecutable.java b/job/src/main/java/org/apache/kylin/job/common/ShellExecutable.java
index 47a3145..aa51d83 100644
--- a/job/src/main/java/org/apache/kylin/job/common/ShellExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/common/ShellExecutable.java
@@ -34,7 +34,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 12/26/14.
  */
 public class ShellExecutable extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java b/job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java
index 6c27cd7..1741692 100644
--- a/job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java
+++ b/job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.constant;
 
 /**
- * Created by qianzhou on 1/5/15.
  */
 public final class ExecutableConstants {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/cube/CubingJob.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/cube/CubingJob.java b/job/src/main/java/org/apache/kylin/job/cube/CubingJob.java
index bf6ae11..4b45b94 100644
--- a/job/src/main/java/org/apache/kylin/job/cube/CubingJob.java
+++ b/job/src/main/java/org/apache/kylin/job/cube/CubingJob.java
@@ -34,7 +34,6 @@ import org.apache.kylin.job.execution.ExecuteResult;
 import org.apache.kylin.job.execution.Output;
 
 /**
- * Created by qianzhou on 12/25/14.
  */
 public class CubingJob extends DefaultChainedExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java b/job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java
index aca62e8..1c34441 100644
--- a/job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java
+++ b/job/src/main/java/org/apache/kylin/job/cube/CubingJobBuilder.java
@@ -46,7 +46,6 @@ import java.util.List;
 import java.util.TimeZone;
 
 /**
- * Created by qianzhou on 12/25/14.
  */
 public final class CubingJobBuilder extends AbstractJobBuilder {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java b/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java
index 5aa6570..e9c2a2c 100644
--- a/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java
+++ b/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterBuildStep.java
@@ -34,7 +34,6 @@ import org.apache.kylin.job.execution.ExecuteResult;
 import org.apache.kylin.job.execution.Output;
 
 /**
- * Created by qianzhou on 1/4/15.
  */
 public class UpdateCubeInfoAfterBuildStep extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java b/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java
index bb5abdc..ea52c36 100644
--- a/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java
+++ b/job/src/main/java/org/apache/kylin/job/cube/UpdateCubeInfoAfterMergeStep.java
@@ -38,7 +38,6 @@ import org.apache.kylin.job.execution.ExecutableContext;
 import org.apache.kylin.job.execution.ExecuteResult;
 
 /**
- * Created by qianzhou on 1/7/15.
  */
 public class UpdateCubeInfoAfterMergeStep extends AbstractExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java b/job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java
index 305d570..d4983e2 100644
--- a/job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java
+++ b/job/src/main/java/org/apache/kylin/job/dao/ExecutableDao.java
@@ -35,7 +35,6 @@ import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public class ExecutableDao {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java b/job/src/main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java
index 73436db..4dacd8a 100644
--- a/job/src/main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java
+++ b/job/src/main/java/org/apache/kylin/job/dao/ExecutableOutputPO.java
@@ -26,7 +26,6 @@ import com.google.common.collect.Maps;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class ExecutableOutputPO extends RootPersistentEntity {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java b/job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java
index cd81d64..6a17b29 100644
--- a/job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java
+++ b/job/src/main/java/org/apache/kylin/job/dao/ExecutablePO.java
@@ -27,7 +27,6 @@ import com.google.common.collect.Maps;
 import org.apache.kylin.common.persistence.RootPersistentEntity;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
 public class ExecutablePO extends RootPersistentEntity {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java b/job/src/main/java/org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java
index 15ba2c4..1aeb50f 100644
--- a/job/src/main/java/org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java
+++ b/job/src/main/java/org/apache/kylin/job/deployment/HbaseConfigPrinterCLI.java
@@ -31,7 +31,6 @@ import org.apache.hadoop.hbase.HConstants;
 import org.apache.kylin.job.tools.LZOSupportnessChecker;
 
 /**
- * Created by honma on 9/30/14.
  * <p/>
  * This class is assumed to be run by
  * "hbase org.apache.hadoop.util.RunJar kylin-job-0.5.7-SNAPSHOT-job.jar org.apache.kylin.job.deployment.HadoopConfigPrinter "

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/exception/ExecuteException.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/exception/ExecuteException.java b/job/src/main/java/org/apache/kylin/job/exception/ExecuteException.java
index 261ad5f..8544fff 100644
--- a/job/src/main/java/org/apache/kylin/job/exception/ExecuteException.java
+++ b/job/src/main/java/org/apache/kylin/job/exception/ExecuteException.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.exception;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public class ExecuteException extends Exception {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/exception/IllegalStateTranferException.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/exception/IllegalStateTranferException.java b/job/src/main/java/org/apache/kylin/job/exception/IllegalStateTranferException.java
index e6c0e7f..f19b0ca 100644
--- a/job/src/main/java/org/apache/kylin/job/exception/IllegalStateTranferException.java
+++ b/job/src/main/java/org/apache/kylin/job/exception/IllegalStateTranferException.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.exception;
 
 /**
- * Created by qianzhou on 12/26/14.
  */
 public class IllegalStateTranferException extends RuntimeException {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/exception/LockException.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/exception/LockException.java b/job/src/main/java/org/apache/kylin/job/exception/LockException.java
index abe2232..cf43ac9 100644
--- a/job/src/main/java/org/apache/kylin/job/exception/LockException.java
+++ b/job/src/main/java/org/apache/kylin/job/exception/LockException.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.exception;
 
 /**
- * Created by qianzhou on 12/17/14.
  */
 public class LockException extends Exception {
     private static final long serialVersionUID = 2072745879281754945L;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/exception/PersistentException.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/exception/PersistentException.java b/job/src/main/java/org/apache/kylin/job/exception/PersistentException.java
index 0440411..8507a53 100644
--- a/job/src/main/java/org/apache/kylin/job/exception/PersistentException.java
+++ b/job/src/main/java/org/apache/kylin/job/exception/PersistentException.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.exception;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public class PersistentException extends Exception {
     private static final long serialVersionUID = -4239863858506718998L;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/exception/SchedulerException.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/exception/SchedulerException.java b/job/src/main/java/org/apache/kylin/job/exception/SchedulerException.java
index b5bfeec..057bd4a 100644
--- a/job/src/main/java/org/apache/kylin/job/exception/SchedulerException.java
+++ b/job/src/main/java/org/apache/kylin/job/exception/SchedulerException.java
@@ -19,7 +19,6 @@
 package org.apache.kylin.job.exception;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public class SchedulerException extends Exception {
     private static final long serialVersionUID = 349041244824274861L;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/AbstractExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/AbstractExecutable.java b/job/src/main/java/org/apache/kylin/job/execution/AbstractExecutable.java
index ee1607a..54f05bf 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/AbstractExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/AbstractExecutable.java
@@ -41,7 +41,6 @@ import java.util.Map;
 import java.util.UUID;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public abstract class AbstractExecutable implements Executable, Idempotent {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/ChainedExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/ChainedExecutable.java b/job/src/main/java/org/apache/kylin/job/execution/ChainedExecutable.java
index 3eddf1d..f352ead 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/ChainedExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/ChainedExecutable.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.execution;
 import java.util.List;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public interface ChainedExecutable extends Executable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/DefaultChainedExecutable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/DefaultChainedExecutable.java b/job/src/main/java/org/apache/kylin/job/execution/DefaultChainedExecutable.java
index e6b0d8e..2e7bcde 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/DefaultChainedExecutable.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/DefaultChainedExecutable.java
@@ -28,7 +28,6 @@ import org.apache.kylin.job.exception.ExecuteException;
 import org.apache.kylin.job.manager.ExecutableManager;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public class DefaultChainedExecutable extends AbstractExecutable implements ChainedExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/DefaultOutput.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/DefaultOutput.java b/job/src/main/java/org/apache/kylin/job/execution/DefaultOutput.java
index d6d2ddb..6bc3281 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/DefaultOutput.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/DefaultOutput.java
@@ -23,7 +23,6 @@ import org.apache.commons.lang3.StringUtils;
 import java.util.Map;
 
 /**
- * Created by qianzhou on 1/6/15.
  */
 public class DefaultOutput implements Output {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/Executable.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/Executable.java b/job/src/main/java/org/apache/kylin/job/execution/Executable.java
index 7bd2351..a7f1358 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/Executable.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/Executable.java
@@ -23,7 +23,6 @@ import org.apache.kylin.job.exception.ExecuteException;
 import java.util.Map;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public interface Executable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/ExecutableContext.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/ExecutableContext.java b/job/src/main/java/org/apache/kylin/job/execution/ExecutableContext.java
index d12bd7b..e3f99ca 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/ExecutableContext.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/ExecutableContext.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.execution;
 import org.apache.kylin.common.KylinConfig;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public interface ExecutableContext {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/ExecutableState.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/ExecutableState.java b/job/src/main/java/org/apache/kylin/job/execution/ExecutableState.java
index 24d23ee..5dad4b3 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/ExecutableState.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/ExecutableState.java
@@ -28,7 +28,6 @@ import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public enum ExecutableState {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/ExecuteResult.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/ExecuteResult.java b/job/src/main/java/org/apache/kylin/job/execution/ExecuteResult.java
index bc0137d..cddc0f7 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/ExecuteResult.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/ExecuteResult.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.execution;
 import com.google.common.base.Preconditions;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public final class ExecuteResult {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/Idempotent.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/Idempotent.java b/job/src/main/java/org/apache/kylin/job/execution/Idempotent.java
index d6b5476..98c950e 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/Idempotent.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/Idempotent.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.execution;
 import org.apache.kylin.job.exception.ExecuteException;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public interface Idempotent {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/execution/Output.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/execution/Output.java b/job/src/main/java/org/apache/kylin/job/execution/Output.java
index a835404..4d93132 100644
--- a/job/src/main/java/org/apache/kylin/job/execution/Output.java
+++ b/job/src/main/java/org/apache/kylin/job/execution/Output.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.execution;
 import java.util.Map;
 
 /**
- * Created by qianzhou on 1/6/15.
  */
 public interface Output {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java b/job/src/main/java/org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java
index 91fdc71..3081b7d 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cube/BaseCuboidMapperBase.java
@@ -31,7 +31,6 @@ import java.util.Arrays;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/27/15.
  */
 public class BaseCuboidMapperBase<KEYIN, VALUEIN> extends KylinMapper<KEYIN, VALUEIN, Text, Text> {
     protected static final Logger logger = LoggerFactory.getLogger(HiveToBaseCuboidMapper.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java b/job/src/main/java/org/apache/kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java
index d0edbc6..6bd25a8 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cube/FactDistinctColumnsMapperBase.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 3/26/15.
  */
 public class FactDistinctColumnsMapperBase<KEYIN, VALUEIN> extends KylinMapper<KEYIN, VALUEIN, LongWritable, Text> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java
index 692364e..cccc995 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/IGTRecordWriter.java
@@ -5,7 +5,6 @@ import org.apache.kylin.storage.gridtable.GTRecord;
 import java.io.IOException;
 
 /**
- * Created by shaoshi on 4/7/15.
  */
 public interface IGTRecordWriter {
     void write(Long cuboidId, GTRecord record) throws IOException;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java
index f869caa..83e4a79 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCubeBuilder.java
@@ -64,7 +64,6 @@ import java.util.*;
 import java.util.concurrent.BlockingQueue;
 
 /**
- * Created by shaoshi on 3/12/2015.
  */
 @SuppressWarnings("rawtypes")
 public class InMemCubeBuilder implements Runnable {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java
index f442264..4454e43 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidMapper.java
@@ -28,7 +28,6 @@ import java.util.Map;
 import java.util.concurrent.*;
 
 /**
- * Created by shaoshi on 3/24/15.
  */
 public class InMemCuboidMapper<KEYIN> extends KylinMapper<KEYIN, HCatRecord, ImmutableBytesWritable, Text> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java
index a287c19..7e024bc 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/InMemCuboidReducer.java
@@ -25,7 +25,6 @@ import java.nio.ByteBuffer;
 import java.util.List;
 
 /**
- * Created by shaoshi on 3/25/15.
  */
 public class InMemCuboidReducer extends KylinReducer<ImmutableBytesWritable, Text, ImmutableBytesWritable, KeyValue> {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java
index df3f345..299143f 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/cubev2/MapContextGTRecordWriter.java
@@ -18,7 +18,6 @@ import java.nio.ByteBuffer;
 import java.util.BitSet;
 
 /**
- * Created by shaoshi on 4/7/15.
  */
 public class MapContextGTRecordWriter implements IGTRecordWriter {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java b/job/src/main/java/org/apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java
index 9e5bd92..c25b164 100644
--- a/job/src/main/java/org/apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java
+++ b/job/src/main/java/org/apache/kylin/job/hadoop/invertedindex/IIFlattenHiveJob.java
@@ -37,7 +37,6 @@ import org.apache.kylin.job.JobInstance;
 import org.apache.kylin.invertedindex.model.IIJoinedFlatTableDesc;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 12/30/14.
  */
 public class IIFlattenHiveJob extends AbstractHadoopJob {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultContext.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultContext.java b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultContext.java
index b2dc06d..e959ae2 100644
--- a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultContext.java
+++ b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultContext.java
@@ -27,7 +27,6 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public class DefaultContext implements ExecutableContext {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
index b486a3e..2acba4e 100644
--- a/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
+++ b/job/src/main/java/org/apache/kylin/job/impl/threadpool/DefaultScheduler.java
@@ -54,7 +54,6 @@ import com.google.common.collect.Maps;
 import org.apache.kylin.common.util.HadoopUtil;
 
 /**
- * Created by qianzhou on 12/15/14.
  */
 public class DefaultScheduler implements Scheduler<AbstractExecutable>, ConnectionStateListener {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java b/job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java
index 7382bbf..4b93b6e 100644
--- a/job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java
+++ b/job/src/main/java/org/apache/kylin/job/invertedindex/IIJob.java
@@ -21,7 +21,6 @@ package org.apache.kylin.job.invertedindex;
 import org.apache.kylin.job.execution.DefaultChainedExecutable;
 
 /**
- * Created by shaoshi on 1/15/15.
  */
 public class IIJob extends DefaultChainedExecutable {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/invertedindex/IIJobBuilder.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/invertedindex/IIJobBuilder.java b/job/src/main/java/org/apache/kylin/job/invertedindex/IIJobBuilder.java
index e2bcfd2..26a67f4 100644
--- a/job/src/main/java/org/apache/kylin/job/invertedindex/IIJobBuilder.java
+++ b/job/src/main/java/org/apache/kylin/job/invertedindex/IIJobBuilder.java
@@ -42,7 +42,6 @@ import org.apache.kylin.job.hadoop.invertedindex.InvertedIndexJob;
 import org.apache.kylin.metadata.model.DataModelDesc.RealizationCapacity;
 
 /**
- * Created by shaoshi on 1/15/15.
  */
 public final class IIJobBuilder extends AbstractJobBuilder {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/manager/ExecutableManager.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/manager/ExecutableManager.java b/job/src/main/java/org/apache/kylin/job/manager/ExecutableManager.java
index f51ff69..3c066cb 100644
--- a/job/src/main/java/org/apache/kylin/job/manager/ExecutableManager.java
+++ b/job/src/main/java/org/apache/kylin/job/manager/ExecutableManager.java
@@ -46,7 +46,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 /**
- * Created by qianzhou on 12/16/14.
  */
 public class ExecutableManager {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java b/job/src/main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java
index 5577dce..d1be49a 100644
--- a/job/src/main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java
+++ b/job/src/main/java/org/apache/kylin/job/streaming/KafkaDataLoader.java
@@ -14,7 +14,6 @@ import java.util.List;
 import java.util.Properties;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 5/5/15.
  */
 public class KafkaDataLoader {
     /**

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/streaming/StreamingBootstrap.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/streaming/StreamingBootstrap.java b/job/src/main/java/org/apache/kylin/job/streaming/StreamingBootstrap.java
index 5211516..7854fd5 100644
--- a/job/src/main/java/org/apache/kylin/job/streaming/StreamingBootstrap.java
+++ b/job/src/main/java/org/apache/kylin/job/streaming/StreamingBootstrap.java
@@ -58,7 +58,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 /**
- * Created by qianzhou on 3/26/15.
  */
 public class StreamingBootstrap {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/streaming/StreamingCLI.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/streaming/StreamingCLI.java b/job/src/main/java/org/apache/kylin/job/streaming/StreamingCLI.java
index ba13434..c2dd2ea 100644
--- a/job/src/main/java/org/apache/kylin/job/streaming/StreamingCLI.java
+++ b/job/src/main/java/org/apache/kylin/job/streaming/StreamingCLI.java
@@ -40,7 +40,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Created by qianzhou on 3/26/15.
  */
 public class StreamingCLI {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java b/job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java
index 65e645d..e1ebe20 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/CleanHtableCLI.java
@@ -32,7 +32,6 @@ import org.slf4j.LoggerFactory;
 import org.apache.kylin.job.hadoop.AbstractHadoopJob;
 
 /**
- * Created by honma on 11/11/14.
  */
 public class CleanHtableCLI extends AbstractHadoopJob {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java b/job/src/main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java
index 97373b8..4dfbf6c 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/CubeMigrationCLI.java
@@ -55,7 +55,6 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * Created by honma on 9/3/14.
  * <p/>
  * This tool serves for the purpose of migrating cubes. e.g. upgrade cube from
  * dev env to test(prod) env, or vice versa.

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java b/job/src/main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java
index 2a9abf9..80ae002 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/HadoopStatusGetter.java
@@ -35,7 +35,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 
 /**
- * Created by qianzhou on 1/20/15.
  */
 public class HadoopStatusGetter {
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java b/job/src/main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java
index 8dcfa6d..e38a574 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/HbaseStreamingInput.java
@@ -19,7 +19,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.collect.Lists;
 
 /**
- * Created by Hongbin Ma(Binmahone) on 2/13/15.
  */
 public class HbaseStreamingInput {
     private static final Logger logger = LoggerFactory.getLogger(HbaseStreamingInput.class);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java b/job/src/main/java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java
index 80b9fa7..94eac97 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/HtableAlterMetadataCLI.java
@@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 
 /**
- * Created by honma on 11/11/14.
  */
 @SuppressWarnings("static-access")
 public class HtableAlterMetadataCLI extends AbstractHadoopJob {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/fc056fda/job/src/main/java/org/apache/kylin/job/tools/LZOSupportnessChecker.java
----------------------------------------------------------------------
diff --git a/job/src/main/java/org/apache/kylin/job/tools/LZOSupportnessChecker.java b/job/src/main/java/org/apache/kylin/job/tools/LZOSupportnessChecker.java
index ae16f7c..e9eabb7 100644
--- a/job/src/main/java/org/apache/kylin/job/tools/LZOSupportnessChecker.java
+++ b/job/src/main/java/org/apache/kylin/job/tools/LZOSupportnessChecker.java
@@ -23,7 +23,6 @@ import org.apache.hadoop.hbase.util.CompressionTest;
 import java.io.File;
 
 /**
- * Created by honma on 10/21/14.
  */
 public class LZOSupportnessChecker {
     public static boolean getSupportness() {



[43/52] [abbrv] incubator-kylin git commit: #KYLIN-661, only admin can drop model

Posted by ma...@apache.org.
#KYLIN-661,only admin can drop model


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

Branch: refs/heads/0.8.0
Commit: 00888849269fc0a4a03d709f221ad03cf736a0a2
Parents: 97963b8
Author: jiazhong <ji...@ebay.com>
Authored: Tue Apr 7 17:45:12 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:38:33 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/modelSchema.js     | 6 +++---
 webapp/app/partials/models/model_detail.html | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/00888849/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 81df1df..17a3b06 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -135,9 +135,9 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
      */
     $scope.check_data_model = function(){
         var errors = [];
-        if(!$scope.model.lookups.length){
-            errors.push("No lookup table defined");
-        }
+//        if(!$scope.model.lookups.length){
+//            errors.push("No lookup table defined");
+//        }
         var errorInfo = "";
         angular.forEach(errors,function(item){
             errorInfo+="\n"+item;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/00888849/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 bda87c1..dd8b23c 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -37,7 +37,7 @@
                 <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
                     <a href="models/edit/{{model.name}}" data-widget="collapse">Edit</a>
                 </li>
-                <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                <li ng-if="userService.hasRole('ROLE_ADMIN')">
                     <a ng-click="dropModel(model)">Drop</a>
                 </li>
                 <li role="presentation" class="divider"></li>


[36/52] [abbrv] incubator-kylin git commit: try to use abn-tree for loaded table show

Posted by ma...@apache.org.
try to use abn-tree for loaded table show


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

Branch: refs/heads/0.8.0
Commit: b61dba0454cee877d4f9935e7b578cf51dd5d69e
Parents: db883f4
Author: jiazhong <ji...@ebay.com>
Authored: Thu Mar 26 15:58:21 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 .../js/directives/kylin_abn_tree_directive.js   |  2 +
 webapp/app/js/model/tableModel.js               | 68 ++++++++++++++------
 webapp/app/partials/models/model_detail.html    |  2 +-
 webapp/app/partials/models/model_schema.html    |  4 +-
 webapp/app/partials/models/models.html          | 21 ++++--
 webapp/app/partials/models/models_tree.html     |  2 +-
 webapp/app/partials/tables/source_metadata.html | 17 +++++
 .../app/partials/tables/source_table_tree.html  | 16 ++---
 webapp/app/partials/tables/table_detail.html    | 32 ++++++++-
 9 files changed, 128 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/js/directives/kylin_abn_tree_directive.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/directives/kylin_abn_tree_directive.js b/webapp/app/js/directives/kylin_abn_tree_directive.js
index f309995..dd75d15 100644
--- a/webapp/app/js/directives/kylin_abn_tree_directive.js
+++ b/webapp/app/js/directives/kylin_abn_tree_directive.js
@@ -17,6 +17,7 @@
           treeControl: '='
         },
         link: function(scope, element, attrs) {
+            console.log(attrs.iconLeaf);
           var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
           error = function(s) {
             console.log('ERROR:' + s);
@@ -193,6 +194,7 @@
               }
               if (!branch.noLeaf && (!branch.children || branch.children.length === 0)) {
                 tree_icon = attrs.iconLeaf;
+
                 if (__indexOf.call(branch.classes, "leaf") < 0) {
                   branch.classes.push("leaf");
                 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/js/model/tableModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/tableModel.js b/webapp/app/js/model/tableModel.js
index 687acb5..b812b24 100755
--- a/webapp/app/js/model/tableModel.js
+++ b/webapp/app/js/model/tableModel.js
@@ -16,7 +16,7 @@
  * limitations under the License.
 */
 
-KylinApp.service('TableModel', function(ProjectModel,$q,TableService) {
+KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
 
 
     var _this = this;
@@ -43,21 +43,6 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService) {
     this.init = function(){
       this.selectedSrcDb = [];
       this.selectedSrcTable = {};
-    }
-
-
-    this.treeOptions = {
-        nodeChildren: "columns",
-        injectClasses: {
-            ul: "a1",
-            li: "a2",
-            liSelected: "a7",
-            iExpanded: "a3",
-            iCollapsed: "a4",
-            iLeaf: "a5",
-            label: "a6",
-            labelSelected: "a8"
-        }
     };
 
     this.aceSrcTbLoaded = function (forceLoad) {
@@ -79,6 +64,9 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService) {
         TableService.list(param, function (tables) {
             var tableMap = [];
             angular.forEach(tables, function (table) {
+
+                var tableData = [];
+
                 if (!tableMap[table.database]) {
                     tableMap[table.database] = [];
                 }
@@ -102,10 +90,50 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService) {
             _this.selectedSrcDb = [];
             for (var key in  tableMap) {
                 var tables = tableMap[key];
-                _this.selectedSrcDb.push({
-                    "name": key,
-                    "columns": tables
-                });
+
+                var _db_node = {
+                    label:key,
+                    data:tables,
+                    onSelect:function(branch){
+                        $log.info("db "+key +"selected");
+                    }
+                }
+
+
+                angular.forEach(tables,function(_table){
+                        var _table_node_list = [];
+
+                        var _table_node = {
+                            label:_table.name,
+//                            noLeaf:true,
+                            data:_table,
+                            onSelect:function(branch){
+                                // set selected model
+                                _this.selectedSrcTable = branch.data;
+                            }
+                        }
+
+                        var _column_node_list = [];
+                        angular.forEach(_table.columns,function(_column){
+                            _column_node_list.push({
+                                    label:_column.name,
+                                    noLeaf:true,
+                                    data:_column,
+                                    onSelect:function(branch){
+                                        // set selected model
+//                                        _this.selectedSrcTable = branch.data;
+                                        $log.info("selected column info:"+_column.name);
+                                    }
+                                });
+                        });
+                         _table_node.children =_column_node_list;
+                        _table_node_list.push(_table_node);
+
+                        _db_node.children = _table_node_list;
+                    }
+                );
+
+                _this.selectedSrcDb.push(_db_node);
             }
             defer.resolve();
         });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/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 5f2830d..1808d5e 100644
--- a/webapp/app/partials/models/model_detail.html
+++ b/webapp/app/partials/models/model_detail.html
@@ -9,7 +9,7 @@
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
-* Unless required by applicable law or agreed to in writing, software
+* Unless required by applnewAccess.sidicable 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

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index aef280b..67adf69 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -72,7 +72,8 @@
 <div ng-show="state.mode=='view'&&!models_treedata.length" style="margin-top:40px;">
     <div class="box box-primary">
         <div class="box-header with-border">
-            <h3 class="box-title">No model</h3>
+            <i class="fa fa-bullhorn"></i>
+            <h3 class="box-title">No models</h3>
         </div>
         <div class="box-body">
             <p>
@@ -86,6 +87,7 @@
 <div ng-show="state.mode=='view'&&!!models_treedata.length&&!model.name" style="margin-top:40px;">
     <div class="box box-primary">
         <div class="box-header with-border">
+            <i class="fa fa-bullhorn"></i>
             <h3 class="box-title">No model selected</h3>
         </div>
         <div class="box-body">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index e4e7d57..8e592ee 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -15,6 +15,19 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
+
+<div class="page-header" style="height: 50px;">
+    <!--Project-->
+    <form class="navbar-form navbar-left" style="margin-top: 0px !important;" ng-if="userService.isAuthorized()">
+        <div class="form-group">
+            <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
+            <a class="btn btn-xs btn-primary" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'" style="width: 29px" tooltip="Add Project" ng-click="toCreateProj()">
+                <i class="fa fa-plus"></i>
+            </a>
+        </div>
+    </form>
+</div>
+
 <div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
 
@@ -28,14 +41,14 @@
             </tab>
         </tabset>
     </div>
-    <div  ng-show="showModels&&!cubeSelected"  class="col-xs-9 models-main">
+    <div  ng-if="showModels&&!cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/models/model_detail.html'"></div>
     </div>
-    <div  ng-show="showModels&&cubeSelected"  class="col-xs-9 models-main">
+    <div  ng-if="showModels&&cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/cubes/cube_detail.html'"></div>
     </div>
 
-    <div ng-show="!showModels" class="col-xs-9 models-main">
+    <div ng-if="!showModels" class="col-xs-9 models-main">
         <div ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
 
@@ -45,4 +58,4 @@
 <div ng-include="'partials/jobs/job_submit.html'"></div>
 <div ng-include="'partials/jobs/job_refresh.html'"></div>
 <div ng-include="'partials/jobs/job_merge.html'"></div>
-<div ng-include="'partials/projects/project_create.html'"></div>
\ No newline at end of file
+<div ng-include="'partials/projects/project_create.html'"></div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 727c498..142ef0b 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -40,6 +40,6 @@
                 icon-collapse     = "fa fa-star-o"
                 expand-level      = "2"
                 initial-selection = "">
-            ></abn-tree>
+            </abn-tree>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/tables/source_metadata.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_metadata.html b/webapp/app/partials/tables/source_metadata.html
index d7b5a1e..8e39c95 100755
--- a/webapp/app/partials/tables/source_metadata.html
+++ b/webapp/app/partials/tables/source_metadata.html
@@ -157,6 +157,23 @@
         </div>
     </div>
 
+
+    <!--show load hive table tip when no models list-->
+    <div ng-show="!models_treedata.length" style="margin-top:40px;">
+        <div class="box box-primary">
+            <div class="box-header with-border">
+                <h3 class="box-title">No tables</h3>
+            </div>
+            <div class="box-body">
+                <p>
+                    <a href="models/add" ng-if="userService.hasRole('ROLE_MODELER')">Click here to load your hive table</a>
+                </p>
+            </div><!-- /.box-body -->
+        </div>
+    </div>
+
+
+
     <script type="text/ng-template" id="addHiveTable.html">
         <div class="modal-header">
             <h4>Load Hive Table Metadata</h4>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/tables/source_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_table_tree.html b/webapp/app/partials/tables/source_table_tree.html
index 627234e..deb5a64 100755
--- a/webapp/app/partials/tables/source_table_tree.html
+++ b/webapp/app/partials/tables/source_table_tree.html
@@ -34,13 +34,13 @@
     <div class="space-4"></div>
     <!--tree-->
     <div style="width:100%; height:{{window}}px; overflow:auto;">
-        <treecontrol ng-if="tableModel.selectedSrcDb.length > 0" class="tree-light"
-                     dirSelection="true"
-                     tree-model="tableModel.selectedSrcDb"
-                     options="tableModel.treeOptions"
-                     on-selection="showSelected(node)"
-                     selected-node="tableModel.selectedSrcTable">
-            {{node.name}} {{!!(node.datatype)?'(' + trimType(node.datatype) + ')' : ''}}
-        </treecontrol>
+        <abn-tree
+                tree-data         = "tableModel.selectedSrcDb"
+                tree-control      = "my_tree"
+                icon-leaf         = "fa fa-table"
+                icon-expand       = "fa fa-database"
+                icon-collapse     = "fa fa-database"
+                expand-level      = "3">
+        </abn-tree>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b61dba04/webapp/app/partials/tables/table_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html
index 9801eb1..44d2978 100644
--- a/webapp/app/partials/tables/table_detail.html
+++ b/webapp/app/partials/tables/table_detail.html
@@ -1,5 +1,5 @@
 <div  ng-controller="SourceMetaCtrl" class="nav-tabs-custom">
-    <div class="col-xs-12">
+    <div class="col-xs-12" ng-show="models_treedata.length&&tableModel.selectedSrcTable.name">
         <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
         <div class="tabbable nav-tabs-custom">
             <ul class="nav nav-tabs">
@@ -120,6 +120,36 @@
         </div>
     </div>
 
+
+    <!--show load hive table tip when no models list-->
+    <div ng-show="!models_treedata.length" style="margin-top:40px;">
+        <div class="box box-primary">
+            <div class="box-header with-border">
+                <i class="fa fa-bullhorn"></i>
+                <h3 class="box-title">No tables</h3>
+            </div>
+            <div class="box-body">
+                <div>
+                    <a tooltip="Load Hive Table" href="javascript:void(0);" ng-if="userService.hasRole('ROLE_MODELER')" ng-click="openModal()">Click here to load your hive table</a>
+                </div>
+            </div><!-- /.box-body -->
+        </div>
+    </div>
+
+    <!--show load hive table tip when no models list-->
+    <div ng-show="models_treedata.length&&!tableModel.selectedSrcTable.name" style="margin-top:40px;">
+        <div class="box box-primary">
+            <div class="box-header with-border">
+                <i class="fa fa-bullhorn"></i>
+                <h3 class="box-title">No table selected</h3>
+            </div>
+            <div class="box-body">
+                Select your table
+            </div><!-- /.box-body -->
+        </div>
+    </div>
+
+
     <script type="text/ng-template" id="addHiveTable.html">
         <div class="modal-header">
             <h4>Load Hive Table Metadata</h4>


[37/52] [abbrv] incubator-kylin git commit: use abn-tree replace treecontrol

Posted by ma...@apache.org.
use abn-tree replace treecontrol


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

Branch: refs/heads/0.8.0
Commit: 5926d46dffd1e1f3858f2f9f175df1831a4436a4
Parents: b61dba0
Author: jiazhong <ji...@ebay.com>
Authored: Thu Mar 26 17:44:03 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/projectMeta.js        | 67 ++++++++++++++------
 .../js/directives/kylin_abn_tree_directive.js   | 10 +--
 webapp/app/js/model/tableModel.js               |  8 +--
 webapp/app/less/component.less                  |  4 +-
 webapp/app/partials/cubes/cube_detail.html      |  2 +-
 webapp/app/partials/models/models.html          |  1 -
 .../partials/projects/project_table_tree.html   | 17 ++---
 .../app/partials/tables/source_table_tree.html  |  2 +-
 webapp/app/partials/tables/table_detail.html    | 24 +++++--
 9 files changed, 91 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/js/controllers/projectMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projectMeta.js b/webapp/app/js/controllers/projectMeta.js
index aa35d03..9ca2092 100644
--- a/webapp/app/js/controllers/projectMeta.js
+++ b/webapp/app/js/controllers/projectMeta.js
@@ -19,22 +19,9 @@
 'use strict';
 
 KylinApp
-    .controller('ProjectMetaCtrl', function ($scope, $q, ProjectService, QueryService) {
+    .controller('ProjectMetaCtrl', function ($scope, $q, ProjectService, QueryService,$log) {
         $scope.selectedSrcDb = [];
         $scope.selectedSrcTable = {};
-        $scope.treeOptions = {
-            nodeChildren: "columns",
-            injectClasses: {
-                ul: "a1",
-                li: "a2",
-                liSelected: "a7",
-                iExpanded: "a3",
-                iCollapsed: "a4",
-                iLeaf: "a5",
-                label: "a6",
-                labelSelected: "a8"
-            }
-        };
 
         $scope.showSelected = function (table) {
             if (table.uuid) {
@@ -63,11 +50,48 @@ KylinApp
                 });
 
                 for (var key in  tableMap) {
+
                     var tables = tableMap[key];
-                    $scope.selectedSrcDb.push({
-                        "name": key,
-                        "columns": tables
-                    });
+                    var _db_node = {
+                        label:key,
+                        data:tables,
+                        onSelect:function(branch){
+                            $log.info("db "+key +"selected");
+                        }
+                    }
+
+                    angular.forEach(tables,function(_table){
+                            var _table_node_list = [];
+
+                            var _table_node = {
+                                label:_table.name,
+                                data:_table,
+                                icon:"fa fa-table",
+                                onSelect:function(branch){
+                                    // set selected model
+                                    $scope.selectedSrcTable = branch.data;
+                                }
+                            }
+
+                            var _column_node_list = [];
+                            angular.forEach(_table.columns,function(_column){
+                                _column_node_list.push({
+                                    label:_column.name+$scope.columnTypeFormat(_column.type_NAME),
+                                    data:_column,
+                                    onSelect:function(branch){
+                                        // set selected model
+                                        $log.info("selected column info:"+_column.name);
+                                    }
+                                });
+                            });
+                            _table_node.children =_column_node_list;
+                            _table_node_list.push(_table_node);
+
+                            _db_node.children = _table_node_list;
+                        }
+                    );
+
+                    $scope.selectedSrcDb.push(_db_node);
                 }
 
                 $scope.loading = false;
@@ -81,6 +105,13 @@ KylinApp
                 $scope.projectMetaLoad();
         });
 
+        $scope.columnTypeFormat = function(typeName){
+            if(typeName){
+                return "("+$scope.trimType(typeName)+")";
+            }else{
+                return "";
+            }
+        }
         $scope.trimType = function(typeName){
             if (typeName.match(/VARCHAR/i))
             {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/js/directives/kylin_abn_tree_directive.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/directives/kylin_abn_tree_directive.js b/webapp/app/js/directives/kylin_abn_tree_directive.js
index dd75d15..4625098 100644
--- a/webapp/app/js/directives/kylin_abn_tree_directive.js
+++ b/webapp/app/js/directives/kylin_abn_tree_directive.js
@@ -17,7 +17,6 @@
           treeControl: '='
         },
         link: function(scope, element, attrs) {
-            console.log(attrs.iconLeaf);
           var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
           error = function(s) {
             console.log('ERROR:' + s);
@@ -194,14 +193,17 @@
               }
               if (!branch.noLeaf && (!branch.children || branch.children.length === 0)) {
                 tree_icon = attrs.iconLeaf;
-
                 if (__indexOf.call(branch.classes, "leaf") < 0) {
                   branch.classes.push("leaf");
                 }
               } else {
-                if (branch.expanded) {
+                if(branch.icon){
+                  tree_icon = branch.icon;
+                }
+                else if (branch.expanded) {
                   tree_icon = attrs.iconCollapse;
-                } else {
+                }
+                else {
                   tree_icon = attrs.iconExpand;
                 }
               }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/js/model/tableModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/tableModel.js b/webapp/app/js/model/tableModel.js
index b812b24..f482909 100755
--- a/webapp/app/js/model/tableModel.js
+++ b/webapp/app/js/model/tableModel.js
@@ -89,8 +89,8 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
 
             _this.selectedSrcDb = [];
             for (var key in  tableMap) {
-                var tables = tableMap[key];
 
+                var tables = tableMap[key];
                 var _db_node = {
                     label:key,
                     data:tables,
@@ -99,14 +99,13 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                     }
                 }
 
-
                 angular.forEach(tables,function(_table){
                         var _table_node_list = [];
 
                         var _table_node = {
                             label:_table.name,
-//                            noLeaf:true,
                             data:_table,
+                            icon:"fa fa-table",
                             onSelect:function(branch){
                                 // set selected model
                                 _this.selectedSrcTable = branch.data;
@@ -116,8 +115,7 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                         var _column_node_list = [];
                         angular.forEach(_table.columns,function(_column){
                             _column_node_list.push({
-                                    label:_column.name,
-                                    noLeaf:true,
+                                    label:_column.name+"("+_column.datatype+")",
                                     data:_column,
                                     onSelect:function(branch){
                                         // set selected model

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index 9e05fcf..4ab31e5 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -961,6 +961,6 @@ Angular 1.2.0 Animation
   border-top:solid 2px #3c8dbc !important;
 }
 
-treecontrol{
-  font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+.abn-tree i.indented{
+  font-size:14px !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 5ee5e3e..f5652eb 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -48,7 +48,7 @@
         </li>
         <li class="dropdown" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
             <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
-                <i class="fa fa-cubes"> Action </i> <span class="caret"></span>
+                <i class="fa fa-cubes">Action</i> <span class="caret"></span>
             </a>
             <ul class="dropdown-menu">
                 <li ng-if="cube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 8e592ee..2d3e79f 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -30,7 +30,6 @@
 
 <div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
-
     <div class="col-xs-3">
         <tabset class="nav-tabs-custom">
             <tab heading="Models" select="toggleTab(true);">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/partials/projects/project_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/projects/project_table_tree.html b/webapp/app/partials/projects/project_table_tree.html
index ce53ddd..3ee6d5b 100644
--- a/webapp/app/partials/projects/project_table_tree.html
+++ b/webapp/app/partials/projects/project_table_tree.html
@@ -24,14 +24,15 @@
     </div>
     <div class="space-4"></div>
     <div style="width:310px; height:800px; overflow:auto">
-        <treecontrol ng-if="selectedSrcDb.length > 0" class="tree-light"
-                     dirSelection="true"
-                     tree-model="selectedSrcDb"
-                     options="treeOptions"
-                     on-selection="showSelected(node)"
-                     selected-node="selectedSrcTable">
-            {{node.name}} {{!!(node.type_NAME)?'(' + trimType(node.type_NAME) + ')' : ''}}
-        </treecontrol>
+        <abn-tree ng-if="selectedSrcDb.length > 0"
+                tree-data         = "selectedSrcDb"
+                tree-control      = "my_tree"
+                icon-leaf         = "fa fa-columns"
+                icon-expand       = "fa fa-database"
+                icon-collapse     = "fa fa-database"
+                expand-level      = "3">
+        </abn-tree>
+
         <div no-result ng-if="selectedSrcDb.length == 0"></div>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/partials/tables/source_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/source_table_tree.html b/webapp/app/partials/tables/source_table_tree.html
index deb5a64..c7229a9 100755
--- a/webapp/app/partials/tables/source_table_tree.html
+++ b/webapp/app/partials/tables/source_table_tree.html
@@ -37,7 +37,7 @@
         <abn-tree
                 tree-data         = "tableModel.selectedSrcDb"
                 tree-control      = "my_tree"
-                icon-leaf         = "fa fa-table"
+                icon-leaf         = "fa fa-columns"
                 icon-expand       = "fa fa-database"
                 icon-collapse     = "fa fa-database"
                 expand-level      = "3">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/5926d46d/webapp/app/partials/tables/table_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html
index 44d2978..d19addf 100644
--- a/webapp/app/partials/tables/table_detail.html
+++ b/webapp/app/partials/tables/table_detail.html
@@ -1,5 +1,5 @@
 <div  ng-controller="SourceMetaCtrl" class="nav-tabs-custom">
-    <div class="col-xs-12" ng-show="models_treedata.length&&tableModel.selectedSrcTable.name">
+    <div class="col-xs-12" ng-show="tableModel.selectedSrcDb&&tableModel.selectedSrcTable.name">
         <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
         <div class="tabbable nav-tabs-custom">
             <ul class="nav nav-tabs">
@@ -122,8 +122,10 @@
 
 
     <!--show load hive table tip when no models list-->
-    <div ng-show="!models_treedata.length" style="margin-top:40px;">
-        <div class="box box-primary">
+    <div ng-show="!tableModel.selectedSrcDb.length" style="margin-top:40px;">
+
+        <!--project selected tip-->
+        <div ng-if="projectModel.getSelectedProject();" class="box box-primary">
             <div class="box-header with-border">
                 <i class="fa fa-bullhorn"></i>
                 <h3 class="box-title">No tables</h3>
@@ -134,10 +136,24 @@
                 </div>
             </div><!-- /.box-body -->
         </div>
+        <!--roject not selected tip-->
+        <div ng-if="!projectModel.getSelectedProject();" class="box box-primary">
+            <div class="box-header with-border">
+                <i class="icon fa fa-warning"></i>
+                <h3 class="box-title">No project selected</h3>
+            </div>
+            <div class="box-body">
+                <div class="callout callout-danger">
+                    <p  class="text-danger">
+                       Please select your project first
+                    </p>
+                </div>
+            </div><!-- /.box-body -->
+        </div>
     </div>
 
     <!--show load hive table tip when no models list-->
-    <div ng-show="models_treedata.length&&!tableModel.selectedSrcTable.name" style="margin-top:40px;">
+    <div ng-show="tableModel.selectedSrcDb.length&&!tableModel.selectedSrcTable.name" style="margin-top:40px;">
         <div class="box box-primary">
             <div class="box-header with-border">
                 <i class="fa fa-bullhorn"></i>


[19/52] [abbrv] incubator-kylin git commit: show models list page

Posted by ma...@apache.org.
show models list page


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

Branch: refs/heads/0.8.0
Commit: 7b526242ce17ec6f59ecf1e87b44d0bf309bc58a
Parents: 286e520
Author: jiazhong <ji...@ebay.com>
Authored: Fri Mar 13 16:28:25 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:35:49 2015 +0800

----------------------------------------------------------------------
 .../apache/kylin/rest/service/ModelService.java |   1 +
 webapp/app/index.html                           |  16 +
 webapp/app/js/controllers/cubeModel.js          |  25 +-
 webapp/app/js/controllers/modelDimensions.js    | 402 +++++++++++++++++++
 webapp/app/js/controllers/modelMeasures.js      |  27 ++
 webapp/app/js/controllers/modelRefresh.js       |  23 ++
 webapp/app/js/controllers/modelSchema.js        | 209 ++++++++++
 webapp/app/js/controllers/models.js             |  79 ++++
 webapp/app/js/model/jobListModel.js             |   4 +
 webapp/app/js/model/metaModel.js                |   3 +
 webapp/app/js/model/modelConfig.js              |  26 ++
 webapp/app/js/model/modelList.js                |  52 +++
 webapp/app/js/services/models.js                |  26 ++
 webapp/app/js/services/tree.js                  |  71 ++--
 webapp/app/js/services/users.js                 |   6 +-
 webapp/app/less/app.less                        |   6 +-
 .../app/partials/cubeDesigner/data_model.html   | 199 ---------
 webapp/app/partials/header.html                 |   4 +-
 .../app/partials/modelDesigner/data_model.html  | 199 +++++++++
 .../app/partials/modelDesigner/incremental.html |  94 +++++
 .../modelDesigner/model_dimensions.html         | 354 ++++++++++++++++
 .../partials/modelDesigner/model_measures.html  | 185 +++++++++
 webapp/app/partials/models/model_detail.html    |  43 ++
 webapp/app/partials/models/model_edit.html      |  34 ++
 webapp/app/partials/models/model_schema.html    |  68 ++++
 webapp/app/partials/models/models.html          | 117 ++++++
 webapp/app/routes.json                          |   8 +
 27 files changed, 2038 insertions(+), 243 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index ddf2594..093efe3 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -58,6 +58,7 @@ public class ModelService extends BasicService {
         } else {
             //TO-DO
 //            models = listAllModels(projectName);
+            models=Collections.emptyList();
         }
 
         List<DataModelDesc> filterModels = new ArrayList();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index 44021a9..9e7317f 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -127,11 +127,16 @@
 <script src="js/services/tree.js"></script>
 <script src="js/services/users.js"></script>
 <script src="js/services/ngLoading.js"></script>
+<!--New GUI-->
+<script src="js/services/models.js"></script>
 
 <script src="js/model/cubeConfig.js"></script>
 <script src="js/model/jobConfig.js"></script>
 <script src="js/model/projectConfig.js"></script>
 <script src="js/model/tableConfig.js"></script>
+<!--New GUI-->
+<script src="js/model/modelConfig.js"></script>
+
 <script src="js/model/cubeDescModel.js"></script>
 <script src="js/model/metaModel.js"></script>
 <script src="js/model/projectModel.js"></script>
@@ -139,6 +144,9 @@
 <script src="js/model/cubeListModel.js"></script>
 <script src="js/model/jobListModel.js"></script>
 
+<!--New GUI-->
+<script src="js/model/modelList.js"></script>
+
 <script src="js/controllers/page.js"></script>
 <script src="js/controllers/index.js"></script>
 <script src="js/controllers/access.js"></script>
@@ -158,6 +166,14 @@
 <script src="js/controllers/cubeFilter.js"></script>
 <script src="js/controllers/cubeRefresh.js"></script>
 <script src="js/controllers/cubeAdvanceSetting.js"></script>
+<!--New GUI-->
+<script src="js/controllers/modelSchema.js"></script>
+<script src="js/controllers/modelDimensions.js"></script>
+<script src="js/controllers/modelRefresh.js"></script>
+
+<!--New GUI-->
+<script src="js/controllers/models.js"></script>
+
 <!-- endref -->
 
 <!-- ref:remove -->

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index 2874742..038f7be 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,7 +18,28 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,CubeGraphService,$log) {
+
+
+    $scope.buildGraph = function (cube) {
+        CubeGraphService.buildTree(cube);
+    };
+    $scope.cleanStatus = function(model){
+
+        if (!model)
+        {
+            return;
+        }
+        var newModel = jQuery.extend(true, {}, model);
+        delete newModel.visiblePage;
+        delete newModel.showDetail;
+
+        angular.forEach(newModel.dimensions, function(dimension, index){
+            delete dimension.status;
+        });
+
+        return newModel;
+    };
 
     $scope.cubeConfig = cubeConfig;
     var DataModel = function () {
@@ -49,7 +70,7 @@ KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelSe
 
     $scope.newLookup = Lookup();
 
-    var lookupList = $scope.metaModel.model.lookups;
+    var lookupList = $scope.model.lookups;
 
     $scope.openLookupModal = function () {
         var modalInstance = $modal.open({

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/modelDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDimensions.js b/webapp/app/js/controllers/modelDimensions.js
new file mode 100644
index 0000000..aa197e6
--- /dev/null
+++ b/webapp/app/js/controllers/modelDimensions.js
@@ -0,0 +1,402 @@
+/*
+ * 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('ModelDimensionsCtrl', function ($scope, $modal,MetaModel) {
+
+    // Available columns list derived from cube data model.
+    $scope.availableColumns = {};
+
+    // 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.
+     * 2. hierarchy dimension: column array, the array index is the hierarchy level.
+     * 3. derived dimension: derived columns array.
+     * TODO new cube schema change
+     */
+    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.hierarchy) {
+            referredCols.push(dim.column);
+        }
+
+        return referredCols;
+    };
+
+    // Dump available columns plus column table name, whether is from lookup table.
+    $scope.initColumns = function () {
+        var factTable = $scope.model.fact_table;
+
+        // At first dump the columns of fact table.
+        var cols = $scope.getColumnsByTable(factTable);
+
+        // Initialize selected available.
+        var factAvailable = {};
+        var factSelectAvailable = {};
+
+        for (var i = 0; i < cols.length; i++) {
+            cols[i].table = factTable;
+            cols[i].isLookup = false;
+
+            factAvailable[cols[i].name] = cols[i];
+
+            // Default not selected and not disabled.
+            factSelectAvailable[cols[i].name] = {selected: false, disabled: false};
+        }
+
+        $scope.availableColumns[factTable] = factAvailable;
+        $scope.selectedColumns[factTable] = factSelectAvailable;
+        $scope.availableTables.push(factTable);
+
+        // Then dump each lookup tables.
+        var lookups = $scope.model.lookups;
+
+        for (var j = 0; j < lookups.length; j++) {
+            var cols2 = $scope.getColumnsByTable(lookups[j].table);
+
+            // Initialize selected available.
+            var lookupAvailable = {};
+            var lookupSelectAvailable = {};
+
+            for (var k = 0; k < cols2.length; k++) {
+                cols2[k].table = lookups[j].table;
+                cols2[k].isLookup = true;
+
+                lookupAvailable[cols2[k].name] = cols2[k];
+
+                // Default not selected and not disabled.
+                lookupSelectAvailable[cols2[k].name] = {selected: false, disabled: false};
+            }
+
+            $scope.availableColumns[lookups[j].table] = lookupAvailable;
+            $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
+            $scope.availableTables.push(lookups[j].table);
+        }
+    };
+
+    // Check column status: selected or disabled based on current cube dimensions.
+    $scope.initColumnStatus = function () {
+        angular.forEach($scope.model.dimensions, function (dim) {
+            var cols = dimCols(dim);
+
+            angular.forEach(cols, function (colName) {
+                $scope.selectedColumns[dim.table][colName] = {selected: true, disabled: true};
+            });
+        });
+    };
+
+    // Initialize data for columns widget in auto-gen when add/edit cube.
+    if ($scope.state.mode == 'edit') {
+        $scope.initColumns();
+    }
+
+    // Initialize params for add/edit dimension.
+    $scope.dimState = {
+        editing: false,
+        editingIndex: -1,
+        filter: ''
+    };
+
+    // Init the dimension, dimension name default as the column key. TODO new cube schema change.
+    var Dimension = function (table, selectedCols, dimType) {
+        var origin = {name: '', table: table,hierarchy:false,derived:null,column:null};
+
+        switch (dimType) {
+            case 'normal':
+                // Default name as 1st column name.
+                if (table && selectedCols.length) {
+                    origin.name = table + '.' + selectedCols[0];
+                }
+
+                origin.column = selectedCols;
+                break;
+
+            case 'derived':
+                if (table && selectedCols.length) {
+                    origin.name = table + '_derived';
+                }
+
+                origin.derived = selectedCols;
+                break;
+
+            case 'hierarchy':
+                if (table && selectedCols.length) {
+                    origin.name = table + '_hierarchy';
+                }
+
+                origin.hierarchy = true;
+                origin.column = selectedCols;
+                break;
+        }
+
+        return origin;
+    };
+
+    // Since old schema may be both derived and hierarchy. TODO new cube schema change.
+    $scope.getDimType = function (dim) {
+        var types = [];
+
+        if (dim.derived && dim.derived.length) {
+            types.push('derived');
+        }
+
+        if (dim.hierarchy && dim.column.length) {
+            types.push('hierarchy');
+        }
+
+        if (!types.length) {
+            types.push('normal');
+        }
+
+        return types;
+    };
+
+    var dimList = $scope.model.dimensions;
+
+    // Open add/edit dimension modal.
+    $scope.openDimModal = function (dimType) {
+        var modalInstance = $modal.open({
+            templateUrl: 'addEditDimension.html',
+            controller: cubeDimModalCtrl,
+            backdrop: 'static',
+            scope: $scope,
+            resolve: {
+                dimType: function () {
+                    // For old schema compatibility, convert into array here. TODO new cube schema change.
+                    return angular.isArray(dimType) ? dimType : [dimType];
+                }
+            }
+        });
+
+        modalInstance.result.then(function () {
+            if (!$scope.dimState.editing) {
+                $scope.doneAddDim();
+            } else {
+                $scope.doneEditDim();
+            }
+
+        }, function () {
+            $scope.cancelDim();
+        });
+    };
+
+    // Controller for cube dimension add/edit modal.
+    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType) {
+        $scope.dimType = dimType;
+
+        $scope.ok = function () {
+            $modalInstance.close();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+        };
+    };
+
+    $scope.addDim = function (dimType) {
+        $scope.newDimension = Dimension('', [], dimType);
+
+        $scope.openDimModal(dimType);
+    };
+
+    $scope.editDim = function (dim) {
+        $scope.dimState.editingIndex = dimList.indexOf(dim);
+        $scope.dimState.editing = true;
+
+        // Make a copy of model will be editing.
+        $scope.newDimension = angular.copy(dim);
+
+        $scope.openDimModal($scope.getDimType(dim));
+    };
+
+    $scope.doneAddDim = function () {
+        // Push new dimension which bound user input data.
+        dimList.push(angular.copy($scope.newDimension));
+
+        $scope.resetParams();
+    };
+
+    $scope.doneEditDim = function () {
+        // Copy edited model to destination model.
+        angular.copy($scope.newDimension, dimList[$scope.dimState.editingIndex]);
+
+        $scope.resetParams();
+    };
+
+    $scope.cancelDim = function () {
+        $scope.resetParams();
+    };
+
+    $scope.removeDim = function (dim) {
+        dimList.splice(dimList.indexOf(dim), 1);
+    };
+
+    $scope.resetParams = function () {
+        $scope.dimState.editing = false;
+        $scope.dimState.editingIndex = -1;
+
+        $scope.newDimension = {};
+    };
+
+    // Open auto-gen dimension modal.
+    $scope.openAutoGenModal = function (dimType) {
+        // Init columns status.
+        $scope.initColumnStatus();
+
+        var modalInstance = $modal.open({
+            templateUrl: 'autoGenDimension.html',
+            controller: cubeAutoGenDimModalCtrl,
+            backdrop: 'static',
+            scope: $scope
+        });
+
+        modalInstance.result.then(function () {
+            $scope.autoGenDims();
+        }, function () {
+            $scope.resetGenDims();
+        });
+    };
+
+    // Controller for cube dimension auto-gen modal.
+    var cubeAutoGenDimModalCtrl = function ($scope, $modalInstance) {
+        $scope.ok = function () {
+            $modalInstance.close();
+        };
+
+        $scope.cancel = function () {
+            $modalInstance.dismiss('cancel');
+        };
+    };
+
+    // Helper func to get the selected status in auto gen.
+    $scope.getSelectedCols = function () {
+        var selectedCols = {};
+
+        angular.forEach($scope.selectedColumns, function (value, table) {
+            angular.forEach(value, function (status, colName) {
+                if (status.selected && !status.disabled) {
+                    if (!selectedCols[table]) {
+                        selectedCols[table] = [];
+                    }
+
+                    selectedCols[table].push(colName);
+                }
+            });
+        });
+
+        return selectedCols;
+    };
+
+    // Auto generate dimensions.
+    $scope.autoGenDims = function () {
+        var selectedCols = $scope.getSelectedCols();
+
+        angular.forEach(selectedCols, function (cols, table) {
+            if ($scope.model.fact_table == table) {
+                // Fact table: for each selected column, create one normal dimension.
+                for (var i = 0; i < cols.length; i++) {
+                    dimList.push(Dimension(table, [cols[i]], 'normal'));
+                }
+            } else {
+                // Per lookup table, create one derived dimension for all its selected columns;
+                if (cols.length) {
+                    dimList.push(Dimension(table, cols, 'derived'));
+                }
+            }
+        });
+    };
+
+    // Just reset the selected status of columns.
+    $scope.resetGenDims = function () {
+        var selectedCols = $scope.getSelectedCols();
+
+        angular.forEach(selectedCols, function (cols, table) {
+            for (var i = 0; i < cols.length; i++) {
+                $scope.selectedColumns[table][cols[i]].selected = false;
+            }
+        });
+    };
+
+    // Check whether there is column conflicts.
+    $scope.dimConflicts = [];
+
+    $scope.$watch('cubeMetaFrame.dimensions', function (newVal, oldVal) {
+        if (!newVal || !newVal.length) {
+            return;
+        }
+
+        var referredCols = {};
+
+        angular.forEach(newVal, function (curDim) {
+            var table = curDim.table;
+            var cols = dimCols(curDim);
+
+            for (var i = 0; i < cols.length; i++) {
+                var key = table + '.' + cols[i];
+
+                if (!referredCols[key]) {
+                    referredCols[key] = [];
+                }
+
+                referredCols[key].push({id: curDim.id, name: curDim.name});
+            }
+        });
+
+        var conflicts = [];
+
+        angular.forEach(referredCols, function (dims, key) {
+            if (dims.length > 1) {
+                // More than 1 dimensions has referred this column.
+                var colInfo = key.split('.');
+                conflicts.push({table: colInfo[0], column: colInfo[1], dims: dims});
+            }
+        });
+
+        $scope.dimConflicts = conflicts;
+    }, true);
+
+
+
+    if ($scope.state.mode == 'edit') {
+        $scope.$on('$destroy', function () {
+           // $scope.dimensionsAdapter();
+            // Emit dimensions edit event in order to re-generate row key.
+            $scope.$emit('DimensionsEdited');
+        });
+    }
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/modelMeasures.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelMeasures.js b/webapp/app/js/controllers/modelMeasures.js
new file mode 100644
index 0000000..01cd35a
--- /dev/null
+++ b/webapp/app/js/controllers/modelMeasures.js
@@ -0,0 +1,27 @@
+/*
+ * 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('ModelMeasuresCtrl', function ($scope) {
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/modelRefresh.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelRefresh.js b/webapp/app/js/controllers/modelRefresh.js
new file mode 100644
index 0000000..04b5bf7
--- /dev/null
+++ b/webapp/app/js/controllers/modelRefresh.js
@@ -0,0 +1,23 @@
+/*
+ * 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('ModelRefreshCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
new file mode 100644
index 0000000..638e119
--- /dev/null
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -0,0 +1,209 @@
+/*
+ * 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('ModelSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,$log) {
+
+    $log.info($scope.model);
+
+    $scope.projects = [];
+    $scope.newDimension = null;
+    $scope.newMeasure = null;
+
+
+    $scope.wizardSteps = [
+        {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false},
+        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false},
+        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false},
+        {title: 'Refresh Setting', src: 'partials/modelDesigner/incremental.html', isComplete: false}
+    ];
+
+    $scope.curStep = $scope.wizardSteps[0];
+
+
+    // ~ init
+    if (!$scope.state) {
+        $scope.state = {mode: "view"};
+    }
+
+    $scope.$watch('cubeMetaFrame', function (newValue, oldValue) {
+        if(!newValue){
+            return;
+        }
+        if ($scope.cubeMode=="editExistCube"&&newValue && !newValue.project) {
+            initProject();
+        }
+
+    });
+
+    // ~ public methods
+    $scope.filterProj = function(project){
+        return $scope.userService.hasRole('ROLE_ADMIN') || $scope.hasPermission(project,$scope.permissions.ADMINISTRATION.mask);
+    };
+
+    $scope.addNewMeasure = function (measure) {
+        $scope.newMeasure = (!!measure)? measure:CubeDescModel.createMeasure();
+    };
+
+    $scope.clearNewMeasure = function () {
+        $scope.newMeasure = null;
+    };
+
+    $scope.saveNewMeasure = function () {
+        if ($scope.cubeMetaFrame.measures.indexOf($scope.newMeasure) === -1) {
+            $scope.cubeMetaFrame.measures.push($scope.newMeasure);
+        }
+        $scope.newMeasure = null;
+    };
+
+    //map right return type for param
+    $scope.measureReturnTypeUpdate = function(){
+        if($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
+
+
+            switch($scope.newMeasure.function.expression){
+                case "SUM":
+                    if(colType==="smallint"||colType==="int"||colType==="bigint"){
+                        $scope.newMeasure.function.returntype= 'bigint';
+                    }else{
+                        $scope.newMeasure.function.returntype= 'decimal';
+                    }
+                    break;
+                case "MIN":
+                case "MAX":
+                    $scope.newMeasure.function.returntype = colType;
+                    break;
+                case "COUNT":
+                    $scope.newMeasure.function.returntype = "bigint";
+                    break;
+                default:
+                    $scope.newMeasure.function.returntype = "";
+                    break;
+            }
+        }
+    }
+
+    $scope.addNewRowkeyColumn = function () {
+        $scope.cubeMetaFrame.rowkey.rowkey_columns.push({
+            "column": "",
+            "length": 0,
+            "dictionary": "true",
+            "mandatory": false
+        });
+    };
+
+    $scope.addNewAggregationGroup = function () {
+        $scope.cubeMetaFrame.rowkey.aggregation_groups.push([]);
+    };
+
+    $scope.refreshAggregationGroup = function (list, index, aggregation_groups) {
+        if (aggregation_groups) {
+            list[index] = aggregation_groups;
+        }
+    };
+
+    $scope.removeElement = function (arr, element) {
+        var index = arr.indexOf(element);
+        if (index > -1) {
+            arr.splice(index, 1);
+        }
+    };
+
+    $scope.open = function ($event) {
+        $event.preventDefault();
+        $event.stopPropagation();
+
+        $scope.opened = true;
+    };
+
+    $scope.preView = function () {
+        var stepIndex = $scope.wizardSteps.indexOf($scope.curStep);
+        if (stepIndex >= 1) {
+            $scope.curStep.isComplete = false;
+            $scope.curStep = $scope.wizardSteps[stepIndex - 1];
+        }
+    };
+
+    $scope.nextView = function () {
+        var stepIndex = $scope.wizardSteps.indexOf($scope.curStep);
+
+        if (stepIndex < ($scope.wizardSteps.length - 1)) {
+            $scope.curStep.isComplete = true;
+            $scope.curStep = $scope.wizardSteps[stepIndex + 1];
+
+            AuthenticationService.ping(function (data) {
+                UserService.setCurUser(data);
+            });
+        }
+    };
+
+    $scope.goToStep = function(stepIndex){
+        for(var i=0;i<$scope.wizardSteps.length;i++){
+            if(i<=stepIndex){
+                $scope.wizardSteps[i].isComplete = true;
+            }else{
+                $scope.wizardSteps[i].isComplete = false;
+            }
+        }
+        if (stepIndex < ($scope.wizardSteps.length)) {
+            $scope.curStep = $scope.wizardSteps[stepIndex];
+
+            AuthenticationService.ping(function (data) {
+                UserService.setCurUser(data);
+            });
+        }
+    }
+
+    // ~ private methods
+    function initProject() {
+        ProjectService.list({}, function (projects) {
+            $scope.projects = projects;
+
+            var cubeName = (!!$scope.routeParams.cubeName)? $scope.routeParams.cubeName:$scope.state.cubeName;
+            if (cubeName) {
+                var projName = null;
+                if(ProjectModel.getSelectedProject()){
+                    projName=ProjectModel.getSelectedProject();
+                }else{
+                    angular.forEach($scope.projects, function (project, index) {
+                        angular.forEach(project.realizations, function (unit, index) {
+                            if (!projName && unit.type=="CUBE"&&unit.realization === cubeName) {
+                                projName = project.name;
+                            }
+                        });
+                    });
+                }
+
+                if(!ProjectModel.getSelectedProject()){
+                    ProjectModel.setSelectedProject(projName);
+                    TableModel.aceSrcTbLoaded();
+                }
+
+                $scope.cubeMetaFrame.project = projName;
+            }
+
+            angular.forEach($scope.projects, function (project, index) {
+                $scope.listAccess(project, 'ProjectInstance');
+            });
+        });
+    }
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
new file mode 100644
index 0000000..1777723
--- /dev/null
+++ b/webapp/app/js/controllers/models.js
@@ -0,0 +1,79 @@
+/*
+ * 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('ModelsCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,modelConfig,ProjectModel,ModelService,MetaModel,ModelList) {
+        $scope.modelList = ModelList;
+        $scope.modelConfig = modelConfig;
+        ModelList.removeAll();
+        $scope.loading = false;
+        $scope.action = {};
+
+        $scope.listParams={
+            cubeName: $routeParams.cubeName,
+            projectName: $routeParams.projectName
+        };
+
+        $scope.list = function (offset, limit) {
+            if(!$scope.projectModel.projects.length){
+                return [];
+            }
+            offset = (!!offset) ? offset : 0;
+            limit = (!!limit) ? limit : 20;
+
+            var queryParam = {offset: offset, limit: limit};
+            if ($scope.listParams.modelName) {
+                queryParam.modelName = $scope.listParams.modelName;
+            }
+            queryParam.projectName = $scope.projectModel.selectedProject;
+
+            $scope.loading = true;
+
+            var defer = $q.defer();
+            return ModelList.list(queryParam).then(function(resp){
+                $scope.loading = false;
+                defer.resolve(resp);
+                defer.promise;
+            },function(resp){
+                $scope.loading = false;
+                defer.resolve([]);
+                defer.promise;
+            });
+        };
+
+
+        $scope.loadDetail = function (model) {
+            $log.info(model);
+        };
+
+
+        $scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
+            if(newValue!=oldValue||newValue==null){
+                ModelList.removeAll();
+                $scope.reload();
+            }
+
+        });
+        $scope.reload = function () {
+            // trigger reload action in pagination directive
+            $scope.action.reload = !$scope.action.reload;
+        };
+
+    });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/model/jobListModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/jobListModel.js b/webapp/app/js/model/jobListModel.js
index 764791a..404bf20 100755
--- a/webapp/app/js/model/jobListModel.js
+++ b/webapp/app/js/model/jobListModel.js
@@ -16,6 +16,10 @@
  * limitations under the License.
 */
 
+/*
+ *jobListModel will manage data in list job page
+ */
+
 KylinApp.service('JobList',function(JobService,$q){
     var _this = this;
     this.jobs=[];

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index a21c83c..021dda7 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -16,6 +16,9 @@
  * limitations under the License.
 */
 
+/**
+ *MetaModel will manage model info of cube
+ */
 KylinApp.service('MetaModel',function(){
 
     //data model when edit model

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/model/modelConfig.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelConfig.js b/webapp/app/js/model/modelConfig.js
new file mode 100644
index 0000000..e910ce5
--- /dev/null
+++ b/webapp/app/js/model/modelConfig.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+*/
+
+KylinApp.constant('modelConfig', {
+//  models config
+    theaditems : [
+    {attr: 'name', name: 'Name'},
+    {attr: 'factTable', name: 'Fact Table'},
+    {attr: 'date_modified', name: 'Date Modified'}
+     ]
+    });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
new file mode 100644
index 0000000..30e9b70
--- /dev/null
+++ b/webapp/app/js/model/modelList.js
@@ -0,0 +1,52 @@
+/*
+ * 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.
+*/
+
+KylinApp.service('ModelList',function(ModelService,$q){
+    var models=[];
+    var _this = this;
+
+    this.list = function(queryParam){
+
+        var defer = $q.defer();
+        ModelService.list(queryParam, function (_models) {
+            angular.forEach(_models, function (models, index) {
+                if(models.name){
+//                    $scope.listAccess(models, 'modelsInstance');
+                }
+            });
+            _models = _.filter(_models,function(models){return models.name!=undefined});
+            _this.models = _this.models.concat(_models);
+            defer.resolve(_this.models.length);
+        },function(){
+            defer.reject("Failed to load models");
+        });
+        return defer.promise;
+
+    };
+
+    this.removemodels = function(models){
+        var modelsIndex = _this.models.indexOf(models);
+        if (modelsIndex > -1) {
+            _this.models.splice(modelsIndex, 1);
+        }
+    }
+
+    this.removeAll = function(){
+        _this.models=[];
+    };
+});

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/services/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/models.js b/webapp/app/js/services/models.js
new file mode 100644
index 0000000..7698e49
--- /dev/null
+++ b/webapp/app/js/services/models.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+*/
+
+KylinApp.factory('ModelService', ['$resource', function ($resource, config) {
+    return $resource(Config.service.url + 'models/:modelId/:propName/:propValue/:action', {}, {
+        list: {method: 'GET', params: {}, isArray: true},
+        drop: {method: 'DELETE', params: {}, isArray: false},
+        save: {method: 'POST', params: {}, isArray: false},
+        update: {method: 'PUT', params: {}, isArray: false},
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/services/tree.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/tree.js b/webapp/app/js/services/tree.js
index 0a565af..d6f346f 100755
--- a/webapp/app/js/services/tree.js
+++ b/webapp/app/js/services/tree.js
@@ -22,15 +22,15 @@ KylinApp.service('CubeGraphService', function () {
         width = 1100 - margin.right - margin.left,
         height = 600;
 
-    this.buildTree = function (cube) {
-        $("#cube_graph_" + cube.name).empty();
+    this.buildTree = function (model) {
+        $("#model_graph_" + model.name).empty();
 
         var tree = d3.layout.tree().size([height, width - 160]);
         var diagonal = d3.svg.diagonal().projection(function (d) {
             return [d.y, d.x];
         });
 
-        var svg = d3.select("#cube_graph_" + cube.name).append("svg:svg")
+        var svg = d3.select("#model_graph_" + model.name).append("svg:svg")
             .attr("width", width + margin.right + margin.left)
             .attr("height", height)
             .append("svg:g")
@@ -38,14 +38,13 @@ KylinApp.service('CubeGraphService', function () {
 
         var graphData = {
             "type": "fact",
-            "name": cube.model.fact_table,
+            "name": model.fact_table,
             "children": []
         };
 
-        cube.graph = (!!cube.graph) ? cube.graph : {};
+        model.graph = (!!model.graph) ? model.graph : {};
 
-      //angular.forEach(cube.detail.dimensions, function (dimension, index) {
-      angular.forEach(cube.model.lookups, function (lookup, index) {
+      angular.forEach(model.lookups, function (lookup, index) {
         if (lookup.join && lookup.join.primary_key.length > 0) {
 
           var dimensionNode;
@@ -76,9 +75,9 @@ KylinApp.service('CubeGraphService', function () {
         }
       });
 
-      angular.forEach(cube.detail.dimensions, function (dimension, index) {
+      angular.forEach(model.dimensions, function (dimension, index) {
         // for dimension on lookup table
-        if(cube.model.fact_table!==dimension.table){
+        if(model.fact_table!==dimension.table){
             var lookup = _.find(graphData.children,function(item){
               return item.name === dimension.table;
             });
@@ -130,28 +129,28 @@ KylinApp.service('CubeGraphService', function () {
 
         };
       });
-        cube.graph.columnsCount = 0;
-        cube.graph.tree = tree;
-        cube.graph.root = graphData;
-        cube.graph.svg = svg;
-        cube.graph.diagonal = diagonal;
-        cube.graph.i = 0;
-
-        cube.graph.root.x0 = height / 2;
-        cube.graph.root.y0 = 0;
-        update(cube.graph.root, cube);
+        model.graph.columnsCount = 0;
+        model.graph.tree = tree;
+        model.graph.root = graphData;
+        model.graph.svg = svg;
+        model.graph.diagonal = diagonal;
+        model.graph.i = 0;
+
+        model.graph.root.x0 = height / 2;
+        model.graph.root.y0 = 0;
+        update(model.graph.root, model);
     }
 
-    function update(source, cube) {
+    function update(source, model) {
         var duration = 750;
 
         // Compute the new tree layout.
-        var nodes = cube.graph.tree.nodes(cube.graph.root).reverse();
+        var nodes = model.graph.tree.nodes(model.graph.root).reverse();
 
         // Update the nodes
-        var node = cube.graph.svg.selectAll("g.node")
+        var node = model.graph.svg.selectAll("g.node")
             .data(nodes, function (d) {
-                return d.id || (d.id = ++cube.graph.i);
+                return d.id || (d.id = ++model.graph.i);
             });
 
         var nodeEnter = node.enter().append("svg:g")
@@ -181,22 +180,22 @@ KylinApp.service('CubeGraphService', function () {
                     d.children = null;
 
                     if (d.type == 'dimension') {
-                        cube.graph.columnsCount -= d._children.length;
+                        model.graph.columnsCount -= d._children.length;
                     }
                 } else {
                     d.children = d._children;
                     d._children = null;
 
                     if (d.type == 'dimension') {
-                        cube.graph.columnsCount += d.children.length;
+                        model.graph.columnsCount += d.children.length;
                     }
                 }
 
                 var perColumn = 35;
-                var newHeight = (((cube.graph.columnsCount * perColumn > height) ? cube.graph.columnsCount * perColumn : height));
-                $("#cube_graph_" + cube.name + " svg").height(newHeight);
-                cube.graph.tree.size([newHeight, width - 160]);
-                update(d, cube);
+                var newHeight = (((model.graph.columnsCount * perColumn > height) ? model.graph.columnsCount * perColumn : height));
+                $("#model_graph_" + model.name + " svg").height(newHeight);
+                model.graph.tree.size([newHeight, width - 160]);
+                update(d, model);
             });
 
         nodeEnter.append("svg:text")
@@ -210,7 +209,7 @@ KylinApp.service('CubeGraphService', function () {
                     var joinTip = "";
 
                     angular.forEach(d.join.primary_key, function (pk, index) {
-                        joinTip += ( cube.graph.root.name + "." + d.join.foreign_key[index] + " = " + d.name + "." + pk + "<br>");
+                        joinTip += ( model.graph.root.name + "." + d.join.foreign_key[index] + " = " + d.name + "." + pk + "<br>");
                     });
 
                     d.tooltip = d3.select("body")
@@ -286,8 +285,8 @@ KylinApp.service('CubeGraphService', function () {
             .remove();
 
         // Update the links…
-        var link = cube.graph.svg.selectAll("path.link")
-            .data(cube.graph.tree.links(nodes), function (d) {
+        var link = model.graph.svg.selectAll("path.link")
+            .data(model.graph.tree.links(nodes), function (d) {
                 return d.target.id;
             });
 
@@ -296,23 +295,23 @@ KylinApp.service('CubeGraphService', function () {
             .attr("class", "link")
             .attr("d", function (d) {
                 var o = {x: source.x0, y: source.y0};
-                return cube.graph.diagonal({source: o, target: o});
+                return model.graph.diagonal({source: o, target: o});
             })
             .transition()
             .duration(duration)
-            .attr("d", cube.graph.diagonal);
+            .attr("d", model.graph.diagonal);
 
         // Transition links to their new position.
         link.transition()
             .duration(duration)
-            .attr("d", cube.graph.diagonal);
+            .attr("d", model.graph.diagonal);
 
         // Transition exiting nodes to the parent's new position.
         link.exit().transition()
             .duration(duration)
             .attr("d", function (d) {
                 var o = {x: source.x, y: source.y};
-                return cube.graph.diagonal({source: o, target: o});
+                return model.graph.diagonal({source: o, target: o});
             })
             .remove();
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/js/services/users.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/users.js b/webapp/app/js/services/users.js
index 7308a98..55c1508 100644
--- a/webapp/app/js/services/users.js
+++ b/webapp/app/js/services/users.js
@@ -18,9 +18,9 @@
 
 KylinApp.service('UserService', function ($http, $q) {
     var roles = {
-        'ROLE_MODELER': '/cubes',
-        'ROLE_ANALYST': '/cubes',
-        'ROLE_ADMIN': '/cubes'
+        'ROLE_MODELER': '/models',
+        'ROLE_ANALYST': '/models',
+        'ROLE_ADMIN': '/models'
     };
     var curUser = {};
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index f60a698..7296eb9 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -213,6 +213,10 @@ table .radio {
 .cube-detail {
   background-color: white;
 }
+.model-detail {
+  background-color: white;
+}
+
 
 /* Query content */
 .query-content {
@@ -316,7 +320,7 @@ pre {
 }
 
 //cube graph
-.cube_graph {
+.model_graph {
   svg {
     width: auto;
     height: auto;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/cubeDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/data_model.html b/webapp/app/partials/cubeDesigner/data_model.html
deleted file mode 100644
index 4aeb1da..0000000
--- a/webapp/app/partials/cubeDesigner/data_model.html
+++ /dev/null
@@ -1,199 +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.
--->
-
-<div ng-controller="CubeModelCtrl">
-    <ng-form name="model_form">
-
-    <!-- Fact Table Name -->
-    <div class="form-group">
-        <div class="row">
-            <label class="col-xs-12 col-sm-2 concube.detailtrol-label no-padding-right font-color-default">
-                <b>Fact Table</b>
-            </label>
-            <div class="col-xs-12 col-sm-6">
-                <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
-                           title="name" model="metaModel.model.fact_table" required="true"></typeahead>
-                <span ng-if="state.mode=='view'">{{metaModel.model.fact_table}}</span>
-            </div>
-        </div>
-    </div>
-
-    <!-- Lookup Tables Summary -->
-    <div class="dataTables_wrapper form-inline no-footer">
-        <div class="row">
-            <div class="col-xs-6" ng-if="state.mode=='edit'">
-                <button type="button" class="btn btn-primary" ng-disabled="!metaModel.model.fact_table.length"
-                        ng-click="openLookupModal()">
-                    <i class="fa fa-plus"></i> Add Lookup Table
-                </button>
-            </div>
-            <div class="col-xs-6" ng-if="state.mode!='edit'">
-                <b>{{metaModel.model.lookups.length ? 'Lookup Tables' : 'No Lookup 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="metaModel.model.lookups.length">
-                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="lookupState.filter"/>
-                    <i class="ace-icon fa fa-search nav-search-icon"></i>
-                </span>
-            </div>
-        </div>
-        <table class="table table-striped table-hover" ng-if="metaModel.model.lookups.length">
-            <thead>
-            <tr>
-                <th>ID</th>
-                <th>Table Name</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 metaModel.model.lookups | filter:lookupState.filter track by $index">
-                <td>
-                    <b>{{$index + 1}}</b>
-                </td>
-                <!-- Table Name -->
-                <td>
-                    <span tooltip="Lookup Table Name">{{lookup.table}}</span>
-                </td>
-                <!-- Join Type -->
-                <td>
-                    <span>{{lookup.join.type}}</span>
-                </td>
-                <!-- Join Condition -->
-                <td>
-                    <ul class="list-unstyled">
-                        <li ng-repeat="pk in lookup.join.primary_key track by $index">
-                            <code>{{lookup.table + '.' + pk}} = {{metaModel.model.fact_table + '.' + lookup.join.foreign_key[$index]}}</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>
-                    <!-- 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>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-    </div>
-    </ng-form>
-
-    <!-- Add Lookup 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>
-        </div>
-        <div class="modal-body">
-            <div class="row">
-                <div class="col-xs-8">
-                    <ng-form name="lookup_form">
-                    <!--Table Name-->
-                    <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 class="col-xs-12 col-sm-6">
-                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" title="name" model="newLookup.table"></typeahead>
-                            </div>
-                        </div>
-                    </div>
-
-                    <!--Join Type and Columns-->
-                    <div class="form-group">
-                        <div class="row">
-                            <label class="col-sm-3 control-label font-color-default"><b>Join Type</b></label>
-                            <div class="col-sm-6">
-                                <select class="form-control" chosen ng-model="newLookup.join.type"
-                                        ng-options="joinType.value as joinType.name for joinType in cubeConfig.joinTypes">
-                                    <option value=""></option>
-                                </select>
-                            </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="Lookup Table Column"
-                                                ng-model="newLookup.join.primary_key[$index]"
-                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(newLookup.table)" >
-                                            <option value=""></option>
-                                        </select>
-                                        <b>=</b>
-                                        <select style="width: 45%" chosen data-placeholder="Fact Table Column"
-                                                ng-model="newLookup.join.foreign_key[$index]"
-                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
-                                            <option value=""></option>
-                                        </select>
-                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer" tooltip="Delete"
-                                                ng-click="removeJoin($index);">
-                                            <i class="fa fa-trash-o pointer"></i>
-                                        </button>
-                                    </div>
-                                    <div class="space-4"></div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="form-group">
-                        <div class="row">
-                            <div class="col-sm-3">
-                                <button class="btn btn-xs btn-info"
-                                        ng-if="newLookup.join.type"
-                                        ng-click="addNewJoin();">
-                                    <i class="fa fa-plus"></i> New Join Condition</button>
-                            </div>
-                        </div>
-                    </div>
-
-                    </ng-form>
-                </div>
-
-                <!--Tips-->
-                <div class="col-xs-4">
-                    <div class="box box-solid">
-                        <div class="box-header">
-                            <h4 class="box-title">Tips</h4>
-                        </div>
-                        <div class="box-body">
-                            <div class="row">
-                                <div class="col-xs-12">
-                                    <ol class="text-info">
-                                        <li>Pick up lookup table at first</li>
-                                        <li>Specify join relationship between chosen lookup table and fact table</li>
-                                        <li>Join Type have to be same as will be used in query</li>
-                                    </ol>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <div class="modal-footer">
-            <button class="btn btn-primary" ng-disabled="lookup_form.$invalid || !newLookup.join.primary_key.length" ng-click="ok()">OK</button>
-            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-        </div>
-    </script>
-</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index 18a9b66..9a55034 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -43,8 +43,8 @@
                     <li class="{{activeTab=='query'?'purple':'green'}}" ng-if="userService.isAuthorized()">
                         <a href="query">Insight</a>
                     </li>
-                    <li class="{{activeTab=='cubes'?'purple':'green'}}" ng-if="userService.isAuthorized()">
-                        <a href="cubes">Model</a>
+                    <li class="{{activeTab=='models'?'purple':'green'}}" ng-if="userService.isAuthorized()">
+                        <a href="models">Model</a>
                     </li>
                     <li class="{{activeTab=='jobs'?'purple':'green'}}" ng-if="userService.isAuthorized()">
                         <a href="jobs">Monitor</a>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/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
new file mode 100644
index 0000000..c8cc5a7
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -0,0 +1,199 @@
+<!--
+* 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.
+-->
+
+<div ng-controller="CubeModelCtrl">
+    <ng-form name="model_form">
+
+    <!-- Fact Table Name -->
+    <div class="form-group">
+        <div class="row">
+            <label class="col-xs-12 col-sm-2 concube.detailtrol-label no-padding-right font-color-default">
+                <b>Fact Table</b>
+            </label>
+            <div class="col-xs-12 col-sm-6">
+                <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
+                           title="name" model="model.fact_table" required="true"></typeahead>
+                <span ng-if="state.mode=='view'">{{model.fact_table}}</span>
+            </div>
+        </div>
+    </div>
+
+    <!-- Lookup Tables Summary -->
+    <div class="dataTables_wrapper form-inline no-footer">
+        <div class="row">
+            <div class="col-xs-6" ng-if="state.mode=='edit'">
+                <button type="button" class="btn btn-primary" ng-disabled="!model.fact_table.length"
+                        ng-click="openLookupModal()">
+                    <i class="fa fa-plus"></i> Add Lookup Table
+                </button>
+            </div>
+            <div class="col-xs-6" ng-if="state.mode!='edit'">
+                <b>{{model.lookups.length ? 'Lookup Tables' : 'No Lookup 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="model.lookups.length">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="lookupState.filter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
+        </div>
+        <table class="table table-striped table-hover" ng-if="model.lookups.length">
+            <thead>
+            <tr>
+                <th>ID</th>
+                <th>Table Name</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 model.lookups | filter:lookupState.filter track by $index">
+                <td>
+                    <b>{{$index + 1}}</b>
+                </td>
+                <!-- Table Name -->
+                <td>
+                    <span tooltip="Lookup Table Name">{{lookup.table}}</span>
+                </td>
+                <!-- Join Type -->
+                <td>
+                    <span>{{lookup.join.type}}</span>
+                </td>
+                <!-- Join Condition -->
+                <td>
+                    <ul class="list-unstyled">
+                        <li ng-repeat="pk in lookup.join.primary_key track by $index">
+                            <code>{{lookup.table + '.' + pk}} = {{model.fact_table + '.' + lookup.join.foreign_key[$index]}}</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>
+                    <!-- 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>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+    </ng-form>
+
+    <!-- Add Lookup 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>
+        </div>
+        <div class="modal-body">
+            <div class="row">
+                <div class="col-xs-8">
+                    <ng-form name="lookup_form">
+                    <!--Table Name-->
+                    <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 class="col-xs-12 col-sm-6">
+                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" title="name" model="newLookup.table"></typeahead>
+                            </div>
+                        </div>
+                    </div>
+
+                    <!--Join Type and Columns-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-sm-3 control-label font-color-default"><b>Join Type</b></label>
+                            <div class="col-sm-6">
+                                <select class="form-control" chosen ng-model="newLookup.join.type"
+                                        ng-options="joinType.value as joinType.name for joinType in cubeConfig.joinTypes">
+                                    <option value=""></option>
+                                </select>
+                            </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="Lookup Table Column"
+                                                ng-model="newLookup.join.primary_key[$index]"
+                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(newLookup.table)" >
+                                            <option value=""></option>
+                                        </select>
+                                        <b>=</b>
+                                        <select style="width: 45%" chosen data-placeholder="Fact Table Column"
+                                                ng-model="newLookup.join.foreign_key[$index]"
+                                                ng-options="columns.name as columns.name for columns in getColumnsByTable(model.fact_table)" >
+                                            <option value=""></option>
+                                        </select>
+                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer" tooltip="Delete"
+                                                ng-click="removeJoin($index);">
+                                            <i class="fa fa-trash-o pointer"></i>
+                                        </button>
+                                    </div>
+                                    <div class="space-4"></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="row">
+                            <div class="col-sm-3">
+                                <button class="btn btn-xs btn-info"
+                                        ng-if="newLookup.join.type"
+                                        ng-click="addNewJoin();">
+                                    <i class="fa fa-plus"></i> New Join Condition</button>
+                            </div>
+                        </div>
+                    </div>
+
+                    </ng-form>
+                </div>
+
+                <!--Tips-->
+                <div class="col-xs-4">
+                    <div class="box box-solid">
+                        <div class="box-header">
+                            <h4 class="box-title">Tips</h4>
+                        </div>
+                        <div class="box-body">
+                            <div class="row">
+                                <div class="col-xs-12">
+                                    <ol class="text-info">
+                                        <li>Pick up lookup table at first</li>
+                                        <li>Specify join relationship between chosen lookup table and fact table</li>
+                                        <li>Join Type have to be same as will be used in query</li>
+                                    </ol>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-disabled="lookup_form.$invalid || !newLookup.join.primary_key.length" ng-click="ok()">OK</button>
+            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7b526242/webapp/app/partials/modelDesigner/incremental.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/incremental.html b/webapp/app/partials/modelDesigner/incremental.html
new file mode 100644
index 0000000..3238b1c
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/incremental.html
@@ -0,0 +1,94 @@
+<!--
+* 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.
+-->
+
+<div ng-controller="ModelRefreshCtrl">
+<div class="row">
+    <div class="col-xs-8">
+
+        <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="model.partition_desc.partition_type"
+                        ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
+                        <option value=""></option>
+                    </select>
+                    <span ng-if="state.mode=='view'">{{model.partition_desc.partition_type}}</span>
+                </div>
+            </div>
+        </div>
+
+        <!--Partition Column-->
+        <div class="form-group">
+            <div class="row">
+                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></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-required="model.partition_desc.partition_date_start"
+                            ng-model="model.partition_desc.partition_date_column"
+                            ng-if="state.mode=='edit'"
+                            data-placement=""
+                            ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
+                        <option value="">--Select Partition Column--</option>
+                    </select>
+                    <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+                    <span ng-if="state.mode=='view'">
+                        {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
+                </div>
+            </div>
+        </div>
+
+        <!--Data Range Start-->
+        <div class="form-group">
+            <div class="row">
+                <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
+                <div class="col-xs-12 col-sm-6">
+                  <!--edit model will convert in MetaModel.converDateToGMT-->
+                    <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
+                           ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
+                           placeholder="Click to choose start date..." is-open="opened" />
+                  <!--vier model will convert use filter-->
+                    <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <div class="box box-solid">
+            <div class="box-header">
+                <h4 class="box-title">Tips</h4>
+            </div>
+            <div class="box-body">
+                <div class="row">
+                    <div class="col-xs-12">
+                        <ol class="text-info">
+                            <li>Not required,leave as default if cube always need full build</li>
+                            <li>Partition column will select 'date' or 'string' type column from fact table</li>
+                            <li>If column selected,please indicate start date to just pull certain data from source</li>
+                        </ol>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+</div>


[34/52] [abbrv] incubator-kylin git commit: step check enhance

Posted by ma...@apache.org.
step check enhance


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

Branch: refs/heads/0.8.0
Commit: aebd109efce17c0d826d362d653dfda3dd0639cb
Parents: 992fd74
Author: jiazhong <ji...@ebay.com>
Authored: Wed Apr 1 19:37:15 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeDimensions.js     |   4 +-
 webapp/app/js/controllers/cubeEdit.js           |   5 +-
 webapp/app/js/controllers/cubeSchema.js         |  46 +++-
 webapp/app/js/controllers/modelEdit.js          |  12 +-
 webapp/app/js/controllers/modelSchema.js        |   6 +
 webapp/app/js/controllers/models.js             |   1 -
 webapp/app/js/controllers/projectMeta.js        |   3 +-
 webapp/app/js/model/metaModel.js                |   8 +-
 webapp/app/js/model/tableModel.js               |   3 +-
 .../cubeDesigner/advanced_settings.html         | 236 ++++++++++---------
 webapp/app/partials/cubeDesigner/info.html      |  16 +-
 webapp/app/partials/cubes/cube_schema.html      |   8 +-
 webapp/app/partials/header.html                 |   4 +-
 .../modelDesigner/conditions_settings.html      |   8 +-
 .../app/partials/modelDesigner/data_model.html  |  15 +-
 .../modelDesigner/model_dimensions.html         |  12 +-
 .../app/partials/modelDesigner/model_info.html  |  27 +--
 webapp/app/partials/models/model_schema.html    |   8 +-
 .../partials/projects/project_table_tree.html   |   2 +-
 19 files changed, 232 insertions(+), 192 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index f114ccb..35b66ab 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -106,7 +106,9 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
 
             $scope.availableColumns[lookups[j].table] = lookupAvailable;
             $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
-            $scope.availableTables.push(lookups[j].table);
+            if($scope.availableTables.indexOf(lookups[j].table)==-1){
+                $scope.availableTables.push(lookups[j].table);
+            }
         }
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 2bbdd05..98fc9a3 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -181,7 +181,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         return $interpolate($templateCache.get(tmpl))(notification);
     };
 
-    $scope.saveCube = function (design_form) {
+    $scope.saveCube = function () {
 
         try {
             angular.fromJson($scope.state.cubeSchema);
@@ -208,9 +208,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                             $scope.state.cubeSchema = request.cubeDescData;
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
 
-                            if (design_form) {
-                                design_form.$invalid = true;
-                            }
                         } else {
                             $scope.saveCubeRollBack();
                             $scope.cubeMetaFrame.project = $scope.state.project;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index a3bbd89..327dc25 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -32,7 +32,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     if (UserService.hasRole("ROLE_ADMIN")) {
             $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false,form:'cube_setting_form'});
     }
-    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false,form:'cube_overview_form'});
+    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false,form:null});
 
     $scope.curStep = $scope.wizardSteps[0];
 
@@ -157,6 +157,11 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.goToStep = function(stepIndex){
+        if($scope.state.mode=="edit"){
+            if(stepIndex+1>=$scope.curStep.step){
+                return;
+            }
+        }
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;
@@ -183,6 +188,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         else{
             //form validation
             if($scope.forms[$scope.curStep.form].$invalid){
+                $scope.forms[$scope.curStep.form].$submitted = true;
                 return false;
             }else{
                 //business rule check
@@ -193,6 +199,8 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
                     case 'cube_measure_form':
                         return $scope.check_cube_measure();
                         break;
+                    case 'cube_setting_form':
+                        return $scope.check_cube_setting();
                     default:
                         return true;
                         break;
@@ -220,10 +228,44 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.check_cube_measure = function(){
+        var _measures = $scope.cubeMetaFrame.measures;
         var errors = [];
-        if(!$scope.cubeMetaFrame.measures||!$scope.cubeMetaFrame.measures.length){
+        if(!_measures||!_measures.length){
             errors.push("Please define your metrics.");
         }
+
+        var existCountExpression = false;
+        for(var i=0;i<_measures.length;i++){
+            if(_measures[i].function.expression=="COUNT"){
+                existCountExpression=true;
+                break;
+            }
+        }
+        if(!existCountExpression){
+            errors.push("[COUNT] metric is required.");
+        }
+
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    }
+
+    $scope.check_cube_setting = function(){
+        var errors = [];
+
+        angular.forEach($scope.cubeMetaFrame.rowkey.aggregation_groups,function(group){
+            if(!group.length){
+                errors.push("Each aggregation group can't be empty.");
+            }
+        })
+
         var errorInfo = "";
         angular.forEach(errors,function(item){
             errorInfo+="\n"+item;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 8e676d2..810242e 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -23,8 +23,13 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
-    $scope.cubeConfig = cubeConfig;
 
+    if($scope.modelMode=="addNewModel"&&!ProjectModel.getSelectedProject()){
+        SweetAlert.swal('Oops...', 'Please select your project first.', 'warning');
+        $location.path("/models");
+    }
+
+    $scope.cubeConfig = cubeConfig;
 
     $scope.getPartitonColumns = function(tableName){
         var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
@@ -96,10 +101,11 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         $scope.model.project = ProjectModel.getSelectedProject();
     }
 
+
     $scope.prepareModel = function () {
         // generate column family
 
-        if ($scope.model.partition_desc.partition_date_column&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
+        if ($scope.model.partition_desc.partition_date_column!=null&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
             var dateStart = new Date($scope.model.partition_desc.partition_date_start);
             dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
             //switch selected time to utc timestamp
@@ -126,6 +132,8 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
     $scope.saveModel = function () {
 
+        $scope.prepareModel();
+
         try {
             angular.fromJson($scope.state.modelSchema);
         } catch (e) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 2ec1fa7..409582a 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -105,6 +105,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         else{
             //form validation
             if($scope.forms[$scope.curStep.form].$invalid){
+                $scope.forms[$scope.curStep.form].$sbumitted=true;
                 return false;
             }else{
                 //business rule check
@@ -222,6 +223,11 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
 
     $scope.goToStep = function(stepIndex){
+        if($scope.state.mode=="edit"){
+            if(stepIndex+1>=$scope.curStep.step){
+                return;
+            }
+        }
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index e9e942f..20ccffb 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -31,7 +31,6 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
         $scope.toggleTab = function(showModel){
             $scope.showModels = showModel;
-            console.log($scope.showModels);
         }
 
         $scope.modelList = ModelList;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/projectMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projectMeta.js b/webapp/app/js/controllers/projectMeta.js
index 9ca2092..d0e8781 100644
--- a/webapp/app/js/controllers/projectMeta.js
+++ b/webapp/app/js/controllers/projectMeta.js
@@ -60,9 +60,8 @@ KylinApp
                         }
                     }
 
+                    var _table_node_list = [];
                     angular.forEach(tables,function(_table){
-                            var _table_node_list = [];
-
                             var _table_node = {
                                 label:_table.name,
                                 data:_table,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 28e9f69..5366809 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -31,8 +31,8 @@ KylinApp.service('MetaModel',function(){
         dimensions:[],
         metrics:[],
         "partition_desc" : {
-            "partition_date_column" : '',
-            "partition_date_start" : 0,
+            "partition_date_column" : null,
+            "partition_date_start" : null,
             "partition_type" : 'APPEND'
         },
         last_modified:0
@@ -82,8 +82,8 @@ KylinApp.service('MetaModel',function(){
             dimensions:[],
             metrics:[],
             "partition_desc" : {
-                "partition_date_column" : '',
-                "partition_date_start" : 0,
+                "partition_date_column" : null,
+                "partition_date_start" : null,
                 "partition_type" : 'APPEND'
             },
             last_modified:0

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/model/tableModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/tableModel.js b/webapp/app/js/model/tableModel.js
index 55b4e7b..d3bc026 100755
--- a/webapp/app/js/model/tableModel.js
+++ b/webapp/app/js/model/tableModel.js
@@ -99,8 +99,8 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                     }
                 }
 
+                var _table_node_list = [];
                 angular.forEach(tables,function(_table){
-                        var _table_node_list = [];
 
                         var _table_node = {
                             label:_table.name,
@@ -120,6 +120,7 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                                     onSelect:function(branch){
                                         // set selected model
 //                                        _this.selectedSrcTable = branch.data;
+                                        _this.selectedSrcTable.selectedSrcColumn = branch.data;
                                         $log.info("selected column info:"+_column.name);
                                     }
                                 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 cb2eaed..ba2e20d 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -17,132 +17,134 @@
 -->
 
 <div ng-controller="CubeAdvanceSettingCtrl">
-<div>
-    <div class="form-group">
-        <h4 style="margin-left:42px">Aggregation Groups</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="cubeMetaFrame.rowkey.aggregation_groups.length > 0"
-               class="table table-hover list">
-            <tr class="row">
-                <th class="col-xs-1">ID</th>
-                <th class="col-xs-10">Aggregation Groups</th>
-                <th ng-if="state.mode=='edit'" class="col-xs-1"></th>
-            </tr>
-
-            <tr ng-repeat="aggregation_groups in cubeMetaFrame.rowkey.aggregation_groups" class="row">
-                <td class="col-xs-1">
-                    <!-- ID -->
-                    <b>{{($index + 1)}}</b>
-                </td>
-                <td class="col-xs-11">
-                    <!-- Dimensions -->
-                    <select ng-if="state.mode=='edit'" style="width: 100%"
-                            ng-model="aggregation_groups" required chosen multiple
-                            ng-change="refreshAggregationGroup(cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
-                            ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubeMetaFrame.rowkey.rowkey_columns">
-                        <option value=""></option>
-                    </select>
-                    <p ng-if="state.mode=='view'" style="word-wrap: break-word; word-break: normal;max-width: 1000px ">{{aggregation_groups}}</p>
-                </td>
-                <td ng-if="state.mode=='edit'" class="col-xs-1">
-                    <button class="btn btn-xs btn-info"
-                            ng-click="removeElement(cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
-                            class="fa fa-minus"></i>
-                    </button>
-                </td>
-            </tr>
-        </table>
-
-        <button class="btn btn-sm btn-info" style="margin-left:42px" ng-click="addNewAggregationGroup()"
-                ng-show="state.mode=='edit'">New Aggregation Group<i class="fa fa-plus"></i>
-        </button>
-
-
-    </div>
-
-
-    <div class="form-group">
-        <h4 style="margin-left:42px">Rowkeys</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="cubeMetaFrame.rowkey.rowkey_columns.length > 0"
-               class="table table-hover list"
-                >
-           <thead>
-                <tr>
-                    <th>ID</th>
-                    <th>Column</th>
-                    <th>Mandatory</th>
-                    <th>Dictionary</th>
-                    <th>Length</th>
-                    <th ng-if="state.mode=='edit'"></th>
+  <ng-form name="forms.cube_setting_form">
+    <div>
+        <div class="form-group">
+            <h4 style="margin-left:42px">Aggregation Groups</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="cubeMetaFrame.rowkey.aggregation_groups.length > 0"
+                   class="table table-hover list">
+                <tr class="row">
+                    <th class="col-xs-1">ID</th>
+                    <th class="col-xs-10">Aggregation Groups</th>
+                    <th ng-if="state.mode=='edit'" class="col-xs-1"></th>
                 </tr>
-           </thead>
 
-            <tbody ui-sortable="state.mode=='edit'" ng-model="cubeMetaFrame.rowkey.rowkey_columns">
-
-                <tr  ng-repeat="rowkey_column in cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
-
-                    <td>
+                <tr ng-repeat="aggregation_groups in cubeMetaFrame.rowkey.aggregation_groups" class="row">
+                    <td class="col-xs-1">
                         <!-- ID -->
-                        <span class="ng-binding" ng-class="state.mode=='edit'?'badge':''">{{($index + 1)}}</span>
-                    </td>
-                    <td>
-                        <!--Column Name -->
-                        <input type="text" class="form-control" placeholder="Column Name.." ng-if="state.mode=='edit'"
-                               tooltip="rowkey column name.." tooltip-trigger="focus"
-                               ng-model="rowkey_column.column" class="form-control">
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.column}}</span>
-                    </td>
-                    <td>
-                        <!-- Mandatory -->
-                        <button type="button " ng-if="state.mode=='edit'"
-                                class="btn btn-xs btn-default {{rowkey_column.mandatory? 'active':''}}"
-                                ng-model="rowkey_column.mandatory"
-                                ng-click="updateMandatory(rowkey_column);"
-                                btn-checkbox btn-checkbox-true="true" btn-checkbox-false="false">
-                            {{rowkey_column.mandatory? 'Y':'N'}}
-                        </button>
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.mandatory? 'Y':'N'}}</span>
+                        <b>{{($index + 1)}}</b>
                     </td>
-
-                    <td>
-                        <!--Use Dictionary-->
-                        <div>
-                            <select ng-if="state.mode=='edit'" style="width:80px;"
-                                    chosen ng-model="rowkey_column.dictionary"
-                                    ng-change="dictionaryUpdated(rowkey_column);"
-                                    ng-options="dt as dt for dt in cubeConfig.dictionaries">
-                                <option value=""></option>
-                            </select>
-                            <span ng-if="state.mode=='view'">{{rowkey_column.dictionary}}</span>
-                        </div>
-                    </td>
-
-                    <td>
-                        <!--Column Length -->
-                        <input type="text" class="form-control" placeholder="Column Length.." ng-if="state.mode=='edit'"
-                               tooltip="rowkey column length.." tooltip-trigger="focus"
-                               ng-disabled="rowkey_column.dictionary=='true'"
-                               ng-model="rowkey_column.length"  class="form-control">
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.length}}</span>
+                    <td class="col-xs-11">
+                        <!-- Dimensions -->
+                        <select ng-if="state.mode=='edit'" style="width: 100%"
+                                ng-model="aggregation_groups"  chosen multiple
+                                ng-change="refreshAggregationGroup(cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
+                                ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubeMetaFrame.rowkey.rowkey_columns">
+                            <option value=""></option>
+                        </select>
+                        <p ng-if="state.mode=='view'" style="word-wrap: break-word; word-break: normal;max-width: 1000px ">{{aggregation_groups}}</p>
                     </td>
-
-
-                    <td ng-if="state.mode=='edit'">
+                    <td ng-if="state.mode=='edit'" class="col-xs-1">
                         <button class="btn btn-xs btn-info"
-                                ng-click="removeElement(cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
+                                ng-click="removeElement(cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
                                 class="fa fa-minus"></i>
                         </button>
                     </td>
                 </tr>
-            </tbody>
-        </table>
-
-        <button class="btn btn-sm btn-info" style="margin-left:42px"
-                ng-click="addNewRowkeyColumn()" ng-show="state.mode=='edit'">New Rowkey Column<i class="fa fa-plus"></i></button>
+            </table>
+
+            <button class="btn btn-sm btn-info" style="margin-left:42px" ng-click="addNewAggregationGroup()"
+                    ng-show="state.mode=='edit'">New Aggregation Group<i class="fa fa-plus"></i>
+            </button>
+
+
+        </div>
+
+
+        <div class="form-group">
+            <h4 style="margin-left:42px">Rowkeys</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="cubeMetaFrame.rowkey.rowkey_columns.length > 0"
+                   class="table table-hover list"
+                    >
+               <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Column</th>
+                        <th>Mandatory</th>
+                        <th>Dictionary</th>
+                        <th>Length</th>
+                        <th ng-if="state.mode=='edit'"></th>
+                    </tr>
+               </thead>
+
+                <tbody ui-sortable="state.mode=='edit'" ng-model="cubeMetaFrame.rowkey.rowkey_columns">
+
+                    <tr  ng-repeat="rowkey_column in cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
+
+                        <td>
+                            <!-- ID -->
+                            <span class="ng-binding" ng-class="state.mode=='edit'?'badge':''">{{($index + 1)}}</span>
+                        </td>
+                        <td>
+                            <!--Column Name -->
+                            <input type="text" class="form-control" placeholder="Column Name.." ng-if="state.mode=='edit'"
+                                   tooltip="rowkey column name.." tooltip-trigger="focus"
+                                   ng-model="rowkey_column.column" class="form-control">
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.column}}</span>
+                        </td>
+                        <td>
+                            <!-- Mandatory -->
+                            <button type="button " ng-if="state.mode=='edit'"
+                                    class="btn btn-xs btn-default {{rowkey_column.mandatory? 'active':''}}"
+                                    ng-model="rowkey_column.mandatory"
+                                    ng-click="updateMandatory(rowkey_column);"
+                                    btn-checkbox btn-checkbox-true="true" btn-checkbox-false="false">
+                                {{rowkey_column.mandatory? 'Y':'N'}}
+                            </button>
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.mandatory? 'Y':'N'}}</span>
+                        </td>
+
+                        <td>
+                            <!--Use Dictionary-->
+                            <div>
+                                <select ng-if="state.mode=='edit'" style="width:80px;"
+                                        chosen ng-model="rowkey_column.dictionary"
+                                        ng-change="dictionaryUpdated(rowkey_column);"
+                                        ng-options="dt as dt for dt in cubeConfig.dictionaries">
+                                    <option value=""></option>
+                                </select>
+                                <span ng-if="state.mode=='view'">{{rowkey_column.dictionary}}</span>
+                            </div>
+                        </td>
+
+                        <td>
+                            <!--Column Length -->
+                            <input type="text" class="form-control" placeholder="Column Length.." ng-if="state.mode=='edit'"
+                                   tooltip="rowkey column length.." tooltip-trigger="focus"
+                                   ng-disabled="rowkey_column.dictionary=='true'"
+                                   ng-model="rowkey_column.length"  class="form-control">
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.length}}</span>
+                        </td>
+
+
+                        <td ng-if="state.mode=='edit'">
+                            <button class="btn btn-xs btn-info"
+                                    ng-click="removeElement(cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
+                                    class="fa fa-minus"></i>
+                            </button>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+
+            <button class="btn btn-sm btn-info" style="margin-left:42px"
+                    ng-click="addNewRowkeyColumn()" ng-show="state.mode=='edit'">New Rowkey Column<i class="fa fa-plus"></i></button>
+        </div>
     </div>
-</div>
+  </ng-form>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index d724ffd..1833818 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -25,10 +25,14 @@
                     <label class="col-xs-12 col-sm-3 control-label no-padding-right">
                         <b>Model Name</b>
                     </label>
-                    <div class="col-xs-12 col-sm-6"  ng-class="forms.cube_info_form.model_name.$invalid?'has-error':''">
-                        <input ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.cube_info_form.model_name.$invalid && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)}">
+                        <input disabled ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
+                               placeholder="You can use letters, numbers, and '_'"
+                               ng-maxlength=100 ng-pattern="/^\w+$/"
                                ng-model="cubeMetaFrame.model_name"/>
-                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required">The model is required</small>
+                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is required.</small>
+                        <small class="help-block" ng-show="!forms.cube_info_form.model_name.$error.required&&forms.cube_info_form.model_name.$invalid && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is invalid.</small>
+
                         <span ng-if="state.mode=='view'">
                             {{cubeMetaFrame.model_name}}
                         </span>
@@ -42,13 +46,13 @@
                     <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
                         <b>Cube Name</b>
                     </label>
-                    <div class="col-xs-12 col-sm-6" ng-class="forms.cube_info_form.cube_name.$invalid?'has-error':''">
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.cube_name.$sbumitted)}">
                         <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
                                ng-model="cubeMetaFrame.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
-                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required  && forms.cube_info_form.cube_name.$dirty">Cube name is required.</small>
-                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$invalid && forms.cube_info_form.cube_name.$dirty && !forms.cube_info_form.cube_name.$error.required">Cube name is invalid.</small>
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is required.</small>
+                        <small class="help-block" ng-show="!forms.cube_info_form.cube_name.$error.required&&forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is invalid.</small>
 
                         <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
                     </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/cubes/cube_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_schema.html b/webapp/app/partials/cubes/cube_schema.html
index 6f3475c..b35e31a 100644
--- a/webapp/app/partials/cubes/cube_schema.html
+++ b/webapp/app/partials/cubes/cube_schema.html
@@ -21,9 +21,6 @@
         <h4 class="box-title text-info">Cube Designer</h4>
     </div>
     <div class="box-body">
-        <ng-form name="design_form" ng-submit="">
-            <!-- Add a mock button to avoid auto submit-->
-            <button ng-click="" ng-show="false"></button>
             <div>
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
@@ -50,18 +47,17 @@
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkCubeForm()?nextView():''" ng-disabled="forms[curStep.form].$invalid"
                                 ng-show="curStep.title!='Overview'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareCube();saveCube(design_form)" ng-disabled="design_form.$invalid"
+                        <button class="btn btn-primary" ng-click="prepareCube();saveCube()" ng-disabled="design_form.$invalid"
                                 ng-if="curStep.title=='Overview' && state.mode=='edit'">
                             Save
                         </button>
                     </div>
                 </div>
             </div>
-        </ng-form>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index 43bf27d..bac16cd 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -26,7 +26,7 @@
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
-                <a class="navbar-brand" href="home" style="padding: 2px 10px 0px 0px"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
+                <a class="navbar-brand" href="query" style="padding: 2px 10px 0px 0px"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
             </div>
 
             <div class="navbar-collapse collapse" collapse="isCollapsed">
@@ -34,7 +34,7 @@
                     <li class="project-cntnr"  style="padding:7px 15px;background-color:#2e8965;" ng-if="userService.isAuthorized()">
                         <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
                                 ng-options="project.name as project.name for project in projectModel.projects"
-                                style="width: 150px"
+                                style="width: 180px"
                                 data-placeholder="select a project"
                                 class="chosen-select">
                             <option ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null"  value=""> -- Choose Project -- </option>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 98ad8e3..035c777 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -40,7 +40,7 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></label>
-                <div class="col-xs-12 col-sm-6">
+                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null?'has-error':''">
 
                     <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
                             ng-model="model.partition_desc.partition_date_column"
@@ -49,7 +49,9 @@
                             ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
                         <option value="">--Select Partition Column--</option>
                     </select>
+                    <small class="help-block" ng-show="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null">Please select your partitoin date column.</small>
                     <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+
                     <span ng-if="state.mode=='view'">
                         {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
                 </div>
@@ -60,11 +62,12 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
-                <div class="col-xs-12 col-sm-6">
+                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null?'has-error':''">
                   <!--edit model will convert in MetaModel.converDateToGMT-->
                     <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
                            ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
                            placeholder="Click to choose start date..." is-open="opened" />
+                    <small class="help-block" ng-show="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null">Please input start date when partition date column selected.</small>
                   <!--vier model will convert use filter-->
                     <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
                 </div>
@@ -131,7 +134,6 @@
                         <ol class="text-info">
                             <li>Not required,leave as default if cube always need full build</li>
                             <li>Partition column will select 'date' or 'string' type column from fact table</li>
-                            <li>If column selected,please indicate start date to just pull certain data from source</li>
                         </ol>
                     </div>
                 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 79c6533..5f31201 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -25,11 +25,10 @@
             <label class="col-xs-12 col-sm-2 concube.detailtrol-label no-padding-right font-color-default">
                 <b>Fact Table</b>
             </label>
-            <div class="col-xs-12 col-sm-6" ng-class="forms.data_model_form.innerform.typeahead.$invalid?'has-error':''">
+            <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.innerform.typeahead.$invalid && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$sbumitted)}">
                 <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
                            title="name" model="model.fact_table" required="true"></typeahead>
-                <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required">The fact table is required</small>
-
+                <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.$sbumitted)">The fact table is required</small>
                 <span ng-if="state.mode=='view'">{{model.fact_table}}</span>
             </div>
         </div>
@@ -111,13 +110,15 @@
                 <div class="col-xs-8">
                     <ng-form name="lookup_form">
                     <!--Table Name-->
-                    <div class="form-group" ng-class="lookup_form.innerform.typeahead.$invalid?'has-error':''">
+                    <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 class="col-xs-12 col-sm-6">
-                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" required="true" title="name" model="newLookup.table"></typeahead>
+                            <div ng-class="{'has-error':lookup_form.innerform.typeahead.$invalid && (lookup_form.innerform.typeahead.$dirty||forms.model_info_form.$sbumitted)}">
+                                <div class="col-xs-12 col-sm-6">
+                                    <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" required="true" title="name" model="newLookup.table"></typeahead>
+                                    <small class="help-block" ng-show="lookup_form.innerform.typeahead.$invalid && (lookup_form.innerform.typeahead.$dirty||forms.model_info_form.$sbumitted)">Table name required</small>
+                                </div>
                             </div>
-                            <small class="help-block" ng-show="lookup_form.innerform.typeahead.$error.required">Table name required</small>
                         </div>
                     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 095203d..e7fe07e 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -18,6 +18,7 @@
 
 <div ng-controller="ModelDimensionsCtrl">
 
+   <ng-form name="forms.model_dimensions_form" novalidate>
     <!-- Dimensions Summary -->
     <div class="dataTables_wrapper form-inline no-footer">
         <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
@@ -32,8 +33,8 @@
             </div>
         </div>
 
-        <ng-form name="forms.model_dimensions_form" novalidate>
          <!-- VIEW MODE -->
+        <div class="row">
             <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
                 <thead>
                     <tr>
@@ -53,13 +54,13 @@
                             <span>{{dimension.table}}</span>
                         </td>
                         <!--Table Name -->
-                        <td>
+                        <td class="tb-breakword">
                             <span>{{dimension.columns}}</span>
                         </td>
                     </tr>
                 </tbody>
             </table>
-        </ng-form>
+        </div>
         <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
             <h4 style="margin-left:42px">Dimensions</h4>
             <table style="margin-left:42px; width:92%"
@@ -82,7 +83,7 @@
                     <td class="col-xs-9">
                         <!-- Dimensions -->
                         <select ng-if="state.mode=='edit'" style="width: 100%"
-                                ng-model="model.dimensions[$index].columns" required chosen multiple
+                                ng-model="model.dimensions[$index].columns" chosen multiple
                                 ng-change=""
                                 ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
                             <option value=""></option>
@@ -93,4 +94,5 @@
          </div>
 
     </div>
-</div>
\ No newline at end of file
+   </ng-form>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index 21a8185..097739c 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -20,27 +20,6 @@
     <div class="col-xs-8">
         <!--Project-->
         <ng-form name="forms.model_info_form" novalidate>
-            <div class="form-group">
-                <div class="row">
-                    <label class="col-xs-3 control-label no-padding-right">
-                        <a ng-if="state.mode=='edit'" href="projects">
-                            <b>Project</b>
-                        </a>
-                        <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
-                    </label>
-                    <div class="col-xs-6" ng-class="forms.model_info_form.project_name.$invalid?'has-error':''">
-                         <!--edit-->
-                        <input ng-if="state.mode=='edit'" required name="project_name" type="text" class="form-control"
-                               ng-model="model.project"/>
-                        <small class="help-block" ng-show="forms.model_info_form.project_name.$error.required">The project is required</small>
-
-                        <!--view-->
-                        <span ng-if="state.mode=='view'">
-                            {{model.project}}
-                        </span>
-                    </div>
-                </div>
-            </div>
 
             <!--Model Name-->
             <div class="form-group">
@@ -49,15 +28,15 @@
                         <b>Model Name</b>
                     </label>
 
-                    <div class="col-xs-12 col-sm-6" ng-class="forms.model_info_form.model_name.$invalid?'has-error':''">
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.model_info_form.model_name.$invalid && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)}">
 
                         <!-- edit -->
                         <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
                                ng-model="model.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
-                        <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required  && forms.model_info_form.model_name.$dirty">Model name is required.</small>
-                        <small class="help-block" ng-show="forms.model_info_form.model_name.$invalid && forms.model_info_form.model_name.$dirty && !forms.model_info_form.model_name.$error.required"> Model name is invalid.</small>
+                        <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is required.</small>
+                        <small class="help-block" ng-show="!forms.model_info_form.model_name.$error.required&&forms.model_info_form.model_name.$invalid && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is invalid.</small>
 
 
                         <span ng-if="state.mode=='view'">{{model.name}}</span>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 2f58bed..b2cf20c 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -14,7 +14,7 @@
 * 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.
--->
+-->A
 
 <!--hide when view model and no model selected-->
 <div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
@@ -46,16 +46,16 @@
                         </div>
                     </div>
                     <div class="col-xs-4 pull-right">
-                        <button class="btn btn-prev" ng-click="checkForm()?preView():''" ng-show="curStep.title!='Model Info'">
+                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Model Info'">
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''"
+                        <button id="nextButton" class="btn btn-success btn-next" ng-disabled="forms[curStep.form].$invalid" ng-click="checkForm()?nextView():''"
                                 ng-show="curStep.title!='Settings'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareModel();saveModel()"
+                        <button class="btn btn-primary" ng-click="saveModel()"
                                 ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/projects/project_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/projects/project_table_tree.html b/webapp/app/partials/projects/project_table_tree.html
index 3ee6d5b..b0c1e53 100644
--- a/webapp/app/partials/projects/project_table_tree.html
+++ b/webapp/app/partials/projects/project_table_tree.html
@@ -24,7 +24,7 @@
     </div>
     <div class="space-4"></div>
     <div style="width:310px; height:800px; overflow:auto">
-        <abn-tree ng-if="selectedSrcDb.length > 0"
+        <abn-tree
                 tree-data         = "selectedSrcDb"
                 tree-control      = "my_tree"
                 icon-leaf         = "fa fa-columns"