You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2015/07/22 06:13:17 UTC

[27/47] incubator-kylin git commit: KYLIN-875 rename modules: core-common, core-cube, core-dictionary, core-cube

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/java/org/apache/kylin/cube/kv/RowKeyEncoderTest.java
----------------------------------------------------------------------
diff --git a/core-cube/src/test/java/org/apache/kylin/cube/kv/RowKeyEncoderTest.java b/core-cube/src/test/java/org/apache/kylin/cube/kv/RowKeyEncoderTest.java
new file mode 100644
index 0000000..c8164e4
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/cube/kv/RowKeyEncoderTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.cube.kv;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.apache.kylin.common.util.Bytes;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.kylin.common.util.LocalFileMetadataTestCase;
+import org.apache.kylin.cube.cuboid.Cuboid;
+import org.apache.kylin.metadata.MetadataManager;
+
+/**
+ * @author George Song (ysong1)
+ * 
+ */
+public class RowKeyEncoderTest extends LocalFileMetadataTestCase {
+
+    @Before
+    public void setUp() throws Exception {
+        this.createTestMetadata();
+        MetadataManager.clearCache();
+    }
+
+    @After
+    public void after() throws Exception {
+        this.cleanupTestMetadata();
+    }
+
+    @Test
+    public void testEncodeWithoutSlr() throws Exception {
+        CubeInstance cube = CubeManager.getInstance(getTestConfig()).getCube("TEST_KYLIN_CUBE_WITHOUT_SLR_READY");
+        // CubeSegment seg = cube.getTheOnlySegment();
+        CubeDesc cubeDesc = cube.getDescriptor();
+        // String data =
+        // "2013-08-18Abbigliamento e accessoriDonna: AccessoriSciarpFoulard e ScialliAuctionItalyRegular";
+        byte[][] data = new byte[8][];
+        data[0] = Bytes.toBytes("2012-12-15");
+        data[1] = Bytes.toBytes("11848");
+        data[2] = Bytes.toBytes("Health & Beauty");
+        data[3] = Bytes.toBytes("Fragrances");
+        data[4] = Bytes.toBytes("Women");
+        data[5] = Bytes.toBytes("FP-GTC");
+        data[6] = Bytes.toBytes("0");
+        data[7] = Bytes.toBytes("15");
+
+        long baseCuboidId = Cuboid.getBaseCuboidId(cubeDesc);
+        Cuboid baseCuboid = Cuboid.findById(cubeDesc, baseCuboidId);
+        AbstractRowKeyEncoder rowKeyEncoder = AbstractRowKeyEncoder.createInstance(cube.getFirstSegment(), baseCuboid);
+
+        byte[] encodedKey = rowKeyEncoder.encode(data);
+        assertEquals(30, encodedKey.length);
+        byte[] cuboidId = Arrays.copyOfRange(encodedKey, 0, 8);
+        byte[] rest = Arrays.copyOfRange(encodedKey, 8, encodedKey.length);
+        assertEquals(255, Bytes.toLong(cuboidId));
+        assertArrayEquals(new byte[] { 11, 55, -13, 13, 22, 34, 121, 70, 80, 45, 71, 84, 67, 9, 9, 9, 9, 9, 9, 0, 10, 5 }, rest);
+    }
+
+    @Test
+    public void testEncodeWithSlr() throws Exception {
+        CubeInstance cube = CubeManager.getInstance(getTestConfig()).getCube("TEST_KYLIN_CUBE_WITH_SLR_READY");
+        // CubeSegment seg = cube.getTheOnlySegment();
+        CubeDesc cubeDesc = cube.getDescriptor();
+        // String data =
+        // "1234567892013-08-18Abbigliamento e accessoriDonna: AccessoriSciarpFoulard e ScialliAuctionItalyRegular";
+        byte[][] data = new byte[9][];
+        data[0] = Bytes.toBytes("123456789");
+        data[1] = Bytes.toBytes("2012-12-15");
+        data[2] = Bytes.toBytes("11848");
+        data[3] = Bytes.toBytes("Health & Beauty");
+        data[4] = Bytes.toBytes("Fragrances");
+        data[5] = Bytes.toBytes("Women");
+        data[6] = Bytes.toBytes("FP-GTC");
+        data[7] = Bytes.toBytes("0");
+        data[8] = Bytes.toBytes("15");
+
+        long baseCuboidId = Cuboid.getBaseCuboidId(cubeDesc);
+        Cuboid baseCuboid = Cuboid.findById(cubeDesc, baseCuboidId);
+        AbstractRowKeyEncoder rowKeyEncoder = AbstractRowKeyEncoder.createInstance(cube.getFirstSegment(), baseCuboid);
+
+        byte[] encodedKey = rowKeyEncoder.encode(data);
+        assertEquals(48, encodedKey.length);
+        byte[] sellerId = Arrays.copyOfRange(encodedKey, 8, 26);
+        byte[] cuboidId = Arrays.copyOfRange(encodedKey, 0, 8);
+        byte[] rest = Arrays.copyOfRange(encodedKey, 26, encodedKey.length);
+        assertTrue(Bytes.toString(sellerId).startsWith("123456789"));
+        assertEquals(511, Bytes.toLong(cuboidId));
+        assertArrayEquals(new byte[] { 11, 55, -13, 13, 22, 34, 121, 70, 80, 45, 71, 84, 67, 9, 9, 9, 9, 9, 9, 0, 10, 5 }, rest);
+    }
+
+    @Test
+    public void testEncodeWithSlr2() throws Exception {
+        CubeInstance cube = CubeManager.getInstance(getTestConfig()).getCube("TEST_KYLIN_CUBE_WITH_SLR_READY");
+        // CubeSegment seg = cube.getTheOnlySegment();
+        CubeDesc cubeDesc = cube.getDescriptor();
+        // String data =
+        // "1234567892013-08-18Abbigliamento e accessoriDonna: AccessoriSciarpFoulard e ScialliAuctionItalyRegular";
+        byte[][] data = new byte[9][];
+        data[0] = Bytes.toBytes("123456789");
+        data[1] = null;
+        data[2] = null;
+        data[3] = null;
+        data[4] = null;
+        data[5] = null;
+        data[6] = null;
+        data[7] = null;
+        data[8] = null;
+
+        long baseCuboidId = Cuboid.getBaseCuboidId(cubeDesc);
+        Cuboid baseCuboid = Cuboid.findById(cubeDesc, baseCuboidId);
+        AbstractRowKeyEncoder rowKeyEncoder = AbstractRowKeyEncoder.createInstance(cube.getFirstSegment(), baseCuboid);
+
+        byte[] encodedKey = rowKeyEncoder.encode(data);
+        assertEquals(48, encodedKey.length);
+        byte[] sellerId = Arrays.copyOfRange(encodedKey, 8, 26);
+        byte[] cuboidId = Arrays.copyOfRange(encodedKey, 0, 8);
+        byte[] rest = Arrays.copyOfRange(encodedKey, 26, encodedKey.length);
+        assertTrue(Bytes.toString(sellerId).startsWith("123456789"));
+        assertEquals(511, Bytes.toLong(cuboidId));
+        assertArrayEquals(new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, rest);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
----------------------------------------------------------------------
diff --git a/core-cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java b/core-cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
new file mode 100644
index 0000000..369e6f6
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/cube/kv/RowValueDecoderTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.cube.kv;
+
+import org.apache.hadoop.io.LongWritable;
+import org.apache.kylin.common.util.LocalFileMetadataTestCase;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.HBaseColumnDesc;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.measure.MeasureCodec;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+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)
+ * 
+ */
+public class RowValueDecoderTest extends LocalFileMetadataTestCase {
+
+    @Before
+    public void setUp() throws Exception {
+        this.createTestMetadata();
+        MetadataManager.clearCache();
+    }
+
+    @After
+    public void after() throws Exception {
+        this.cleanupTestMetadata();
+    }
+
+    @Test
+    public void testDecode() 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("333.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);
+
+        buf.flip();
+        byte[] valueBytes = new byte[buf.limit()];
+        System.arraycopy(buf.array(), 0, valueBytes, 0, buf.limit());
+
+        RowValueDecoder rowValueDecoder = new RowValueDecoder(hbaseCol);
+        for (MeasureDesc measure : cubeDesc.getMeasures()) {
+            FunctionDesc aggrFunc = measure.getFunction();
+            int index = hbaseCol.findMeasureIndex(aggrFunc);
+            rowValueDecoder.setIndex(index);
+        }
+
+        rowValueDecoder.decode(valueBytes);
+        Object[] measureValues = rowValueDecoder.getValues();
+        //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/7e8896ac/core-cube/src/test/java/org/apache/kylin/cube/project/ProjectManagerTest.java
----------------------------------------------------------------------
diff --git a/core-cube/src/test/java/org/apache/kylin/cube/project/ProjectManagerTest.java b/core-cube/src/test/java/org/apache/kylin/cube/project/ProjectManagerTest.java
new file mode 100644
index 0000000..20f976b
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/cube/project/ProjectManagerTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.cube.project;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.common.util.LocalFileMetadataTestCase;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.realization.IRealization;
+import org.apache.kylin.metadata.realization.RealizationType;
+
+/**
+ * @author xduo
+ */
+public class ProjectManagerTest extends LocalFileMetadataTestCase {
+
+    @Before
+    public void setUp() throws Exception {
+        this.createTestMetadata();
+    }
+
+    @After
+    public void after() throws Exception {
+        this.cleanupTestMetadata();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDropNonemptyProject() throws IOException {
+        ProjectManager.getInstance(getTestConfig()).dropProject("DEFAULT");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDropNonexistProject() throws IOException {
+        ProjectManager.getInstance(getTestConfig()).dropProject("DEFAULT???");
+    }
+
+    @Test
+    public void testNewProject() throws Exception {
+        ProjectManager prjMgr = ProjectManager.getInstance(getTestConfig());
+        CubeManager cubeMgr = CubeManager.getInstance(getTestConfig());
+        CubeDescManager cubeDescMgr = CubeDescManager.getInstance(getTestConfig());
+        
+        int originalProjectCount = prjMgr.listAllProjects().size();
+        int originalCubeCount = cubeMgr.listAllCubes().size();
+        int originalCubeCountInDefault = prjMgr.listAllRealizations("default").size();
+        ResourceStore store = getStore();
+
+        // clean legacy in case last run failed
+        store.deleteResource("/cube/cube_in_alien_project.json");
+
+        CubeDesc desc = cubeDescMgr.getCubeDesc("test_kylin_cube_with_slr_desc");
+        CubeInstance createdCube = cubeMgr.createCube("cube_in_alien_project", "alien", desc, null);
+        assertTrue(createdCube == cubeMgr.getCube("cube_in_alien_project"));
+        ProjectManager proMgr = ProjectManager.getInstance(getTestConfig());
+        Set<IRealization> realizations = proMgr.listAllRealizations("alien");
+        assertTrue(realizations.contains(createdCube));
+
+        System.out.println(JsonUtil.writeValueAsIndentString(createdCube));
+
+        assertTrue(prjMgr.listAllProjects().size() == originalProjectCount + 1);
+        assertTrue(prjMgr.listAllRealizations("ALIEN").iterator().next().getName().equalsIgnoreCase("CUBE_IN_ALIEN_PROJECT"));
+        assertTrue(cubeMgr.listAllCubes().size() == originalCubeCount + 1);
+
+        prjMgr.moveRealizationToProject(RealizationType.CUBE, "cube_in_alien_project", "default", null);
+        assertTrue(prjMgr.listAllRealizations("ALIEN").size() == 0);
+        assertTrue(prjMgr.listAllRealizations("default").size() == originalCubeCountInDefault + 1);
+        assertTrue(ProjectManager.getInstance(getTestConfig()).listAllRealizations("default").contains(createdCube));
+
+        prjMgr.moveRealizationToProject(RealizationType.CUBE, "cube_in_alien_project", "alien", null);
+        assertTrue(prjMgr.listAllRealizations("ALIEN").size() == 1);
+        assertTrue(prjMgr.listAllRealizations("default").size() == originalCubeCountInDefault);
+        assertTrue(ProjectManager.getInstance(getTestConfig()).listAllRealizations("alien").contains(createdCube));
+
+        CubeInstance droppedCube = cubeMgr.dropCube("cube_in_alien_project", true);
+
+        assertTrue(createdCube == droppedCube);
+        assertNull(cubeMgr.getCube("cube_in_alien_project"));
+        assertTrue(prjMgr.listAllProjects().size() == originalProjectCount + 1);
+        assertTrue(cubeMgr.listAllCubes().size() == originalCubeCount);
+
+        prjMgr.dropProject("alien");
+        assertTrue(prjMgr.listAllProjects().size() == originalProjectCount);
+    }
+
+    @Test
+    public void testExistingProject() throws Exception {
+        ProjectManager prjMgr = ProjectManager.getInstance(getTestConfig());
+        CubeManager cubeMgr = CubeManager.getInstance(getTestConfig());
+        CubeDescManager cubeDescMgr = CubeDescManager.getInstance(getTestConfig());
+        
+        int originalProjectCount = prjMgr.listAllProjects().size();
+        int originalCubeCount = cubeMgr.listAllCubes().size();
+        ResourceStore store = getStore();
+
+        // clean legacy in case last run failed
+        store.deleteResource("/cube/new_cube_in_default.json");
+
+        CubeDesc desc = cubeDescMgr.getCubeDesc("test_kylin_cube_with_slr_desc");
+        CubeInstance createdCube = cubeMgr.createCube("new_cube_in_default", ProjectInstance.DEFAULT_PROJECT_NAME, desc, null);
+        assertTrue(createdCube == cubeMgr.getCube("new_cube_in_default"));
+
+        System.out.println(JsonUtil.writeValueAsIndentString(createdCube));
+
+        assertTrue(prjMgr.listAllProjects().size() == originalProjectCount);
+        assertTrue(cubeMgr.listAllCubes().size() == originalCubeCount + 1);
+
+        CubeInstance droppedCube = cubeMgr.dropCube("new_cube_in_default", true);
+
+        assertTrue(createdCube == droppedCube);
+        assertNull(cubeMgr.getCube("new_cube_in_default"));
+        assertTrue(prjMgr.listAllProjects().size() == originalProjectCount);
+        assertTrue(cubeMgr.listAllCubes().size() == originalCubeCount);
+    }
+
+    @Test
+    public void testProjectsDrop() throws IOException {
+        ProjectManager prjMgr = ProjectManager.getInstance(getTestConfig());
+        CubeManager cubeMgr = CubeManager.getInstance(getTestConfig());
+        
+        CubeInstance cube = cubeMgr.getCube("test_kylin_cube_with_slr_empty");
+        assertTrue(prjMgr.getRealizationsByTable("default", "default.test_kylin_fact").contains(cube));
+        assertTrue(prjMgr.listAllRealizations("default").contains(cube));
+
+        cubeMgr.dropCube(cube.getName(), true);
+
+        assertTrue(!prjMgr.getRealizationsByTable("default", "default.test_kylin_fact").contains(cube));
+        assertTrue(!prjMgr.listAllRealizations("default").contains(cube));
+    }
+
+    @Test
+    public void testProjectsLoadAfterProjectChange() throws IOException {
+        ProjectManager prjMgr = ProjectManager.getInstance(getTestConfig());
+        CubeManager cubeMgr = CubeManager.getInstance(getTestConfig());
+        
+        CubeInstance cube = cubeMgr.getCube("test_kylin_cube_with_slr_empty");
+        assertTrue(prjMgr.getRealizationsByTable("default", "default.test_kylin_fact").contains(cube));
+
+        prjMgr.removeRealizationsFromProjects(RealizationType.CUBE, cube.getName());
+
+        assertTrue(!prjMgr.getRealizationsByTable("default", "default.test_kylin_fact").contains(cube));
+
+        prjMgr.moveRealizationToProject(RealizationType.CUBE, cube.getName(), "default", "tester");
+
+        assertTrue(prjMgr.getRealizationsByTable("default", "default.test_kylin_fact").contains(cube));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
----------------------------------------------------------------------
diff --git a/core-cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java b/core-cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
new file mode 100644
index 0000000..17db72c
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/metadata/MetadataUpgradeTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.metadata;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.util.LocalFileMetadataTestCase;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.DimensionDesc;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.model.TableDesc;
+import org.junit.*;
+
+import java.util.List;
+
+/**
+ * Test the data model upgrade
+ * @author shaoshi
+ *
+ */
+@Ignore("Not needed, the migrate and test has been moved to CubeMetadataUpgrade.java")
+public class MetadataUpgradeTest extends LocalFileMetadataTestCase {
+
+    @Before
+    public void setUp() throws Exception {
+        staticCreateTestMetadata(LOCALMETA_TEST_DATA_V1);
+    }
+
+    @After
+    public void after() throws Exception {
+        //this.cleanupTestMetadata();
+    }
+
+    @Test
+    public void testCubeDescUpgrade() throws Exception {
+
+        String[] sampleCubeDescs = new String[] { "test_kylin_cube_with_slr_desc", "test_kylin_cube_with_slr_left_join_desc", "test_kylin_cube_without_slr_desc", "test_kylin_cube_without_slr_left_join_desc" };
+
+        for (String name : sampleCubeDescs)
+            checkCubeDesc(name);
+
+    }
+    
+    @Test
+    public void testTableDescUpgrade() throws Exception {
+
+        MetadataManager metaMgr = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        TableDesc fact = metaMgr.getTableDesc("default.test_kylin_fact");
+        
+        @SuppressWarnings("deprecation")
+        String oldResLocation = fact.getResourcePathV1();
+        String newResLocation = fact.getResourcePath();
+        
+        ResourceStore store = ResourceStore.getStore(KylinConfig.getInstanceFromEnv());
+        
+        Assert.assertTrue(store.exists(newResLocation));
+        Assert.assertTrue(!store.exists(oldResLocation));
+        
+        
+        String oldExdResLocation = TableDesc.concatExdResourcePath("test_kylin_fact".toUpperCase());
+        String newExdResLocation = TableDesc.concatExdResourcePath("default.test_kylin_fact".toUpperCase());
+        
+        Assert.assertTrue(store.exists(newExdResLocation));
+        Assert.assertTrue(!store.exists(oldExdResLocation));
+        
+    }
+
+    private void checkCubeDesc(String descName) {
+        CubeDescManager cubeDescMgr = CubeDescManager.getInstance(KylinConfig.getInstanceFromEnv());
+        CubeDesc cubedesc1 = cubeDescMgr.getCubeDesc(descName);
+        Assert.assertNotNull(cubedesc1);
+        DataModelDesc model = cubedesc1.getModel();
+        Assert.assertNotNull(model);
+        Assert.assertTrue(model.getLookups().length > 0);
+
+        List<DimensionDesc> dims = cubedesc1.getDimensions();
+
+        Assert.assertTrue(dims.size() > 0);
+
+        for (DimensionDesc dim : dims) {
+            Assert.assertTrue(dim.getColumn().length > 0);
+        }
+
+        Assert.assertTrue(cubedesc1.getMeasures().size() > 0);
+
+        CubeManager cubeMgr = CubeManager.getInstance(KylinConfig.getInstanceFromEnv());
+        List<CubeInstance> cubes = cubeMgr.getCubesByDesc(descName);
+
+        Assert.assertTrue(cubes.size() > 0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
----------------------------------------------------------------------
diff --git a/core-cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java b/core-cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
new file mode 100644
index 0000000..80a1543
--- /dev/null
+++ b/core-cube/src/test/java/org/apache/kylin/metadata/measure/MeasureCodecTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.metadata.measure;
+
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import org.apache.hadoop.io.DoubleWritable;
+import org.apache.hadoop.io.LongWritable;
+import org.apache.kylin.common.hll.HyperLogLogPlusCounter;
+import org.apache.kylin.cube.kv.RowConstants;
+import org.apache.kylin.metadata.model.FunctionDesc;
+import org.apache.kylin.metadata.model.MeasureDesc;
+import org.junit.Test;
+
+/**
+ * 
+ */
+public class MeasureCodecTest {
+
+    @Test
+    public void basicTest() {
+        MeasureDesc descs[] = new MeasureDesc[] { measure("double"), measure("long"), measure("decimal"), measure("HLLC16") };
+        MeasureCodec codec = new MeasureCodec(descs);
+
+        DoubleWritable d = new DoubleWritable(1.0);
+        LongWritable l = new LongWritable(2);
+        BigDecimal b = new BigDecimal("333.1234");
+        HyperLogLogPlusCounter hllc = new HyperLogLogPlusCounter(16);
+        hllc.add("1234567");
+        hllc.add("abcdefg");
+        Object values[] = new Object[] { d, l, b, hllc };
+
+        ByteBuffer buf = ByteBuffer.allocate(RowConstants.ROWVALUE_BUFFER_SIZE);
+
+        codec.encode(values, buf);
+        buf.flip();
+        System.out.println("size: " + buf.limit());
+
+        Object copy[] = new Object[values.length];
+
+        codec.decode(buf, copy);
+
+        for (int i = 0; i < values.length; i++) {
+            Object x = values[i];
+            Object y = copy[i];
+            assertEquals(x, y);
+        }
+    }
+
+    private MeasureDesc measure(String returnType) {
+        MeasureDesc desc = new MeasureDesc();
+        FunctionDesc func = new FunctionDesc();
+        func.setReturnType(returnType);
+        desc.setFunction(func);
+        return desc;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/resources/data/TEST1_desc.json
----------------------------------------------------------------------
diff --git a/core-cube/src/test/resources/data/TEST1_desc.json b/core-cube/src/test/resources/data/TEST1_desc.json
new file mode 100644
index 0000000..082a3cf
--- /dev/null
+++ b/core-cube/src/test/resources/data/TEST1_desc.json
@@ -0,0 +1,183 @@
+{
+  "uuid" : "9c53506d-d7b9-4ad4-b3b1-53ea42673c4b",
+  "last_modified" : 1401429176099,
+  "name" : "TEST1_desc",
+  "model_name": "TEST1_model_desc",
+  "fact_table" : "TEST_KYLIN_FACT",
+  "dimensions" : [ {
+    "id" : 1,
+    "name" : "CAL_DT",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "CAL_DT" ],
+      "foreign_key" : [ "CAL_DT" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_CAL_DT",
+    "column" : ["TEST_CAL_DT.CAL_DT"],
+    "derived" : [ "WEEK_BEG_DT" ]
+  }, {
+    "id" : 2,
+    "name" : "CATEGORY",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "LEAF_CATEG_ID", "SITE_ID" ],
+      "foreign_key" : [ "LEAF_CATEG_ID", "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : true,
+    "table" : "TEST_CATEGORY_GROUPINGS",
+    "column" : ["TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME"],
+    "datatype" : null,
+    "derived" : null
+  }, {
+    "id" : 3,
+    "name" : "LSTG_FORMAT_NAME",
+    "join" : null,
+    "hierarchy" : null,
+    "table" : "TEST_KYLIN_FACT",
+    "column" : ["TEST_KYLIN_FACT.LSTG_FORMAT_NAME"],
+    "datatype" : "string",
+    "derived" : null
+  }, {
+    "id" : 4,
+    "name" : "SITE_ID",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SITE_ID" ],
+      "foreign_key" : [ "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_SITES",
+    "column" : ["TEST_SITES.SITE_ID"],
+    "datatype" : "string",
+    "derived" : [ "SITE_NAME", "CRE_USER" ]
+  }, {
+    "id" : 5,
+    "name" : "SELLER_TYPE_CD",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SELLER_TYPE_CD" ],
+      "foreign_key" : [ "SLR_SEGMENT_CD" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_SELLER_TYPE_DIM",
+    "column" : ["TEST_SELLER_TYPE_DIM.SELLER_TYPE_CD"],
+    "datatype" : "string",
+    "derived" : [ "SELLER_TYPE_DESC" ]
+  } ],
+  "measures" : [ {
+    "id" : 1,
+    "name" : "GMV_SUM",
+    "function" : {
+      "expression" : "SUM",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 2,
+    "name" : "GMV_MIN",
+    "function" : {
+      "expression" : "MIN",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 3,
+    "name" : "GMV_MAX",
+    "function" : {
+      "expression" : "MAX",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 4,
+    "name" : "TRANS_CNT",
+    "function" : {
+      "expression" : "COUNT",
+      "parameter" : {
+        "type" : "constant",
+        "value" : "1"
+      },
+      "returntype" : "long"
+    }
+  }, {
+    "id" : 5,
+    "name" : "SELLER_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  }, {
+    "id" : 6,
+    "name" : "SELLER_FORMAT_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "LSTG_FORMAT_NAME,SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  } ],
+  "rowkey" : {
+    "rowkey_columns" : [ {
+      "column" : "CAL_DT",
+      "length" : 0,
+      "dictionary" : "date(yyyy-mm-dd)",
+      "mandatory" : true
+    }, {
+      "column" : "META_CATEG_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL2_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL3_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "LSTG_FORMAT_NAME",
+      "length" : 12,
+      "dictionary" : null,
+      "mandatory" : false
+    }, {
+      "column" : "SITE_ID",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "SELLER_TYPE_CD",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    } ],
+    "aggregation_groups" : [ [ "META_CATEG_NAME", "CATEG_LVL3_NAME", "CATEG_LVL2_NAME", "CAL_DT" ], [ "LSTG_FORMAT_NAME", "SITE_ID", "SELLER_TYPE_CD" ] ]
+  },
+  "hbase_mapping" : {
+    "column_family" : [ {
+      "name" : "F1",
+      "columns" : [ {
+        "qualifier" : "M",
+        "measure_refs" : [ "GMV_SUM", "GMV_MIN", "GMV_MAX", "TRANS_CNT", "SELLER_CNT", "SELLER_FORMAT_CNT" ]
+      } ]
+    } ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/resources/data/TEST2_desc.json
----------------------------------------------------------------------
diff --git a/core-cube/src/test/resources/data/TEST2_desc.json b/core-cube/src/test/resources/data/TEST2_desc.json
new file mode 100644
index 0000000..90bd806
--- /dev/null
+++ b/core-cube/src/test/resources/data/TEST2_desc.json
@@ -0,0 +1,168 @@
+{
+  "uuid" : "9c53506d-d7b9-4ad4-b3b1-53ea42673c4b",
+  "last_modified" : 1401429176099,
+  "model_name": "TEST2_model_desc",
+  "name" : "TEST2_desc",
+  "dimensions" : [ {
+    "name" : "CAL_DT",
+    "hierarchy" : null,
+    "column" : ["TEST_CAL_DT.CAL_DT"],
+    "derived" : [ "WEEK_BEG_DT" ]
+  }, {
+    "id" : 2,
+    "name" : "CATEGORY",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "LEAF_CATEG_ID", "SITE_ID" ],
+      "foreign_key" : [ "LEAF_CATEG_ID", "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : true,
+    "column" : ["TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME"],
+    "derived" : null
+  }, {
+    "id" : 3,
+    "name" : "LSTG_FORMAT_NAME",
+    "hierarchy" : null,
+    "table" : "TEST_KYLIN_FACT",
+    "column" : ["TEST_KYLIN_FACT.LSTG_FORMAT_NAME"],
+    "derived" : null
+  }, {
+    "id" : 4,
+    "name" : "SITE_ID",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SITE_ID" ],
+      "foreign_key" : [ "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : null,
+    "column" : ["TEST_SITES.SITE_ID"],
+    "derived" : [ "SITE_NAME", "CRE_USER" ]
+  }, {
+    "id" : 5,
+    "name" : "SELLER_TYPE_CD",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SELLER_TYPE_CD" ],
+      "foreign_key" : [ "SLR_SEGMENT_CD" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_SELLER_TYPE_DIM",
+    "column" : ["TEST_SELLER_TYPE_DIM.SELLER_TYPE_CD"],
+    "derived" : [ "SELLER_TYPE_DESC" ]
+  } ],
+  "measures" : [ {
+    "id" : 1,
+    "name" : "GMV_SUM",
+    "function" : {
+      "expression" : "SUM",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 2,
+    "name" : "GMV_MIN",
+    "function" : {
+      "expression" : "MIN",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 3,
+    "name" : "GMV_MAX",
+    "function" : {
+      "expression" : "MAX",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 4,
+    "name" : "TRANS_CNT",
+    "function" : {
+      "expression" : "COUNT",
+      "parameter" : {
+        "type" : "constant",
+        "value" : "1"
+      },
+      "returntype" : "long"
+    }
+  }, {
+    "id" : 5,
+    "name" : "SELLER_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  }, {
+    "id" : 6,
+    "name" : "SELLER_FORMAT_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "LSTG_FORMAT_NAME,SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  } ],
+  "rowkey" : {
+    "rowkey_columns" : [ {
+      "column" : "CAL_DT",
+      "length" : 0,
+      "dictionary" : "date(yyyy-mm-dd)",
+      "mandatory" : true
+    }, {
+      "column" : "META_CATEG_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL2_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL3_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "LSTG_FORMAT_NAME",
+      "length" : 12,
+      "dictionary" : null,
+      "mandatory" : false
+    }, {
+      "column" : "SITE_ID",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "SELLER_TYPE_CD",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    } ],
+    "aggregation_groups" : [ [ "META_CATEG_NAME", "CATEG_LVL3_NAME", "CAL_DT" ], [ "LSTG_FORMAT_NAME", "SITE_ID", "SELLER_TYPE_CD", "CATEG_LVL2_NAME" ] ]
+  },
+  "hbase_mapping" : {
+    "column_family" : [ {
+      "name" : "F1",
+      "columns" : [ {
+        "qualifier" : "M",
+        "measure_refs" : [ "GMV_SUM", "GMV_MIN", "GMV_MAX", "TRANS_CNT", "SELLER_CNT", "SELLER_FORMAT_CNT" ]
+      } ]
+    } ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-cube/src/test/resources/data/TEST3_desc.json
----------------------------------------------------------------------
diff --git a/core-cube/src/test/resources/data/TEST3_desc.json b/core-cube/src/test/resources/data/TEST3_desc.json
new file mode 100644
index 0000000..4b0836b
--- /dev/null
+++ b/core-cube/src/test/resources/data/TEST3_desc.json
@@ -0,0 +1,182 @@
+{
+  "uuid" : "9c53506d-d7b9-4ad4-b3b1-53ea42673c4b",
+  "last_modified" : 1401429176099,
+  "name" : "TEST1_desc",
+  "model_name": "TEST1_model_desc",
+  "dimensions" : [ {
+    "id" : 1,
+    "name" : "CAL_DT",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "CAL_DT" ],
+      "foreign_key" : [ "CAL_DT" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_CAL_DT",
+    "column" : ["TEST_CAL_DT.CAL_DT"],
+    "datatype" : "date",
+    "derived" : [ "WEEK_BEG_DT" ]
+  }, {
+    "id" : 2,
+    "name" : "CATEGORY",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "LEAF_CATEG_ID", "SITE_ID" ],
+      "foreign_key" : [ "LEAF_CATEG_ID", "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : true,
+    "table" : "TEST_CATEGORY_GROUPINGS",
+    "column" : ["TEST_CATEGORY_GROUPINGS.META_CATEG_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL2_NAME", "TEST_CATEGORY_GROUPINGS.CATEG_LVL3_NAME"],
+    "derived" : null
+  }, {
+    "id" : 3,
+    "name" : "LSTG_FORMAT_NAME",
+    "join" : null,
+    "hierarchy" : null,
+    "table" : "TEST_KYLIN_FACT",
+    "column" : ["TEST_KYLIN_FACT.LSTG_FORMAT_NAME"],
+    "datatype" : "string",
+    "derived" : null
+  }, {
+    "id" : 4,
+    "name" : "SITE_ID",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SITE_ID" ],
+      "foreign_key" : [ "LSTG_SITE_ID" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_SITES",
+    "column" : ["TEST_SITES.SITE_ID"],
+    "datatype" : "string",
+    "derived" : [ "SITE_NAME", "CRE_USER" ]
+  }, {
+    "id" : 5,
+    "name" : "SELLER_TYPE_CD",
+    "join" : {
+      "type" : "inner",
+      "primary_key" : [ "SELLER_TYPE_CD" ],
+      "foreign_key" : [ "SLR_SEGMENT_CD" ]
+    },
+    "hierarchy" : null,
+    "table" : "TEST_SELLER_TYPE_DIM",
+    "column" : ["TEST_SELLER_TYPE_DIM.SELLER_TYPE_CD"],
+    "datatype" : "string",
+    "derived" : [ "SELLER_TYPE_DESC" ]
+  } ],
+  "measures" : [ {
+    "id" : 1,
+    "name" : "GMV_SUM",
+    "function" : {
+      "expression" : "SUM",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 2,
+    "name" : "GMV_MIN",
+    "function" : {
+      "expression" : "MIN",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 3,
+    "name" : "GMV_MAX",
+    "function" : {
+      "expression" : "MAX",
+      "parameter" : {
+        "type" : "column",
+        "value" : "PRICE"
+      },
+      "returntype" : "decimal"
+    }
+  }, {
+    "id" : 4,
+    "name" : "TRANS_CNT",
+    "function" : {
+      "expression" : "COUNT",
+      "parameter" : {
+        "type" : "constant",
+        "value" : "1"
+      },
+      "returntype" : "long"
+    }
+  }, {
+    "id" : 5,
+    "name" : "SELLER_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  }, {
+    "id" : 6,
+    "name" : "SELLER_FORMAT_CNT",
+    "function" : {
+      "expression" : "COUNT_DISTINCT",
+      "parameter" : {
+        "type" : "column",
+        "value" : "LSTG_FORMAT_NAME,SELLER_ID"
+      },
+      "returntype" : "hllc10"
+    }
+  } ],
+  "rowkey" : {
+    "rowkey_columns" : [ {
+      "column" : "CAL_DT",
+      "length" : 10,
+      "dictionary" : "date(yyyy-mm-dd)",
+      "mandatory" : false
+    }, {
+      "column" : "META_CATEG_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL2_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "CATEG_LVL3_NAME",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "LSTG_FORMAT_NAME",
+      "length" : 12,
+      "dictionary" : null,
+      "mandatory" : false
+    }, {
+      "column" : "SITE_ID",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    }, {
+      "column" : "SELLER_TYPE_CD",
+      "length" : 0,
+      "dictionary" : "string",
+      "mandatory" : false
+    } ],
+    "aggregation_groups" : [ [ "META_CATEG_NAME", "CATEG_LVL3_NAME", "CATEG_LVL2_NAME", "CAL_DT" ], [ "LSTG_FORMAT_NAME", "SITE_ID", "SELLER_TYPE_CD" ] ]
+  },
+  "hbase_mapping" : {
+    "column_family" : [ {
+      "name" : "F1",
+      "columns" : [ {
+        "qualifier" : "M",
+        "measure_refs" : [ "GMV_SUM", "GMV_MIN", "GMV_MAX", "TRANS_CNT", "SELLER_CNT", "SELLER_FORMAT_CNT" ]
+      } ]
+    } ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/core-dictionary/.settings/org.eclipse.core.resources.prefs b/core-dictionary/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..8bc0e1c
--- /dev/null
+++ b/core-dictionary/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/<project>=UTF-8

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/core-dictionary/.settings/org.eclipse.jdt.core.prefs b/core-dictionary/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a903301
--- /dev/null
+++ b/core-dictionary/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,379 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=false
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=999
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/.settings/org.eclipse.jdt.ui.prefs
----------------------------------------------------------------------
diff --git a/core-dictionary/.settings/org.eclipse.jdt.ui.prefs b/core-dictionary/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..dece0e6
--- /dev/null
+++ b/core-dictionary/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+formatter_profile=_Space Indent & Long Lines
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=1

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/pom.xml
----------------------------------------------------------------------
diff --git a/core-dictionary/pom.xml b/core-dictionary/pom.xml
new file mode 100644
index 0000000..a3e7ce3
--- /dev/null
+++ b/core-dictionary/pom.xml
@@ -0,0 +1,128 @@
+<?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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>kylin-core-dictionary</artifactId>
+    <packaging>jar</packaging>
+    <name>Kylin:Core-Dictionary</name>
+
+    <parent>
+        <groupId>org.apache.kylin</groupId>
+        <artifactId>kylin</artifactId>
+        <version>0.7.2-incubating-SNAPSHOT</version>
+    </parent>
+
+    <properties>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-core-common</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+        <!--Kylin Jar -->
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-core-metadata</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <!-- Env & Test -->
+
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-common</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-hdfs</artifactId>
+            <scope>provided</scope>
+            <!-- protobuf version conflict with hbase-->
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-common</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+         <dependency>
+            <groupId>org.apache.hive.hcatalog</groupId>
+            <artifactId>hive-hcatalog-core</artifactId>
+            <version>${hive-hcatalog.version}</version>
+            <scope>provided</scope>
+          </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-testing-util</artifactId>
+            <version>${hbase-hadoop2.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.servlet</groupId>
+                    <artifactId>servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.servlet.jsp</groupId>
+                    <artifactId>jsp-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/src/main/java/org/apache/kylin/dict/BytesConverter.java
----------------------------------------------------------------------
diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/BytesConverter.java b/core-dictionary/src/main/java/org/apache/kylin/dict/BytesConverter.java
new file mode 100644
index 0000000..90b0a52
--- /dev/null
+++ b/core-dictionary/src/main/java/org/apache/kylin/dict/BytesConverter.java
@@ -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.
+*/
+
+package org.apache.kylin.dict;
+
+public interface BytesConverter<T> {
+
+    public byte[] convertToBytes(T v);
+
+    public T convertFromBytes(byte[] b, int offset, int length);
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-dictionary/src/main/java/org/apache/kylin/dict/DateStrDictionary.java
----------------------------------------------------------------------
diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/DateStrDictionary.java b/core-dictionary/src/main/java/org/apache/kylin/dict/DateStrDictionary.java
new file mode 100644
index 0000000..0ee1d06
--- /dev/null
+++ b/core-dictionary/src/main/java/org/apache/kylin/dict/DateStrDictionary.java
@@ -0,0 +1,191 @@
+/*
+ * 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.dict;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.io.*;
+import java.util.Date;
+
+import static org.apache.kylin.common.util.DateFormat.*;
+
+/**
+ * A dictionary for date string (date only, no time).
+ * 
+ * Dates are numbered from 0000-1-1 -- 0 for "0000-1-1", 1 for "0000-1-2", 2 for "0000-1-3" and
+ * up to 3652426 for "9999-12-31".
+ * 
+ * Note the implementation is not thread-safe.
+ * 
+ * @author yangli9
+ */
+public class DateStrDictionary extends Dictionary<String> {
+
+    static final int ID_9999_12_31 = 3652426; // assume 0 based
+
+    private String pattern;
+    private int baseId;
+    private int maxId;
+
+    public DateStrDictionary() {
+        init(DEFAULT_DATE_PATTERN, 0);
+    }
+
+    public DateStrDictionary(String datePattern, int baseId) {
+        init(datePattern, baseId);
+    }
+
+    private void init(String datePattern, int baseId) {
+        this.pattern = datePattern;
+        this.baseId = baseId;
+        this.maxId = baseId + ID_9999_12_31;
+    }
+
+    @Override
+    public int getMinId() {
+        return baseId;
+    }
+
+    @Override
+    public int getMaxId() {
+        return maxId;
+    }
+
+    @Override
+    public int getSizeOfId() {
+        return 3;
+    }
+
+    @Override
+    public int getSizeOfValue() {
+        return pattern.length();
+    }
+
+    @Override
+    protected boolean isNullByteForm(byte[] value, int offset, int len) {
+        return value == null || len == 0;
+    }
+
+    @Override
+    final protected int getIdFromValueImpl(String value, int roundFlag) {
+        Date date = stringToDate(value, pattern);
+        int id = calcIdFromSeqNo(getNumOfDaysSince0000(date));
+        if (id < baseId || id > maxId)
+            throw new IllegalArgumentException("'" + value + "' encodes to '" + id + "' which is out of range [" + baseId + "," + maxId + "]");
+
+        return id;
+    }
+
+    @Override
+    final protected String getValueFromIdImpl(int id) {
+        if (id < baseId || id > maxId)
+            throw new IllegalArgumentException("ID '" + id + "' is out of range [" + baseId + "," + maxId + "]");
+        Date d = getDateFromNumOfDaysSince0000(calcSeqNoFromId(id));
+        return dateToString(d, pattern);
+    }
+
+    private int getNumOfDaysSince0000(Date d) {
+        // 86400000 = 1000 * 60 * 60 * 24
+        // -719530 is offset of 0000-01-01
+        return (int) (d.getTime() / 86400000 + 719530);
+    }
+
+    private Date getDateFromNumOfDaysSince0000(int n) {
+        long millis = ((long) n - 719530) * 86400000;
+        return new Date(millis);
+    }
+
+    @Override
+    final protected int getIdFromValueBytesImpl(byte[] value, int offset, int len, int roundingFlag) {
+        try {
+            return getIdFromValue(new String(value, offset, len, "ISO-8859-1"));
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e); // never happen
+        }
+    }
+
+    @Override
+    final protected byte[] getValueBytesFromIdImpl(int id) {
+        String date = getValueFromId(id);
+        byte bytes[];
+        try {
+            bytes = date.getBytes("ISO-8859-1");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e); // never happen
+        }
+        return bytes;
+    }
+
+    @Override
+    final protected int getValueBytesFromIdImpl(int id, byte[] returnValue, int offset) {
+        byte bytes[] = getValueBytesFromIdImpl(id);
+        System.arraycopy(bytes, 0, returnValue, offset, bytes.length);
+        return bytes.length;
+    }
+
+    private int calcIdFromSeqNo(int seq) {
+        return seq < 0 ? seq : baseId + seq;
+    }
+
+    private int calcSeqNoFromId(int id) {
+        return id - baseId;
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        out.writeUTF(pattern);
+        out.writeInt(baseId);
+    }
+
+    @Override
+    public void readFields(DataInput in) throws IOException {
+        String pattern = in.readUTF();
+        int baseId = in.readInt();
+        init(pattern, baseId);
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 * baseId + pattern.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if ((o instanceof DateStrDictionary) == false)
+            return false;
+        DateStrDictionary that = (DateStrDictionary) o;
+        return StringUtils.equals(this.pattern, that.pattern) && this.baseId == that.baseId;
+    }
+
+    @Override
+    public boolean containedBy(Dictionary other) {
+        return this.equals(other);
+    }
+
+    @Override
+    public void dump(PrintStream out) {
+        out.println(this.toString());
+    }
+
+    @Override
+    public String toString() {
+        return "DateStrDictionary [pattern=" + pattern + ", baseId=" + baseId + "]";
+    }
+
+}