You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/08/08 04:17:12 UTC

[1/4] TAJO-95: Eliminate the lazy copy approach from the classes wrapping protobuf-generated classes. (hyunsik)

Updated Branches:
  refs/heads/master 87420eb3a -> 1c677cc5c


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryUnitRequestImpl.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryUnitRequestImpl.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryUnitRequestImpl.java
index 9245acb..bb7caa1 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryUnitRequestImpl.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryUnitRequestImpl.java
@@ -18,7 +18,6 @@
 
 package org.apache.tajo.engine.query;
 
-import com.google.gson.annotations.Expose;
 import org.apache.tajo.QueryUnitAttemptId;
 import org.apache.tajo.engine.MasterWorkerProtos.Fetch;
 import org.apache.tajo.engine.MasterWorkerProtos.QueryUnitRequestProto;
@@ -32,22 +31,14 @@ import java.util.List;
 
 public class QueryUnitRequestImpl implements QueryUnitRequest {
 	
-  @Expose
-	private QueryUnitAttemptId id;
-  @Expose
-	private List<Fragment> fragments;
-  @Expose
-	private String outputTable;
+  private QueryUnitAttemptId id;
+  private List<Fragment> fragments;
+  private String outputTable;
 	private boolean isUpdated;
-	@Expose
 	private boolean clusteredOutput;
-	@Expose
 	private String serializedData;     // logical node
-	@Expose
 	private Boolean interQuery;
-	@Expose
 	private List<Fetch> fetches;
-  @Expose
   private Boolean shouldDie;
 	
 	private QueryUnitRequestProto proto = QueryUnitRequestProto.getDefaultInstance();
@@ -268,37 +259,4 @@ public class QueryUnitRequestImpl implements QueryUnitRequest {
 		proto = builder.build();
 		viaProto = true;
 	}
-
-  @Override
-  public void initFromProto() {
-    QueryUnitRequestProtoOrBuilder p = viaProto ? proto : builder;
-    if (id == null && p.hasId()) {
-      this.id = new QueryUnitAttemptId(p.getId());
-    }
-    if (fragments == null && p.getFragmentsCount() > 0) {
-      this.fragments = new ArrayList<Fragment>();
-      for (int i = 0; i < p.getFragmentsCount(); i++) {
-        this.fragments.add(new Fragment(p.getFragments(i)));
-      }
-    }
-    if (outputTable == null && p.hasOutputTable()) {
-      this.outputTable = p.getOutputTable();
-    }
-    if (isUpdated == false && p.hasClusteredOutput()) {
-      this.clusteredOutput = p.getClusteredOutput();
-    }
-    if (serializedData == null && p.hasSerializedData()) {
-      this.serializedData = p.getSerializedData();
-    }
-    if (interQuery == null && p.hasInterQuery()) {
-      this.interQuery = p.getInterQuery();
-    }
-    if (fetches == null && p.getFetchesCount() > 0) {
-      this.fetches = p.getFetchesList();
-    }
-    if (shouldDie == null && p.getShouldDie()) {
-      this.shouldDie = true;
-    }
-  }
-  
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
index a0bd27f..6ea3c8b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
@@ -219,7 +219,7 @@ public class GlobalEngine extends AbstractService {
         return true;
 
       default:
-        throw new InternalError("updateQuery cannot handle such query: \n" + root.toJSON());
+        throw new InternalError("updateQuery cannot handle such query: \n" + root.toJson());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TaskSchedulerImpl.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TaskSchedulerImpl.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TaskSchedulerImpl.java
index cbb0cf9..381c333 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TaskSchedulerImpl.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TaskSchedulerImpl.java
@@ -353,7 +353,7 @@ public class TaskSchedulerImpl extends AbstractService
               new ArrayList<Fragment>(task.getAllFragments()),
               task.getOutputName(),
               false,
-              task.getLogicalPlan().toJSON());
+              task.getLogicalPlan().toJson());
           if (task.getStoreTableNode().isLocal()) {
             taskAssign.setInterQuery();
           }
@@ -395,7 +395,7 @@ public class TaskSchedulerImpl extends AbstractService
               Lists.newArrayList(task.getAllFragments()),
               task.getOutputName(),
               false,
-              task.getLogicalPlan().toJSON());
+              task.getLogicalPlan().toJson());
           if (task.getStoreTableNode().isLocal()) {
             taskAssign.setInterQuery();
           }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/util/IndexUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/util/IndexUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/util/IndexUtil.java
index 883725c..5557b2a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/util/IndexUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/util/IndexUtil.java
@@ -28,7 +28,7 @@ import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.engine.eval.EvalNode.Type;
 import org.apache.tajo.engine.eval.EvalNodeVisitor;
 import org.apache.tajo.engine.eval.FieldEval;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.planner.logical.IndexScanNode;
 import org.apache.tajo.engine.planner.logical.ScanNode;
 import org.apache.tajo.storage.Fragment;
@@ -50,7 +50,7 @@ public class IndexUtil {
        
   }
   
-  public static String getIndexName (String indexName , SortSpec[] keys) {
+  public static String getIndexName(String indexName , SortSpec[] keys) {
     StringBuilder builder = new StringBuilder();
     builder.append(indexName + "_");
     for(int i = 0 ; i < keys.length ; i ++) {
@@ -63,7 +63,7 @@ public class IndexUtil {
       Iterator<Entry<String, String>> iter ) {
    
     EvalNode qual = scanNode.getQual();
-    Gson gson = GsonCreator.getInstance();
+    Gson gson = CoreGsonHelper.getInstance();
     
     FieldAndValueFinder nodeFinder = new FieldAndValueFinder();
     qual.preOrder(nodeFinder);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/Task.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/Task.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/Task.java
index c8a11c6..9e281c6 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/Task.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/Task.java
@@ -39,7 +39,7 @@ import org.apache.tajo.catalog.TableMeta;
 import org.apache.tajo.catalog.statistics.TableStat;
 import org.apache.tajo.engine.MasterWorkerProtos.*;
 import org.apache.tajo.engine.exception.UnfinishedTaskException;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.planner.PlannerUtil;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.SortNode;
@@ -146,8 +146,7 @@ public class Task {
     this.context = new TaskAttemptContext(conf, taskId,
         request.getFragments().toArray(new Fragment[request.getFragments().size()]),
         taskDir);
-    plan = GsonCreator.getInstance().fromJson(request.getSerializedData(),
-        LogicalNode.class);
+    plan = CoreGsonHelper.fromJson(request.getSerializedData(), LogicalNode.class);
     interQuery = request.getProto().getInterQuery();
     if (interQuery) {
       context.setInterQuery();

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
index 05c5165..ca8ef43 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
@@ -280,19 +280,24 @@ public class TaskRunner extends AbstractService {
                   }
 
                   LOG.info("Initializing: " + taskAttemptId);
-                  Task task = new Task(taskAttemptId, workerContext, master,
-                      new QueryUnitRequestImpl(taskRequest));
-                  tasks.put(taskAttemptId, task);
-
-                  task.init();
-                  if (task.hasFetchPhase()) {
-                    task.fetch(); // The fetch is performed in an asynchronous way.
+                  Task task;
+                  try {
+                    task = new Task(taskAttemptId, workerContext, master,
+                        new QueryUnitRequestImpl(taskRequest));
+                    tasks.put(taskAttemptId, task);
+
+                    task.init();
+                    if (task.hasFetchPhase()) {
+                      task.fetch(); // The fetch is performed in an asynchronous way.
+                    }
+                    // task.run() is a blocking call.
+                    task.run();
+                  } catch (Throwable t) {
+                    fatalError(workerContext.getMaster(), taskAttemptId, t.getMessage());
+                  } finally {
+                    callFuture = null;
+                    taskRequest = null;
                   }
-                  // task.run() is a blocking call.
-                  task.run();
-
-                  callFuture = null;
-                  taskRequest = null;
                 }
               }
             } catch (Throwable t) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestQueryUnitId.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestQueryUnitId.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestQueryUnitId.java
deleted file mode 100644
index 837fbba..0000000
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestQueryUnitId.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo;
-
-import org.apache.hadoop.yarn.api.records.ApplicationId;
-import org.apache.hadoop.yarn.util.BuilderUtils;
-import org.junit.Test;
-import org.apache.tajo.util.TajoIdUtils;
-
-import static org.junit.Assert.*;
-
-public class TestQueryUnitId {
-  @Test
-  public void testQueryId() {
-    long ts1 = 1315890136000l;
-    long ts2 = 1315890136001l;
-
-    QueryId j1 = createQueryId(ts1, 2, 1);
-    QueryId j2 = createQueryId(ts1, 1, 2);
-    QueryId j3 = createQueryId(ts2, 1, 2);
-    QueryId j4 = createQueryId(ts1, 2, 1);
-
-    assertTrue(j1.equals(j4));
-    assertFalse(j1.equals(j2));
-    assertFalse(j1.equals(j3));
-
-    assertTrue(j1.compareTo(j4) == 0);
-    assertTrue(j1.compareTo(j2) > 0);
-    assertTrue(j1.compareTo(j3) < 0);
-
-    assertTrue(j1.hashCode() == j4.hashCode());
-    assertFalse(j1.hashCode() == j2.hashCode());
-    assertFalse(j1.hashCode() == j3.hashCode());
-
-    QueryId j5 = createQueryId(ts1, 231415, 2);
-    assertEquals("q_" + ts1 + "_0002_000001", j1.toString());
-    assertEquals("q_" + ts1 + "_231415_000002", j5.toString());
-  }
-
-  @Test
-  public void testQueryIds() {
-    long timeId = 1315890136000l;
-    
-    QueryId queryId = createQueryId(timeId, 1, 1);
-    assertEquals("q_" + timeId + "_0001_000001", queryId.toString());
-    
-    SubQueryId subId = TajoIdUtils.newSubQueryId(queryId, 2);
-    assertEquals("sq_" + timeId +"_0001_000001_02", subId.toString());
-    
-    QueryUnitId qId = new QueryUnitId(subId, 5);
-    assertEquals("t_" + timeId + "_0001_000001_02_000005", qId.toString());
-
-    QueryUnitAttemptId attemptId = new QueryUnitAttemptId(qId, 4);
-    assertEquals("ta_" + timeId + "_0001_000001_02_000005_04", attemptId.toString());
-  }
-
-  @Test
-  public void testEqualsObject() {
-    long timeId = System.currentTimeMillis();
-    
-    QueryId queryId1 = createQueryId(timeId, 1, 1);
-    QueryId queryId2 = createQueryId(timeId, 2, 2);
-    assertNotSame(queryId1, queryId2);    
-    QueryId queryId3 = createQueryId(timeId, 1, 1);
-    assertEquals(queryId1, queryId3);
-    
-    SubQueryId sid1 = TajoIdUtils.newSubQueryId(queryId1, 1);
-    SubQueryId sid2 = TajoIdUtils.newSubQueryId(queryId1, 2);    
-    assertNotSame(sid1, sid2);
-    SubQueryId sid3 = TajoIdUtils.newSubQueryId(queryId1, 1);
-    assertEquals(sid1, sid3);
-    
-    QueryUnitId qid1 = new QueryUnitId(sid1, 9);
-    QueryUnitId qid2 = new QueryUnitId(sid1, 10);
-    assertNotSame(qid1, qid2);
-    QueryUnitId qid3 = new QueryUnitId(sid1, 9);
-    assertEquals(qid1, qid3);
-  }
-
-  @Test
-  public void testCompareTo() {
-    long time = System.currentTimeMillis();
-    
-    QueryId queryId1 = createQueryId(time, 1, 1);
-    QueryId queryId2 = createQueryId(time, 2, 2);
-    QueryId queryId3 = createQueryId(time, 1, 1);
-    assertEquals(-1, queryId1.compareTo(queryId2));
-    assertEquals(1, queryId2.compareTo(queryId1));
-    assertEquals(0, queryId3.compareTo(queryId1));
-    
-    SubQueryId sid1 = TajoIdUtils.newSubQueryId(queryId1, 1);
-    SubQueryId sid2 = TajoIdUtils.newSubQueryId(queryId1, 2);    
-    SubQueryId sid3 = TajoIdUtils.newSubQueryId(queryId1, 1);
-    assertEquals(-1, sid1.compareTo(sid2));
-    assertEquals(1, sid2.compareTo(sid1));
-    assertEquals(0, sid3.compareTo(sid1));
-    
-    QueryUnitId qid1 = new QueryUnitId(sid1, 9);
-    QueryUnitId qid2 = new QueryUnitId(sid1, 10);
-    QueryUnitId qid3 = new QueryUnitId(sid1, 9);
-    assertEquals(-1, qid1.compareTo(qid2));
-    assertEquals(1, qid2.compareTo(qid1));
-    assertEquals(0, qid3.compareTo(qid1));
-  }
-  
-  @Test
-  public void testConstructFromString() {
-    QueryIdFactory.reset();
-    QueryId qid1 = QueryIdFactory.newQueryId();
-    QueryId qid2 = TajoIdUtils.createQueryId(qid1.toString());
-    assertEquals(qid1, qid2);
-    
-    SubQueryId sub1 = QueryIdFactory.newSubQueryId(qid1);
-    SubQueryId sub2 = TajoIdUtils.newSubQueryId(sub1.toString());
-    assertEquals(sub1, sub2);
-    
-    QueryUnitId u1 = QueryIdFactory.newQueryUnitId(sub1);
-    QueryUnitId u2 = new QueryUnitId(u1.toString());
-    assertEquals(u1, u2);
-
-    QueryUnitAttemptId attempt1 = new QueryUnitAttemptId(u1, 1);
-    QueryUnitAttemptId attempt2 = new QueryUnitAttemptId(attempt1.toString());
-    assertEquals(attempt1, attempt2);
-  }
-
-  @Test
-  public void testConstructFromPB() {
-    QueryIdFactory.reset();
-    QueryId qid1 = QueryIdFactory.newQueryId();
-    QueryId qid2 = new QueryId(qid1.getProto());
-    assertEquals(qid1, qid2);
-
-    SubQueryId sub1 = QueryIdFactory.newSubQueryId(qid1);
-    SubQueryId sub2 = new SubQueryId(sub1.getProto());
-    assertEquals(sub1, sub2);
-
-    QueryUnitId u1 = QueryIdFactory.newQueryUnitId(sub1);
-    QueryUnitId u2 = new QueryUnitId(u1.getProto());
-    assertEquals(u1, u2);
-
-    QueryUnitAttemptId attempt1 = new QueryUnitAttemptId(u1, 1);
-    QueryUnitAttemptId attempt2 = new QueryUnitAttemptId(attempt1.getProto());
-    assertEquals(attempt1, attempt2);
-  }
-
-  public static QueryId createQueryId(long timestamp, int id, int attemptId) {
-    ApplicationId appId = BuilderUtils.newApplicationId(timestamp, id);
-
-    return TajoIdUtils.createQueryId(appId, attemptId);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestTajoIds.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestTajoIds.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestTajoIds.java
new file mode 100644
index 0000000..386fe02
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TestTajoIds.java
@@ -0,0 +1,167 @@
+/**
+ * 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.tajo;
+
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.util.BuilderUtils;
+import org.junit.Test;
+import org.apache.tajo.util.TajoIdUtils;
+
+import static org.junit.Assert.*;
+
+public class TestTajoIds {
+  @Test
+  public void testQueryId() {
+    long ts1 = 1315890136000l;
+    long ts2 = 1315890136001l;
+
+    QueryId j1 = createQueryId(ts1, 2, 1);
+    QueryId j2 = createQueryId(ts1, 1, 2);
+    QueryId j3 = createQueryId(ts2, 1, 2);
+    QueryId j4 = createQueryId(ts1, 2, 1);
+
+    assertTrue(j1.equals(j4));
+    assertFalse(j1.equals(j2));
+    assertFalse(j1.equals(j3));
+
+    assertTrue(j1.compareTo(j4) == 0);
+    assertTrue(j1.compareTo(j2) > 0);
+    assertTrue(j1.compareTo(j3) < 0);
+
+    assertTrue(j1.hashCode() == j4.hashCode());
+    assertFalse(j1.hashCode() == j2.hashCode());
+    assertFalse(j1.hashCode() == j3.hashCode());
+
+    QueryId j5 = createQueryId(ts1, 231415, 2);
+    assertEquals("q_" + ts1 + "_0002_000001", j1.toString());
+    assertEquals("q_" + ts1 + "_231415_000002", j5.toString());
+  }
+
+  @Test
+  public void testQueryIds() {
+    long timeId = 1315890136000l;
+    
+    QueryId queryId = createQueryId(timeId, 1, 1);
+    assertEquals("q_" + timeId + "_0001_000001", queryId.toString());
+    
+    SubQueryId subId = TajoIdUtils.newSubQueryId(queryId, 2);
+    assertEquals("sq_" + timeId +"_0001_000001_02", subId.toString());
+    
+    QueryUnitId qId = new QueryUnitId(subId, 5);
+    assertEquals("t_" + timeId + "_0001_000001_02_000005", qId.toString());
+
+    QueryUnitAttemptId attemptId = new QueryUnitAttemptId(qId, 4);
+    assertEquals("ta_" + timeId + "_0001_000001_02_000005_04", attemptId.toString());
+  }
+
+  @Test
+  public void testEqualsObject() {
+    long timeId = System.currentTimeMillis();
+    
+    QueryId queryId1 = createQueryId(timeId, 1, 1);
+    QueryId queryId2 = createQueryId(timeId, 2, 2);
+    assertNotSame(queryId1, queryId2);    
+    QueryId queryId3 = createQueryId(timeId, 1, 1);
+    assertEquals(queryId1, queryId3);
+    
+    SubQueryId sid1 = TajoIdUtils.newSubQueryId(queryId1, 1);
+    SubQueryId sid2 = TajoIdUtils.newSubQueryId(queryId1, 2);    
+    assertNotSame(sid1, sid2);
+    SubQueryId sid3 = TajoIdUtils.newSubQueryId(queryId1, 1);
+    assertEquals(sid1, sid3);
+    
+    QueryUnitId qid1 = new QueryUnitId(sid1, 9);
+    QueryUnitId qid2 = new QueryUnitId(sid1, 10);
+    assertNotSame(qid1, qid2);
+    QueryUnitId qid3 = new QueryUnitId(sid1, 9);
+    assertEquals(qid1, qid3);
+  }
+
+  @Test
+  public void testCompareTo() {
+    long time = System.currentTimeMillis();
+    
+    QueryId queryId1 = createQueryId(time, 1, 1);
+    QueryId queryId2 = createQueryId(time, 2, 2);
+    QueryId queryId3 = createQueryId(time, 1, 1);
+    assertEquals(-1, queryId1.compareTo(queryId2));
+    assertEquals(1, queryId2.compareTo(queryId1));
+    assertEquals(0, queryId3.compareTo(queryId1));
+    
+    SubQueryId sid1 = TajoIdUtils.newSubQueryId(queryId1, 1);
+    SubQueryId sid2 = TajoIdUtils.newSubQueryId(queryId1, 2);    
+    SubQueryId sid3 = TajoIdUtils.newSubQueryId(queryId1, 1);
+    assertEquals(-1, sid1.compareTo(sid2));
+    assertEquals(1, sid2.compareTo(sid1));
+    assertEquals(0, sid3.compareTo(sid1));
+    
+    QueryUnitId qid1 = new QueryUnitId(sid1, 9);
+    QueryUnitId qid2 = new QueryUnitId(sid1, 10);
+    QueryUnitId qid3 = new QueryUnitId(sid1, 9);
+    assertEquals(-1, qid1.compareTo(qid2));
+    assertEquals(1, qid2.compareTo(qid1));
+    assertEquals(0, qid3.compareTo(qid1));
+  }
+  
+  @Test
+  public void testConstructFromString() {
+    QueryIdFactory.reset();
+    QueryId qid1 = QueryIdFactory.newQueryId();
+    QueryId qid2 = TajoIdUtils.createQueryId(qid1.toString());
+    assertEquals(qid1, qid2);
+    
+    SubQueryId sub1 = QueryIdFactory.newSubQueryId(qid1);
+    SubQueryId sub2 = TajoIdUtils.newSubQueryId(sub1.toString());
+    assertEquals(sub1, sub2);
+    
+    QueryUnitId u1 = QueryIdFactory.newQueryUnitId(sub1);
+    QueryUnitId u2 = new QueryUnitId(u1.toString());
+    assertEquals(u1, u2);
+
+    QueryUnitAttemptId attempt1 = new QueryUnitAttemptId(u1, 1);
+    QueryUnitAttemptId attempt2 = new QueryUnitAttemptId(attempt1.toString());
+    assertEquals(attempt1, attempt2);
+  }
+
+  @Test
+  public void testConstructFromPB() {
+    QueryIdFactory.reset();
+    QueryId qid1 = QueryIdFactory.newQueryId();
+    QueryId qid2 = new QueryId(qid1.getProto());
+    assertEquals(qid1, qid2);
+
+    SubQueryId sub1 = QueryIdFactory.newSubQueryId(qid1);
+    SubQueryId sub2 = new SubQueryId(sub1.getProto());
+    assertEquals(sub1, sub2);
+
+    QueryUnitId u1 = QueryIdFactory.newQueryUnitId(sub1);
+    QueryUnitId u2 = new QueryUnitId(u1.getProto());
+    assertEquals(u1, u2);
+
+    QueryUnitAttemptId attempt1 = new QueryUnitAttemptId(u1, 1);
+    QueryUnitAttemptId attempt2 = new QueryUnitAttemptId(attempt1.getProto());
+    assertEquals(attempt1, attempt2);
+  }
+
+  public static QueryId createQueryId(long timestamp, int id, int attemptId) {
+    ApplicationId appId = BuilderUtils.newApplicationId(timestamp, id);
+
+    return TajoIdUtils.createQueryId(appId, attemptId);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
index 6b3d14b..7aa60d5 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
@@ -29,7 +29,7 @@ import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.engine.eval.EvalNode.Type;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.LogicalPlan;
 import org.apache.tajo.engine.planner.LogicalPlanner;
@@ -114,10 +114,6 @@ public class TestEvalTree {
       y =  params.get(1).asInt4();
       return DatumFactory.createInt4(x + y);
     }
-    
-    public String toJSON() {
-    	return GsonCreator.getInstance().toJson(this, GeneralFunction.class);
-    }
   }
 
   static String[] QUERIES = {
@@ -531,8 +527,8 @@ public class TestEvalTree {
     BinaryEval gth = new BinaryEval(Type.GTH, e3, plus3);
     assertCloneEqual(gth);
     
-    String json = gth.toJSON();
-    EvalNode eval = GsonCreator.getInstance().fromJson(json, EvalNode.class);
+    String json = gth.toJson();
+    EvalNode eval = CoreGsonHelper.fromJson(json, EvalNode.class);
     assertCloneEqual(eval);
     
     assertEquals(gth.getType(), eval.getType());

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
index f66eabb..6a1760e 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
@@ -20,7 +20,6 @@ package org.apache.tajo.engine.planner;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import com.google.gson.Gson;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
@@ -32,7 +31,7 @@ import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.engine.function.builtin.SumInt;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.master.TajoMaster;
@@ -144,6 +143,7 @@ public class TestLogicalPlanner {
     assertEquals(ExprType.ROOT, plan.getType());
     TestLogicalNode.testCloneLogicalNode(plan);
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
 
     assertEquals(ExprType.PROJECTION, root.getSubNode().getType());
     ProjectionNode projNode = (ProjectionNode) root.getSubNode();
@@ -176,6 +176,7 @@ public class TestLogicalPlanner {
 
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
     TestLogicalNode.testCloneLogicalNode(root);
 
     Schema expectedSchema = new Schema();
@@ -210,6 +211,7 @@ public class TestLogicalPlanner {
     // three relations
     expr = sqlAnalyzer.parse(QUERIES[2]);
     plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
     expectedSchema.addColumn("score", Type.INT4);
@@ -266,6 +268,7 @@ public class TestLogicalPlanner {
     // two relations
     Expr context = sqlAnalyzer.parse(JOINS[0]);
     LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     assertSchema(expectedJoinSchema, plan.getOutSchema());
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -301,6 +304,7 @@ public class TestLogicalPlanner {
     // two relations
     Expr expr = sqlAnalyzer.parse(JOINS[1]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     assertSchema(expectedJoinSchema, plan.getOutSchema());
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -336,6 +340,7 @@ public class TestLogicalPlanner {
     // two relations
     Expr expr = sqlAnalyzer.parse(JOINS[2]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     assertSchema(expectedJoinSchema, plan.getOutSchema());
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -376,6 +381,7 @@ public class TestLogicalPlanner {
 
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
     testQuery7(root.getSubNode());
 
     // with having clause
@@ -410,6 +416,7 @@ public class TestLogicalPlanner {
     Expr expr = sqlAnalyzer.parse(
         FileUtil.readTextFile(new File("src/test/queries/tpch_q2_simplified.tql")));
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     Schema expected = tpch.getOutSchema("q2");
     assertSchema(expected, plan.getOutSchema());
 //    LogicalNode optimized = LogicalOptimizer.optimize(context, plan);
@@ -441,6 +448,7 @@ public class TestLogicalPlanner {
     Expr context = sqlAnalyzer.parse(QUERIES[8]);
     LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
     TestLogicalNode.testCloneLogicalNode(plan);
+    testJsonSerDerObject(plan);
 
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
@@ -455,6 +463,7 @@ public class TestLogicalPlanner {
   public final void testOrderBy() throws CloneNotSupportedException {
     Expr expr = sqlAnalyzer.parse(QUERIES[4]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -481,6 +490,7 @@ public class TestLogicalPlanner {
   public final void testLimit() throws CloneNotSupportedException {
     Expr expr = sqlAnalyzer.parse(QUERIES[12]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -499,6 +509,7 @@ public class TestLogicalPlanner {
   public final void testSPJPush() throws CloneNotSupportedException {
     Expr expr = sqlAnalyzer.parse(QUERIES[5]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
     assertEquals(ExprType.ROOT, plan.getType());
@@ -527,6 +538,7 @@ public class TestLogicalPlanner {
   public final void testSPJ() throws CloneNotSupportedException {
     Expr expr = sqlAnalyzer.parse(QUERIES[6]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
   }
 
@@ -534,11 +546,10 @@ public class TestLogicalPlanner {
   public final void testJson() {
 	  Expr expr = sqlAnalyzer.parse(QUERIES[9]);
 	  LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-	  //LogicalOptimizer.optimize(context, plan);
+    testJsonSerDerObject(plan);
 
-	  String json = plan.toJSON();
-	  Gson gson = GsonCreator.getInstance();
-	  LogicalNode fromJson = gson.fromJson(json, LogicalNode.class);
+	  String json = plan.toJson();
+	  LogicalNode fromJson = CoreGsonHelper.fromJson(json, LogicalNode.class);
 	  assertEquals(ExprType.ROOT, fromJson.getType());
 	  LogicalNode groupby = ((LogicalRootNode)fromJson).getSubNode();
 	  assertEquals(ExprType.PROJECTION, groupby.getType());
@@ -576,9 +587,9 @@ public class TestLogicalPlanner {
   @Test
   public final void testExprNode() {
     Expr expr = sqlAnalyzer.parse(QUERIES[10]);
-    LogicalPlan planNode = planner.createPlan(expr);
-//    LogicalOptimizer.optimize(context, plan);
-    LogicalNode plan = planNode.getRootBlock().getRoot();
+    LogicalPlan rootNode = planner.createPlan(expr);
+    LogicalNode plan = rootNode.getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     assertEquals(ExprType.EXPRS, root.getSubNode().getType());
@@ -603,8 +614,8 @@ public class TestLogicalPlanner {
   public final void testAlias1() {
     Expr expr = sqlAnalyzer.parse(ALIAS[0]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(expr, plan);
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
 
     Schema finalSchema = root.getOutSchema();
     Iterator<Column> it = finalSchema.getColumns().iterator();
@@ -630,8 +641,8 @@ public class TestLogicalPlanner {
   public final void testAlias2() {
     Expr expr = sqlAnalyzer.parse(ALIAS[1]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(expr, plan);
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
 
     Schema finalSchema = root.getOutSchema();
     Iterator<Column> it = finalSchema.getColumns().iterator();
@@ -649,8 +660,8 @@ public class TestLogicalPlanner {
   public final void testCreateTableDef() {
     Expr expr = sqlAnalyzer.parse(CREATE_TABLE[0]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(context, plan);
     LogicalRootNode root = (LogicalRootNode) plan;
+    testJsonSerDerObject(root);
     assertEquals(ExprType.CREATE_TABLE, root.getSubNode().getType());
     CreateTableNode createTable = (CreateTableNode) root.getSubNode();
 
@@ -733,7 +744,7 @@ public class TestLogicalPlanner {
   public final void testCubeBy() {
     Expr expr = sqlAnalyzer.parse(CUBE_ROLLUP[0]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(expr, plan);
+    testJsonSerDerObject(plan);
 
     Set<Set<Column>> cuboids = Sets.newHashSet();
 
@@ -778,6 +789,7 @@ public class TestLogicalPlanner {
   public final void testSetPlan() {
     Expr expr = sqlAnalyzer.parse(setStatements[0]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     assertEquals(ExprType.UNION, root.getSubNode().getType());
@@ -795,7 +807,7 @@ public class TestLogicalPlanner {
     // for testing multiple set statements
     Expr expr = sqlAnalyzer.parse(setStatements[1]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(expr, plan);
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     assertEquals(ExprType.UNION, root.getSubNode().getType());
@@ -812,7 +824,7 @@ public class TestLogicalPlanner {
     // for testing multiple set statements
     Expr expr = sqlAnalyzer.parse(setStatements[2]);
     LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(expr, plan);
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     assertEquals(ExprType.EXCEPT, root.getSubNode().getType());
@@ -839,7 +851,7 @@ public class TestLogicalPlanner {
   public void testSetQualifier() {
     Expr context = sqlAnalyzer.parse(setQualifiers[0]);
     LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(context, plan);
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     assertEquals(ExprType.PROJECTION, root.getSubNode().getType());
@@ -848,7 +860,7 @@ public class TestLogicalPlanner {
 
     context = sqlAnalyzer.parse(setQualifiers[1]);
     plan = planner.createPlan(context).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(context, plan);
+    testJsonSerDerObject(plan);
     assertEquals(ExprType.ROOT, plan.getType());
     root = (LogicalRootNode) plan;
     assertEquals(ExprType.PROJECTION, root.getSubNode().getType());
@@ -857,10 +869,16 @@ public class TestLogicalPlanner {
 
     context = sqlAnalyzer.parse(setQualifiers[2]);
     plan = planner.createPlan(context).getRootBlock().getRoot();
-//    plan = LogicalOptimizer.optimize(context, plan);
+    testJsonSerDerObject(plan);
     root = (LogicalRootNode) plan;
     assertEquals(ExprType.PROJECTION, root.getSubNode().getType());
     projectionNode = (ProjectionNode) root.getSubNode();
     assertEquals(ExprType.SCAN, projectionNode.getSubNode().getType());
   }
+
+  public void testJsonSerDerObject(LogicalNode rootNode) {
+    String json = rootNode.toJson();
+    LogicalNode fromJson = CoreGsonHelper.fromJson(json, LogicalNode.class);
+    assertEquals("JSON (de) serialization equivalence check", rootNode, fromJson);
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestRepartitioner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestRepartitioner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestRepartitioner.java
index 40f94db..55b9a91 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestRepartitioner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestRepartitioner.java
@@ -18,11 +18,11 @@
 
 package org.apache.tajo.master;
 
+import org.apache.tajo.TestTajoIds;
 import org.jboss.netty.handler.codec.http.QueryStringDecoder;
 import org.junit.Test;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.SubQueryId;
-import org.apache.tajo.TestQueryUnitId;
 import org.apache.tajo.master.ExecutionBlock.PartitionType;
 import org.apache.tajo.util.TUtil;
 import org.apache.tajo.util.TajoIdUtils;
@@ -35,7 +35,7 @@ import static junit.framework.Assert.assertEquals;
 public class TestRepartitioner {
   @Test
   public void testCreateHashFetchURL() throws Exception {
-    QueryId q1 = TestQueryUnitId.createQueryId(1315890136000l, 2, 1);
+    QueryId q1 = TestTajoIds.createQueryId(1315890136000l, 2, 1);
     String hostName = "tajo1";
     int port = 1234;
     SubQueryId sid = TajoIdUtils.createSubQueryId(q1, 2);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/storage/TestFragment.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/storage/TestFragment.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/storage/TestFragment.java
index 587e486..f273bba 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/storage/TestFragment.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/storage/TestFragment.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.storage;
 
 import com.google.common.collect.Sets;
-import com.google.gson.Gson;
 import org.apache.hadoop.fs.Path;
 import org.junit.Before;
 import org.junit.Test;
@@ -28,7 +27,6 @@ import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.TableMeta;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.common.TajoDataTypes.Type;
-import org.apache.tajo.engine.json.GsonCreator;
 
 import java.util.Arrays;
 import java.util.SortedSet;
@@ -123,20 +121,4 @@ public class TestFragment {
     }
     assertEquals(num, sortedSet.size());
   }
-  
-//  @Test
-  public final void testJson() {
-	  Fragment frag1 = new Fragment("table1_1", new Path("/table0"), meta1, 0, 500, null);
-    frag1.setDistCached();
-	  String json = frag1.toString();
-	  System.out.println(json);
-	  Gson gson = GsonCreator.getInstance();
-	  Fragment fromJson = gson.fromJson(json, Fragment.class);
-	  assertEquals(frag1.getId(), fromJson.getId());
-	  assertEquals(frag1.getPath(), fromJson.getPath());
-	  assertEquals(frag1.getStartOffset(), fromJson.getStartOffset());
-	  assertEquals(frag1.getLength(), fromJson.getLength());
-	  assertEquals(frag1.getMeta(), fromJson.getMeta());
-    assertEquals(frag1.isDistCached(), fromJson.isDistCached());
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TaskRunnerTest.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TaskRunnerTest.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TaskRunnerTest.java
index 2119ccc..e61f721 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TaskRunnerTest.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TaskRunnerTest.java
@@ -28,7 +28,7 @@ import org.apache.hadoop.yarn.util.BuilderUtils;
 import org.apache.tajo.QueryConf;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.SubQueryId;
-import org.apache.tajo.TestQueryUnitId;
+import org.apache.tajo.TestTajoIds;
 import org.apache.tajo.ipc.MasterWorkerProtocol.MasterWorkerProtocolService;
 import org.apache.tajo.rpc.ProtoAsyncRpcClient;
 import org.apache.tajo.util.TajoIdUtils;
@@ -38,7 +38,7 @@ import static org.mockito.Mockito.when;
 
 public class TaskRunnerTest {
   long ts1 = 1315890136000l;
-  QueryId q1 = TestQueryUnitId.createQueryId(ts1, 2, 5);
+  QueryId q1 = TestTajoIds.createQueryId(ts1, 2, 5);
   SubQueryId sq1 = TajoIdUtils.createSubQueryId(q1, 5);
 
   //@Test

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
index 5e98e01..498d0df 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
@@ -32,7 +32,7 @@ import org.apache.tajo.catalog.TableMeta;
 import org.apache.tajo.catalog.statistics.TableStat;
 import org.apache.tajo.datum.*;
 import org.apache.tajo.storage.exception.AlreadyExistsStorageException;
-import org.apache.tajo.storage.json.GsonCreator;
+import org.apache.tajo.storage.json.StorageGsonHelper;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -144,7 +144,7 @@ public class CSVFile {
              * sb.append(field.asChars()); } sb.append("]");
              */
             ArrayDatum array = (ArrayDatum) tuple.get(i);
-            sb.append(array.toJSON());
+            sb.append(array.toJson());
             break;
           default:
             throw new UnsupportedOperationException("Cannot write such field: "
@@ -394,7 +394,7 @@ public class CSVFile {
                 tuple.put(i, DatumFactory.createInet4(cell));
                 break;
               case ARRAY:
-                Datum data = GsonCreator.getInstance().fromJson(cell,
+                Datum data = StorageGsonHelper.getInstance().fromJson(cell,
                     Datum.class);
                 tuple.put(i, data);
                 break;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/Fragment.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/Fragment.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/Fragment.java
index c1605b6..08a2ac0 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/Fragment.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/Fragment.java
@@ -22,32 +22,22 @@ import com.google.common.base.Objects;
 import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.hadoop.fs.Path;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos.FragmentProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.FragmentProtoOrBuilder;
 import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProto;
-import org.apache.tajo.storage.json.GsonCreator;
+import org.apache.tajo.storage.json.StorageGsonHelper;
 import org.apache.tajo.util.TUtil;
 
-public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject {
-
-  protected FragmentProto proto = FragmentProto.getDefaultInstance();
+public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject, GsonObject {
   protected FragmentProto.Builder builder = null;
-  protected boolean viaProto = false;
-
-  @Expose
-  private String fragmentId;
-  @Expose
-  private Path path;
-  @Expose
-  private TableMeta meta;
-  @Expose
-  private Long startOffset;
-  @Expose
-  private Long length;
 
-  @Expose
-  private Boolean distCached;
+  @Expose private String fragmentId; // required
+  @Expose private Path path; // required
+  @Expose private TableMeta meta; // required
+  @Expose private Long startOffset; // required
+  @Expose private Long length; // required
+  @Expose private boolean distCached = false; // optional
 
   private String [] dataLocations;
 
@@ -94,43 +84,21 @@ public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject {
   }
 
   public String getId() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.fragmentId != null) {
-      return this.fragmentId;
-    }
-
-    if (!p.hasId()) {
-      return null;
-    }
-    this.fragmentId = p.getId();
-
     return this.fragmentId;
   }
 
   @Override
   public void setId(String fragmentId) {
-    setModified();
     this.fragmentId = fragmentId;
   }
   
   @Override
   public Path getPath() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.path != null) {
-      return this.path;
-    }
-    if (!p.hasPath()) {
-      return null;
-    }
-    this.path = new Path(p.getPath());
     return this.path;
   }
 
   @Override
   public void setPath(Path path) {
-    setModified();
     this.path = path;
   }
   
@@ -139,65 +107,27 @@ public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject {
   }
 
   public TableMeta getMeta() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.meta != null) {
-      return this.meta;
-    }
-    if (!p.hasMeta()) {
-      return null;
-    }
-    this.meta = new TableMetaImpl(p.getMeta());
     return this.meta;
   }
 
   @Override
   public void setMeta(TableMeta meta) {
-    setModified();
     this.meta = meta;
   }
 
   public Long getStartOffset() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.startOffset != null) {
-      return this.startOffset;
-    }
-    if (!p.hasStartOffset()) {
-      return null;
-    }
-    this.startOffset = p.getStartOffset();
     return this.startOffset;
   }
 
   public Long getLength() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.length != null) {
-      return this.length;
-    }
-    if (!p.hasLength()) {
-      return null;
-    }
-    this.length = p.getLength();
     return this.length;
   }
 
   public Boolean isDistCached() {
-    FragmentProtoOrBuilder p = viaProto ? proto : builder;
-
-    if (this.distCached != null) {
-      return distCached;
-    }
-    if (!p.hasDistCached()) {
-      return false;
-    }
-    this.distCached = p.getDistCached();
     return this.distCached;
   }
 
   public void setDistCached() {
-    setModified();
     this.distCached = true;
   }
 
@@ -240,15 +170,11 @@ public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject {
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(getPath(), getStartOffset(), getLength(),
-        isDistCached());
+    return Objects.hashCode(fragmentId, path, startOffset, length, isDistCached());
   }
   
   public Object clone() throws CloneNotSupportedException {
     Fragment frag = (Fragment) super.clone();
-    initFromProto();
-    frag.proto = null;
-    frag.viaProto = false;
     frag.builder = FragmentProto.newBuilder();
     frag.fragmentId = fragmentId;
     frag.path = path;
@@ -267,84 +193,22 @@ public class Fragment implements TableDesc, Comparable<Fragment>, SchemaObject {
 
   @Override
   public FragmentProto getProto() {
-    if (!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }
-    
-    return proto;
-  }
-
-  private void setModified() {
-    if (viaProto || builder == null) {
-      builder = FragmentProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-
-  protected void mergeLocalToBuilder() {
     if (builder == null) {
-      this.builder = FragmentProto.newBuilder(proto);
-    }
-    
-    if (this.fragmentId != null) {
-      builder.setId(this.fragmentId);
-    }
-
-    if (this.startOffset != null) {
-      builder.setStartOffset(this.startOffset);
-    }
-
-    if (this.meta != null) {
-      builder.setMeta(meta.getProto());
+      builder = FragmentProto.newBuilder();
     }
+    builder.setId(this.fragmentId);
+    builder.setStartOffset(this.startOffset);
+    builder.setMeta(meta.getProto());
+    builder.setLength(this.length);
+    builder.setPath(this.path.toString());
+    builder.setDistCached(this.distCached);
 
-    if (this.length!= null) {
-      builder.setLength(this.length);
-    }
-
-    if (this.path != null) {
-      builder.setPath(this.path.toString());
-    }
-
-    if (this.distCached != null) {
-      builder.setDistCached(this.distCached);
-    }
-  }
-  
-  private void mergeProtoToLocal() {
-	  FragmentProtoOrBuilder p = viaProto ? proto : builder;
-	  if (fragmentId == null && p.hasId()) {
-	    fragmentId = p.getId();
-	  }
-	  if (path == null && p.hasPath()) {
-		  path = new Path(p.getPath());
-	  }
-	  if (meta == null && p.hasMeta()) {
-		  meta = new TableMetaImpl(p.getMeta());
-	  }
-	  if (startOffset == null && p.hasStartOffset()) {
-		  startOffset = p.getStartOffset();
-	  }
-	  if (length == null && p.hasLength()) {
-		  length = p.getLength();
-	  }
-    if (distCached == null && p.hasDistCached()) {
-      distCached = p.getDistCached();
-    }
+    return builder.build();
   }
 
   @Override
-  public String toJSON() {
-	  initFromProto();
-	  Gson gson = GsonCreator.getInstance();
+  public String toJson() {
+	  Gson gson = StorageGsonHelper.getInstance();
 	  return gson.toJson(this, TableDesc.class);
   }
-
-  @Override
-  public void initFromProto() {
-	  mergeProtoToLocal();
-    meta.initFromProto();
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RawFile.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RawFile.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RawFile.java
index 3b7aa98..b3f158b 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RawFile.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RawFile.java
@@ -26,7 +26,7 @@ import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.ArrayDatum;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
-import org.apache.tajo.datum.json.GsonCreator;
+import org.apache.tajo.json.CommonGsonHelper;
 import org.apache.tajo.util.BitArray;
 
 import java.io.File;
@@ -210,8 +210,7 @@ public class RawFile {
             byte [] arrayBytes = new byte[arrayByteSize];
             buffer.get(arrayBytes);
             String json = new String(arrayBytes);
-            ArrayDatum array = (ArrayDatum) GsonCreator
-                .getInstance().fromJson(json, Datum.class);
+            ArrayDatum array = (ArrayDatum) CommonGsonHelper.fromJson(json, Datum.class);
             tuple.put(i, array);
             break;
 
@@ -415,7 +414,7 @@ public class RawFile {
 
           case ARRAY :
             ArrayDatum array = (ArrayDatum) t.get(i);
-            String json = array.toJSON();
+            String json = array.toJson();
             byte [] jsonBytes = json.getBytes();
             if (flushBufferAndReplace(recordOffset, jsonBytes.length + 4)) {
               recordOffset = 0;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RowFile.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RowFile.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RowFile.java
index 39136a1..cd6dc00 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RowFile.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/RowFile.java
@@ -32,7 +32,7 @@ import org.apache.tajo.conf.TajoConf.ConfVars;
 import org.apache.tajo.datum.ArrayDatum;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
-import org.apache.tajo.datum.json.GsonCreator;
+import org.apache.tajo.json.CommonGsonHelper;
 import org.apache.tajo.storage.exception.AlreadyExistsStorageException;
 import org.apache.tajo.util.BitArray;
 
@@ -276,7 +276,7 @@ public class RowFile {
               byte [] bytes = new byte[bufSize];
               buffer.get(bytes);
               String json = new String(bytes);
-              ArrayDatum array = (ArrayDatum) GsonCreator.getInstance().fromJson(json, Datum.class);
+              ArrayDatum array = (ArrayDatum) CommonGsonHelper.fromJson(json, Datum.class);
               tuple.put(i, array);
               break;
 
@@ -460,7 +460,7 @@ public class RowFile {
               buffer.put(t.getIPv6Bytes(i));
             case ARRAY: {
               ArrayDatum array = (ArrayDatum) t.get(i);
-              String json = array.toJSON();
+              String json = array.toJson();
               byte [] byteArray = json.getBytes();
 //              out.writeInt(byteArray.length);
 //              out.write(byteArray);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TupleComparator.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TupleComparator.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TupleComparator.java
index b97d5cf..522b5a2 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TupleComparator.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TupleComparator.java
@@ -135,10 +135,6 @@ public class TupleComparator implements Comparator<Tuple>, ProtoObject<TupleComp
   }
 
   @Override
-  public void initFromProto() {
-  }
-
-  @Override
   public TupleComparatorProto getProto() {
     TupleComparatorProto.Builder builder = TupleComparatorProto.newBuilder();
     SortSpecProto.Builder sortSpecBuilder;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/FragmentDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/FragmentDeserializer.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/FragmentDeserializer.java
index 35bf016..b74fcdf 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/FragmentDeserializer.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/FragmentDeserializer.java
@@ -36,7 +36,7 @@ public class FragmentDeserializer implements JsonDeserializer<Fragment> {
 	@Override
 	public Fragment deserialize(JsonElement json, Type type,
 			JsonDeserializationContext ctx) throws JsonParseException {
-		Gson gson = GsonCreator.getInstance();
+		Gson gson = StorageGsonHelper.getInstance();
 		JsonObject fragObj = json.getAsJsonObject();
 		JsonObject metaObj = fragObj.get("meta").getAsJsonObject();
 		TableMetaImpl meta = new TableMetaImpl(

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/GsonCreator.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/GsonCreator.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/GsonCreator.java
deleted file mode 100644
index 6f51332..0000000
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/GsonCreator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.storage.json;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.TableMeta;
-import org.apache.tajo.catalog.function.AggFunction;
-import org.apache.tajo.catalog.function.Function;
-import org.apache.tajo.catalog.function.GeneralFunction;
-import org.apache.tajo.catalog.json.FunctionAdapter;
-import org.apache.tajo.catalog.json.TableDescAdapter;
-import org.apache.tajo.catalog.json.TableMetaAdapter;
-import org.apache.tajo.datum.Datum;
-import org.apache.tajo.datum.json.DatumAdapter;
-import org.apache.tajo.gson.*;
-import org.apache.tajo.storage.Fragment;
-
-public class GsonCreator {
-	private static GsonBuilder builder;
-	private static Gson gson;
-	
-	private static void init() {
-		if (builder == null) {
-			builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
-			builder.registerTypeAdapter(Path.class, new PathSerializer());
-			builder.registerTypeAdapter(Path.class, new PathDeserializer());
-			builder.registerTypeAdapter(TableDesc.class, new TableDescAdapter());
-			builder.registerTypeAdapter(Class.class, new ClassNameSerializer());
-			builder.registerTypeAdapter(Class.class, new ClassNameDeserializer());
-			builder.registerTypeAdapter(TableMeta.class, new TableMetaAdapter());
-			builder.registerTypeAdapter(Datum.class, new DatumTypeAdapter());
-			builder.registerTypeAdapter(Function.class, new FunctionAdapter());
-      builder.registerTypeAdapter(GeneralFunction.class, new FunctionAdapter());
-      builder.registerTypeAdapter(AggFunction.class, new FunctionAdapter());
-			builder.registerTypeAdapter(Datum.class, new DatumAdapter());
-      builder.registerTypeAdapter(Fragment.class, new FragmentDeserializer());
-		}
-	}
-
-	public static Gson getInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.create();
-	  }
-	  return gson;
-	}
-
-	public static Gson getPrettyInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.setPrettyPrinting().create();
-	  }
-	  return gson;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/StorageGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/StorageGsonHelper.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/StorageGsonHelper.java
new file mode 100644
index 0000000..c4c1298
--- /dev/null
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/json/StorageGsonHelper.java
@@ -0,0 +1,90 @@
+/**
+ * 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.tajo.storage.json;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.function.AggFunction;
+import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.catalog.function.GeneralFunction;
+import org.apache.tajo.catalog.json.FunctionAdapter;
+import org.apache.tajo.catalog.json.TableDescAdapter;
+import org.apache.tajo.catalog.json.TableMetaAdapter;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.json.*;
+import org.apache.tajo.util.TUtil;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class StorageGsonHelper {
+  private static Gson gson;
+  private static Gson gsonPretty;
+
+  private StorageGsonHelper() {
+  }
+
+  private static Map<Type, GsonSerDerAdapter> registerAdapters() {
+    Map<Type, GsonSerDerAdapter> adapters = TUtil.newHashMap();
+    adapters.put(Path.class, new PathSerializer());
+    adapters.put(TableDesc.class, new TableDescAdapter());
+    adapters.put(Class.class, new ClassNameSerializer());
+    adapters.put(TableMeta.class, new TableMetaAdapter());
+    adapters.put(Datum.class, new DatumTypeAdapter());
+    adapters.put(Function.class, new FunctionAdapter());
+    adapters.put(GeneralFunction.class, new FunctionAdapter());
+    adapters.put(AggFunction.class, new FunctionAdapter());
+    adapters.put(Datum.class, new DatumAdapter());
+    return adapters;
+  }
+
+  public static Gson getInstance() {
+    if (gson == null ) {
+      GsonHelper helper = new GsonHelper(registerAdapters());
+      gson = helper.getGson();
+    }
+    return gson;
+  }
+
+  public static Gson getPrettyInstance() {
+    if (gsonPretty == null) {
+      GsonBuilder prettyBuilder = new GsonBuilder()
+          .setPrettyPrinting()
+          .excludeFieldsWithoutExposeAnnotation();
+      GsonHelper.registerAdapters(prettyBuilder, registerAdapters());
+      gsonPretty = prettyBuilder.create();
+    }
+
+    return gsonPretty;
+  }
+
+  public static String toJson(GsonObject object, Class<? extends GsonObject> clazz) {
+    return getInstance().toJson(object, clazz);
+  }
+
+  public static <T extends GsonObject> T fromJson(String json, Class<T> clazz) {
+    return getInstance().fromJson(json, clazz);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/rcfile/RCFileWrapper.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/rcfile/RCFileWrapper.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/rcfile/RCFileWrapper.java
index 63c20f8..402c354 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/rcfile/RCFileWrapper.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/rcfile/RCFileWrapper.java
@@ -117,7 +117,7 @@ public class RCFileWrapper {
               break;
             case ARRAY: {
               ArrayDatum array = (ArrayDatum) t.get(i);
-              String json = array.toJSON();
+              String json = array.toJson();
               bytes = json.getBytes();
               cu = new BytesRefWritable(bytes, 0, bytes.length);
               byteRef.set(i, cu);


[2/4] TAJO-95: Eliminate the lazy copy approach from the classes wrapping protobuf-generated classes. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/ClassNameSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/ClassNameSerializer.java b/tajo-common/src/main/java/org/apache/tajo/json/ClassNameSerializer.java
new file mode 100644
index 0000000..9e9a4ee
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/ClassNameSerializer.java
@@ -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.
+ */
+
+/**
+ * 
+ */
+package org.apache.tajo.json;
+
+import com.google.gson.*;
+
+import java.lang.reflect.Type;
+
+public class ClassNameSerializer implements GsonSerDerAdapter<Class> {
+
+	@Override
+	public JsonElement serialize(Class clazz, Type type,
+			JsonSerializationContext ctx) {
+		return new JsonPrimitive(clazz.getName());
+	}
+
+  @Override
+  public Class deserialize(JsonElement json, Type type,
+                           JsonDeserializationContext ctx) throws JsonParseException {
+    try {
+      return Class.forName(json.getAsString());
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java b/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
new file mode 100644
index 0000000..3badbc0
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
@@ -0,0 +1,70 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.util.TUtil;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class CommonGsonHelper {
+  private static Gson gson;
+  private static Gson gsonPretty;
+
+  private CommonGsonHelper() {
+  }
+	
+	private static Map<Type, GsonSerDerAdapter> registerAdapters() {
+    Map<Type, GsonSerDerAdapter> adapters = TUtil.newHashMap();
+    adapters.put(Datum.class, new DatumAdapter());
+
+    return adapters;
+	}
+
+	public static Gson getInstance() {
+	  if (gson == null ) {
+      GsonHelper helper = new GsonHelper(registerAdapters());
+      gson = helper.getGson();
+	  }
+	  return gson;
+	}
+
+  public static Gson getPrettyInstance() {
+    if (gsonPretty == null) {
+      GsonBuilder prettyBuilder = new GsonBuilder()
+          .setPrettyPrinting()
+          .excludeFieldsWithoutExposeAnnotation();
+      GsonHelper.registerAdapters(prettyBuilder, registerAdapters());
+      gsonPretty = prettyBuilder.create();
+    }
+
+    return gsonPretty;
+  }
+
+  public static String toJson(GsonObject object, Class<? extends GsonObject> clazz) {
+    return getInstance().toJson(object, clazz);
+  }
+
+  public static <T extends GsonObject> T fromJson(String json, Class<T> clazz) {
+    return getInstance().fromJson(json, clazz);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/DataTypeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/DataTypeAdapter.java b/tajo-common/src/main/java/org/apache/tajo/json/DataTypeAdapter.java
new file mode 100644
index 0000000..3df6939
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/DataTypeAdapter.java
@@ -0,0 +1,63 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.*;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+
+import java.lang.reflect.Type;
+
+
+public class DataTypeAdapter implements GsonSerDerAdapter<DataType> {
+
+  @Override
+  public DataType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+      throws JsonParseException {
+
+    JsonObject obj = (JsonObject) json;
+    DataType.Builder builder = DataType.newBuilder();
+    TajoDataTypes.Type type = Enum.valueOf(TajoDataTypes.Type.class, obj.get("type").getAsString());
+    builder.setType(type);
+
+    JsonElement len = obj.get("len");
+    if (len != null) {
+      builder.setLength(len.getAsInt());
+    }
+    JsonElement code = obj.get("code");
+    if (code != null) {
+      builder.setCode(code.getAsString());
+    }
+    return builder.build();
+  }
+
+  @Override
+  public JsonElement serialize(DataType src, Type typeOfSrc, JsonSerializationContext context) {
+    JsonObject json = new JsonObject();
+    json.addProperty("type", src.getType().name());
+    if (src.hasLength()) {
+      json.addProperty("len", src.getLength());
+    }
+    if (src.hasCode()) {
+      json.addProperty("code", src.getCode());
+    }
+
+    return json;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/DatumAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/DatumAdapter.java b/tajo-common/src/main/java/org/apache/tajo/json/DatumAdapter.java
new file mode 100644
index 0000000..8f9bb4e
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/DatumAdapter.java
@@ -0,0 +1,54 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.*;
+import org.apache.tajo.datum.Datum;
+
+import java.lang.reflect.Type;
+
+public class DatumAdapter implements GsonSerDerAdapter<Datum> {
+
+	@Override
+	public Datum deserialize(JsonElement json, Type typeOfT,
+			JsonDeserializationContext context) throws JsonParseException {
+		JsonObject jsonObject = json.getAsJsonObject();
+		String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
+		
+		Class clazz;
+		try {
+			clazz = Class.forName(className);
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+			throw new JsonParseException(e);
+		}
+		return context.deserialize(jsonObject.get("property"), clazz);
+	}
+
+	@Override
+	public JsonElement serialize(Datum src, Type typeOfSrc, JsonSerializationContext context) {
+		JsonObject jsonObj = new JsonObject();
+		String className = src.getClass().getCanonicalName();
+		jsonObj.addProperty("classname", className);
+		JsonElement jsonElem = context.serialize(src);
+		jsonObj.add("property", jsonElem);
+		return jsonObj;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/DatumTypeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/DatumTypeAdapter.java b/tajo-common/src/main/java/org/apache/tajo/json/DatumTypeAdapter.java
new file mode 100644
index 0000000..70af19f
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/DatumTypeAdapter.java
@@ -0,0 +1,55 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.*;
+import org.apache.tajo.datum.Datum;
+
+import java.lang.reflect.Type;
+
+public class DatumTypeAdapter implements GsonSerDerAdapter<Datum> {
+
+  @Override
+  public Datum deserialize(JsonElement json, Type typeOfT,
+      JsonDeserializationContext context) throws JsonParseException {
+    JsonObject jsonObject = json.getAsJsonObject();
+    String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
+    
+    Class clazz;
+    try {
+      clazz = Class.forName(className);
+    } catch (ClassNotFoundException e) {
+      e.printStackTrace();
+      throw new JsonParseException(e);
+    }
+    return context.deserialize(jsonObject.get("property"), clazz);
+  }
+
+  @Override
+  public JsonElement serialize(Datum src, Type typeOfSrc,
+      JsonSerializationContext context) {
+    JsonObject jsonObj = new JsonObject();
+    String className = src.getClass().getCanonicalName();
+    jsonObj.addProperty("classname", className);
+    JsonElement jsonElem = context.serialize(src);
+    jsonObj.add("property", jsonElem);
+    return jsonObj;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/GsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/GsonHelper.java b/tajo-common/src/main/java/org/apache/tajo/json/GsonHelper.java
new file mode 100644
index 0000000..8c6d891
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/GsonHelper.java
@@ -0,0 +1,49 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.*;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class GsonHelper {
+  private final GsonBuilder builder;
+  private final Gson gson;
+
+  public GsonHelper(Map<Type, GsonSerDerAdapter> adapters) {
+    builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
+    registerAdapters(builder, adapters);
+    gson = builder.create();
+  }
+
+  public static void registerAdapters(GsonBuilder builder, Map<Type, GsonSerDerAdapter> adapters) {
+    for (Map.Entry<Type, GsonSerDerAdapter> entry : adapters.entrySet()) {
+      try {
+        builder.registerTypeAdapter(entry.getKey(), entry.getValue());
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  public Gson getGson() {
+    return gson;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/GsonObject.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/GsonObject.java b/tajo-common/src/main/java/org/apache/tajo/json/GsonObject.java
new file mode 100644
index 0000000..b7e69c1
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/GsonObject.java
@@ -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.
+ */
+
+package org.apache.tajo.json;
+
+public interface GsonObject {
+  String toJson();
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/GsonSerDerAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/GsonSerDerAdapter.java b/tajo-common/src/main/java/org/apache/tajo/json/GsonSerDerAdapter.java
new file mode 100644
index 0000000..80a40f8
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/GsonSerDerAdapter.java
@@ -0,0 +1,25 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSerializer;
+
+public interface GsonSerDerAdapter<T> extends JsonSerializer<T>, JsonDeserializer<T> {
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/PathDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/PathDeserializer.java b/tajo-common/src/main/java/org/apache/tajo/json/PathDeserializer.java
new file mode 100644
index 0000000..739a28a
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/PathDeserializer.java
@@ -0,0 +1,40 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import org.apache.hadoop.fs.Path;
+
+import java.lang.reflect.Type;
+
+public class PathDeserializer implements JsonDeserializer<Path> {
+
+	@Override
+	public Path deserialize(JsonElement arg0, Type arg1,
+			JsonDeserializationContext arg2) throws JsonParseException {
+		return new Path(arg0.getAsJsonPrimitive().getAsString());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/PathSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/PathSerializer.java b/tajo-common/src/main/java/org/apache/tajo/json/PathSerializer.java
new file mode 100644
index 0000000..3ee8e2b
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/PathSerializer.java
@@ -0,0 +1,42 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.*;
+import org.apache.hadoop.fs.Path;
+
+import java.lang.reflect.Type;
+
+public class PathSerializer implements GsonSerDerAdapter<Path> {
+
+	@Override
+	public JsonElement serialize(Path arg0, Type arg1,
+			JsonSerializationContext arg2) {
+		return new JsonPrimitive(arg0.toString());
+	}
+
+  @Override
+  public Path deserialize(JsonElement arg0, Type arg1,
+                          JsonDeserializationContext arg2) throws JsonParseException {
+    return new Path(arg0.getAsJsonPrimitive().getAsString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
index f44062d..7eaade8 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
@@ -78,6 +78,14 @@ public class TUtil {
     return new HashSet<T>(Arrays.asList(items));
   }
 
+  public static <K,V> Map<K,V> newHashMap() {
+    return new HashMap<K, V>();
+  }
+
+  public static <K,V> Map<K,V> newHashMap(Map<K,V> map) {
+    return new HashMap<K, V>(map);
+  }
+
   public static <T> List<T> newList() {
     return new ArrayList<T>();
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
index 399f615..3ae8522 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
@@ -18,8 +18,8 @@
 
 package org.apache.tajo.datum;
 
-import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
index fa4d4d6..94aafe8 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
@@ -18,9 +18,9 @@
 
 package org.apache.tajo.datum;
 
-import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
-import org.apache.tajo.datum.json.GsonCreator;
+import org.apache.tajo.json.CommonGsonHelper;
+import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -48,8 +48,8 @@ public class TestBytesDatum {
   @Test
   public final void testJson() {
 	  Datum d = DatumFactory.createBlob("12345".getBytes());
-	  String json = d.toJSON();
-	  Datum fromJson = GsonCreator.getInstance().fromJson(json, Datum.class);
+	  String json = d.toJson();
+	  Datum fromJson = CommonGsonHelper.fromJson(json, Datum.class);
 	  assertTrue(d.equalsTo(fromJson).asBool());
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
index 77b3363..2708386 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
@@ -18,9 +18,9 @@
 
 package org.apache.tajo.datum;
 
+import org.apache.tajo.json.CommonGsonHelper;
 import org.junit.Before;
 import org.junit.Test;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.util.Arrays;
 
@@ -68,8 +68,8 @@ public class TestInet4Datum {
 	@Test
 	public final void testJson() {
 		Datum d = DatumFactory.createInet4("163.152.163.152");
-		String json = d.toJSON();
-		Datum fromJson = GsonCreator.getInstance().fromJson(json, Datum.class);
+		String json = d.toJson();
+		Datum fromJson = CommonGsonHelper.fromJson(json, Datum.class);
 		assertTrue(d.equalsTo(fromJson).asBool());
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggFuncCallEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggFuncCallEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggFuncCallEval.java
index 0e46c32..9aae34e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggFuncCallEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggFuncCallEval.java
@@ -25,7 +25,6 @@ import org.apache.tajo.catalog.function.AggFunction;
 import org.apache.tajo.catalog.function.FunctionContext;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 
@@ -41,9 +40,7 @@ public class AggFuncCallEval extends FuncEval implements Cloneable {
 
   @Override
   public EvalContext newContext() {
-    AggFunctionCtx newCtx = new AggFunctionCtx(argEvals, instance.newContext());
-
-    return newCtx;
+    return new AggFunctionCtx(argEvals, instance.newContext());
   }
 
   @Override
@@ -87,13 +84,8 @@ public class AggFuncCallEval extends FuncEval implements Cloneable {
     }
   }
 
-  public String toJSON() {
-	  return GsonCreator.getInstance().toJson(this, EvalNode.class);
-  }
-
   public Object clone() throws CloneNotSupportedException {
-    AggFuncCallEval agg = (AggFuncCallEval) super.clone();
-    return agg;
+    return super.clone();
   }
 
   public void setFirstPhase() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
index a30e77c..2a95ddf 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -20,7 +20,6 @@ package org.apache.tajo.engine.eval;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Schema;
@@ -28,7 +27,6 @@ import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.storage.Tuple;
 
@@ -202,11 +200,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
 		return leftExpr +" "+type+" "+rightExpr;
 	}
 	
-	public String toJSON() {
-	  Gson gson = GsonCreator.getInstance();
-	  return gson.toJson(this, EvalNode.class);
-	}
-	
   @Override
   public boolean equals(Object obj) {
     if (obj instanceof BinaryEval) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
index 4f385b0..4bbdcb8 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
@@ -20,17 +20,20 @@ package org.apache.tajo.engine.eval;
 
 import com.google.common.collect.Lists;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.util.TUtil;
 
 import java.util.List;
 
-public class CaseWhenEval extends EvalNode {
+public class CaseWhenEval extends EvalNode implements GsonObject {
   @Expose private List<WhenEval> whens = Lists.newArrayList();
   @Expose private EvalNode elseResult;
 
@@ -87,6 +90,7 @@ public class CaseWhenEval extends EvalNode {
     }
   }
 
+  @Override
   public String toString() {
     StringBuilder sb = new StringBuilder("CASE\n");
     for (WhenEval when : whens) {
@@ -130,13 +134,13 @@ public class CaseWhenEval extends EvalNode {
           return false;
         }
       }
-      return elseResult.equals(other.elseResult);
+      return TUtil.checkEquals(elseResult, other.elseResult);
     } else {
       return false;
     }
   }
 
-  public static class WhenEval extends EvalNode {
+  public static class WhenEval extends EvalNode implements GsonObject {
     @Expose private EvalNode condition;
     @Expose private EvalNode result;
 
@@ -179,10 +183,27 @@ public class CaseWhenEval extends EvalNode {
       return this.result;
     }
 
+    @Override
+    public boolean equals(Object object) {
+      if (object instanceof WhenEval) {
+        WhenEval other = (WhenEval) object;
+        return condition.equals(other.condition) &&
+            result.equals(other.result);
+      } else {
+        return false;
+      }
+    }
+
+    @Override
     public String toString() {
       return "WHEN " + condition + " THEN " + result;
     }
 
+    @Override
+    public String toJson() {
+      return CoreGsonHelper.toJson(WhenEval.this, WhenEval.class);
+    }
+
     private class WhenContext implements EvalContext {
       EvalContext condCtx;
       EvalContext resultCtx;
@@ -210,17 +231,6 @@ public class CaseWhenEval extends EvalNode {
       result.postOrder(visitor);
       visitor.visit(this);
     }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj instanceof WhenEval) {
-       WhenEval other = (WhenEval) obj;
-        return this.condition == other.condition
-            && this.result == other.result;
-      } else {
-        return false;
-      }
-    }
   }
 
   private class CaseContext implements EvalContext {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
index 7ab019f..069db2c 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
@@ -19,13 +19,11 @@
 package org.apache.tajo.engine.eval;
 
 import com.google.common.base.Objects;
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
 
 public class ConstEval extends EvalNode implements Comparable<ConstEval>, Cloneable {
 	@Expose Datum datum = null;
@@ -53,11 +51,6 @@ public class ConstEval extends EvalNode implements Comparable<ConstEval>, Clonea
 	public String toString() {
 		return datum.toString();
 	}
-	
-	public String toJSON() {
-		Gson gson = GsonCreator.getInstance();
-		return gson.toJson(this, EvalNode.class);
-	}
 
   @Override
 	public DataType [] getValueType() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
index b6c7276..12e1cf8 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
@@ -18,21 +18,18 @@
 
 package org.apache.tajo.engine.eval;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.storage.Tuple;
 
-public abstract class EvalNode implements Cloneable {
-	@Expose
-	protected Type type;
-	@Expose
-	protected EvalNode leftExpr;
-	@Expose
-	protected EvalNode rightExpr;
+public abstract class EvalNode implements Cloneable, GsonObject {
+	@Expose protected Type type;
+	@Expose protected EvalNode leftExpr;
+	@Expose protected EvalNode rightExpr;
 	
 	public EvalNode(Type type) {
 		this.type = type;
@@ -83,10 +80,10 @@ public abstract class EvalNode implements Cloneable {
 	public String toString() {
 		return "("+this.type+"("+leftExpr.toString()+" "+rightExpr.toString()+"))";
 	}
-	
-	public String toJSON() {
-	  Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, EvalNode.class);
+
+  @Override
+	public String toJson() {
+    return CoreGsonHelper.toJson(this, EvalNode.class);
 	}
 	
 	public void eval(EvalContext ctx, Schema schema, Tuple tuple) {}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
index 75a6eb7..9282497 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
@@ -18,13 +18,11 @@
 
 package org.apache.tajo.engine.eval;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.storage.Tuple;
 
@@ -130,11 +128,6 @@ public class FieldEval extends EvalNode implements Cloneable {
     
     return eval;
   }
-  
-  public String toJSON() {
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, EvalNode.class);
-  }
 
   public void preOrder(EvalNodeVisitor visitor) {
     visitor.visit(this);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncCallEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncCallEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncCallEval.java
index 9787805..d44385e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncCallEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncCallEval.java
@@ -19,13 +19,11 @@
 package org.apache.tajo.engine.eval;
 
 import com.google.common.base.Objects;
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.function.GeneralFunction;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 import org.apache.tajo.util.TUtil;
@@ -66,12 +64,6 @@ public class FuncCallEval extends FuncEval {
     }
     return instance.eval(params);
   }
-
-  @Override
-	public String toJSON() {
-	  Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, EvalNode.class);
-	}
 	
 	@Override
 	public boolean equals(Object obj) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncEval.java
index 350b761..2ff6d19 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FuncEval.java
@@ -19,13 +19,11 @@
 package org.apache.tajo.engine.eval;
 
 import com.google.common.base.Objects;
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.util.TUtil;
 
@@ -77,12 +75,6 @@ public abstract class FuncEval extends EvalNode implements Cloneable {
 		}
 		return funcDesc.getSignature()+"("+sb+")";
 	}
-
-  @Override
-	public String toJSON() {
-	  Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, EvalNode.class);
-	}
 	
 	@Override
 	public boolean equals(Object obj) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/CoreGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/CoreGsonHelper.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/CoreGsonHelper.java
new file mode 100644
index 0000000..a3b8ac6
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/CoreGsonHelper.java
@@ -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.
+ */
+
+package org.apache.tajo.engine.json;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.function.AggFunction;
+import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.catalog.function.GeneralFunction;
+import org.apache.tajo.catalog.json.FunctionAdapter;
+import org.apache.tajo.catalog.json.TableDescAdapter;
+import org.apache.tajo.catalog.json.TableMetaAdapter;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.logical.LogicalNode;
+import org.apache.tajo.json.*;
+import org.apache.tajo.util.TUtil;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class CoreGsonHelper {
+  private static Gson gson;
+  private static Gson gsonPretty;
+
+  private CoreGsonHelper() {
+  }
+	
+	private static Map<Type, GsonSerDerAdapter> registerAdapters() {
+    Map<Type, GsonSerDerAdapter> adapters = TUtil.newHashMap();
+    adapters.put(Path.class, new PathSerializer());
+    adapters.put(TableDesc.class, new TableDescAdapter());
+    adapters.put(Class.class, new ClassNameSerializer());
+    adapters.put(LogicalNode.class, new LogicalNodeAdapter());
+    adapters.put(EvalNode.class, new EvalNodeAdapter());
+    adapters.put(TableMeta.class, new TableMetaAdapter());
+    adapters.put(Function.class, new FunctionAdapter());
+    adapters.put(GeneralFunction.class, new FunctionAdapter());
+    adapters.put(AggFunction.class, new FunctionAdapter());
+    adapters.put(Datum.class, new DatumAdapter());
+    adapters.put(DataType.class, new DataTypeAdapter());
+
+    return adapters;
+	}
+
+	public static Gson getInstance() {
+	  if (gson == null ) {
+      GsonHelper helper = new GsonHelper(registerAdapters());
+      gson = helper.getGson();
+	  }
+	  return gson;
+	}
+
+  public static Gson getPrettyInstance() {
+    if (gsonPretty == null) {
+      GsonBuilder prettyBuilder = new GsonBuilder()
+          .setPrettyPrinting()
+          .excludeFieldsWithoutExposeAnnotation();
+      GsonHelper.registerAdapters(prettyBuilder, registerAdapters());
+      gsonPretty = prettyBuilder.create();
+    }
+
+    return gsonPretty;
+  }
+
+  public static String toJson(GsonObject object, Class<? extends GsonObject> clazz) {
+    return getInstance().toJson(object, clazz);
+  }
+
+  public static <T extends GsonObject> T fromJson(String json, Class<T> clazz) {
+    return getInstance().fromJson(json, clazz);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/EvalNodeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/EvalNodeAdapter.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/EvalNodeAdapter.java
index 49ea542..74c7305 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/EvalNodeAdapter.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/EvalNodeAdapter.java
@@ -23,10 +23,11 @@ package org.apache.tajo.engine.json;
 
 import com.google.gson.*;
 import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;
 
-public class EvalNodeAdapter implements JsonSerializer<EvalNode>, JsonDeserializer<EvalNode> {
+public class EvalNodeAdapter implements GsonSerDerAdapter<EvalNode> {
 
 	@Override
 	public EvalNode deserialize(JsonElement json, Type type,

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FragmentDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FragmentDeserializer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FragmentDeserializer.java
index 41b2ef6..6231c03 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FragmentDeserializer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FragmentDeserializer.java
@@ -36,11 +36,11 @@ public class FragmentDeserializer implements JsonDeserializer<Fragment> {
 	@Override
 	public Fragment deserialize(JsonElement json, Type type,
 			JsonDeserializationContext ctx) throws JsonParseException {
-		Gson gson = GsonCreator.getInstance();
+		Gson gson = CoreGsonHelper.getInstance();
 		JsonObject fragObj = json.getAsJsonObject();
 		JsonObject metaObj = fragObj.get("meta").getAsJsonObject();
 		TableMetaImpl meta = new TableMetaImpl(
-		    gson.fromJson(metaObj.get("schema"), Schema.class), 
+		    gson.fromJson(metaObj.get("schema"), Schema.class),
 				gson.fromJson(metaObj.get("storeType"), StoreType.class), 
 				gson.fromJson(metaObj.get("options"), Options.class));
 		Fragment fragment = new Fragment(fragObj.get("tabletId").getAsString(), 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FromTableDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FromTableDeserializer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FromTableDeserializer.java
index 4a5b2ac..501ae0a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FromTableDeserializer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/FromTableDeserializer.java
@@ -34,7 +34,7 @@ public class FromTableDeserializer implements JsonDeserializer<FromTable> {
 	@Override
 	public FromTable deserialize(JsonElement json, Type type,
 			JsonDeserializationContext ctx) throws JsonParseException {
-		Gson gson = GsonCreator.getInstance();
+		Gson gson = CoreGsonHelper.getInstance();
 		JsonObject fromTableObj = json.getAsJsonObject();
 		boolean isFragment = fromTableObj.get("isFragment").getAsBoolean();
 		TableDesc desc;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/GsonCreator.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/GsonCreator.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/GsonCreator.java
deleted file mode 100644
index 98e7f1f..0000000
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/GsonCreator.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.engine.json;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.TableMeta;
-import org.apache.tajo.catalog.function.AggFunction;
-import org.apache.tajo.catalog.function.Function;
-import org.apache.tajo.catalog.function.GeneralFunction;
-import org.apache.tajo.catalog.json.FunctionAdapter;
-import org.apache.tajo.catalog.json.TableDescAdapter;
-import org.apache.tajo.catalog.json.TableMetaAdapter;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.datum.Datum;
-import org.apache.tajo.datum.json.DatumAdapter;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.planner.logical.LogicalNode;
-import org.apache.tajo.gson.*;
-
-public class GsonCreator {
-	private static GsonBuilder builder;
-	private static Gson gson;
-	
-	private static void init() {
-		if (builder == null) {
-			builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
-			builder.registerTypeAdapter(Path.class, new PathSerializer());
-			builder.registerTypeAdapter(Path.class, new PathDeserializer());
-			builder.registerTypeAdapter(TableDesc.class, new TableDescAdapter());
-			builder.registerTypeAdapter(Class.class, new ClassNameSerializer());
-			builder.registerTypeAdapter(Class.class, new ClassNameDeserializer());
-			builder.registerTypeAdapter(LogicalNode.class, new LogicalNodeAdapter());
-			builder.registerTypeAdapter(EvalNode.class, new EvalNodeAdapter());
-			builder.registerTypeAdapter(TableMeta.class, new TableMetaAdapter());
-			builder.registerTypeAdapter(Datum.class, new DatumTypeAdapter());
-			builder.registerTypeAdapter(Function.class, new FunctionAdapter());
-      builder.registerTypeAdapter(GeneralFunction.class, new FunctionAdapter());
-      builder.registerTypeAdapter(AggFunction.class, new FunctionAdapter());
-			builder.registerTypeAdapter(Datum.class, new DatumAdapter());
-      builder.registerTypeAdapter(DataType.class, new DataTypeAdapter());
-		}
-	}
-
-	public static Gson getInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.create();
-	  }
-	  return gson;
-	}
-
-	public static Gson getPrettyInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.setPrettyPrinting().create();
-	  }
-	  return gson;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/LogicalNodeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/LogicalNodeAdapter.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/LogicalNodeAdapter.java
index 1716916..d98bd53 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/LogicalNodeAdapter.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/json/LogicalNodeAdapter.java
@@ -23,10 +23,11 @@ package org.apache.tajo.engine.json;
 
 import com.google.gson.*;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
+import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;
 
-public class LogicalNodeAdapter implements JsonSerializer<LogicalNode>, JsonDeserializer<LogicalNode> {
+public class LogicalNodeAdapter implements GsonSerDerAdapter<LogicalNode> {
 
 	@Override
 	public LogicalNode deserialize(JsonElement json, Type type,

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/FromTable.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/FromTable.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/FromTable.java
index 24161d4..04c1bb9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/FromTable.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/FromTable.java
@@ -18,19 +18,17 @@
 
 package org.apache.tajo.engine.planner;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.util.TUtil;
 
-public class FromTable implements Cloneable {
-  @Expose
-  private TableDesc desc;
-  @Expose
-  private String alias = null;
+public class FromTable implements Cloneable, GsonObject {
+  @Expose private TableDesc desc;
+  @Expose private String alias = null;
 
   public FromTable() {}
 
@@ -97,9 +95,8 @@ public class FromTable implements Cloneable {
     return table;
   }
 
-  public String toJSON() {
-    desc.initFromProto();
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, FromTable.class);
+  @Override
+  public String toJson() {
+    return CoreGsonHelper.toJson(this, FromTable.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
index b2651a1..3db4d94 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
@@ -19,17 +19,18 @@
 package org.apache.tajo.engine.planner;
 
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.util.TUtil;
 
 /**
  * A Target contains how to evaluate an expression and its alias name.
  */
-public class Target implements Cloneable {
+public class Target implements Cloneable, GsonObject {
   @Expose private EvalNode expr;
   @Expose private Column column;
   @Expose private String alias = null;
@@ -109,7 +110,7 @@ public class Target implements Cloneable {
     return target;
   }
 
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, Target.class);
+  public String toJson() {
+    return CoreGsonHelper.toJson(this, Target.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
index 061964d..1adddf3 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
@@ -22,13 +22,11 @@
 package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.json.GsonObject;
 
-public abstract class BinaryNode extends LogicalNode implements Cloneable {
-	@Expose
-	LogicalNode outer = null;
-	@Expose
-	LogicalNode inner = null;
+public abstract class BinaryNode extends LogicalNode implements Cloneable, GsonObject {
+	@Expose LogicalNode outer = null;
+	@Expose LogicalNode inner = null;
 	
 	public BinaryNode() {
 		super();
@@ -77,10 +75,4 @@ public abstract class BinaryNode extends LogicalNode implements Cloneable {
     inner.postOrder(visitor);
     visitor.visit(this);
   }
-
-  public String toJSON() {
-    outer.toJSON();
-    inner.toJSON();
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
index c7a6ad2..a4d335b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
@@ -24,7 +24,6 @@ import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Options;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.util.TUtil;
 
 public class CreateTableNode extends LogicalNode implements Cloneable {
@@ -143,10 +142,6 @@ public class CreateTableNode extends LogicalNode implements Cloneable {
     
     return sb.toString();
   }
-  
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 
   @Override
   public void preOrder(LogicalNodeVisitor visitor) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
index 877b805..d586bf9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
@@ -18,8 +18,6 @@
 
 package org.apache.tajo.engine.planner.logical;
 
-import org.apache.tajo.engine.json.GsonCreator;
-
 public class DropTableNode extends LogicalNode {
   private String tableName;
 
@@ -53,12 +51,6 @@ public class DropTableNode extends LogicalNode {
     return "DROP TABLE " + tableName;
   }
 
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
-
   @Override
   public void preOrder(LogicalNodeVisitor visitor) {
     visitor.visit(this);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
index 7bcf168..2ac6b2b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
@@ -21,10 +21,9 @@
  */
 package org.apache.tajo.engine.planner.logical;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
 
 public class EvalExprNode extends LogicalNode implements Projectable {
   @Expose private Target[] exprs;
@@ -35,12 +34,6 @@ public class EvalExprNode extends LogicalNode implements Projectable {
   }
 
   @Override
-  public String toJSON() {
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this);
-  }
-
-  @Override
   public boolean hasTargets() {
     return true;
   }
@@ -77,6 +70,15 @@ public class EvalExprNode extends LogicalNode implements Projectable {
     sb.append("}");
     return sb.toString();
   }
+
+  public boolean equals(Object object) {
+    if (object instanceof EvalExprNode) {
+      EvalExprNode other = (EvalExprNode) object;
+      return TUtil.checkEquals(this.exprs, other.exprs);
+    } else {
+      return false;
+    }
+  }
   
   @Override
   public void preOrder(LogicalNodeVisitor visitor) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
index 41e606f..379a83b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
@@ -21,8 +21,6 @@
  */
 package org.apache.tajo.engine.planner.logical;
 
-import org.apache.tajo.engine.json.GsonCreator;
-
 public class ExceptNode extends BinaryNode {
 
   public ExceptNode() {
@@ -38,9 +36,4 @@ public class ExceptNode extends BinaryNode {
   public String toString() {
     return getOuterNode().toString() + "\n EXCEPT \n" + getInnerNode().toString();
   }
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
index 9c1c116..b35a291 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
@@ -21,19 +21,13 @@ package org.apache.tajo.engine.planner.logical;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.planner.Target;
 import org.apache.tajo.util.TUtil;
 
-import java.util.Arrays;
-
 public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
-	@Expose
-	private Column[] columns;
-	@Expose
-	private EvalNode havingCondition = null;
-	@Expose
-	private Target[] targets;
+	@Expose private Column [] columns;
+	@Expose private EvalNode havingCondition = null;
+	@Expose private Target [] targets;
 	
 	public GroupbyNode() {
 		super();
@@ -118,11 +112,12 @@ public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
   public boolean equals(Object obj) {
     if (obj instanceof GroupbyNode) {
       GroupbyNode other = (GroupbyNode) obj;
-      return super.equals(other) 
-          && Arrays.equals(columns, other.columns)
-          && TUtil.checkEquals(havingCondition, other.havingCondition)
-          && TUtil.checkEquals(targets, other.targets)
-          && getSubNode().equals(other.getSubNode());
+      boolean eq = super.equals(other);
+      eq = eq && TUtil.checkEquals(columns, other.columns);
+      eq = eq && TUtil.checkEquals(havingCondition, other.havingCondition);
+      eq = eq && TUtil.checkEquals(targets, other.targets);
+      eq = eq && subExpr.equals(other.subExpr);
+      return eq;
     } else {
       return false;  
     }
@@ -148,8 +143,4 @@ public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
 
     return grp;
   }
-  
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
index af3b2c4..b14a54b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
@@ -23,11 +23,10 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.SortSpec;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 
 public class IndexScanNode extends ScanNode {
-  
-  @Expose private SortSpec[]sortKeys;
+  @Expose private SortSpec [] sortKeys;
   @Expose private Schema keySchema = null;
   @Expose private Datum[] datum = null;
   //TODO- @Expose private IndexType type;
@@ -66,15 +65,10 @@ public class IndexScanNode extends ScanNode {
   public void setKeySchema( Schema keySchema ) {
     this.keySchema = keySchema;
   }
-  
-  @Override
-  public String toJSON() {
-    GsonCreator.getInstance().toJson(this, LogicalNode.class);
-    return null;
-  }
+
   @Override
   public String toString() {
-    Gson gson = GsonCreator.getInstance();
+    Gson gson = CoreGsonHelper.getInstance();
     StringBuilder builder = new StringBuilder();
     builder.append("IndexScanNode : {\n");
     builder.append("  \"keySchema\" : \"" + gson.toJson(this.keySchema) + "\"\n");

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
index aa90df9..1d00a56 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
@@ -21,8 +21,6 @@
  */
 package org.apache.tajo.engine.planner.logical;
 
-import org.apache.tajo.engine.json.GsonCreator;
-
 public class IntersectNode extends BinaryNode {
 
   public IntersectNode() {
@@ -38,9 +36,4 @@ public class IntersectNode extends BinaryNode {
   public String toString() {
     return getOuterNode().toString() + "\n INTERSECT \n" + getInnerNode().toString();
   }
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
index a5c288c..cd79e4d 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
@@ -24,7 +24,6 @@ package org.apache.tajo.engine.planner.logical;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.algebra.JoinType;
 import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.planner.Target;
 
 public class JoinNode extends BinaryNode implements Projectable, Cloneable {
@@ -122,8 +121,4 @@ public class JoinNode extends BinaryNode implements Projectable, Cloneable {
     sb.append("\n" + getOuterNode().toString()).append(" and ").append(getInnerNode());
     return sb.toString();
   }
-
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
index ceef9d0..1d24941 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
@@ -19,11 +19,9 @@
 package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
 
 public final class LimitNode extends UnaryNode implements Cloneable {
-	@Expose
-  private long fetchFirstNum;
+	@Expose private long fetchFirstNum;
 
 	public LimitNode() {
 		super();
@@ -66,8 +64,4 @@ public final class LimitNode extends UnaryNode implements Cloneable {
 
     return sb.toString();
   }
-  
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
index d47a84f..4891d82 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
@@ -22,9 +22,12 @@
 package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.util.TUtil;
 
-public abstract class LogicalNode implements Cloneable {
+public abstract class LogicalNode implements Cloneable, GsonObject {
   @Expose private ExprType type;
 	@Expose private Schema inputSchema;
 	@Expose	private Schema outputSchema;
@@ -76,12 +79,12 @@ public abstract class LogicalNode implements Cloneable {
 	  if (obj instanceof LogicalNode) {
 	    LogicalNode other = (LogicalNode) obj;
 
-      boolean b1 = this.type == other.type;
-      boolean b2 = this.inputSchema.equals(other.inputSchema);
-      boolean b3 = this.outputSchema.equals(other.outputSchema);
-      boolean b4 = this.cost == other.cost;
+      boolean eq = this.type == other.type;
+      eq = eq && TUtil.checkEquals(this.inputSchema, other.inputSchema);
+      eq = eq && TUtil.checkEquals(this.outputSchema, other.outputSchema);
+      eq = eq && this.cost == other.cost;
       
-      return b1 && b2 && b3 && b4;
+      return eq;
 	  } else {
 	    return false;
 	  }
@@ -98,8 +101,11 @@ public abstract class LogicalNode implements Cloneable {
 	  
 	  return node;
 	}
-	
-	public abstract String toJSON();
+
+  @Override
+  public String toJson() {
+    return CoreGsonHelper.toJson(this, LogicalNode.class);
+  }
 
 	public abstract void preOrder(LogicalNodeVisitor visitor);
   public abstract void postOrder(LogicalNodeVisitor visitor);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
index 154b931..8b2fa77 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
@@ -18,8 +18,6 @@
 
 package org.apache.tajo.engine.planner.logical;
 
-import org.apache.tajo.engine.json.GsonCreator;
-
 public class LogicalRootNode extends UnaryNode implements Cloneable {
   public LogicalRootNode() {
     super(ExprType.ROOT);
@@ -30,11 +28,6 @@ public class LogicalRootNode extends UnaryNode implements Cloneable {
   }
   
   @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
-  
-  @Override
   public boolean equals(Object obj) {
     if (obj instanceof LogicalRootNode) {
       LogicalRootNode other = (LogicalRootNode) obj;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
index 999b804..128bd43 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.planner.Target;
 
 import java.util.Arrays;
@@ -109,8 +108,4 @@ public class ProjectionNode extends UnaryNode implements Projectable {
 	  
 	  return projNode;
 	}
-	
-	public String toJSON() {
-	  return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
index 7c195dd..6b45e8a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
@@ -22,7 +22,6 @@ import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.engine.planner.FromTable;
 import org.apache.tajo.engine.planner.Target;
 import org.apache.tajo.util.TUtil;
@@ -147,10 +146,6 @@ public class ScanNode extends LogicalNode implements Projectable {
 	  sb.append("\n  \"in schema\": ").append(getInSchema());
 	  return sb.toString();
 	}
-	
-	public String toJSON() {
-	  return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-	}
 
   @Override
   public int hashCode() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SelectionNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SelectionNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SelectionNode.java
index b822d8a..2bd1e81 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SelectionNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SelectionNode.java
@@ -20,12 +20,9 @@ package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.GsonCreator;
 
 public class SelectionNode extends UnaryNode implements Cloneable {
-
-	@Expose
-	private EvalNode qual;
+	@Expose private EvalNode qual;
 	
 	public SelectionNode() {
 		super();
@@ -73,8 +70,4 @@ public class SelectionNode extends UnaryNode implements Cloneable {
     
     return selNode;
   }
-  
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SortNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SortNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SortNode.java
index 947553a..4efe842 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SortNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/SortNode.java
@@ -22,12 +22,11 @@ import com.google.common.base.Preconditions;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.SortSpec;
-import org.apache.tajo.engine.json.GsonCreator;
 import org.apache.tajo.util.TUtil;
 
 public final class SortNode extends UnaryNode implements Cloneable {
 	@Expose
-  private SortSpec[] sortKeys;
+  private SortSpec [] sortKeys;
 	
 	public SortNode() {
 		super();
@@ -54,9 +53,10 @@ public final class SortNode extends UnaryNode implements Cloneable {
   public boolean equals(Object obj) {
     if (obj instanceof SortNode) {
       SortNode other = (SortNode) obj;
-      return super.equals(other)
-          && TUtil.checkEquals(sortKeys, other.sortKeys)
-          && subExpr.equals(other.subExpr);
+      boolean eq = super.equals(other);
+      eq = eq && TUtil.checkEquals(sortKeys, other.sortKeys);
+      eq = eq && subExpr.equals(other.subExpr);
+      return eq;
     } else {
       return false;
     }
@@ -86,12 +86,4 @@ public final class SortNode extends UnaryNode implements Cloneable {
     return sb.toString()+"\n"
         + getSubNode().toString();
   }
-
-  public String toJSON() {
-    subExpr.toJSON();
-    for (int i = 0; i < sortKeys.length; i++) {
-      sortKeys[i].toJSON();
-    }
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/StoreTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/StoreTableNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/StoreTableNode.java
index c3d292f..ec7b1b7 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/StoreTableNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/StoreTableNode.java
@@ -115,13 +115,14 @@ public class StoreTableNode extends UnaryNode implements Cloneable {
   public boolean equals(Object obj) {
     if (obj instanceof StoreTableNode) {
       StoreTableNode other = (StoreTableNode) obj;
-      return super.equals(other)
-          && this.tableName.equals(other.tableName)
-          && this.storageType.equals(other.storageType)
-          && this.numPartitions == other.numPartitions
-          && TUtil.checkEquals(partitionKeys, other.partitionKeys)
-          && TUtil.checkEquals(options, other.options)
-          && subExpr.equals(other.subExpr);
+      boolean eq = super.equals(other);
+      eq = eq && this.tableName.equals(other.tableName);
+      eq = eq && this.storageType.equals(other.storageType);
+      eq = eq && this.numPartitions == other.numPartitions;
+      eq = eq && TUtil.checkEquals(partitionKeys, other.partitionKeys);
+      eq = eq &&  TUtil.checkEquals(options, other.options);
+      eq = eq && subExpr.equals(other.subExpr);
+      return eq;
     } else {
       return false;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnaryNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnaryNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnaryNode.java
index b415442..cd3aa1c 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnaryNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnaryNode.java
@@ -22,12 +22,10 @@
 package org.apache.tajo.engine.planner.logical;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
 
 
 public abstract class UnaryNode extends LogicalNode implements Cloneable {
-	@Expose
-	LogicalNode subExpr;
+	@Expose LogicalNode subExpr;
 	
 	public UnaryNode() {
 		super();
@@ -65,9 +63,4 @@ public abstract class UnaryNode extends LogicalNode implements Cloneable {
 	  subExpr.postOrder(visitor);	  
 	  visitor.visit(this);
 	}
-
-  public String toJSON() {
-    subExpr.toJSON();
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnionNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnionNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnionNode.java
index e336549..d0ded08 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnionNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/UnionNode.java
@@ -21,8 +21,6 @@
  */
 package org.apache.tajo.engine.planner.logical;
 
-import org.apache.tajo.engine.json.GsonCreator;
-
 public class UnionNode extends BinaryNode {
 
   public UnionNode() {
@@ -38,9 +36,4 @@ public class UnionNode extends BinaryNode {
   public String toString() {
     return getOuterNode().toString() + "\n UNION \n" + getInnerNode().toString();
   }
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/ReceiveNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/ReceiveNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/ReceiveNode.java
index 2a6112e..94ecffe 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/ReceiveNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/ReceiveNode.java
@@ -25,9 +25,8 @@ import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.planner.logical.ExprType;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.LogicalNodeVisitor;
@@ -107,16 +106,11 @@ public final class ReceiveNode extends LogicalNode implements Cloneable {
 
   @Override
   public String toString() {
-    Gson gson = new GsonBuilder().setPrettyPrinting().create();
+    Gson gson = CoreGsonHelper.getPrettyInstance();
     return gson.toJson(this);
   }
 
   @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
-
-  @Override
   public void preOrder(LogicalNodeVisitor visitor) {
     visitor.visit(this);
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/SendNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/SendNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/SendNode.java
index a994c6c..8d9064e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/SendNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/extended/SendNode.java
@@ -25,12 +25,10 @@ import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Column;
-import org.apache.tajo.engine.json.GsonCreator;
+import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.planner.logical.ExprType;
-import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.UnaryNode;
 import org.apache.tajo.util.TUtil;
 
@@ -141,12 +139,7 @@ public class SendNode extends UnaryNode {
 
   @Override
   public String toString() {
-    Gson gson = new GsonBuilder().setPrettyPrinting().create();
+    Gson gson = CoreGsonHelper.getPrettyInstance();
     return gson.toJson(this);
   }
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, LogicalNode.class);
-  }
 }
\ No newline at end of file


[3/4] TAJO-95: Eliminate the lazy copy approach from the classes wrapping protobuf-generated classes. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/ColumnStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/ColumnStat.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/ColumnStat.java
index ccfae2b..f7793c3 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/ColumnStat.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/ColumnStat.java
@@ -22,140 +22,92 @@
 package org.apache.tajo.catalog.statistics;
 
 import com.google.common.base.Objects;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
 import com.google.protobuf.ByteString;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnStatProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.ColumnStatProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.util.TUtil;
 
-public class ColumnStat implements ProtoObject<ColumnStatProto>, Cloneable {
-  private ColumnStatProto proto = ColumnStatProto.getDefaultInstance();
-  private ColumnStatProto.Builder builder = null;
-  private boolean viaProto = false;
+public class ColumnStat implements ProtoObject<ColumnStatProto>, Cloneable, GsonObject {
+  private ColumnStatProto.Builder builder = ColumnStatProto.newBuilder();
 
-  @Expose private Column column = null;
-  @Expose private Long numDistVals = null;
-  @Expose private Long numNulls = null;
-  @Expose private Datum minValue = null;
-  @Expose private Datum maxValue = null;
+  @Expose private Column column = null; // required
+  @Expose private Long numDistVals = null; // optional
+  @Expose private Long numNulls = null; // optional
+  @Expose private Datum minValue = null; // optional
+  @Expose private Datum maxValue = null; // optional
 
   public ColumnStat(Column column) {
-    builder = ColumnStatProto.newBuilder();
     this.column = column;
     numDistVals = 0l;
     numNulls = 0l;
   }
 
   public ColumnStat(ColumnStatProto proto) {
-    this.proto = proto;
-    this.viaProto = true;
-  }
+    this.column = new Column(proto.getColumn());
 
-  public Column getColumn() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (column != null) {
-      return column;
+    if (proto.hasNumDistVal()) {
+      this.numDistVals = proto.getNumDistVal();
+    }
+    if (proto.hasNumNulls()) {
+      this.numNulls = proto.getNumNulls();
+    }
+    if (proto.hasMinValue()) {
+      this.minValue = TupleUtil.createFromBytes(getColumn().getDataType(), proto.getMinValue().toByteArray());
     }
-    if (!p.hasColumn()) {
-      return null;
+    if (proto.hasMaxValue()) {
+      this.maxValue = TupleUtil.createFromBytes(getColumn().getDataType(), proto.getMaxValue().toByteArray());
     }
-    this.column = new Column(p.getColumn());
+  }
 
+  public Column getColumn() {
     return this.column;
   }
 
   public Long getNumDistValues() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (numDistVals != null) {
-      return this.numDistVals;
-    }
-    if (!p.hasNumDistVal()) {
-      return null;
-    }
-    this.numDistVals = p.getNumDistVal();
-
     return this.numDistVals;
   }
 
   public void setNumDistVals(long numDistVals) {
-    setModified();
     this.numDistVals = numDistVals;
   }
 
   public boolean minIsNotSet() {
-    return minValue == null && (!proto.hasMinValue());
+    return minValue == null;
   }
 
   public Datum getMinValue() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (minValue != null) {
-      return this.minValue;
-    }
-    if (!p.hasMinValue()) {
-      return null;
-    }
-    this.minValue = TupleUtil.createFromBytes(getColumn().getDataType(), p.getMinValue().toByteArray());
-
     return this.minValue;
   }
 
   public void setMinValue(Datum minValue) {
-    setModified();
     this.minValue = minValue;
   }
 
   public boolean maxIsNotSet() {
-    return maxValue == null && (!proto.hasMaxValue());
+    return maxValue == null;
   }
 
   public Datum getMaxValue() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (maxValue != null) {
-      return this.maxValue;
-    }
-    if (!p.hasMaxValue()) {
-      return null;
-    }
-    this.maxValue = TupleUtil.createFromBytes(getColumn().getDataType(), p.getMaxValue().toByteArray());
-
     return this.maxValue;
   }
 
   public void setMaxValue(Datum maxValue) {
-    setModified();
     this.maxValue = maxValue;
   }
 
   public Long getNumNulls() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (numNulls != null) {
-      return this.numNulls;
-    }
-    if (!p.hasNumNulls()) {
-      return null;
-    }
-    this.numNulls = p.getNumNulls();
-
     return this.numNulls;
   }
 
   public void setNumNulls(long numNulls) {
-    setModified();
     this.numNulls = numNulls;
   }
 
-  private void setModified() {
-    if (viaProto && builder == null) {
-      builder = ColumnStatProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-
   public boolean equals(Object obj) {
     if (obj instanceof ColumnStat) {
       ColumnStat other = (ColumnStat) obj;
@@ -175,7 +127,7 @@ public class ColumnStat implements ProtoObject<ColumnStatProto>, Cloneable {
 
   public Object clone() throws CloneNotSupportedException {
     ColumnStat stat = (ColumnStat) super.clone();
-    initFromProto();
+    stat.builder = ColumnStatProto.newBuilder();
     stat.column = (Column) this.column.clone();
     stat.numDistVals = numDistVals;
     stat.numNulls = numNulls;
@@ -186,46 +138,19 @@ public class ColumnStat implements ProtoObject<ColumnStatProto>, Cloneable {
   }
 
   public String toString() {
-    initFromProto();
-    Gson gson = new GsonBuilder().setPrettyPrinting().
-        excludeFieldsWithoutExposeAnnotation().create();
-    return gson.toJson(this);
+    return CatalogGsonHelper.getPrettyInstance().toJson(this, ColumnStat.class);
   }
 
   @Override
-  public void initFromProto() {
-    ColumnStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.column == null && p.hasColumn()) {
-      this.column = new Column(p.getColumn());
-    }
-    if (this.numDistVals == null && p.hasNumDistVal()) {
-      this.numDistVals = p.getNumDistVal();
-    }
-    if (this.numNulls == null && p.hasNumNulls()) {
-      this.numNulls = p.getNumNulls();
-    }
-    if (this.minValue == null && p.hasMinValue()) {
-      this.minValue = TupleUtil.createFromBytes(getColumn().getDataType(), p.getMinValue().toByteArray());
-    }
-    if (this.maxValue == null && p.hasMaxValue()) {
-      this.maxValue = TupleUtil.createFromBytes(getColumn().getDataType(), p.getMaxValue().toByteArray());
-    }
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, ColumnStat.class);
   }
 
+
   @Override
   public ColumnStatProto getProto() {
-    if (!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }
-
-    return proto;
-  }
-
-  private void mergeLocalToBuilder() {
     if (builder == null) {
-      builder = ColumnStatProto.newBuilder(proto);
+      builder = ColumnStatProto.newBuilder();
     }
     if (this.column != null) {
       builder.setColumn(this.column.getProto());
@@ -242,5 +167,7 @@ public class ColumnStat implements ProtoObject<ColumnStatProto>, Cloneable {
     if (this.maxValue != null) {
       builder.setMaxValue(ByteString.copyFrom(this.maxValue.asByteArray()));
     }
+
+    return builder.build();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/StatSet.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/StatSet.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/StatSet.java
index d3a3c3e..f8d24b0 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/StatSet.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/StatSet.java
@@ -20,7 +20,7 @@ package org.apache.tajo.catalog.statistics;
 
 import com.google.common.collect.Maps;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.StatProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.StatSetProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.StatSetProtoOrBuilder;
@@ -83,14 +83,7 @@ public class StatSet implements ProtoObject<StatSetProto>, Cloneable {
   }
   
   public Object clone() throws CloneNotSupportedException {
-    StatSet group = (StatSet) super.clone();
-    initFromProto();
-    group.stats = Maps.newHashMap();
-    for (Stat stat : stats.values()) {
-      group.stats.put(stat.getType(), (Stat) stat.clone());
-    }
-    
-    return group;
+    return new StatSet(this.getProto());
   }
 
   private void initStats() {
@@ -112,17 +105,6 @@ public class StatSet implements ProtoObject<StatSetProto>, Cloneable {
   }
 
   @Override
-  public void initFromProto() {
-    StatSetProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.stats == null && p.getStatsCount() > 0) {
-      this.stats = Maps.newHashMap();
-      for (StatProto statProto : p.getStatsList()) {
-        this.stats.put(statProto.getType(), new Stat(statProto));
-      }
-    }
-  }
-
-  @Override
   public StatSetProto getProto() {
     if (!viaProto) {
       mergeLocalToBuilder();
@@ -146,6 +128,6 @@ public class StatSet implements ProtoObject<StatSetProto>, Cloneable {
   }
   
   public String toString() {
-    return GsonCreator.getPrettyInstance().toJson(this);
+    return CatalogGsonHelper.getPrettyInstance().toJson(this);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStat.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStat.java
index 56396b1..950e9b5 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStat.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStat.java
@@ -23,158 +23,118 @@ package org.apache.tajo.catalog.statistics;
 
 import com.google.common.base.Objects;
 import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnStatProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableStatProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.TableStatProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.util.TUtil;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class TableStat implements ProtoObject<TableStatProto>, Cloneable {
-  private TableStatProto proto = TableStatProto.getDefaultInstance();
-  private TableStatProto.Builder builder = null;
-  private boolean viaProto = false;
+public class TableStat implements ProtoObject<TableStatProto>, Cloneable, GsonObject {
+  private TableStatProto.Builder builder = TableStatProto.newBuilder();
 
-  @Expose private Long numRows = null;
-  @Expose private Long numBytes = null;
-  @Expose private Integer numBlocks = null;
-  @Expose private Integer numPartitions = null;
-  @Expose private Long avgRows = null;
-  @Expose private List<ColumnStat> columnStats = null;
+  @Expose private Long numRows = null; // required
+  @Expose private Long numBytes = null; // required
+  @Expose private Integer numBlocks = null; // optional
+  @Expose private Integer numPartitions = null; // optional
+  @Expose private Long avgRows = null; // optional
+  @Expose private List<ColumnStat> columnStats = null; // repeated
 
   public TableStat() {
-    builder = TableStatProto.newBuilder();
     numRows = 0l;
     numBytes = 0l;
     numBlocks = 0;
     numPartitions = 0;
     avgRows = 0l;
+    columnStats = TUtil.newList();
   }
 
   public TableStat(TableStatProto proto) {
-    this.proto = proto;
-    this.viaProto = true;
-  }
+    this.numRows = proto.getNumRows();
+    this.numBytes = proto.getNumBytes();
 
-  public Long getNumRows() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if(numRows != null) {
-      return this.numRows;
+    if (proto.hasNumBlocks()) {
+      this.numBlocks = proto.getNumBlocks();
+    }
+    if (proto.hasNumPartitions()) {
+      this.numPartitions = proto.getNumPartitions();
     }
-    if(!p.hasNumRows()) {
-      return 0l;
+    if (proto.hasAvgRows()) {
+      this.avgRows = proto.getAvgRows();
     }
-    this.numRows = p.getNumRows();
 
+    this.columnStats = TUtil.newList();
+    for (ColumnStatProto colProto : proto.getColStatList()) {
+      columnStats.add(new ColumnStat(colProto));
+    }
+  }
+
+  public Long getNumRows() {
     return this.numRows;
   }
 
   public void setNumRows(long numRows) {
-    setModified();
     this.numRows = numRows;
   }
 
   public Integer getNumBlocks() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if(numBlocks != null) {
-      return this.numBlocks;
-    }
-    if(!p.hasNumBlocks()) {
-      return 0;
-    }
-    this.numBlocks = p.getNumBlocks();
-
     return this.numBlocks;
   }
 
   public void setNumBytes(long numBytes) {
-    setModified();
     this.numBytes = numBytes;
   }
 
   public Long getNumBytes() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (numBytes != null) {
-      return this.numBytes;
-    }
-    if (!p.hasNumBytes()) {
-      return 0l;
-    }
-    this.numBytes = p.getNumBytes();
     return this.numBytes;
   }
 
   public void setNumBlocks(int numBlocks) {
-    setModified();
     this.numBlocks = numBlocks;
   }
 
   public Integer getNumPartitions() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if(numPartitions != null) {
-      return this.numPartitions;
-    }
-    if(!p.hasNumPartitions()) {
-      return 0;
-    }
-    this.numPartitions = p.getNumPartitions();
-
     return this.numPartitions;
   }
 
   public void setNumPartitions(int numPartitions) {
-    setModified();
     this.numPartitions = numPartitions;
   }
 
   public Long getAvgRows() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if(avgRows != null) {
-      return this.avgRows;
-    }
-    if(!p.hasAvgRows()) {
-      return 0l;
-    }
-    this.avgRows = p.getAvgRows();
-
     return this.avgRows;
   }
 
   public void setAvgRows(long avgRows) {
-    setModified();
     this.avgRows = avgRows;
   }
 
   public List<ColumnStat> getColumnStats() {
-    initColumnStats();
     return this.columnStats;
   }
 
   public void setColumnStats(List<ColumnStat> columnStats) {
-    setModified();
     this.columnStats = new ArrayList<ColumnStat>(columnStats);
   }
 
   public void addColumnStat(ColumnStat columnStat) {
-    initColumnStats();
     this.columnStats.add(columnStat);
   }
 
   public boolean equals(Object obj) {
     if (obj instanceof TableStat) {
       TableStat other = (TableStat) obj;
-      initFromProto();
-      other.initFromProto();
 
       return this.numRows.equals(other.numRows)
           && this.numBytes.equals(other.numBytes)
-          && this.numBlocks.equals(other.numBlocks)
-          && this.numPartitions.equals(other.numPartitions)
-          && this.avgRows.equals(other.avgRows)
-          && columnStats.equals(other.columnStats);
+          && TUtil.checkEquals(this.numBlocks, other.numBlocks)
+          && TUtil.checkEquals(this.numPartitions, other.numPartitions)
+          && TUtil.checkEquals(this.avgRows, other.avgRows)
+          && TUtil.checkEquals(this.columnStats, other.columnStats);
     } else {
       return false;
     }
@@ -187,7 +147,7 @@ public class TableStat implements ProtoObject<TableStatProto>, Cloneable {
 
   public Object clone() throws CloneNotSupportedException {
     TableStat stat = (TableStat) super.clone();
-    initFromProto();
+    stat.builder = TableStatProto.newBuilder();
     stat.numRows = numRows;
     stat.numBytes = numBytes;
     stat.numBlocks = numBlocks;
@@ -198,75 +158,26 @@ public class TableStat implements ProtoObject<TableStatProto>, Cloneable {
   }
 
   public String toString() {
-    Gson gson = new GsonBuilder().setPrettyPrinting().
-        excludeFieldsWithoutExposeAnnotation().create();
+    Gson gson = CatalogGsonHelper.getPrettyInstance();
     return gson.toJson(this);
   }
 
-  private void initColumnStats() {
-    if (this.columnStats != null) {
-      return;
-    }
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    this.columnStats = new ArrayList<ColumnStat>();
-    for (ColumnStatProto colProto : p.getColStatList()) {
-      columnStats.add(new ColumnStat(colProto));
-    }
-  }
-
-  private void setModified() {
-    if (viaProto && builder == null) {
-      builder = TableStatProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-
   @Override
-  public void initFromProto() {
-    TableStatProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.numRows == null && p.hasNumRows()) {
-      this.numRows = p.getNumRows();
-    }
-    if (this.numBytes == null && p.hasNumBytes()) {
-      this.numBytes = p.getNumBytes();
-    }
-    if (this.numBlocks == null && p.hasNumBlocks()) {
-      this.numBlocks = p.getNumBlocks();
-    }
-    if (this.numPartitions == null && p.hasNumPartitions()) {
-      this.numPartitions = p.getNumPartitions();
-    }
-    if (this.avgRows == null && p.hasAvgRows()) {
-      this.avgRows = p.getAvgRows();
-    }
-
-    initColumnStats();
-    for (ColumnStat col : columnStats) {
-      col.initFromProto();
-    }
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, TableStat.class);
   }
 
   @Override
   public TableStatProto getProto() {
-    if (!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
+    if (builder == null) {
+      builder = TableStatProto.newBuilder();
+    } else {
+      builder.clear();
     }
 
-    return proto;
-  }
+    builder.setNumRows(this.numRows);
+    builder.setNumBytes(this.numBytes);
 
-  private void mergeLocalToBuilder() {
-    if (builder == null) {
-      builder = TableStatProto.newBuilder(proto);
-    }
-    if (this.numRows != null) {
-      builder.setNumRows(this.numRows);
-    }
-    if (this.numBytes != null) {
-      builder.setNumBytes(this.numBytes);
-    }
     if (this.numBlocks != null) {
       builder.setNumBlocks(this.numBlocks);
     }
@@ -281,5 +192,6 @@ public class TableStat implements ProtoObject<TableStatProto>, Cloneable {
         builder.addColStat(colStat.getProto());
       }
     }
+    return builder.build();
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestColumn.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestColumn.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestColumn.java
index 794176e..dfea828 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestColumn.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestColumn.java
@@ -18,12 +18,12 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
-import org.junit.Before;
-import org.junit.Test;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
+import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.junit.Before;
+import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -86,11 +86,17 @@ public class TestColumn {
 	@Test
 	public final void testToJson() {
 		Column col = new Column(field1.getProto());
-		String json = col.toJSON();
+		String json = col.toJson();
 		System.out.println(json);
-		Gson gson = GsonCreator.getInstance();
-		Column fromJson = gson.fromJson(json, Column.class);
-		assertEquals(col.getColumnName(), fromJson.getColumnName());
-		assertEquals(col.getDataType(), fromJson.getDataType());
+		Column fromJson = CatalogGsonHelper.fromJson(json, Column.class);
+		assertEquals(col, fromJson);
 	}
+
+  @Test
+  public final void testToProto() {
+    Column column = new Column(field1.getProto());
+    CatalogProtos.ColumnProto proto = column.getProto();
+    Column fromProto = new Column(proto);
+    assertEquals(column, fromProto);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
index 3546612..936e8c1 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
@@ -18,10 +18,8 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
-import org.junit.Test;
 import org.apache.tajo.catalog.function.GeneralFunction;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
 import org.apache.tajo.common.TajoDataTypes;
@@ -32,6 +30,7 @@ import org.apache.tajo.exception.InternalException;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.FileUtil;
+import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -58,13 +57,13 @@ public class TestFunctionDesc {
     }
 
     public String toJSON() {
-      return GsonCreator.getInstance().toJson(this, GeneralFunction.class);
+      return CatalogGsonHelper.toJson(this, GeneralFunction.class);
     }
   }
 
 
   @Test
-  public void testGetSignature() throws IOException {
+  public void testGetSignature() throws IOException, ClassNotFoundException {
     FunctionDesc desc = new FunctionDesc("sum", TestSum.class, FunctionType.GENERAL,
         CatalogUtil.newDataTypesWithoutLen(Type.INT4),
         CatalogUtil.newDataTypesWithoutLen(Type.INT4, Type.INT8));
@@ -94,23 +93,25 @@ public class TestFunctionDesc {
   }
   
   @Test
-  public void testJson() throws InternalException {
+  public void testToJson() throws InternalException {
 	  FunctionDesc desc = new FunctionDesc("sum", TestSum.class, FunctionType.GENERAL,
         CatalogUtil.newDataTypesWithoutLen(Type.INT4),
         CatalogUtil.newDataTypesWithoutLen(Type.INT4, Type.INT8));
-	  String json = desc.toJSON();
-	  System.out.println(json);
-	  Gson gson = GsonCreator.getInstance();
-	  FunctionDesc fromJson = gson.fromJson(json, FunctionDesc.class);
-	  
-	  assertEquals("sum", fromJson.getSignature());
-	    assertEquals(TestSum.class, fromJson.getFuncClass());
-	    assertEquals(FunctionType.GENERAL, fromJson.getFuncType());
-	    assertEquals(Type.INT4, fromJson.getReturnType()[0].getType());
-	    assertArrayEquals(CatalogUtil.newDataTypesWithoutLen(Type.INT4, Type.INT8),
-	    		fromJson.getParamTypes());
-
-	    assertEquals(desc.getProto(), fromJson.getProto());
+	  String json = desc.toJson();
+	  FunctionDesc fromJson = CatalogGsonHelper.fromJson(json, FunctionDesc.class);
+	  assertEquals(desc, fromJson);
+	  assertEquals(desc.getProto(), fromJson.getProto());
+  }
+
+  @Test
+  public void testGetProto() throws InternalException, ClassNotFoundException {
+    FunctionDesc desc = new FunctionDesc("sum", TestSum.class, FunctionType.GENERAL,
+        CatalogUtil.newDataTypesWithoutLen(Type.INT4),
+        CatalogUtil.newDataTypesWithoutLen(Type.INT4, Type.INT8));
+    FunctionDescProto proto = desc.getProto();
+    FunctionDesc fromProto = new FunctionDesc(proto);
+    assertEquals(desc, fromProto);
+    assertEquals(desc.toJson(), fromProto.toJson());
   }
   
   @Test

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
index 904d4b7..689f004 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.junit.Before;
 import org.junit.Test;
 import org.apache.tajo.catalog.exception.AlreadyExistsFieldException;
-import org.apache.tajo.catalog.json.GsonCreator;
 import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProto;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -123,11 +122,16 @@ public class TestSchema {
 	public final void testJson() {
 		Schema schema2 = new Schema(schema.getProto());
 		String json = schema2.toJson();
-		System.out.println(json);
-		Gson gson = GsonCreator.getInstance();
-		Schema fromJson = gson.fromJson(json, Schema.class);
-		assertEquals(schema2.getProto(), fromJson.getProto());
-		assertEquals(schema2.getColumn(0), fromJson.getColumn(0));
-		assertEquals(schema2.getColumnNum(), fromJson.getColumnNum());
+		Schema fromJson = CatalogGsonHelper.fromJson(json, Schema.class);
+		assertEquals(schema2, fromJson);
+    assertEquals(schema2.getProto(), fromJson.getProto());
 	}
+
+  @Test
+  public final void testProto() {
+    Schema schema2 = new Schema(schema.getProto());
+    SchemaProto proto = schema2.getProto();
+    Schema fromJson = new Schema(proto);
+    assertEquals(schema2, fromJson);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
index 4816c45..5235af1 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
@@ -18,11 +18,11 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
 import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
+import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.junit.Before;
 import org.junit.Test;
-import org.apache.tajo.catalog.json.GsonCreator;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -50,50 +50,41 @@ public class TestTableDesc {
     TableMeta info = CatalogUtil.newTableMeta(schema, StoreType.CSV);
     testClone(info);
 
-    TableDesc desc = new TableDescImpl("table1", info, new Path("/nta/data"));
+    TableDesc desc = new TableDescImpl("table1", info, new Path("/tajo/data"));
     assertEquals("table1", desc.getId());
     
-    assertEquals(new Path("/nta/data"), desc.getPath());
+    assertEquals(new Path("/tajo/data"), desc.getPath());
     assertEquals(info, desc.getMeta());
     testClone(desc);
   }
-  
+
   @Test
-  public void testTableMetaToJson() throws CloneNotSupportedException {
-    TableMeta meta = new TableMetaImpl(info.getProto());
-    Gson gson = GsonCreator.getInstance();
-    String json = meta.toJSON();
-    System.out.println(json);
-    TableMeta jsonMeta = gson.fromJson(json, TableMeta.class);
-    assertEquals(meta.getSchema(), jsonMeta.getSchema());
-    assertEquals(meta.getStoreType(), jsonMeta.getStoreType());
-    assertEquals(meta, jsonMeta);
-    testClone(meta);
+  public void testGetProto() throws CloneNotSupportedException {
+    TableDesc desc = new TableDescImpl("table1", info, new Path("/tajo/data"));
+    CatalogProtos.TableDescProto proto = (CatalogProtos.TableDescProto) desc.getProto();
+
+    TableDesc fromProto = new TableDescImpl(proto);
+    assertEquals("equality check the object deserialized from json", desc, fromProto);
   }
-  
-  @Test
-  public void testTableDescToJson() throws CloneNotSupportedException {
-    Gson gson = GsonCreator.getInstance();
 
-    TableDesc desc = new TableDescImpl("table1", info, new Path("/nta/data"));
-    testClone(desc);
+  @Test
+  public void testToJson() throws CloneNotSupportedException {
+    TableDesc desc = new TableDescImpl("table1", info, new Path("/tajo/data"));
+    String json = desc.toJson();
 
-    String json = desc.toJSON();
-    System.out.println(json);
-    TableDesc fromJson = gson.fromJson(json, TableDesc.class);
-    assertEquals(desc.getId(), fromJson.getId());
-    assertEquals(desc.getPath(), fromJson.getPath());
-    assertEquals(desc.getMeta(), fromJson.getMeta());
-    testClone(fromJson);
+    TableDesc fromJson = CatalogGsonHelper.fromJson(json, TableDesc.class);
+    assertEquals("equality check the object deserialized from json", desc, fromJson);
+    assertEquals("equality between protos", desc.getProto(), fromJson.getProto());
   }
 
-  public void testClone(TableDesc desc) throws CloneNotSupportedException {
+  public TableDesc testClone(TableDesc desc) throws CloneNotSupportedException {
     TableDesc copy = (TableDesc) desc.clone();
-    assertEquals(desc, copy);
+    assertEquals("clone check", desc, copy);
+    return copy;
   }
   
   public void testClone(TableMeta meta) throws CloneNotSupportedException {
     TableMeta copy = (TableMeta) meta.clone();
-    assertEquals(meta, copy);
+    assertEquals("clone check", meta, copy);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableMeta.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableMeta.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableMeta.java
index 590e343..88bc74f 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableMeta.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableMeta.java
@@ -18,11 +18,14 @@
 
 package org.apache.tajo.catalog;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableProto;
+import org.apache.tajo.catalog.statistics.ColumnStat;
+import org.apache.tajo.catalog.statistics.TableStat;
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.junit.Before;
+import org.junit.Test;
 
 import static org.junit.Assert.*;
 
@@ -36,6 +39,23 @@ public class TestTableMeta {
     schema.addColumn("name", Type.BLOB);
     schema.addColumn("addr", Type.TEXT);
     meta = CatalogUtil.newTableMeta(schema, StoreType.CSV);
+
+    TableStat stat = new TableStat();
+    stat.setNumRows(957685);
+    stat.setNumBytes(1023234);
+    stat.setNumBlocks(3123);
+    stat.setNumPartitions(5);
+    stat.setAvgRows(80000);
+
+    int numCols = 2;
+    ColumnStat[] cols = new ColumnStat[numCols];
+    for (int i = 0; i < numCols; i++) {
+      cols[i] = new ColumnStat(schema.getColumn(i));
+      cols[i].setNumDistVals(1024 * i);
+      cols[i].setNumNulls(100 * i);
+      stat.addColumnStat(cols[i]);
+    }
+    meta.setStat(stat);
   }
   
   @Test
@@ -106,22 +126,41 @@ public class TestTableMeta {
     schema2.addColumn("name", Type.BLOB);
     schema2.addColumn("addr", Type.TEXT);
     TableMeta meta2 = CatalogUtil.newTableMeta(schema2, StoreType.CSV);
-    
+
+    TableStat stat = new TableStat();
+    stat.setNumRows(957685);
+    stat.setNumBytes(1023234);
+    stat.setNumBlocks(3123);
+    stat.setNumPartitions(5);
+    stat.setAvgRows(80000);
+
+    int numCols = 2;
+    ColumnStat[] cols = new ColumnStat[numCols];
+    for (int i = 0; i < numCols; i++) {
+      cols[i] = new ColumnStat(schema2.getColumn(i));
+      cols[i].setNumDistVals(1024 * i);
+      cols[i].setNumNulls(100 * i);
+      stat.addColumnStat(cols[i]);
+    }
+    meta2.setStat(stat);
+
+
     assertTrue(meta.equals(meta2));
-    
     assertNotSame(meta, meta2);
   }
   
   @Test
-  public void testGetProto() {    
-    Schema schema1 = new Schema();
-    schema1.addColumn("name", Type.BLOB);
-    schema1.addColumn("addr", Type.TEXT);
-    TableMeta meta1 = CatalogUtil.newTableMeta(schema1, StoreType.CSV);
-    
-    TableProto proto = meta1.getProto();
+  public void testGetProto() {
+    TableProto proto = meta.getProto();
     TableMeta newMeta = new TableMetaImpl(proto);
-    
-    assertTrue(meta1.equals(newMeta));
-  }   
+    assertEquals(meta, newMeta);
+  }
+
+  @Test
+  public void testToJson() {
+    String json = meta.toJson();
+    TableMeta fromJson = CatalogGsonHelper.fromJson(json, TableMeta.class);
+    assertEquals(meta, fromJson);
+    assertEquals(meta.getProto(), fromJson.getProto());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
index 2f09358..c9dea3c 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
@@ -18,10 +18,11 @@
 
 package org.apache.tajo.catalog.statistics;
 
-import org.junit.Test;
 import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.datum.DatumFactory;
+import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -55,6 +56,19 @@ public class TestColumnStat {
   }
 
   @Test
+  public final void testJson() throws CloneNotSupportedException {
+    ColumnStat stat = new ColumnStat(new Column("test", Type.INT8));
+    stat.setNumDistVals(1000);
+    stat.setNumNulls(999);
+    stat.setMinValue(DatumFactory.createInt8(5));
+    stat.setMaxValue(DatumFactory.createInt8(10));
+
+    String json = stat.toJson();
+    ColumnStat fromJson = CatalogGsonHelper.fromJson(json, ColumnStat.class);
+    assertEquals(stat, fromJson);
+  }
+
+  @Test
   public final void testClone() throws CloneNotSupportedException {
     ColumnStat stat = new ColumnStat(new Column("test", Type.INT8));
     stat.setNumDistVals(1000);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
index 6fdd7e2..5372291 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
@@ -18,9 +18,10 @@
 
 package org.apache.tajo.catalog.statistics;
 
-import org.junit.Test;
 import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -58,7 +59,11 @@ public class TestTableStat {
     tableStatEquals(stat, stat2);
     
     TableStat stat3 = (TableStat) stat.clone();
-    tableStatEquals(stat, stat3);    
+    tableStatEquals(stat, stat3);
+
+    String json = stat.toJson();
+    TableStat fromJson = CatalogGsonHelper.fromJson(json, TableStat.class);
+    tableStatEquals(stat, fromJson);
   }
   
   public void tableStatEquals(TableStat s1, TableStat s2) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
deleted file mode 100644
index 2f09358..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestColumnStat.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.statistics;
-
-import org.junit.Test;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.common.TajoDataTypes.Type;
-import org.apache.tajo.datum.DatumFactory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class TestColumnStat {
-
-  @Test
-  public final void testColumnStat() {
-    ColumnStat stat = new ColumnStat(new Column("test", Type.INT8));
-    stat.setNumDistVals(1000);
-    stat.setNumNulls(999);
-    
-    assertTrue(1000 == stat.getNumDistValues());
-    assertTrue(999 == stat.getNumNulls());
-    
-    ColumnStat stat2 = new ColumnStat(stat.getProto());
-    assertTrue(1000 == stat2.getNumDistValues());
-    assertTrue(999 == stat2.getNumNulls());
-  }
-
-  @Test
-  public final void testEqualsObject() {
-    ColumnStat stat = new ColumnStat(new Column("test", Type.INT8));
-    stat.setNumDistVals(1000);
-    stat.setNumNulls(999);
-    stat.setMinValue(DatumFactory.createInt8(5));
-    stat.setMaxValue(DatumFactory.createInt8(10));
-    
-    ColumnStat stat2 = new ColumnStat(stat.getProto());
-    assertEquals(stat, stat2);
-  }
-
-  @Test
-  public final void testClone() throws CloneNotSupportedException {
-    ColumnStat stat = new ColumnStat(new Column("test", Type.INT8));
-    stat.setNumDistVals(1000);
-    stat.setNumNulls(999);
-    stat.setMinValue(DatumFactory.createInt8(5));
-    stat.setMaxValue(DatumFactory.createInt8(10));
-    
-    ColumnStat stat2 = (ColumnStat) stat.clone();
-    assertEquals(stat, stat2);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatSet.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatSet.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatSet.java
deleted file mode 100644
index 9285c8d..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatSet.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.statistics;
-
-import org.junit.Test;
-import org.apache.tajo.catalog.proto.CatalogProtos.StatType;
-
-import static org.junit.Assert.assertEquals;
-
-public class TestStatSet {
-  @Test
-  public final void testStatGroup() throws CloneNotSupportedException {
-    Stat stat = new Stat(StatType.TABLE_NUM_ROWS);
-    stat.increment();
-    stat.incrementBy(100);
-    assertEquals(101, stat.getValue());
-    
-    Stat stat2 = (Stat) stat.clone();
-    assertEquals(stat, stat2);
-    
-    Stat stat3 = new Stat(StatType.TABLE_NUM_BLOCKS);
-    stat3.increment();
-    stat3.increment();
-    stat3.increment();
-    stat3.subtract();
-    stat3.subtractBy(2);
-    stat3.increment();
-    assertEquals(1, stat3.getValue());
-    
-    StatSet group = new StatSet();
-    group.putStat(stat);
-    group.putStat(stat3);
-    
-    assertEquals(2, group.getAllStats().size());
-    assertEquals(stat, group.getStat(StatType.TABLE_NUM_ROWS));
-    assertEquals(101, group.getStat(StatType.TABLE_NUM_ROWS).getValue());
-    assertEquals(1, group.getStat(StatType.TABLE_NUM_BLOCKS).getValue());
-    
-    StatSet group2 = new StatSet(group.getProto());
-    assertEquals(2, group2.getAllStats().size());
-    assertEquals(stat, group2.getStat(StatType.TABLE_NUM_ROWS));
-    assertEquals(101, group2.getStat(StatType.TABLE_NUM_ROWS).getValue());
-    assertEquals(1, group2.getStat(StatType.TABLE_NUM_BLOCKS).getValue());
-    
-    StatSet group3 = (StatSet) group.clone();
-    assertEquals(2, group3.getAllStats().size());
-    assertEquals(stat, group3.getStat(StatType.TABLE_NUM_ROWS));
-    assertEquals(101, group3.getStat(StatType.TABLE_NUM_ROWS).getValue());
-    assertEquals(1, group3.getStat(StatType.TABLE_NUM_BLOCKS).getValue());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatisticsUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatisticsUtil.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatisticsUtil.java
deleted file mode 100644
index 8019fec..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestStatisticsUtil.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.statistics;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.apache.tajo.catalog.proto.CatalogProtos.StatType;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-public class TestStatisticsUtil {
-  @Test
-  public void testAggregate() throws CloneNotSupportedException {
-    Stat stat = new Stat(StatType.TABLE_NUM_ROWS);
-    stat.incrementBy(100); // 100
-    assertEquals(100, stat.getValue());
-    
-    Stat stat2 = (Stat) stat.clone();
-    stat2.incrementBy(100); // 200
-    assertEquals(200, stat2.getValue());
-    
-    Stat stat3 = new Stat(StatType.TABLE_NUM_BLOCKS);
-    stat3.incrementBy(50); // 50
-    assertEquals(50, stat3.getValue());
-    
-    StatSet group = new StatSet();
-    group.putStat(stat); // num of rows - 100 
-    group.putStat(stat2); // num of rows - 200
-    group.putStat(stat3); // num of blocks - 50
-    
-    // One group has 300 rows and 50 blocks, and it is cloned.
-    StatSet group2 = (StatSet) group.clone();
-    group2.getStat(StatType.TABLE_NUM_ROWS).incrementBy(100); // plus 100
-    
-    // expected that num of rows = 200 * 2 + 100, num of blocks = 50 * 2 
-    StatSet agg = StatisticsUtil.aggregateStatSet(
-        Lists.newArrayList(group, group2));
-    assertEquals(500, agg.getStat(StatType.TABLE_NUM_ROWS).getValue());
-    assertEquals(100, agg.getStat(StatType.TABLE_NUM_BLOCKS).getValue());
-  }
-
-  @Test
-  public void testEmptyAggregate() {
-    TableStat stat1 = new TableStat();
-    TableStat stat2 = new TableStat();
-    TableStat stat3 = new TableStat();
-
-    assertNotNull(StatisticsUtil.aggregateTableStat(
-        Lists.newArrayList(stat1, stat2, stat3)));
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
deleted file mode 100644
index 6fdd7e2..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/statistics/TestTableStat.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.statistics;
-
-import org.junit.Test;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.common.TajoDataTypes.Type;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class TestTableStat {
-  @Test
-  public final void testTableStat() throws CloneNotSupportedException {
-    TableStat stat = new TableStat();
-    stat.setNumRows(957685);
-    stat.setNumBytes(1023234);
-    stat.setNumBlocks(3123);
-    stat.setNumPartitions(5);
-    stat.setAvgRows(80000);
-        
-    int numCols = 3;
-    ColumnStat[] cols = new ColumnStat[numCols];
-    for (int i = 0; i < numCols; i++) {
-      cols[i] = new ColumnStat(new Column("col_" + i, Type.INT8));
-      cols[i].setNumDistVals(1024 * i);
-      cols[i].setNumNulls(100 * i);
-      stat.addColumnStat(cols[i]);
-    }
-    
-    assertTrue(957685 == stat.getNumRows());
-    assertTrue(1023234 == stat.getNumBytes());
-    assertTrue(3123 == stat.getNumBlocks());
-    assertTrue(5 == stat.getNumPartitions());
-    assertTrue(80000 == stat.getAvgRows());
-    assertEquals(3, stat.getColumnStats().size());
-    for (int i = 0; i < numCols; i++) {
-      assertEquals(cols[i], stat.getColumnStats().get(i));
-    }
-    
-    TableStat stat2 = new TableStat(stat.getProto());
-    tableStatEquals(stat, stat2);
-    
-    TableStat stat3 = (TableStat) stat.clone();
-    tableStatEquals(stat, stat3);    
-  }
-  
-  public void tableStatEquals(TableStat s1, TableStat s2) {
-    assertEquals(s1.getNumRows(), s2.getNumRows());
-    assertEquals(s1.getNumBlocks(), s2.getNumBlocks());
-    assertEquals(s1.getNumPartitions(), s2.getNumPartitions());
-    assertEquals(s1.getAvgRows(), s2.getAvgRows());
-    assertEquals(s1.getColumnStats().size(), s2.getColumnStats().size());
-    for (int i = 0; i < s1.getColumnStats().size(); i++) {
-      assertEquals(s1.getColumnStats().get(i), s2.getColumnStats().get(i));
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/QueryUnitAttemptId.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/QueryUnitAttemptId.java b/tajo-common/src/main/java/org/apache/tajo/QueryUnitAttemptId.java
index 6cea5a9..3ef436e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/QueryUnitAttemptId.java
+++ b/tajo-common/src/main/java/org/apache/tajo/QueryUnitAttemptId.java
@@ -25,8 +25,7 @@ import org.apache.tajo.common.ProtoObject;
 
 import java.text.NumberFormat;
 
-public class QueryUnitAttemptId implements Comparable<QueryUnitAttemptId>,
-    ProtoObject<QueryUnitAttemptIdProto> {
+public class QueryUnitAttemptId implements Comparable<QueryUnitAttemptId>, ProtoObject<QueryUnitAttemptIdProto> {
   private static final String PREFIX="ta";
 
   private static final NumberFormat format = NumberFormat.getInstance();
@@ -133,21 +132,6 @@ public class QueryUnitAttemptId implements Comparable<QueryUnitAttemptId>,
     return this.getId() - o.getId();
   }
 
-  private void mergeProtoToLocal() {
-    QueryUnitAttemptIdProtoOrBuilder p = viaProto ? proto : builder;
-    if (queryUnitId == null) {
-      queryUnitId = new QueryUnitId(p.getQueryUnitId());
-    }
-    if (id == -1) {
-      id = p.getId();
-    }
-  }
-
-  @Override
-  public void initFromProto() {
-    mergeProtoToLocal();
-  }
-
   private void mergeLocalToBuilder() {
     if (builder == null) {
       builder = QueryUnitAttemptIdProto.newBuilder(proto);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/QueryUnitId.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/QueryUnitId.java b/tajo-common/src/main/java/org/apache/tajo/QueryUnitId.java
index 21ca5bb..4826691 100644
--- a/tajo-common/src/main/java/org/apache/tajo/QueryUnitId.java
+++ b/tajo-common/src/main/java/org/apache/tajo/QueryUnitId.java
@@ -44,7 +44,7 @@ public class QueryUnitId implements Comparable<QueryUnitId>,
   private SubQueryId subQueryId = null;
   private int id = -1;
   private String finalId = null;
-  
+
   private QueryUnitIdProto proto = QueryUnitIdProto.getDefaultInstance();
   private QueryUnitIdProto.Builder builder = null;
   private boolean viaProto = false;
@@ -138,21 +138,6 @@ public class QueryUnitId implements Comparable<QueryUnitId>,
     return this.toString().compareTo(o.toString());
   }
   
-  private void mergeProtoToLocal() {
-    QueryUnitIdProtoOrBuilder p = viaProto ? proto : builder;
-    if (subQueryId == null) {
-      subQueryId = TajoIdUtils.newSubQueryId(p.getSubQueryId());
-    }
-    if (id == -1) {
-      id = p.getId();
-    }
-  }
-
-  @Override
-  public void initFromProto() {
-    mergeProtoToLocal();
-  }
-  
   private void mergeLocalToBuilder() {
     if (builder == null) {
       builder = QueryUnitIdProto.newBuilder(proto);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/common/ProtoObject.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/common/ProtoObject.java b/tajo-common/src/main/java/org/apache/tajo/common/ProtoObject.java
index 2c56e01..d5f7533 100644
--- a/tajo-common/src/main/java/org/apache/tajo/common/ProtoObject.java
+++ b/tajo-common/src/main/java/org/apache/tajo/common/ProtoObject.java
@@ -21,6 +21,5 @@ package org.apache.tajo.common;
 import com.google.protobuf.Message;
 
 public interface ProtoObject<P extends Message> {
-	public void initFromProto();
 	public P getProto();
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/ArrayDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/ArrayDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/ArrayDatum.java
index a8578c9..24c38c4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/ArrayDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/ArrayDatum.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.datum;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -73,9 +72,4 @@ public class ArrayDatum extends Datum {
 
     return sb.toString();
   }
-
-  @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, Datum.class);
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
index da40a2e..f5c60f6 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
@@ -21,7 +21,6 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 public class BitDatum extends Datum {
   private static final int size = 1;
@@ -81,10 +80,6 @@ public class BitDatum extends Datum {
 	public String asChars() {
 		return "0x"+val;
 	}
-	
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
 
   @Override
   public int size() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/BlobDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BlobDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BlobDatum.java
index 4bc4c61..c9ecced 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BlobDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BlobDatum.java
@@ -23,7 +23,6 @@ package org.apache.tajo.datum;
 
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
@@ -109,11 +108,6 @@ public class BlobDatum extends Datum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
 	  return this.val.length;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
index adb332a..fc543b4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
@@ -21,7 +21,6 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 public class BooleanDatum extends Datum {
 	@Expose private boolean val;
@@ -120,10 +119,6 @@ public class BooleanDatum extends Datum {
 	public String asChars() {
 		return val ? "true" : "false";
 	}
-	
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
 
   @Override
   public int size() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/CharDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/CharDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/CharDatum.java
index 8277849..4d77dad 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/CharDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/CharDatum.java
@@ -20,7 +20,6 @@ package org.apache.tajo.datum;
 
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -89,11 +88,6 @@ public class CharDatum extends Datum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
index 92100f6..10ae9d9 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
@@ -19,14 +19,15 @@
 package org.apache.tajo.datum;
 
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.json.CommonGsonHelper;
 
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
-public abstract class Datum implements Comparable<Datum> {
-	@Expose
-	private Type type;
+public abstract class Datum implements Comparable<Datum>, GsonObject {
+	@Expose	private Type type;
 	
 	@SuppressWarnings("unused")
   private Datum() {
@@ -149,7 +150,10 @@ public abstract class Datum implements Comparable<Datum> {
 	
   public abstract int compareTo(Datum datum);
 
-  public abstract String toJSON();
+  @Override
+  public String toJson() {
+    return CommonGsonHelper.toJson(this, Datum.class);
+  }
 
   @Override
   public String toString() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
index cbe9206..3bdd332 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
@@ -22,7 +22,6 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 
@@ -92,11 +91,6 @@ public class Float4Datum extends NumericDatum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
index a75f042..a27b4fc 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
@@ -24,7 +24,6 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 
@@ -85,11 +84,6 @@ public class Float8Datum extends NumericDatum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Inet4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Inet4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Inet4Datum.java
index f039220..62f510d 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Inet4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Inet4Datum.java
@@ -21,7 +21,6 @@ package org.apache.tajo.datum;
 import com.google.common.base.Preconditions;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -77,11 +76,6 @@ public class Inet4Datum extends Datum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
index 92a867f..7523432 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
@@ -21,7 +21,6 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 
@@ -82,11 +81,6 @@ public class Int2Datum extends NumericDatum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
index 38f3588..0c993a3 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
@@ -22,7 +22,6 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 
@@ -88,11 +87,6 @@ public class Int4Datum extends NumericDatum {
 	}
 
   @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
-
-  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
index fc02b16..f93c219 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
@@ -22,7 +22,6 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.nio.ByteBuffer;
 
@@ -91,11 +90,6 @@ public class Int8Datum extends NumericDatum {
 	public String asChars() {
 		return ""+val;
 	}
-
-  @Override
-	public String toJSON() {
-		return GsonCreator.getInstance().toJson(this, Datum.class);
-	}
 	
   @Override
   public int size() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
index 222a81e..334e935 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
@@ -101,9 +101,4 @@ public class NullDatum extends Datum {
   public int hashCode() {
     return 23244; // one of the prime number
   }
-
-  @Override
-  public String toJSON() {
-    return "";
-  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
index 8612a35..876803b 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
@@ -23,15 +23,12 @@ import org.apache.hadoop.io.WritableComparator;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
-import org.apache.tajo.datum.json.GsonCreator;
 
 import java.util.Arrays;
 
 public class TextDatum extends Datum {
-  @Expose
-  private int size;
-  @Expose
-  private byte[] bytes;
+  @Expose private int size;
+  @Expose private byte [] bytes;
 
   public TextDatum() {
     super(TajoDataTypes.Type.TEXT);
@@ -130,11 +127,6 @@ public class TextDatum extends Datum {
   }
 
   @Override
-  public String toJSON() {
-    return GsonCreator.getInstance().toJson(this, Datum.class);
-  }
-
-  @Override
   public int hashCode() {
     return Arrays.hashCode(bytes);
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/json/DatumAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/json/DatumAdapter.java b/tajo-common/src/main/java/org/apache/tajo/datum/json/DatumAdapter.java
deleted file mode 100644
index dfe0e21..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/datum/json/DatumAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.datum.json;
-
-import com.google.gson.*;
-import org.apache.tajo.datum.Datum;
-
-import java.lang.reflect.Type;
-
-public class DatumAdapter implements JsonSerializer<Datum>, JsonDeserializer<Datum> {
-
-	@Override
-	public Datum deserialize(JsonElement json, Type typeOfT,
-			JsonDeserializationContext context) throws JsonParseException {
-		JsonObject jsonObject = json.getAsJsonObject();
-		String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
-		
-		Class clazz;
-		try {
-			clazz = Class.forName(className);
-		} catch (ClassNotFoundException e) {
-			e.printStackTrace();
-			throw new JsonParseException(e);
-		}
-		return context.deserialize(jsonObject.get("property"), clazz);
-	}
-
-	@Override
-	public JsonElement serialize(Datum src, Type typeOfSrc,
-			JsonSerializationContext context) {
-		JsonObject jsonObj = new JsonObject();
-		String className = src.getClass().getCanonicalName();
-		jsonObj.addProperty("classname", className);
-		JsonElement jsonElem = context.serialize(src);
-		jsonObj.add("property", jsonElem);
-		return jsonObj;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/datum/json/GsonCreator.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/json/GsonCreator.java b/tajo-common/src/main/java/org/apache/tajo/datum/json/GsonCreator.java
deleted file mode 100644
index d1a9bf2..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/datum/json/GsonCreator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.datum.json;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import org.apache.tajo.datum.Datum;
-
-public class GsonCreator {
-
-	private static GsonBuilder builder;
-	private static Gson gson;
-	
-	private static void init() {
-		if (builder == null) {
-			builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
-			builder.registerTypeAdapter(Datum.class, new DatumAdapter());
-		} 
-		if (gson == null ) {
-			gson = builder.create();
-		}
-	}
-
-	public static Gson getInstance() {
-		init();
-		return gson;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameDeserializer.java b/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameDeserializer.java
deleted file mode 100644
index 43a378e..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameDeserializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.gson;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-
-import java.lang.reflect.Type;
-
-public class ClassNameDeserializer implements JsonDeserializer<Class> {
-
-	@Override
-	public Class deserialize(JsonElement json, Type type,
-			JsonDeserializationContext ctx) throws JsonParseException {
-		try {
-			return Class.forName(json.getAsString());
-		} catch (ClassNotFoundException e) {
-			e.printStackTrace();
-		}
-		return null;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameSerializer.java b/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameSerializer.java
deleted file mode 100644
index 7cc9245..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/ClassNameSerializer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.gson;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-
-public class ClassNameSerializer implements JsonSerializer<Class> {
-
-	@Override
-	public JsonElement serialize(Class clazz, Type type,
-			JsonSerializationContext ctx) {
-		return new JsonPrimitive(clazz.getName());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/DataTypeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/DataTypeAdapter.java b/tajo-common/src/main/java/org/apache/tajo/gson/DataTypeAdapter.java
deleted file mode 100644
index 9fc0586..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/DataTypeAdapter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.gson;
-
-import com.google.gson.*;
-import org.apache.tajo.common.TajoDataTypes;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-
-import java.lang.reflect.Type;
-
-
-public class DataTypeAdapter implements JsonSerializer<DataType>, JsonDeserializer<DataType> {
-
-  @Override
-  public DataType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-      throws JsonParseException {
-
-
-    JsonObject obj = (JsonObject) json;
-    DataType.Builder builder = DataType.newBuilder();
-    TajoDataTypes.Type type = Enum.valueOf(TajoDataTypes.Type.class, obj.get("type").getAsString());
-    builder.setType(type);
-
-    JsonElement len = obj.get("len");
-    if (len != null) {
-      builder.setLength(len.getAsInt());
-    }
-    JsonElement code = obj.get("code");
-    if (code != null) {
-      builder.setCode(code.getAsString());
-    }
-    return builder.build();
-  }
-
-  @Override
-  public JsonElement serialize(DataType src, Type typeOfSrc, JsonSerializationContext context) {
-    JsonObject json = new JsonObject();
-    json.addProperty("type", src.getType().name());
-    if (src.hasLength()) {
-      json.addProperty("len", src.getLength());
-    }
-    if (src.hasCode()) {
-      json.addProperty("code", src.getCode());
-    }
-
-    return json;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/DatumTypeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/DatumTypeAdapter.java b/tajo-common/src/main/java/org/apache/tajo/gson/DatumTypeAdapter.java
deleted file mode 100644
index b457fc1..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/DatumTypeAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.gson;
-
-import com.google.gson.*;
-import org.apache.tajo.datum.Datum;
-
-import java.lang.reflect.Type;
-
-public class DatumTypeAdapter implements JsonSerializer<Datum>, JsonDeserializer<Datum> {
-
-  @Override
-  public Datum deserialize(JsonElement json, Type typeOfT,
-      JsonDeserializationContext context) throws JsonParseException {
-    JsonObject jsonObject = json.getAsJsonObject();
-    String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
-    
-    Class clazz;
-    try {
-      clazz = Class.forName(className);
-    } catch (ClassNotFoundException e) {
-      e.printStackTrace();
-      throw new JsonParseException(e);
-    }
-    return context.deserialize(jsonObject.get("property"), clazz);
-  }
-
-  @Override
-  public JsonElement serialize(Datum src, Type typeOfSrc,
-      JsonSerializationContext context) {
-    JsonObject jsonObj = new JsonObject();
-    String className = src.getClass().getCanonicalName();
-    jsonObj.addProperty("classname", className);
-    JsonElement jsonElem = context.serialize(src);
-    jsonObj.add("property", jsonElem);
-    return jsonObj;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/PathDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/PathDeserializer.java b/tajo-common/src/main/java/org/apache/tajo/gson/PathDeserializer.java
deleted file mode 100644
index ae3eb81..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/PathDeserializer.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.gson;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import org.apache.hadoop.fs.Path;
-
-import java.lang.reflect.Type;
-
-public class PathDeserializer implements JsonDeserializer<Path> {
-
-	@Override
-	public Path deserialize(JsonElement arg0, Type arg1,
-			JsonDeserializationContext arg2) throws JsonParseException {
-		return new Path(arg0.getAsJsonPrimitive().getAsString());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/gson/PathSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/gson/PathSerializer.java b/tajo-common/src/main/java/org/apache/tajo/gson/PathSerializer.java
deleted file mode 100644
index 6564d7d..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/gson/PathSerializer.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * 
- */
-package org.apache.tajo.gson;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import org.apache.hadoop.fs.Path;
-
-import java.lang.reflect.Type;
-
-public class PathSerializer implements JsonSerializer<Path> {
-
-	@Override
-	public JsonElement serialize(Path arg0, Type arg1,
-			JsonSerializationContext arg2) {
-		return new JsonPrimitive(arg0.toString());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-common/src/main/java/org/apache/tajo/json/ClassNameDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/ClassNameDeserializer.java b/tajo-common/src/main/java/org/apache/tajo/json/ClassNameDeserializer.java
new file mode 100644
index 0000000..d069db2
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/ClassNameDeserializer.java
@@ -0,0 +1,44 @@
+/**
+ * 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.tajo.json;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+import java.lang.reflect.Type;
+
+public class ClassNameDeserializer implements JsonDeserializer<Class> {
+
+	@Override
+	public Class deserialize(JsonElement json, Type type,
+			JsonDeserializationContext ctx) throws JsonParseException {
+		try {
+			return Class.forName(json.getAsString());
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+}


[4/4] git commit: TAJO-95: Eliminate the lazy copy approach from the classes wrapping protobuf-generated classes. (hyunsik)

Posted by hy...@apache.org.
TAJO-95: Eliminate the lazy copy approach from the classes wrapping protobuf-generated classes. (hyunsik)


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

Branch: refs/heads/master
Commit: 1c677cc5cc5353177879af157f3bf19a0a1fe1d3
Parents: 87420eb
Author: Hyunsik Choi <hy...@apache.org>
Authored: Thu Aug 8 11:15:40 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Thu Aug 8 11:15:40 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |  12 +-
 .../tajo/catalog/AbstractCatalogClient.java     |  14 +-
 .../java/org/apache/tajo/catalog/Column.java    |  86 ++-------
 .../org/apache/tajo/catalog/FunctionDesc.java   | 170 +++---------------
 .../java/org/apache/tajo/catalog/IndexDesc.java | 165 +++--------------
 .../java/org/apache/tajo/catalog/Options.java   | 107 ++++-------
 .../java/org/apache/tajo/catalog/Schema.java    | 107 +++--------
 .../java/org/apache/tajo/catalog/SortSpec.java  |  31 +++-
 .../java/org/apache/tajo/catalog/TableDesc.java |   7 +-
 .../org/apache/tajo/catalog/TableDescImpl.java  | 101 ++---------
 .../java/org/apache/tajo/catalog/TableMeta.java |   5 +-
 .../org/apache/tajo/catalog/TableMetaImpl.java  | 168 ++++--------------
 .../tajo/catalog/function/AggFunction.java      |   9 +-
 .../apache/tajo/catalog/function/Function.java  |  12 +-
 .../tajo/catalog/function/GeneralFunction.java  |  12 +-
 .../tajo/catalog/json/CatalogGsonHelper.java    |  86 +++++++++
 .../tajo/catalog/json/FunctionAdapter.java      |   3 +-
 .../apache/tajo/catalog/json/GsonCreator.java   |  72 --------
 .../tajo/catalog/json/PathDeserializer.java     |  37 ----
 .../tajo/catalog/json/PathSerializer.java       |  37 ----
 .../tajo/catalog/json/TableDescAdapter.java     |   9 +-
 .../tajo/catalog/json/TableMetaAdapter.java     |   6 +-
 .../tajo/catalog/statistics/ColumnStat.java     | 137 ++++-----------
 .../apache/tajo/catalog/statistics/StatSet.java |  24 +--
 .../tajo/catalog/statistics/TableStat.java      | 174 +++++-------------
 .../org/apache/tajo/catalog/TestColumn.java     |  24 ++-
 .../apache/tajo/catalog/TestFunctionDesc.java   |  39 ++--
 .../org/apache/tajo/catalog/TestSchema.java     |  20 ++-
 .../org/apache/tajo/catalog/TestTableDesc.java  |  53 +++---
 .../org/apache/tajo/catalog/TestTableMeta.java  |  67 +++++--
 .../tajo/catalog/statistics/TestColumnStat.java |  16 +-
 .../tajo/catalog/statistics/TestTableStat.java  |   9 +-
 .../tajo/catalog/statistics/TestColumnStat.java |  68 -------
 .../tajo/catalog/statistics/TestStatSet.java    |  67 -------
 .../catalog/statistics/TestStatisticsUtil.java  |  68 -------
 .../tajo/catalog/statistics/TestTableStat.java  |  74 --------
 .../org/apache/tajo/QueryUnitAttemptId.java     |  18 +-
 .../main/java/org/apache/tajo/QueryUnitId.java  |  17 +-
 .../org/apache/tajo/common/ProtoObject.java     |   1 -
 .../java/org/apache/tajo/datum/ArrayDatum.java  |   6 -
 .../java/org/apache/tajo/datum/BitDatum.java    |   5 -
 .../java/org/apache/tajo/datum/BlobDatum.java   |   6 -
 .../org/apache/tajo/datum/BooleanDatum.java     |   5 -
 .../java/org/apache/tajo/datum/CharDatum.java   |   6 -
 .../main/java/org/apache/tajo/datum/Datum.java  |  12 +-
 .../java/org/apache/tajo/datum/Float4Datum.java |   6 -
 .../java/org/apache/tajo/datum/Float8Datum.java |   6 -
 .../java/org/apache/tajo/datum/Inet4Datum.java  |   6 -
 .../java/org/apache/tajo/datum/Int2Datum.java   |   6 -
 .../java/org/apache/tajo/datum/Int4Datum.java   |   6 -
 .../java/org/apache/tajo/datum/Int8Datum.java   |   6 -
 .../java/org/apache/tajo/datum/NullDatum.java   |   5 -
 .../java/org/apache/tajo/datum/TextDatum.java   |  12 +-
 .../apache/tajo/datum/json/DatumAdapter.java    |  55 ------
 .../org/apache/tajo/datum/json/GsonCreator.java |  44 -----
 .../apache/tajo/gson/ClassNameDeserializer.java |  44 -----
 .../apache/tajo/gson/ClassNameSerializer.java   |  39 ----
 .../org/apache/tajo/gson/DataTypeAdapter.java   |  64 -------
 .../org/apache/tajo/gson/DatumTypeAdapter.java  |  55 ------
 .../org/apache/tajo/gson/PathDeserializer.java  |  40 -----
 .../org/apache/tajo/gson/PathSerializer.java    |  40 -----
 .../apache/tajo/json/ClassNameDeserializer.java |  44 +++++
 .../apache/tajo/json/ClassNameSerializer.java   |  46 +++++
 .../org/apache/tajo/json/CommonGsonHelper.java  |  70 ++++++++
 .../org/apache/tajo/json/DataTypeAdapter.java   |  63 +++++++
 .../java/org/apache/tajo/json/DatumAdapter.java |  54 ++++++
 .../org/apache/tajo/json/DatumTypeAdapter.java  |  55 ++++++
 .../java/org/apache/tajo/json/GsonHelper.java   |  49 ++++++
 .../java/org/apache/tajo/json/GsonObject.java   |  23 +++
 .../org/apache/tajo/json/GsonSerDerAdapter.java |  25 +++
 .../org/apache/tajo/json/PathDeserializer.java  |  40 +++++
 .../org/apache/tajo/json/PathSerializer.java    |  42 +++++
 .../main/java/org/apache/tajo/util/TUtil.java   |   8 +
 .../org/apache/tajo/datum/TestBoolDatum.java    |   2 +-
 .../org/apache/tajo/datum/TestBytesDatum.java   |   8 +-
 .../org/apache/tajo/datum/TestInet4Datum.java   |   6 +-
 .../tajo/engine/eval/AggFuncCallEval.java       |  12 +-
 .../org/apache/tajo/engine/eval/BinaryEval.java |   7 -
 .../apache/tajo/engine/eval/CaseWhenEval.java   |  38 ++--
 .../org/apache/tajo/engine/eval/ConstEval.java  |   7 -
 .../org/apache/tajo/engine/eval/EvalNode.java   |  23 ++-
 .../org/apache/tajo/engine/eval/FieldEval.java  |   7 -
 .../apache/tajo/engine/eval/FuncCallEval.java   |   8 -
 .../org/apache/tajo/engine/eval/FuncEval.java   |   8 -
 .../apache/tajo/engine/json/CoreGsonHelper.java |  94 ++++++++++
 .../tajo/engine/json/EvalNodeAdapter.java       |   3 +-
 .../tajo/engine/json/FragmentDeserializer.java  |   4 +-
 .../tajo/engine/json/FromTableDeserializer.java |   2 +-
 .../apache/tajo/engine/json/GsonCreator.java    |  81 ---------
 .../tajo/engine/json/LogicalNodeAdapter.java    |   3 +-
 .../apache/tajo/engine/planner/FromTable.java   |  19 +-
 .../org/apache/tajo/engine/planner/Target.java  |   9 +-
 .../tajo/engine/planner/logical/BinaryNode.java |  16 +-
 .../engine/planner/logical/CreateTableNode.java |   5 -
 .../engine/planner/logical/DropTableNode.java   |   8 -
 .../engine/planner/logical/EvalExprNode.java    |  18 +-
 .../tajo/engine/planner/logical/ExceptNode.java |   7 -
 .../engine/planner/logical/GroupbyNode.java     |  27 +--
 .../engine/planner/logical/IndexScanNode.java   |  14 +-
 .../engine/planner/logical/IntersectNode.java   |   7 -
 .../tajo/engine/planner/logical/JoinNode.java   |   5 -
 .../tajo/engine/planner/logical/LimitNode.java  |   8 +-
 .../engine/planner/logical/LogicalNode.java     |  22 ++-
 .../engine/planner/logical/LogicalRootNode.java |   7 -
 .../engine/planner/logical/ProjectionNode.java  |   5 -
 .../tajo/engine/planner/logical/ScanNode.java   |   5 -
 .../engine/planner/logical/SelectionNode.java   |   9 +-
 .../tajo/engine/planner/logical/SortNode.java   |  18 +-
 .../engine/planner/logical/StoreTableNode.java  |  15 +-
 .../tajo/engine/planner/logical/UnaryNode.java  |   9 +-
 .../tajo/engine/planner/logical/UnionNode.java  |   7 -
 .../planner/logical/extended/ReceiveNode.java   |  10 +-
 .../planner/logical/extended/SendNode.java      |  11 +-
 .../tajo/engine/query/QueryUnitRequestImpl.java |  48 +----
 .../org/apache/tajo/master/GlobalEngine.java    |   2 +-
 .../apache/tajo/master/TaskSchedulerImpl.java   |   4 +-
 .../java/org/apache/tajo/util/IndexUtil.java    |   6 +-
 .../main/java/org/apache/tajo/worker/Task.java  |   5 +-
 .../java/org/apache/tajo/worker/TaskRunner.java |  29 +--
 .../java/org/apache/tajo/TestQueryUnitId.java   | 167 ------------------
 .../test/java/org/apache/tajo/TestTajoIds.java  | 167 ++++++++++++++++++
 .../apache/tajo/engine/eval/TestEvalTree.java   |  10 +-
 .../tajo/engine/planner/TestLogicalPlanner.java |  54 ++++--
 .../apache/tajo/master/TestRepartitioner.java   |   4 +-
 .../org/apache/tajo/storage/TestFragment.java   |  18 --
 .../org/apache/tajo/worker/TaskRunnerTest.java  |   4 +-
 .../java/org/apache/tajo/storage/CSVFile.java   |   6 +-
 .../java/org/apache/tajo/storage/Fragment.java  | 176 +++----------------
 .../java/org/apache/tajo/storage/RawFile.java   |   7 +-
 .../java/org/apache/tajo/storage/RowFile.java   |   6 +-
 .../apache/tajo/storage/TupleComparator.java    |   4 -
 .../tajo/storage/json/FragmentDeserializer.java |   2 +-
 .../apache/tajo/storage/json/GsonCreator.java   |  77 --------
 .../tajo/storage/json/StorageGsonHelper.java    |  90 ++++++++++
 .../tajo/storage/rcfile/RCFileWrapper.java      |   2 +-
 135 files changed, 1646 insertions(+), 2941 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 97eaa6b..e7bea99 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -15,6 +15,9 @@ Release 0.2.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-95: Eliminate the lazy copy approach from the classes wrapping
+    protobuf-generated classes. (hyunsik)
+
     TAJO-102: Add AlgebraVisitor and Refactor LogicalPlanner to use the visitor.    (hyunsik)
 
     TAJO-87: Integration of tajo algebra module and SQL parser. (hyunsik)
@@ -27,9 +30,11 @@ Release 0.2.0 - unreleased
 
     TAJO-79: Refactor and Improve TajoCli. (hyunsik)
 
-    TAJO-77: Rename TabletProto as FragmentProto in CatalogProtos.proto. (jihoon)
+    TAJO-77: Rename TabletProto as FragmentProto in CatalogProtos.proto. 
+    (jihoon)
 
-    TAJO-22: The package prefix should be org.apache.tajo. (DaeMyung Kang via hyunsik)
+    TAJO-22: The package prefix should be org.apache.tajo. (DaeMyung Kang via 
+    hyunsik)
 
     TAJO-75: Separate SQL.g into SQLParser.g and SQLLexer.g. (hyunsik)
 
@@ -83,7 +88,8 @@ Release 0.2.0 - unreleased
 
   BUG FIXES
 
-    TAJO-82: NullPointerException occurs when Schema is converted as an array of columns. (jihoon)
+    TAJO-82: NullPointerException occurs when Schema is converted as an array 
+    of columns. (jihoon)
 
     TAJO-65: Invalid pom.xml configurations for source directories. 
     (Takuya Ueshin via hyunsik)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
index f9eebfc..ac4c796 100644
--- a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
+++ b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
@@ -87,7 +87,12 @@ public abstract class AbstractCatalogClient implements CatalogService {
     }
     int size = response.getFunctionDescCount();
     for (int i = 0; i < size; i++) {
-      list.add(new FunctionDesc(response.getFunctionDesc(i)));
+      try {
+        list.add(new FunctionDesc(response.getFunctionDesc(i)));
+      } catch (ClassNotFoundException e) {
+        LOG.error(e);
+        return null;
+      }
     }
     return list;
   }
@@ -239,7 +244,12 @@ public abstract class AbstractCatalogClient implements CatalogService {
       LOG.error(e);
       return null;
     }
-    return new FunctionDesc(descProto);
+    try {
+      return new FunctionDesc(descProto);
+    } catch (ClassNotFoundException e) {
+      LOG.error(e);
+      return null;
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
index e1adc53..c215661 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
@@ -19,20 +19,18 @@
 package org.apache.tajo.catalog;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 
-public class Column implements ProtoObject<ColumnProto>, Cloneable {
-	private ColumnProto proto = ColumnProto.getDefaultInstance();
+public class Column implements ProtoObject<ColumnProto>, Cloneable, GsonObject {
 	private ColumnProto.Builder builder = null;
-	private boolean viaProto = false;
 	
-	@Expose protected String name;
-	@Expose protected DataType dataType;
+	@Expose protected String name; // required
+	@Expose protected DataType dataType; // required
 	
 	public Column() {
 		this.builder = ColumnProto.newBuilder();
@@ -49,21 +47,10 @@ public class Column implements ProtoObject<ColumnProto>, Cloneable {
   }
 	
 	public Column(ColumnProto proto) {
-		this.proto = proto;
-		this.viaProto = true;
+		this(proto.getColumnName(), proto.getDataType());
 	}
-	
 
 	public String getQualifiedName() {
-		ColumnProtoOrBuilder p = viaProto ? proto : builder;
-		if(name != null) {
-			return this.name;
-		}
-		if(!p.hasColumnName()) {
-			return null;			
-		}		
-		this.name = p.getColumnName();
-		
 		return this.name;
 	}
 	
@@ -87,25 +74,14 @@ public class Column implements ProtoObject<ColumnProto>, Cloneable {
   }
 	
 	public void setName(String name) {
-	  setModified();
 		this.name = name.toLowerCase();
 	}
 	
 	public DataType getDataType() {
-		ColumnProtoOrBuilder p = viaProto ? proto : builder;
-		if(dataType != null) {
-			return this.dataType;
-		}
-		if(!p.hasDataType()) {
-			return null;
-		}
-		this.dataType = p.getDataType();
-		
 		return this.dataType;
 	}
 	
 	public void setDataType(DataType dataType) {
-		setModified();
 		this.dataType = dataType;
 	}
 	
@@ -126,9 +102,6 @@ public class Column implements ProtoObject<ColumnProto>, Cloneable {
   @Override
   public Object clone() throws CloneNotSupportedException {
     Column column = (Column) super.clone();
-    initFromProto();
-    column.proto = null;
-    column.viaProto = false;
     column.builder = ColumnProto.newBuilder();
     column.name = name;
     column.dataType = dataType;
@@ -137,51 +110,18 @@ public class Column implements ProtoObject<ColumnProto>, Cloneable {
 
 	@Override
 	public ColumnProto getProto() {
-	  if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }
-	  
-	  return proto;
-	}
-	
-	private void setModified() {
-	  if (viaProto && builder == null) {
-	    builder = ColumnProto.newBuilder(proto);
-	  }
-	  viaProto = false;
-	}
-	
-	private void mergeLocalToBuilder() {
-	  if (builder == null) {
-	    builder = ColumnProto.newBuilder(proto);
-	  }
-		if (this.name != null) {
-			builder.setColumnName(this.name);			
-		}
-		if (this.dataType != null) {
-			builder.setDataType(this.dataType);
-		}
+    builder.setColumnName(this.name);
+    builder.setDataType(this.dataType);
+
+    return builder.build();
 	}
 	
 	public String toString() {
 	  return getQualifiedName() +" (" + getDataType().getType() +")";
 	}
-	
-	public String toJSON() {
-		initFromProto();
-		return GsonCreator.getInstance().toJson(this);
-	}
 
-	@Override
-	public void initFromProto() {
-		ColumnProtoOrBuilder p = viaProto ? proto : builder;
-		if (this.name == null && p.hasColumnName()) {
-			this.name = p.getColumnName();
-		}
-		if (this.dataType == null && p.hasDataType()) {
-			this.dataType = p.getDataType();
-		}
+  @Override
+	public String toJson() {
+		return CatalogGsonHelper.toJson(this, Column.class);
 	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
index 93bcadd..8f678b9 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
@@ -18,13 +18,11 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.function.Function;
-import org.apache.tajo.catalog.function.GeneralFunction;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProtoOrBuilder;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
 import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.common.TajoDataTypes.DataType;
@@ -33,10 +31,8 @@ import org.apache.tajo.exception.InternalException;
 import java.lang.reflect.Constructor;
 import java.util.Arrays;
 
-public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
-  private FunctionDescProto proto = FunctionDescProto.getDefaultInstance();
-  private FunctionDescProto.Builder builder = null;
-  private boolean viaProto = false;
+public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable, GsonObject {
+  private FunctionDescProto.Builder builder = FunctionDescProto.newBuilder();
   
   @Expose private String signature;
   @Expose private Class<? extends Function> funcClass;
@@ -45,12 +41,10 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
   @Expose private DataType [] params;
 
   public FunctionDesc() {
-    this.builder = FunctionDescProto.newBuilder();
   }
-  
+
   public FunctionDesc(String signature, Class<? extends Function> clazz,
       FunctionType funcType, DataType [] retType, DataType [] params) {
-    this();
     this.signature = signature.toLowerCase();
     this.funcClass = clazz;
     this.funcType = funcType;
@@ -58,12 +52,12 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
     this.params = params;
   }
   
-  public FunctionDesc(FunctionDescProto proto) {
-    this.proto = proto;
-    this.viaProto = true;
+  public FunctionDesc(FunctionDescProto proto) throws ClassNotFoundException {
+    this(proto.getSignature(), proto.getClassName(), proto.getType(),
+        newNoNameSchema(proto.getReturnType()),
+        proto.getParameterTypesList().toArray(new DataType[proto.getParameterTypesCount()]));
   }
 
-  @SuppressWarnings("unchecked")
   public FunctionDesc(String signature, String className, FunctionType type,
                       DataType [] retType, DataType... argTypes) throws ClassNotFoundException {
     this(signature, (Class<? extends Function>) Class.forName(className), type,
@@ -85,75 +79,28 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
   }
 
   public String getSignature() {
-    FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.signature != null) {
-      return this.signature;
-    }
-    if (!proto.hasSignature()) {
-      return null;
-    }
-    this.signature = p.getSignature();
     return this.signature;
   }
 
   @SuppressWarnings("unchecked")
   public Class<? extends Function> getFuncClass() throws InternalException {
-    FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.funcClass != null) {
-      return this.funcClass;
-    }
-    if (!p.hasClassName()) {
-      return null;
-    }
-    try {
-      this.funcClass = (Class<? extends Function>)Class.forName(p.getClassName());
-    } catch (ClassNotFoundException e) {
-      throw new InternalException("The function class ("+p.getClassName()+") cannot be loaded");
-    }
     return this.funcClass;
   }
 
   public FunctionType getFuncType() {
-    FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.funcType != null) {
-      return this.funcType;
-    }
-    if (!p.hasType()) {
-      return null;
-    }
-    this.funcType = p.getType();
     return this.funcType;
   }
 
   public DataType [] getParamTypes() {
-    FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.params != null) {
-      return this.params;
-    }
-    if (p.getParameterTypesCount() == 0) {
-      return null;
-    }
-    this.params = p.getParameterTypesList().toArray(
-        new DataType[p.getParameterTypesCount()]);
     return this.params;
   }
 
   public DataType [] getReturnType() {
-    FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.returnType != null) {
-      return newNoNameSchema(this.returnType);
-    }
-    if (!p.hasReturnType()) {
-      return null;
-    }
-    this.returnType = newNoNameSchema(p.getReturnType());
     return this.returnType;
-    
   }
 
   public static DataType [] newNoNameSchema(DataType ... types) {
-    DataType [] dataTypes = types.clone();
-    return dataTypes;
+    return types.clone();
   }
   
   @Override
@@ -169,14 +116,10 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
   @Override
   public Object clone() throws CloneNotSupportedException{
     FunctionDesc desc  = (FunctionDesc)super.clone();
-    desc.proto = this.proto;
-    desc.builder = this.builder == null?null:this.builder.clone();
     
     desc.signature = this.signature;
-    desc.params = this.params;
-    
+    desc.params = params.clone();
     desc.returnType = this.returnType;
-    desc.viaProto = this.viaProto;
     desc.funcClass = this.funcClass;
     
     return desc;
@@ -184,91 +127,28 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable {
 
   @Override
   public FunctionDescProto getProto() {
-    mergeLocalToProto();
-    proto = viaProto ? proto : builder.build();
-    viaProto = true;
-    return proto;
-  }
-  
-  private void maybeInitBuilder() {
-    if (viaProto || builder == null) {
-      builder = FunctionDescProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-  
-  private void mergeLocalToBuilder() {
-    if (this.signature  != null) {     
-      builder.setSignature(this.signature);
-    }
-    if (this.funcClass != null) {
-      builder.setClassName(this.funcClass.getName());
-    }
-    if (this.funcType != null) {
-      builder.setType(this.funcType);
-    }
-    if (this.returnType != null) {
-      builder.setReturnType(this.returnType[0]);
-    }
-    if (this.params != null) {
+    if (builder == null) {
+      builder = FunctionDescProto.newBuilder();
+    } else {
+      builder.clear();
+    }
+    builder.setSignature(this.signature);
+    builder.setClassName(this.funcClass.getName());
+    builder.setType(this.funcType);
+    builder.setReturnType(this.returnType[0]);
+
+    if (this.params != null) { // repeated field
       builder.addAllParameterTypes(Arrays.asList(params));
     }
-  }
-  
-  private void mergeLocalToProto() {
-    if(viaProto) {
-      maybeInitBuilder();
-    }
-    mergeLocalToBuilder();
-    proto = builder.build();
-    viaProto = true;
-  }
-  
-  @SuppressWarnings("unchecked")
-  private void mergeProtoToLocal() throws InternalException {
-	  FunctionDescProtoOrBuilder p = viaProto ? proto : builder;
-	  if (signature == null && p.hasSignature()) {
-		  signature = p.getSignature();
-	  }
-	  if (funcClass == null && p.hasClassName()) {
-		  try {
-			  this.funcClass = 
-			      (Class<? extends GeneralFunction>)Class.forName(p.getClassName());
-		  } catch (ClassNotFoundException e) {
-			  throw new InternalException("The function class ("+p.getClassName()+") cannot be loaded");
-		  }
-	  }
-	  if (funcType == null && p.hasType()) {
-		  funcType = p.getType();
-	  }
-	  if (returnType == null && p.hasReturnType()) {
-		  returnType = newNoNameSchema(p.getReturnType());
-	  }
-	  if (params == null && p.getParameterTypesCount() > 0) {
-		  params = new DataType[p.getParameterTypesCount()];
-		  for (int i = 0; i < p.getParameterTypesCount(); i++) {
-			  params[i] = p.getParameterTypes(i);
-		  }
-	  }
+    return builder.build();
   }
   
   @Override
   public String toString() {
 	  return getProto().toString();
   }
-
-  @Override
-  public void initFromProto() {
-    try {
-      mergeProtoToLocal();
-    } catch (InternalException e) {
-      e.printStackTrace();
-    }
-  }
   
-  public String toJSON() {
-    initFromProto();
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, FunctionDesc.class);
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, FunctionDesc.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
index fb6058e..9465946 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
@@ -21,24 +21,20 @@ package org.apache.tajo.catalog;
 import com.google.common.base.Objects;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProtoOrBuilder;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
 import org.apache.tajo.common.ProtoObject;
 
 public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
-  private IndexDescProto proto;
   private IndexDescProto.Builder builder;
-  private boolean viaProto;
   
-  @Expose private String name;
-  @Expose private String tableId;
-  @Expose private Column column;
-  @Expose private IndexMethod indexMethod;
-  @Expose private boolean isUnique = false;
-  @Expose private boolean isClustered = false;
-  @Expose private boolean isAscending = false;
+  private String name; // required
+  private String tableId; // required
+  private Column column; // required
+  private IndexMethod indexMethod; // required
+  private boolean isUnique = false; // optional [default = false]
+  private boolean isClustered = false; // optional [default = false]
+  private boolean isAscending = false; // optional [default = false]
   
   public IndexDesc() {
     this.builder = IndexDescProto.newBuilder();
@@ -57,172 +53,52 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   }
   
   public IndexDesc(IndexDescProto proto) {
-    this.proto = proto;
-    this.viaProto = true;
+    this(proto.getName(), proto.getTableId(), new Column(proto.getColumn()),
+        proto.getIndexMethod(), proto.getIsUnique(), proto.getIsClustered(), proto.getIsAscending());
   }
   
   public String getName() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.name != null) {
-      return name;
-    }
-    if (!p.hasName()) {
-      return null;
-    }
-    this.name = p.getName();
-    
     return name;
   }
   
   public String getTableId() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.tableId != null) {
-      return tableId;
-    }
-    if (!p.hasTableId()) {
-      return null;
-    }
-    this.tableId = p.getTableId();
-    
     return tableId;
   }
   
   public Column getColumn() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.column != null) {
-      return column;
-    }
-    if (!p.hasColumn()) {
-      return null;
-    }
-    this.column = new Column(p.getColumn());
-    
     return column;
   }
   
   public IndexMethod getIndexMethod() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;    
-    if (this.indexMethod != null) {
-      return this.indexMethod;
-    }
-    if (!p.hasIndexMethod()) { // if isCluster == false and proto has no set
-      return null;
-    }
-    this.indexMethod = p.getIndexMethod();
-    
     return this.indexMethod;
   }
   
   public boolean isClustered() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (isClustered) {
-      return true;
-    }
-    if (!p.hasIsClustered()) { // if isCluster == false and proto has no set
-      return false;
-    }
-    this.isClustered = p.getIsClustered();
-    
     return this.isClustered;
   }
   
   public boolean isUnique() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;    
-    if (isUnique) {
-      return true;
-    }
-    if (!p.hasIsUnique()) { // if isCluster == false and proto has no set
-      return false;
-    }
-    this.isUnique = p.getIsUnique();
-    
     return this.isUnique;
   }
   
   public boolean isAscending() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;    
-    if (isAscending) {
-      return true;
-    }
-    if (!p.hasIsAscending()) { // if isCluster == false and proto has no set
-      return false;
-    }
-    this.isAscending = p.getIsAscending();
-    
     return this.isAscending;
   }
 
   @Override
   public IndexDescProto getProto() {
-    if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }
-    
-    return proto;
-  }
-  
-  @SuppressWarnings("unused")
-  private void setModified() {
-    if (viaProto && builder == null) {
-      builder = IndexDescProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-  
-  private void mergeLocalToBuilder() {
     if (builder == null) {
-      builder = IndexDescProto.newBuilder(proto);
-    }
-    if (this.name != null) {
-      builder.setName(this.name);
-    }
-    if (this.tableId != null) {
-      builder.setTableId(this.tableId);
-    }
-    if (this.column != null) {
-      builder.setColumn(this.column.getProto());
-    }
-    if (this.indexMethod != null) {
-      builder.setIndexMethod(indexMethod);
-    }
-    if (this.isUnique) {
-      builder.setIsUnique(this.isUnique);
-    }
-    if (this.isClustered) {
-      builder.setIsClustered(this.isClustered);
-    }
-    if (this.isAscending) {
-      builder.setIsAscending(this.isAscending);
-    }
-  }
-  
-  @Override
-  public void initFromProto() {
-    IndexDescProtoOrBuilder p = viaProto ? proto : builder;
-    if (this.name == null && p.hasName()) {
-      this.name = p.getName();
-    }
-    if (this.tableId == null && p.hasTableId()) {
-      this.tableId = p.getTableId();
-    }
-    if (this.column == null && p.hasColumn()) {
-      this.column = new Column(p.getColumn());
-    }
-    if (this.indexMethod == null && p.hasIndexMethod()) {
-      this.indexMethod = p.getIndexMethod();
-    }
-    if (this.isUnique == false && p.hasIsUnique()) {
-      this.isUnique = p.getIsUnique();
-    }
-    if (this.isClustered == false && p.hasIsClustered()) {
-      this.isUnique = p.getIsUnique();
-    }
-    if (this.isAscending == false && p.hasIsAscending()) {
-      this.isAscending = p.getIsAscending();
-    }
-    viaProto = false;
+      builder = IndexDescProto.newBuilder();
+    }
+    builder.setName(this.name);
+    builder.setTableId(this.tableId);
+    builder.setColumn(this.column.getProto());
+    builder.setIndexMethod(indexMethod);
+    builder.setIsUnique(this.isUnique);
+    builder.setIsClustered(this.isClustered);
+    builder.setIsAscending(this.isAscending);
+
+    return builder.build();
   }
   
   public boolean equals(Object obj) {
@@ -247,7 +123,6 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   
   public Object clone() throws CloneNotSupportedException {
     IndexDesc desc = (IndexDesc) super.clone();
-    initFromProto();
     desc.name = name;
     desc.tableId = tableId;
     desc.column = (Column) column.clone();

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Options.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Options.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Options.java
index afd27b2..d5aa559 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Options.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Options.java
@@ -18,42 +18,38 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.common.collect.Maps;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.KeyValueProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.KeyValueSetProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.KeyValueSetProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.util.TUtil;
 
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 
-public class Options implements ProtoObject<KeyValueSetProto>, Cloneable {
-	@Expose(serialize=false,deserialize=false)
-	private KeyValueSetProto proto = KeyValueSetProto.getDefaultInstance();
-	@Expose(serialize=false,deserialize=false)
-	private KeyValueSetProto.Builder builder = null;
-	@Expose(serialize=false,deserialize=false)
-	private boolean viaProto = false;
+public class Options implements ProtoObject<KeyValueSetProto>, Cloneable, GsonObject {
+	private KeyValueSetProto.Builder builder = KeyValueSetProto.newBuilder();
 	
 	@Expose private Map<String,String> keyVals;
 	
 	public Options() {
-		builder = KeyValueSetProto.newBuilder();
+    keyVals = TUtil.newHashMap();
 	}
 	
 	public Options(KeyValueSetProto proto) {
-		this.proto = proto;
-		viaProto = true;
+    this.keyVals = TUtil.newHashMap();
+    for(KeyValueProto keyval : proto.getKeyvalList()) {
+      this.keyVals.put(keyval.getKey(), keyval.getValue());
+    }
 	}
 	
 	public Options(Options options) {
 	  this();
-	  options.initFromProto();
-	  this.keyVals = Maps.newHashMap(options.keyVals);
+	  this.keyVals.putAll(options.keyVals);
 	}
 	
 	public static Options create() {
@@ -65,30 +61,22 @@ public class Options implements ProtoObject<KeyValueSetProto>, Cloneable {
   }
 	
 	public void put(String key, String val) {
-		initOptions();
-		setModified();
 		this.keyVals.put(key, val);
 	}
 
   public void putAll(Map<String, String> keyValues) {
-    initOptions();
-    setModified();
     this.keyVals.putAll(keyValues);
   }
 	
 	public void putAll(Options options) {
-	  initOptions();
-	  setModified();
 	  this.keyVals.putAll(options.keyVals);
 	}
 	
 	public String get(String key) {
-		initOptions();
 		return this.keyVals.get(key);
 	}
 	
 	public String get(String key, String defaultVal) {
-	  initOptions();
 	  if(keyVals.containsKey(key))
 	    return keyVals.get(key);
 	  else {
@@ -97,12 +85,10 @@ public class Options implements ProtoObject<KeyValueSetProto>, Cloneable {
 	}
 	
 	public Iterator<Entry<String,String>> getAllKeyValus() {
-	  initOptions();
 	  return keyVals.entrySet().iterator();
 	}
 	
 	public String delete(String key) {
-		initOptions();
 		return keyVals.remove(key);
 	}
 	
@@ -110,8 +96,6 @@ public class Options implements ProtoObject<KeyValueSetProto>, Cloneable {
 	public boolean equals(Object object) {
 		if(object instanceof Options) {
 			Options other = (Options)object;
-			initOptions();
-			other.initOptions();
 			for(Entry<String, String> entry : other.keyVals.entrySet()) {
 				if(!keyVals.get(entry.getKey()).equals(entry.getValue()))
 					return false;
@@ -125,62 +109,33 @@ public class Options implements ProtoObject<KeyValueSetProto>, Cloneable {
 	@Override
   public Object clone() throws CloneNotSupportedException {    
     Options options = (Options) super.clone();
-    initFromProto();
-    options.proto = null;
-    options.viaProto = false;
     options.builder = KeyValueSetProto.newBuilder();
-    options.keyVals = keyVals != null ? new HashMap<String, String>(keyVals) :
-      null;    
+    options.keyVals = keyVals != null ? new HashMap<String, String>(keyVals) : null;
     return options;
 	}
 	
 	@Override
 	public KeyValueSetProto getProto() {
-	  if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }	  
-		return proto;
-	}
-	
-	private void initOptions() {
-		if (this.keyVals != null) {
-			return;
-		}
-		KeyValueSetProtoOrBuilder p = viaProto ? proto : builder;
-		this.keyVals = Maps.newHashMap();
-		for(KeyValueProto keyval:p.getKeyvalList()) {
-			this.keyVals.put(keyval.getKey(), keyval.getValue());
-		}		
-	}
-	
-	private void setModified() {
-		if (viaProto || builder == null) {
-			builder = KeyValueSetProto.newBuilder(proto);
-		}
-		viaProto = false;
-	}
-	
-	private void mergeLocalToBuilder() {
-		KeyValueProto.Builder kvBuilder = null;
-		if(this.keyVals != null) {
-			for(Entry<String,String> kv : keyVals.entrySet()) {
-				kvBuilder = KeyValueProto.newBuilder();
-				kvBuilder.setKey(kv.getKey());
-				kvBuilder.setValue(kv.getValue());
-				builder.addKeyval(kvBuilder.build());
-			}
-		}
-	}
+    if (builder == null) {
+      builder = KeyValueSetProto.newBuilder();
+    } else {
+      builder.clear();
+    }
 
-  @Override
-  public void initFromProto() {
-    initOptions();
-  }
+    KeyValueProto.Builder kvBuilder;
+    if(this.keyVals != null) {
+      for(Entry<String,String> kv : keyVals.entrySet()) {
+        kvBuilder = KeyValueProto.newBuilder();
+        kvBuilder.setKey(kv.getKey());
+
+        kvBuilder.setValue(kv.getValue());
+        builder.addKeyval(kvBuilder.build());
+      }
+    }
+    return builder.build();
+	}
   
-  public String toJSON() {
-    initFromProto();
-    return GsonCreator.getInstance().toJson(this, Options.class);
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, Options.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
index 7a0168c..9fee40f 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
@@ -18,46 +18,45 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.exception.AlreadyExistsFieldException;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
 import java.util.*;
 
-public class Schema implements ProtoObject<SchemaProto>, Cloneable {
+public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
   private static final Log LOG = LogFactory.getLog(Schema.class);
-  
-	private SchemaProto proto = SchemaProto.getDefaultInstance();
-	private	SchemaProto.Builder builder = null;
-	boolean viaProto = false;
+	private	SchemaProto.Builder builder = SchemaProto.newBuilder();
 
-	@Expose
-	protected List<Column> fields = null;
-	@Expose
-	protected Map<String,Integer> fieldsByName = null;
+	@Expose protected List<Column> fields = null;
+	@Expose protected Map<String,Integer> fieldsByName = null;
 
 	public Schema() {
-		builder = SchemaProto.newBuilder();
+    this.fields = new ArrayList<Column>();
+    this.fieldsByName = new TreeMap<String, Integer>();
 	}
 	
 	public Schema(SchemaProto proto) {
-    this.proto = proto;
-    this.viaProto = true;
+    this.fields = new ArrayList<Column>();
+    this.fieldsByName = new HashMap<String, Integer>();
+    for(ColumnProto colProto : proto.getFieldsList()) {
+      fields.add(new Column(colProto));
+      fieldsByName.put(colProto.getColumnName(), fields.size() - 1);
+    }
   }
 
 	public Schema(Schema schema) {
 	  this();
-		this.fields = new ArrayList<Column>(schema.fields);
-		this.fieldsByName = new TreeMap<String, Integer>(schema.fieldsByName);
+		this.fields.addAll(schema.fields);
+		this.fieldsByName.putAll(schema.fieldsByName);
 	}
 	
 	public Schema(Column [] columns) {
@@ -68,18 +67,15 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable {
   }
 	
 	public int getColumnNum() {
-		initColumns();
 		return this.fields.size();
 	}
 
 	public Column getColumn(String colName) {
-		initColumns();
 		Integer cid = fieldsByName.get(colName.toLowerCase());
 		return cid != null ? fields.get(cid) : null;
 	}
 	
 	public Column getColumnByName(String colName) {
-	  initColumns();
 	  for (Column col : fields) {
 	    if (col.getColumnName().equals(colName.toLowerCase())) {
 	      return col;
@@ -89,17 +85,14 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable {
 	}
 	
 	public Column getColumn(int id) {
-	  initColumns();
 	  return fields.get(id);
 	}
 	
 	public int getColumnId(String colName) {
-	  initColumns();
 	  return fieldsByName.get(colName.toLowerCase());
 	}
 
   public int getColumnIdByName(String colName) {
-    initColumns();
     for (Column col : fields) {
       if (col.getColumnName().equals(colName.toLowerCase())) {
         return fieldsByName.get(col.getQualifiedName());
@@ -109,47 +102,22 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable {
   }
 	
 	public Collection<Column> getColumns() {
-		initColumns();
 		return fields;
 	}
 	
 	public void alter(int idx, Column column) {
-	  initColumns();
 	  this.fields.set(idx, column);
 	}
 	
 	public boolean contains(String colName) {
-		initColumns();
 		return fieldsByName.containsKey(colName.toLowerCase());
 	}
-	
-	public void initFromProto() {
-		initColumns();
-		for (Column col : fields) {
-		  col.initFromProto();
-		}
-	}
-
-	private void initColumns() {
-		if (this.fields != null) {
-			return;
-		}
-		SchemaProtoOrBuilder p = viaProto ? proto : builder;
-		this.fields = new ArrayList<Column>();
-		this.fieldsByName = new HashMap<String, Integer>();
-		for(ColumnProto colProto : p.getFieldsList()) {
-			fields.add(new Column(colProto));
-			fieldsByName.put(colProto.getColumnName(), fields.size() - 1);
-		}
-	}
 
   public synchronized Schema addColumn(String name, Type type) {
     return addColumn(name, CatalogUtil.newDataTypeWithoutLen(type));
   }
 
   public synchronized Schema addColumn(String name, DataType dataType) {
-		initColumns();
-		setModified();
 		String lowcased = name.toLowerCase();
 		if(fieldsByName.containsKey(lowcased)) {
 		  LOG.error("Already exists column " + lowcased);
@@ -185,46 +153,25 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable {
   @Override
   public Object clone() throws CloneNotSupportedException {
     Schema schema = (Schema) super.clone();
-    initFromProto();
-    schema.viaProto = false;
     schema.builder = SchemaProto.newBuilder();
     schema.fields = fields != null ? new ArrayList<Column>(fields) : null;
-    schema.fieldsByName = fieldsByName != null ? new HashMap<String, Integer>(fieldsByName) : null;
+    schema.fieldsByName = fieldsByName != null ? new TreeMap<String, Integer>(fieldsByName) : null;
 
     return schema;
   }
 
 	@Override
 	public SchemaProto getProto() {
-	  if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
+    builder.clearFields();
+    if (this.fields  != null) {
+      for(Column col : fields) {
+        builder.addFields(col.getProto());
+      }
     }
-	  
-		return proto;
-	}
-
-	private void setModified() {
-		viaProto = false;
-	}
-
-	private void mergeLocalToBuilder() {
-	  if (builder == null) {
-	    builder = SchemaProto.newBuilder(proto);
-	  } else {	  
-	    builder.clearFields();
-	  }
-	  
-		if (this.fields  != null) {			
-			for(Column col : fields) {
-				builder.addFields(col.getProto());
-			}
-		}
+    return builder.build();
 	}
 
 	public String toString() {
-	  initColumns();
 	  StringBuilder sb = new StringBuilder();
 	  sb.append("{");
 	  int i = 0;
@@ -239,16 +186,14 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable {
 	  
 	  return sb.toString();
 	}
-	
+
+  @Override
 	public String toJson() {
-	  initFromProto();
-	  Gson gson = GsonCreator.getInstance();
-	  return gson.toJson(this, Schema.class);
+	  return CatalogGsonHelper.toJson(this, Schema.class);
 		
 	}
 
   public Column [] toArray() {
-    initFromProto();
     return this.fields.toArray(new Column[this.fields.size()]);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SortSpec.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SortSpec.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SortSpec.java
index edf7a2b..be73eb3 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SortSpec.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SortSpec.java
@@ -19,11 +19,12 @@
 package org.apache.tajo.catalog;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 
-public class SortSpec implements Cloneable {
-  @Expose
-  private Column sortKey;
+
+public class SortSpec implements Cloneable, GsonObject {
+  @Expose private Column sortKey;
   @Expose private boolean ascending = true;
   @Expose private boolean nullFirst = false;
 
@@ -38,8 +39,7 @@ public class SortSpec implements Cloneable {
    * @param nullFirst
    * Otherwise, it should be false.
    */
-  public SortSpec(final Column sortKey, final boolean asc,
-                  final boolean nullFirst) {
+  public SortSpec(final Column sortKey, final boolean asc, final boolean nullFirst) {
     this(sortKey);
     this.ascending = asc;
     this.nullFirst = nullFirst;
@@ -70,13 +70,26 @@ public class SortSpec implements Cloneable {
     SortSpec key = (SortSpec) super.clone();
     key.sortKey = (Column) sortKey.clone();
     key.ascending = ascending;
+    key.nullFirst = nullFirst;
 
     return key;
   }
 
-  public String toJSON() {
-    sortKey.initFromProto();
-    return GsonCreator.getInstance().toJson(this);
+  @Override
+  public boolean equals(Object object) {
+    if (object instanceof SortSpec) {
+      SortSpec other = (SortSpec) object;
+      return sortKey.equals(other.sortKey) &&
+          ascending == other.ascending &&
+          nullFirst == other.nullFirst;
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, SortSpec.class);
   }
 
   public String toString() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
index feeb0a8..d46bd14 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
@@ -20,8 +20,9 @@ package org.apache.tajo.catalog;
 
 import com.google.protobuf.Message;
 import org.apache.hadoop.fs.Path;
+import org.apache.tajo.json.GsonObject;
 
-public interface TableDesc extends Cloneable {
+public interface TableDesc extends Cloneable, GsonObject {
   void setId(String tableId);
   
   String getId();
@@ -35,10 +36,6 @@ public interface TableDesc extends Cloneable {
   TableMeta getMeta();
   
   Message getProto();
-  
-  void initFromProto();
-  
-  String toJSON();
  
   Object clone() throws CloneNotSupportedException;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDescImpl.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDescImpl.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDescImpl.java
index b690ddf..2771157 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDescImpl.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDescImpl.java
@@ -22,21 +22,17 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
 import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableDescProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.TableDescProtoOrBuilder;
 import org.apache.tajo.common.ProtoObject;
 
-public class TableDescImpl implements TableDesc, ProtoObject<TableDescProto>,
-    Cloneable {
-  protected TableDescProto proto = TableDescProto.getDefaultInstance();
+public class TableDescImpl implements TableDesc, ProtoObject<TableDescProto>, Cloneable {
   protected TableDescProto.Builder builder = null;
-  protected boolean viaProto = false;
   
-	@Expose protected String tableId;
-	@Expose protected Path uri;
-	@Expose protected TableMeta meta;
+	@Expose protected String tableId; // required
+	@Expose protected Path uri; // required
+	@Expose protected TableMeta meta; // required
   
 	public TableDescImpl() {
 		builder = TableDescProto.newBuilder();
@@ -56,65 +52,32 @@ public class TableDescImpl implements TableDesc, ProtoObject<TableDescProto>,
 	}
 	
 	public TableDescImpl(TableDescProto proto) {
-	  this.proto = proto;
-	  viaProto = true;
+	  this(proto.getId(), new TableMetaImpl(proto.getMeta()), new Path(proto.getPath()));
 	}
 	
 	public void setId(String tableId) {
-	  setModified();
 	  // tajo deems all identifiers as lowcase characters
 		this.tableId = tableId.toLowerCase();
 	}
 	
   public String getId() {
-    TableDescProtoOrBuilder p = viaProto ? proto : builder;
-    
-    if (tableId != null) {
-      return this.tableId;
-    }
-    if (!p.hasId()) {
-      return null;
-    }
-    this.tableId = p.getId();
-    
     return this.tableId;
   }
 	
 	public void setPath(Path uri) {
-	  setModified();
 		this.uri = uri;
 	}
 	
   public Path getPath() {
-    TableDescProtoOrBuilder p = viaProto ? proto : builder;
-    
-    if (uri != null) {
-      return this.uri;
-    }
-    if (!proto.hasPath()) {
-      return null;
-    }
-    this.uri = new Path(p.getPath());
-    
     return this.uri;
   }
   
   @Override
   public void setMeta(TableMeta info) {
-    setModified();
     this.meta = info;
   }
 	
 	public TableMeta getMeta() {
-	  TableDescProtoOrBuilder p = viaProto ? proto : builder;
-    
-    if (meta != null) {
-      return this.meta;
-    }
-    if (!p.hasMeta()) {
-      return null;
-    }
-    this.meta = new TableMetaImpl(p.getMeta());
 	  return this.meta;
 	}
 	
@@ -134,10 +97,7 @@ public class TableDescImpl implements TableDesc, ProtoObject<TableDescProto>,
 	
 	public Object clone() throws CloneNotSupportedException {	  
 	  TableDescImpl desc = (TableDescImpl) super.clone();
-	  initFromProto();
-	  desc.proto = null;
 	  desc.builder = TableDescProto.newBuilder();
-	  desc.viaProto = false;
 	  desc.tableId = tableId;
 	  desc.uri = uri;
 	  desc.meta = (TableMeta) meta.clone();
@@ -151,64 +111,23 @@ public class TableDescImpl implements TableDesc, ProtoObject<TableDescProto>,
     return gson.toJson(this);
 	}
 	
-	public String toJSON() {
-		initFromProto();
-		Gson gson = GsonCreator.getInstance();
-		
-		return gson.toJson(this, TableDesc.class);
+	public String toJson() {
+		return CatalogGsonHelper.toJson(this, TableDesc.class);
 	}
 
   public TableDescProto getProto() {
-    if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;
-    }
-    
-    return proto;
-  }
-  
-  private void setModified() {
-    if (viaProto && builder == null) {
-      builder = TableDescProto.newBuilder(proto);
-    }
-    viaProto = false;
-  }
-  
-  protected void mergeLocalToBuilder() {
     if (builder == null) {
-      builder = TableDescProto.newBuilder(proto);
+      builder = TableDescProto.newBuilder();
     }
-    
     if (this.tableId != null) {
       builder.setId(this.tableId);
     }
-    
     if (this.uri != null) {
       builder.setPath(this.uri.toString());
     }
-    
     if (this.meta != null) {
       builder.setMeta(meta.getProto());
     }
-  }
-  
-  private void mergeProtoToLocal() {
-	  TableDescProtoOrBuilder p = viaProto ? proto : builder;
-	  if (tableId == null && p.hasId()) {
-		  tableId = p.getId();
-	  }
-	  if (uri == null && p.hasPath()) {
-		  uri = new Path(p.getPath());
-	  }
-	  if (meta == null && p.hasMeta()) {
-		  meta = new TableMetaImpl(p.getMeta());
-	  }
-  }
-
-  @Override
-  public void initFromProto() {
-	  mergeProtoToLocal();
-    meta.initFromProto();
+    return builder.build();
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMeta.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMeta.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMeta.java
index 268e70c..184bd33 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMeta.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMeta.java
@@ -18,6 +18,7 @@
 
 package org.apache.tajo.catalog;
 
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableProto;
 import org.apache.tajo.catalog.statistics.TableStat;
@@ -26,7 +27,7 @@ import org.apache.tajo.common.ProtoObject;
 import java.util.Iterator;
 import java.util.Map.Entry;
 
-public interface TableMeta extends ProtoObject<TableProto>, Cloneable {
+public interface TableMeta extends ProtoObject<TableProto>, Cloneable, GsonObject {
   
   void setStorageType(StoreType storeType);
   
@@ -49,6 +50,4 @@ public interface TableMeta extends ProtoObject<TableProto>, Cloneable {
   TableStat getStat();
   
   Object clone() throws CloneNotSupportedException;
-  
-  public String toJSON();
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMetaImpl.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMetaImpl.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMetaImpl.java
index 8f6b9b6..e5d5a75 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMetaImpl.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableMetaImpl.java
@@ -22,28 +22,22 @@ import com.google.common.base.Objects;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.TableProtoOrBuilder;
 import org.apache.tajo.catalog.statistics.TableStat;
 
 import java.util.Iterator;
 import java.util.Map.Entry;
 
-public class TableMetaImpl implements TableMeta {
-	protected TableProto proto = TableProto.getDefaultInstance();
+public class TableMetaImpl implements TableMeta, GsonObject {
 	protected TableProto.Builder builder = null;
-	protected boolean viaProto = false;	
 	
-	@Expose
-	protected Schema schema;
-	@Expose
-	protected StoreType storeType;
-	@Expose
-	protected Options options;
-	@Expose
-	protected TableStat stat;
+	@Expose protected Schema schema;
+	@Expose protected StoreType storeType;
+	@Expose protected Options options;
+	@Expose	protected TableStat stat;
 	
 	private TableMetaImpl() {
 	  builder = TableProto.newBuilder();
@@ -66,86 +60,55 @@ public class TableMetaImpl implements TableMeta {
   }
 	
 	public TableMetaImpl(TableProto proto) {
-		this.proto = proto;
-		this.viaProto = true;
+    this();
+    schema = new Schema(proto.getSchema());
+    storeType = proto.getStoreType();
+    options = new Options(proto.getParams());
+
+    if (proto.hasStat() && stat == null) {
+      stat = new TableStat(proto.getStat());
+    }
 	}
 	
 	public void setStorageType(StoreType storeType) {
-    setModified();
     this.storeType = storeType;
   }	
 	
 	public StoreType getStoreType() {
-	  TableProtoOrBuilder p = viaProto ? proto : builder;
-		
-		if(storeType != null) {
-			return this.storeType;
-		}
-		if(!p.hasStoreType()) {
-			return null;
-		}
-		this.storeType = p.getStoreType();
-		
 		return this.storeType;		
 	}
 	
   public void setSchema(Schema schema) {
-    setModified();
     this.schema = schema;
   }
 	
 	public Schema getSchema() {
-		TableProtoOrBuilder p = viaProto ? proto : builder;
-		
-		if(schema != null) {
-			return this.schema;
-		}
-		if(!proto.hasSchema()) {
-		  return null;
-		}
-		this.schema = new Schema(p.getSchema());
-		
 		return this.schema;
 	}
 	
   public void setOptions(Options options) {
-    setModified();
     this.options = options;
   }
 
-  private Options initOptions() {
-    TableProtoOrBuilder p = viaProto ? proto : builder;
-    if(this.options != null) {
-      return this.options;
-    }
-    if(!p.hasParams()) {
-      return null;
-    }
-    this.options = new Options(p.getParams());
-    
-    return this.options;
-  }  
-
   @Override
   public void putOption(String key, String val) {
-    setModified();
-    initOptions().put(key, val);
+    options.put(key, val);
   }
   
 
   @Override
   public String getOption(String key) {    
-    return initOptions().get(key);
+    return options.get(key);
   }
 
   @Override
   public String getOption(String key, String defaultValue) {
-    return initOptions().get(key, defaultValue);
+    return options.get(key, defaultValue);
   }
   
   @Override
   public Iterator<Entry<String,String>> getOptions() {    
-    return initOptions().getAllKeyValus();
+    return options.getAllKeyValus();
   }
 	
 	public boolean equals(Object object) {
@@ -163,11 +126,8 @@ public class TableMetaImpl implements TableMeta {
 	}
 	
 	@Override
-	public Object clone() throws CloneNotSupportedException {    
-	  initFromProto();
-	  TableMetaImpl meta = (TableMetaImpl) super.clone();	  
-	  meta.proto = null;
-    meta.viaProto = false;
+	public Object clone() throws CloneNotSupportedException {
+	  TableMetaImpl meta = (TableMetaImpl) super.clone();
     meta.builder = TableProto.newBuilder();
     meta.schema = (Schema) schema.clone();
     meta.storeType = storeType;
@@ -188,93 +148,31 @@ public class TableMetaImpl implements TableMeta {
 	////////////////////////////////////////////////////////////////////////
 	@Override
 	public TableProto getProto() {
-	  if(!viaProto) {
-      mergeLocalToBuilder();
-      proto = builder.build();
-      viaProto = true;  
-    }
-		return proto;
-	}
-
-  private void setModified() {
-    if (viaProto || builder == null) {
-      builder = TableProto.newBuilder(proto);
-    }
-    this.viaProto = false;
-  }
-	
-	private void mergeLocalToBuilder() {
-    if (this.builder == null) {      
-      this.builder = TableProto.newBuilder(proto);
+    if (builder == null) {
+      builder = TableProto.newBuilder();
     }
-	  
-	  if (this.schema != null) {
-	    builder.setSchema(this.schema.getProto());
-	  }
-	  
-	  if (this.stat != null) {
-	    builder.setStat(this.stat.getProto());
-	  }
+    builder.setSchema(this.schema.getProto());
+    builder.setStoreType(storeType);
+    builder.setParams(options.getProto());
 
-	  if (this.storeType != null) {
-      builder.setStoreType(storeType);
+    if (this.stat != null) {
+      builder.setStat(this.stat.getProto());
     }
-
-		if (this.options != null) {
-		  builder.setParams(options.getProto());
-		}
-	}
-	
-  ////////////////////////////////////////////////////////////////////////
-  // For Json
-  ////////////////////////////////////////////////////////////////////////	
-	private void mergeProtoToLocal() {
-		TableProtoOrBuilder p = viaProto ? proto : builder;
-		if (schema == null) {
-			schema = new Schema(p.getSchema());
-		}
-		if (p.hasStat() && stat == null) {
-		  stat = new TableStat(p.getStat());
-		}
-		if (storeType == null && p.hasStoreType()) {
-			storeType = p.getStoreType();
-		}
-		if (options == null && p.hasParams()) {
-			options = new Options(p.getParams());
-		}
+    return builder.build();
 	}
-	
-	public void initFromProto() {
-		mergeProtoToLocal();
-    schema.initFromProto();
-    if (stat != null) {
-      stat.initFromProto();
-    }
-	}
-	
-	public String toJSON() {
-		initFromProto();
-		Gson gson = GsonCreator.getInstance();
-		return gson.toJson(this, TableMeta.class);
+
+  @Override
+	public String toJson() {
+		return CatalogGsonHelper.toJson(this, TableMeta.class);
 	}
 
   @Override
   public void setStat(TableStat stat) {
-    setModified();
     this.stat = stat;
   }
 
   @Override
   public TableStat getStat() {
-    TableProtoOrBuilder p = viaProto ? proto : builder;
-    if (stat != null) {
-      return stat;
-    }
-    if (!p.hasStat()) {
-      return null;
-    }
-    stat = new TableStat(p.getStat());
-    
     return this.stat;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/AggFunction.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/AggFunction.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/AggFunction.java
index d76a345..6eb6a8b 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/AggFunction.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/AggFunction.java
@@ -18,9 +18,8 @@
 
 package org.apache.tajo.catalog.function;
 
-import com.google.gson.Gson;
 import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.storage.Tuple;
@@ -45,8 +44,8 @@ public abstract class AggFunction<T extends Datum> extends Function<T> {
 
   public abstract T terminate(FunctionContext ctx);
 
-  public String toJSON() {
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, AggFunction.class);
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, AggFunction.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
index ff8bda0..6d3feff 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
@@ -19,14 +19,14 @@
 package org.apache.tajo.catalog.function;
 
 import com.google.common.base.Objects;
-import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.util.TUtil;
 
-public abstract class Function<T extends Datum> implements Cloneable {
+public abstract class Function<T extends Datum> implements Cloneable, GsonObject {
   @Expose protected Column[] definedParams;
   public final static Column [] NoArgs = new Column [] {};
 
@@ -55,8 +55,8 @@ public abstract class Function<T extends Datum> implements Cloneable {
     return func;
   }
 
-  public String toJSON() {
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, Function.class);
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, Function.class);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/GeneralFunction.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/GeneralFunction.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/GeneralFunction.java
index 9a9cb86..7f639ae 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/GeneralFunction.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/GeneralFunction.java
@@ -18,13 +18,13 @@
 
 package org.apache.tajo.catalog.function;
 
-import com.google.gson.Gson;
+import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.json.GsonCreator;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.storage.Tuple;
 
-public abstract class GeneralFunction<T extends Datum> extends Function<T> {
+public abstract class GeneralFunction<T extends Datum> extends Function<T> implements GsonObject {
   public GeneralFunction(Column[] definedArgs) {
     super(definedArgs);
   }
@@ -36,8 +36,8 @@ public abstract class GeneralFunction<T extends Datum> extends Function<T> {
 	  GENERAL
 	}
 
-  public String toJSON() {
-    Gson gson = GsonCreator.getInstance();
-    return gson.toJson(this, GeneralFunction.class);
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, GeneralFunction.class);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
new file mode 100644
index 0000000..a3e9e94
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.catalog.json;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.function.AggFunction;
+import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.catalog.function.GeneralFunction;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.json.*;
+import org.apache.tajo.util.TUtil;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class CatalogGsonHelper {
+  private static Gson gson;
+  private static Gson gsonPretty;
+
+  private CatalogGsonHelper() {
+  }
+
+  private static Map<Type, GsonSerDerAdapter> registerAdapters() {
+    Map<Type, GsonSerDerAdapter> adapters = TUtil.newHashMap();
+    adapters.put(Class.class, new ClassNameSerializer());
+    adapters.put(Path.class, new PathSerializer());
+    adapters.put(TableDesc.class, new TableDescAdapter());
+    adapters.put(TableMeta.class, new TableMetaAdapter());
+    adapters.put(Function.class, new FunctionAdapter());
+    adapters.put(GeneralFunction.class, new FunctionAdapter());
+    adapters.put(AggFunction.class, new FunctionAdapter());
+    adapters.put(Datum.class, new DatumAdapter());
+    adapters.put(DataType.class, new DataTypeAdapter());
+    return adapters;
+  }
+
+  public static Gson getInstance() {
+    if (gson == null ) {
+      GsonHelper helper = new GsonHelper(registerAdapters());
+      gson = helper.getGson();
+    }
+    return gson;
+  }
+
+  public static Gson getPrettyInstance() {
+    if (gsonPretty == null) {
+      GsonBuilder prettyBuilder = new GsonBuilder()
+          .setPrettyPrinting()
+          .excludeFieldsWithoutExposeAnnotation();
+      GsonHelper.registerAdapters(prettyBuilder, registerAdapters());
+      gsonPretty = prettyBuilder.create();
+    }
+
+    return gsonPretty;
+  }
+
+  public static String toJson(GsonObject object, Class<? extends GsonObject> clazz) {
+    return getInstance().toJson(object, clazz);
+  }
+
+  public static <T extends GsonObject> T fromJson(String json, Class<T> clazz) {
+    return getInstance().fromJson(json, clazz);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
index a5c03f6..4736631 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
@@ -20,10 +20,11 @@ package org.apache.tajo.catalog.json;
 
 import com.google.gson.*;
 import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;
 
-public class FunctionAdapter implements JsonDeserializer<Function>, JsonSerializer<Function> {
+public class FunctionAdapter implements GsonSerDerAdapter<Function> {
 
   @Override
   public JsonElement serialize(Function src, Type typeOfSrc,

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/GsonCreator.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/GsonCreator.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/GsonCreator.java
deleted file mode 100644
index 9c56bcd..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/GsonCreator.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.json;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.TableMeta;
-import org.apache.tajo.catalog.function.AggFunction;
-import org.apache.tajo.catalog.function.Function;
-import org.apache.tajo.catalog.function.GeneralFunction;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.datum.Datum;
-import org.apache.tajo.datum.json.DatumAdapter;
-import org.apache.tajo.gson.ClassNameDeserializer;
-import org.apache.tajo.gson.ClassNameSerializer;
-import org.apache.tajo.gson.DataTypeAdapter;
-
-public class GsonCreator {
-	private static GsonBuilder builder;
-	private static Gson gson;
-	
-	private static void init() {
-		if (builder == null) {
-			builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
-      builder.registerTypeAdapter(Class.class, new ClassNameSerializer());
-      builder.registerTypeAdapter(Class.class, new ClassNameDeserializer());
-			builder.registerTypeAdapter(Path.class, new PathSerializer());
-			builder.registerTypeAdapter(Path.class, new PathDeserializer());
-			builder.registerTypeAdapter(TableDesc.class, new TableDescAdapter());
-			builder.registerTypeAdapter(TableMeta.class, new TableMetaAdapter());
-			builder.registerTypeAdapter(Function.class, new FunctionAdapter());
-      builder.registerTypeAdapter(GeneralFunction.class, new FunctionAdapter());
-      builder.registerTypeAdapter(AggFunction.class, new FunctionAdapter());
-			builder.registerTypeAdapter(Datum.class, new DatumAdapter());
-      builder.registerTypeAdapter(DataType.class, new DataTypeAdapter());
-		}
-	}
-
-	public static Gson getInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.create();
-	  }
-	  return gson;
-	}
-
-	public static Gson getPrettyInstance() {
-	  init();
-	  if (gson == null ) {
-	    gson = builder.setPrettyPrinting().create();
-	  }
-	  return gson;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathDeserializer.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathDeserializer.java
deleted file mode 100644
index a5d6477..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathDeserializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.json;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import org.apache.hadoop.fs.Path;
-
-import java.lang.reflect.Type;
-
-public class PathDeserializer implements JsonDeserializer<Path> {
-
-	@Override
-	public Path deserialize(JsonElement arg0, Type arg1,
-			JsonDeserializationContext arg2) throws JsonParseException {
-		return new Path(arg0.getAsJsonPrimitive().getAsString());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathSerializer.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathSerializer.java
deleted file mode 100644
index e589195..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/PathSerializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.json;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import org.apache.hadoop.fs.Path;
-
-import java.lang.reflect.Type;
-
-public class PathSerializer implements JsonSerializer<Path> {
-
-	@Override
-	public JsonElement serialize(Path arg0, Type arg1,
-			JsonSerializationContext arg2) {
-		return new JsonPrimitive(arg0.toString());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableDescAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableDescAdapter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableDescAdapter.java
index 8c63043..e34ef61 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableDescAdapter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableDescAdapter.java
@@ -20,10 +20,11 @@ package org.apache.tajo.catalog.json;
 
 import com.google.gson.*;
 import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;
 
-public class TableDescAdapter implements JsonSerializer<TableDesc>, JsonDeserializer<TableDesc> {
+public class TableDescAdapter implements GsonSerDerAdapter<TableDesc> {
 
 	@Override
 	public TableDesc deserialize(JsonElement json, Type type,
@@ -31,7 +32,7 @@ public class TableDescAdapter implements JsonSerializer<TableDesc>, JsonDeserial
 		JsonObject jsonObject = json.getAsJsonObject();
 		String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
 		
-		Class clazz = null;
+		Class clazz;
 		try {
 			clazz = Class.forName(className);
 		} catch (ClassNotFoundException e) {
@@ -48,12 +49,8 @@ public class TableDescAdapter implements JsonSerializer<TableDesc>, JsonDeserial
 		String className = src.getClass().getCanonicalName();
 		jsonObj.addProperty("classname", className);
 
-		if (src.getClass().getSimpleName().equals("TableDescImpl")) {
-			src.initFromProto();
-		}
 		JsonElement jsonElem = context.serialize(src);
 		jsonObj.add("property", jsonElem);
 		return jsonObj;
 	}
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/1c677cc5/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableMetaAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableMetaAdapter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableMetaAdapter.java
index 9c50897..f8c02e2 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableMetaAdapter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/TableMetaAdapter.java
@@ -20,10 +20,11 @@ package org.apache.tajo.catalog.json;
 
 import com.google.gson.*;
 import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;
 
-public class TableMetaAdapter implements JsonSerializer<TableMeta>, JsonDeserializer<TableMeta> {
+public class TableMetaAdapter implements GsonSerDerAdapter<TableMeta> {
 
 	@Override
 	public TableMeta deserialize(JsonElement json, Type typeOfT,
@@ -31,7 +32,7 @@ public class TableMetaAdapter implements JsonSerializer<TableMeta>, JsonDeserial
 		JsonObject jsonObject = json.getAsJsonObject();
 		String className = jsonObject.get("classname").getAsJsonPrimitive().getAsString();
 		
-		Class clazz = null;
+		Class clazz;
 		try {
 			clazz = Class.forName(className);
 		} catch (ClassNotFoundException e) {
@@ -44,7 +45,6 @@ public class TableMetaAdapter implements JsonSerializer<TableMeta>, JsonDeserial
 	@Override
 	public JsonElement serialize(TableMeta src, Type typeOfSrc,
 			JsonSerializationContext context) {
-		src.initFromProto();
 		JsonObject jsonObj = new JsonObject();
 		String className = src.getClass().getCanonicalName();
 		jsonObj.addProperty("classname", className);