You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ni...@apache.org on 2017/01/03 11:43:20 UTC

[15/20] ambari git commit: AMBARI-19321 : Hive View 2.0 - Minimal view for Hive which includes new UI changes. Also made changes in poms as required (nitirajrathore)

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/DetailedTableInfoParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/DetailedTableInfoParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/DetailedTableInfoParser.java
new file mode 100644
index 0000000..b526789
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/DetailedTableInfoParser.java
@@ -0,0 +1,71 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+import org.apache.ambari.view.hive20.internal.dto.DetailedTableInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class DetailedTableInfoParser extends AbstractTableMetaParser<DetailedTableInfo> {
+  /*
+    | # Detailed Table Information  | NULL                                                                 | NULL                                                                                                                                                                                                                                                              |
+    | Database:                     | default                                                              | NULL                                                                                                                                                                                                                                                              |
+    | Owner:                        | admin                                                                | NULL                                                                                                                                                                                                                                                              |
+    | CreateTime:                   | Mon Aug 01 13:28:42 UTC 2016                                         | NULL                                                                                                                                                                                                                                                              |
+    | LastAccessTime:               | UNKNOWN                                                              | NULL                                                                                                                                                                                                                                                              |
+    | Protect Mode:                 | None                                                                 | NULL                                                                                                                                                                                                                                                              |
+    | Retention:                    | 0                                                                    | NULL                                                                                                                                                                                                                                                              |
+    | Location:                     | hdfs://c6401.ambari.apache.org:8020/apps/hive/warehouse/geolocation  | NULL                                                                                                                                                                                                                                                              |
+    | Table Type:                   | MANAGED_TABLE                                                        | NULL                                                                                                                                                                                                                                                              |
+    | Table Parameters:             | NULL                                                                 | NULL                                                                                                                                                                                                                                                              |
+    |                               | COLUMN_STATS_ACCURATE                                                | {\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"column1\":\"true\",\"column2\":\"true\",\"column3\":\"true\",\"column4\":\"true\",\"column5\":\"true\",\"column6\":\"true\",\"column7\":\"true\",\"column8\":\"true\",\"column9\":\"true\",\"column10\":\"true\"}}  |
+    |                               | numFiles                                                             | 1                                                                                                                                                                                                                                                                 |
+    |                               | numRows                                                              | 8001                                                                                                                                                                                                                                                              |
+    |                               | rawDataSize                                                          | 7104888                                                                                                                                                                                                                                                           |
+    |                               | totalSize                                                            | 43236                                                                                                                                                                                                                                                             |
+    |                               | transient_lastDdlTime                                                | 1479819460                                                                                                                                                                                                                                                        |
+    |                               | NULL                                                                 | NULL                                                                                                                                                                                                                                                              |
+   */
+  public DetailedTableInfoParser() {
+    super("# Detailed Table Information", null, "");
+  }
+
+  @Override
+  public DetailedTableInfo parse(List<Row> rows) {
+    DetailedTableInfo info = new DetailedTableInfo();
+    Map<String, Object> parsedSection = parseSection(rows);
+    info.setDbName(getString(parsedSection, "Database:"));
+    info.setOwner(getString(parsedSection, "Owner:"));
+    info.setCreateTime(getString(parsedSection, "CreateTime:"));
+    info.setLastAccessTime(getString(parsedSection, "LastAccessTime:"));
+    info.setRetention(getString(parsedSection, "Retention:"));
+    info.setLocation(getString(parsedSection, "Location:"));
+    info.setTableType(getString(parsedSection, "Table Type:"));
+
+    info.setParameters(getMap(parsedSection, "Table Parameters:"));
+
+    return info;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ParserUtils.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ParserUtils.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ParserUtils.java
new file mode 100644
index 0000000..b4adf5c
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ParserUtils.java
@@ -0,0 +1,52 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.apache.ambari.view.hive20.internal.parsers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ParserUtils {
+
+  public static final String DATA_TYPE_REGEX = "\\s*([^() ]+)\\s*(\\s*\\(\\s*([0-9]+)\\s*(\\s*,\\s*([0-9]+))?\\s*\\)\\s*)?\\s*";
+
+  /**
+   * @param columnDataTypeString : the string that needs to be parsed as a datatype example : decimal(10,3)
+   * @return a list of string containing type, precision and scale in that order if present, null otherwise
+   */
+  public static List<String> parseColumnDataType(String columnDataTypeString) {
+    List<String> typePrecisionScale = new ArrayList<>(3);
+
+    Pattern pattern = Pattern.compile(DATA_TYPE_REGEX);
+    Matcher matcher = pattern.matcher(columnDataTypeString);
+
+    if (matcher.find()) {
+      typePrecisionScale.add(matcher.group(1));
+      typePrecisionScale.add(matcher.group(3));
+      typePrecisionScale.add(matcher.group(5));
+    }else{
+      typePrecisionScale.add(null);
+      typePrecisionScale.add(null);
+      typePrecisionScale.add(null);
+    }
+
+    return typePrecisionScale;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/PartitionInfoParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/PartitionInfoParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/PartitionInfoParser.java
new file mode 100644
index 0000000..fbcb6e8
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/PartitionInfoParser.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+import org.apache.ambari.view.hive20.internal.dto.ColumnInfo;
+import org.apache.ambari.view.hive20.internal.dto.PartitionInfo;
+import org.apache.parquet.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class PartitionInfoParser extends AbstractTableMetaParser<PartitionInfo> {
+  private static final Logger LOG = LoggerFactory.getLogger(PartitionInfoParser.class);
+
+  /*
+      General format
+      | # Partition Information       | NULL                                                                          | NULL                         |
+      | # col_name                    | data_type                                                                     | comment                      |
+      |                               | NULL                                                                          | NULL                         |
+      | dt                            | string                                                                        |                              |
+      | country                       | string                                                                        |                              |
+      |                               | NULL                                                                          | NULL                         |
+     */
+
+  public PartitionInfoParser() {
+    super("# Partition Information", "# col_name", "", "");
+  }
+
+  @Override
+  public PartitionInfo parse(List<Row> rows) {
+    List<ColumnInfo> columns = new ArrayList<>();
+
+
+    Map<String, Object> parsedSection = parseSection(rows);
+    for(Object obj: parsedSection.values()) {
+      if(obj instanceof Entry) {
+        Entry entry = (Entry)obj;
+        String typeInfo = entry.getValue();
+        // parse precision and scale
+        List<String> typePrecisionScale = ParserUtils.parseColumnDataType(typeInfo);
+        String datatype = typePrecisionScale.get(0);
+        String precisionString = typePrecisionScale.get(1);
+        String scaleString = typePrecisionScale.get(2);
+        Integer precision = !Strings.isNullOrEmpty(precisionString) ? Integer.valueOf(precisionString.trim()): null;
+        Integer scale = !Strings.isNullOrEmpty(scaleString) ? Integer.valueOf(scaleString.trim()): null;
+        ColumnInfo columnInfo = new ColumnInfo(entry.getName(), datatype, precision, scale, entry.getComment());
+        columns.add(columnInfo);
+        LOG.debug("found partition column definition : {}", columnInfo);
+      }
+    }
+    return columns.size() > 0? new PartitionInfo(columns) : null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/StorageInfoParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/StorageInfoParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/StorageInfoParser.java
new file mode 100644
index 0000000..09fcfd0
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/StorageInfoParser.java
@@ -0,0 +1,100 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.view.hive20.client.Row;
+import org.apache.ambari.view.hive20.internal.dto.ColumnOrder;
+import org.apache.ambari.view.hive20.internal.dto.Order;
+import org.apache.ambari.view.hive20.internal.dto.StorageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Parses the Storage Information from the describe formatted output.
+ */
+public class StorageInfoParser extends AbstractTableMetaParser<StorageInfo> {
+  private static final Logger LOG = LoggerFactory.getLogger(StorageInfoParser.class);
+
+
+  public StorageInfoParser() {
+    super("# Storage Information", null, "");
+  }
+
+  @Override
+  public StorageInfo parse(List<Row> rows) {
+    StorageInfo info = new StorageInfo();
+    Map<String, Object> parsedSection = parseSection(rows);
+
+    info.setSerdeLibrary(getString(parsedSection, "SerDe Library:"));
+    info.setInputFormat(getString(parsedSection, "InputFormat:"));
+    info.setOutputFormat(getString(parsedSection, "OutputFormat:"));
+    info.setCompressed(getString(parsedSection, "Compressed:"));
+    info.setNumBuckets(getString(parsedSection, "Num Buckets:"));
+    info.setBucketCols(parseBucketColumns(getString(parsedSection, "Bucket Columns:")));
+    info.setSortCols(parseSortCols(getString(parsedSection, "Sort Columns:")));
+    info.setParameters(getMap(parsedSection, "Storage Desc Params:"));
+
+    return info;
+  }
+
+  private List<String> parseBucketColumns(String string) {
+    String[] strings = string.split("[\\[\\],]");
+    return FluentIterable.from(Arrays.asList(strings)).filter(new Predicate<String>() {
+      @Override
+      public boolean apply(@Nullable String input) {
+        return !(null == input || input.trim().length() == 0) ;
+      }
+    }).transform(new Function<String, String>() {
+      @Override
+      public String apply(String input) {
+        return input.trim();
+      }
+    }).toList();
+  }
+
+  private List<ColumnOrder> parseSortCols(String str) {
+    String patternStr = "Order\\s*\\(\\s*col\\s*:\\s*([^,]+)\\s*,\\s*order\\s*:\\s*(\\d)\\s*\\)";
+    Pattern pattern = Pattern.compile(patternStr);
+
+    Matcher matcher = pattern.matcher(str);
+
+    LinkedList<ColumnOrder> list = new LinkedList<>();
+    while(matcher.find()){
+      String colName = matcher.group(1);
+      String orderString = matcher.group(2);
+      Order order = Order.fromOrdinal(Integer.valueOf(orderString));
+      ColumnOrder co = new ColumnOrder(colName, order);
+      list.add(co);
+      LOG.debug("columnOrder : {}", co);
+    }
+
+    return list;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParser.java
new file mode 100644
index 0000000..aae23c8
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParser.java
@@ -0,0 +1,30 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+
+import java.util.List;
+
+/**
+ *
+ */
+public interface TableMetaParser<T> {
+  T parse(String database, String table, List<Row> createTableStatementRows, List<Row> describeFormattedRows);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParserImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParserImpl.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParserImpl.java
new file mode 100644
index 0000000..5cae34a
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaParserImpl.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+import org.apache.ambari.view.hive20.internal.dto.ColumnInfo;
+import org.apache.ambari.view.hive20.internal.dto.DetailedTableInfo;
+import org.apache.ambari.view.hive20.internal.dto.PartitionInfo;
+import org.apache.ambari.view.hive20.internal.dto.StorageInfo;
+import org.apache.ambari.view.hive20.internal.dto.TableMeta;
+import org.apache.ambari.view.hive20.internal.dto.ViewInfo;
+
+import javax.inject.Inject;
+import java.util.List;
+
+/**
+ *
+ */
+public class TableMetaParserImpl implements TableMetaParser<TableMeta> {
+
+  @Inject
+  private CreateTableStatementParser createTableStatementParser;
+
+  @Inject
+  private ColumnInfoParser columnInfoParser;
+
+  @Inject
+  private PartitionInfoParser partitionInfoParser;
+
+  @Inject
+  private DetailedTableInfoParser detailedTableInfoParser;
+
+  @Inject
+  private StorageInfoParser storageInfoParser;
+
+  @Inject
+  private ViewInfoParser viewInfoParser;
+
+
+
+  @Override
+  public TableMeta parse(String database, String table, List<Row> createTableStatementRows, List<Row> describeFormattedRows) {
+    String createTableStatement = createTableStatementParser.parse(createTableStatementRows);
+    DetailedTableInfo tableInfo = detailedTableInfoParser.parse(describeFormattedRows);
+    StorageInfo storageInfo = storageInfoParser.parse(describeFormattedRows);
+    List<ColumnInfo> columns = columnInfoParser.parse(describeFormattedRows);
+    PartitionInfo partitionInfo = partitionInfoParser.parse(describeFormattedRows);
+    ViewInfo viewInfo = viewInfoParser.parse(describeFormattedRows);
+
+
+    TableMeta meta = new TableMeta();
+    meta.setId(database + "/" + table);
+    meta.setDatabase(database);
+    meta.setTable(table);
+    meta.setColumns(columns);
+    meta.setDdl(createTableStatement);
+    meta.setPartitionInfo(partitionInfo);
+    meta.setDetailedInfo(tableInfo);
+    meta.setStorageInfo(storageInfo);
+    meta.setViewInfo(viewInfo);
+    return meta;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaSectionParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaSectionParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaSectionParser.java
new file mode 100644
index 0000000..7d5e170
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/TableMetaSectionParser.java
@@ -0,0 +1,30 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+
+import java.util.List;
+
+/**
+ *
+ */
+public interface TableMetaSectionParser<T> {
+  T parse(List<Row> rows);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ViewInfoParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ViewInfoParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ViewInfoParser.java
new file mode 100644
index 0000000..ba0b069
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/parsers/ViewInfoParser.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ambari.view.hive20.internal.parsers;
+
+import org.apache.ambari.view.hive20.client.Row;
+import org.apache.ambari.view.hive20.internal.dto.ViewInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Parses the view Information from the describe formatted output.
+ */
+public class ViewInfoParser extends AbstractTableMetaParser<ViewInfo>{
+
+  public ViewInfoParser() {
+    super("# View Information", null, "");
+  }
+
+  @Override
+  public ViewInfo parse(List<Row> rows) {
+    ViewInfo info = new ViewInfo();
+    Map<String, Object> parsedSection = parseSection(rows);
+    if(parsedSection.size() == 0) {
+      return null; // View Information is not present
+    }
+    info.setOriginalText(getString(parsedSection, "View Original Text:"));
+    info.setExtendedText(getString(parsedSection, "View Expanded Text:"));
+    return info;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/AlterTableQueryGenerator.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/AlterTableQueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/AlterTableQueryGenerator.java
new file mode 100644
index 0000000..73f8266
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/AlterTableQueryGenerator.java
@@ -0,0 +1,365 @@
+/*
+* 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.ambari.view.hive20.internal.query.generators;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.view.hive20.internal.dto.ColumnInfo;
+import org.apache.ambari.view.hive20.internal.dto.ColumnOrder;
+import org.apache.ambari.view.hive20.internal.dto.TableMeta;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.ambari.view.hive20.internal.query.generators.QueryGenerationUtils.isNullOrEmpty;
+
+public class AlterTableQueryGenerator implements QueryGenerator {
+  private static final Logger LOG = LoggerFactory.getLogger(AlterTableQueryGenerator.class);
+
+  private final TableMeta oldMeta;
+  private final TableMeta newMeta;
+
+  public AlterTableQueryGenerator(TableMeta oldMeta, TableMeta newMeta) {
+    this.oldMeta = oldMeta;
+    this.newMeta = newMeta;
+  }
+
+  public TableMeta getOldMeta() {
+    return oldMeta;
+  }
+
+  public TableMeta getNewMeta() {
+    return newMeta;
+  }
+
+  public String getQueryPerfix() {
+    return new StringBuffer(" ALTER TABLE ")
+      .append("`").append(this.getOldMeta().getDatabase()).append(".").append(this.getOldMeta().getTable().trim()).append("` ").toString();
+  }
+
+  public Optional<String> getQuery() {
+    List<Optional<String>> queries = new LinkedList<>();
+
+    // TODO: rename of table name has to be handled separately as other queries depend on new name.
+//    Optional<String> tableRenameQuery = this.generateTableRenameQuery(this.getOldMeta().getDatabase(),
+//      this.getOldMeta().getTable(), this.getNewMeta().getDatabase(), this.getNewMeta().getTable());
+//    queries.add(tableRenameQuery);
+
+    Optional<List<Optional<String>>> columnQuery = this.generateColumnQuery();
+    if (columnQuery.isPresent()) {
+      queries.addAll(columnQuery.get());
+    }
+
+    if (null != this.getNewMeta().getDetailedInfo() && null != this.getNewMeta().getDetailedInfo()) {
+      Optional<String> tablePropertiesQuery = this.generateTablePropertiesQuery(this.getOldMeta().getDetailedInfo().getParameters(),
+        this.getNewMeta().getDetailedInfo().getParameters());
+      queries.add(tablePropertiesQuery);
+    }
+
+    if (null != this.getOldMeta().getStorageInfo() && null != this.getNewMeta().getStorageInfo()) {
+      String oldSerde = this.getOldMeta().getStorageInfo().getSerdeLibrary();
+      String newSerde = this.getNewMeta().getStorageInfo().getSerdeLibrary();
+      Map<String, String> oldParameters = this.getOldMeta().getStorageInfo().getParameters();
+      Map<String, String> newParameters = this.getNewMeta().getStorageInfo().getParameters();
+
+      Optional<String> serdeProperties = this.generateSerdeQuery(oldSerde, oldParameters, newSerde, newParameters);
+      queries.add(serdeProperties);
+    }
+
+    if (null != this.getOldMeta().getStorageInfo() && null != this.getNewMeta().getStorageInfo()) {
+      List<String> oldBucketCols = this.getOldMeta().getStorageInfo().getBucketCols();
+      List<ColumnOrder> oldSortCols = this.getOldMeta().getStorageInfo().getSortCols();
+      String oldNumBuckets = this.getOldMeta().getStorageInfo().getNumBuckets();
+
+      List<String> newBucketCols = this.getNewMeta().getStorageInfo().getBucketCols();
+      List<ColumnOrder> newSortCols = this.getNewMeta().getStorageInfo().getSortCols();
+      String newNumBuckets = this.getNewMeta().getStorageInfo().getNumBuckets();
+
+      Optional<String> storagePropertyQuery = this.generateStoragePropertyQuery(oldBucketCols, oldSortCols, oldNumBuckets, newBucketCols, newSortCols, newNumBuckets);
+      queries.add(storagePropertyQuery);
+    }
+
+
+    List<String> queryList = FluentIterable.from(queries).filter(new Predicate<Optional<String>>() {
+      @Override
+      public boolean apply(Optional<String> input) {
+        return input.isPresent();
+      }
+    }).transform(new Function<Optional<String>, String>() {
+      @Override
+      public String apply(Optional<String> input) {
+          return input.get();
+      }
+    }).toList();
+
+    if (!queryList.isEmpty()) {
+      return Optional.of(Joiner.on(";\n").join(queryList));
+    } else {
+      return Optional.absent();
+    }
+
+  }
+
+  Optional<List<Optional<String>>> generateColumnQuery() {
+    List<ColumnInfo> oldColumns = this.getOldMeta().getColumns();
+    List<ColumnInfo> newColumns = this.getNewMeta().getColumns();
+    boolean cascade = null != this.getNewMeta().getPartitionInfo() && !isNullOrEmpty(this.getNewMeta().getPartitionInfo().getColumns());
+    Optional<List<String>> queries = createColumnQueries(oldColumns, newColumns, cascade);
+    if (queries.isPresent()) {
+      List<Optional<String>> queryList = FluentIterable.from(queries.get()).transform(new Function<String, Optional<String>>() {
+        @Override
+        public Optional<String> apply(String input) {
+          return Optional.of(getQueryPerfix() + input);
+        }
+      }).toList();
+      return Optional.of(queryList);
+    } else {
+      return Optional.absent();
+    }
+  }
+
+  /**
+   * TODO : this uses CASCADE. confirm that it is expected.
+   * ALTER TABLE table_name [PARTITION partition_spec] CHANGE [COLUMN] col_old_name col_new_name column_type
+   * [COMMENT col_comment] [FIRST|AFTER column_name] [CASCADE|RESTRICT];
+   * <p>
+   * ALTER TABLE table_name
+   * [PARTITION partition_spec]                 -- (Note: Hive 0.14.0 and later)
+   * ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
+   * [CASCADE|RESTRICT]                         -- (Note: Hive 0.15.0 and later)
+   *
+   * @param oldColumns
+   * @param newColumns
+   * @return
+   */
+  static Optional<List<String>> createColumnQueries(List<ColumnInfo> oldColumns, List<ColumnInfo> newColumns, boolean cascade) {
+    if (isNullOrEmpty(oldColumns) || isNullOrEmpty(newColumns)) {
+      LOG.error("oldColumns = {} or newColumns = {} was null.", oldColumns, newColumns);
+      throw new IllegalArgumentException("Old or new columns cannot be empty.");
+    }
+
+    //TODO : removing columns not allowed right now. handle this later using REPLACE for native serde or error.
+    if (oldColumns.size() > newColumns.size()) {
+      LOG.error("removing columns from hive table is not supported yet.");
+      throw new IllegalArgumentException("removing columns is not allowed.");
+    }
+
+    List<String> queries = new LinkedList<>();
+    int i = 0;
+    boolean foundChange = false;
+    for (; i < oldColumns.size(); i++) {
+      ColumnInfo oldColumn = oldColumns.get(i);
+      ColumnInfo newColumn = newColumns.get(i);
+
+      if (!oldColumn.equals(newColumn)) {
+        foundChange = true;
+        StringBuilder queryBuilder = new StringBuilder();
+        queryBuilder.append(" CHANGE COLUMN `").append(oldColumn.getName()).append("` ")
+          .append(QueryGenerationUtils.getColumnRepresentation(newColumn));
+
+          if(cascade){
+            queryBuilder.append(" CASCADE");
+          }
+
+        queries.add(queryBuilder.toString());
+      }
+    }
+
+    if (i < newColumns.size()) {
+      StringBuilder queryBuilder = new StringBuilder();
+      queryBuilder.append(" ADD COLUMNS ( ");
+      boolean first = true;
+      for (; i < newColumns.size(); i++) {
+        foundChange = true;
+        ColumnInfo columnInfo = newColumns.get(i);
+        if (!first) {
+          queryBuilder.append(", ");
+        } else {
+          first = false;
+        }
+
+        queryBuilder.append(QueryGenerationUtils.getColumnRepresentation(columnInfo));
+      }
+      queryBuilder.append(" )");
+
+      if(cascade){
+        queryBuilder.append(" CASCADE");
+      }
+
+      queries.add(queryBuilder.toString());
+    }
+
+    if (foundChange) {
+      return Optional.of(queries);
+    } else {
+      return Optional.absent();
+    }
+  }
+
+  Optional<String> generateStoragePropertyQuery(List<String> oldBucketCols, List<ColumnOrder> oldSortCols, String oldNumBuckets, List<String> newBucketCols, List<ColumnOrder> newSortCols, String newNumBuckets) {
+    Optional<String> query = createStoragePropertyQuery(oldBucketCols, oldSortCols, oldNumBuckets, newBucketCols, newSortCols, newNumBuckets);
+    if (query.isPresent()) return Optional.of(getQueryPerfix() + query.get());
+    else return Optional.absent();
+  }
+
+  /**
+   * ALTER TABLE table_name CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name, ...)]
+   * INTO num_buckets BUCKETS;
+   *
+   * @param oldBucketCols
+   * @param oldSortCols
+   * @param oldNumBuckets
+   * @param newBucketCols
+   * @param newSortCols
+   * @param newNumBuckets
+   * @return
+   */
+  static Optional<String> createStoragePropertyQuery(List<String> oldBucketCols, List<ColumnOrder> oldSortCols, String oldNumBuckets, List<String> newBucketCols, List<ColumnOrder> newSortCols, String newNumBuckets) {
+    StringBuilder queryBuilder = new StringBuilder();
+    boolean foundDiff = false;
+
+    if (isNullOrEmpty(newBucketCols)) {
+      if (!isNullOrEmpty(oldBucketCols)) {
+        // TODO : all cols removed. how to handle this. Ignoring
+        LOG.error("cannot handle removal of all the columns from buckets.");
+        throw new IllegalArgumentException("removing all columns from CLUSTERED BY not allowed.");
+      } else {
+        // NOTHING ADDED to CLUSTERED BY.
+        return Optional.absent();
+      }
+    } else {
+      queryBuilder.append(" CLUSTERED BY ( ").append(Joiner.on(",").join(newBucketCols)).append(" ) ");
+    }
+
+    if (!isNullOrEmpty(newSortCols)) {
+      queryBuilder.append(" SORTED BY ( ")
+        .append(Joiner.on(",").join(FluentIterable.from(newSortCols).transform(new Function<ColumnOrder, String>() {
+          @Nullable
+          @Override
+          public String apply(@Nullable ColumnOrder input) {
+            return input.getColumnName() + " " + input.getOrder().name();
+          }
+        })))
+        .append(" ) ");
+    }
+
+    if (Strings.isNullOrEmpty(newNumBuckets)) {
+      LOG.error("Number of buckets cannot be empty if CLUSTERED BY is mentioned.");
+      throw new IllegalArgumentException("Number of buckets cannot be empty.");
+    } else {
+      queryBuilder.append(" INTO ").append(newNumBuckets).append(" BUCKETS ");
+    }
+
+    return Optional.of(queryBuilder.toString());
+  }
+
+  Optional<String> generateSerdeQuery(String oldSerde, Map<String, String> oldParameters, String newSerde, Map<String, String> newParameters) {
+    Optional<String> query = createSerdeQuery(oldSerde, oldParameters, newSerde, newParameters);
+    if (query.isPresent()) return Optional.of(getQueryPerfix() + query.get());
+    else return Optional.absent();
+  }
+
+  /**
+   * assuming that getStorageInfo().getParameters() gives only serde properties
+   *
+   * @return
+   */
+  static Optional<String> createSerdeQuery(String oldSerde, Map<String, String> oldParameters, String newSerde, Map<String, String> newParameters) {
+    String query = "";
+    boolean serdeChanged = false;
+    if (null != newSerde) {
+      serdeChanged = !newSerde.equals(oldSerde);
+      query += " SET SERDE " + newSerde + " ";
+    }
+    Optional<Map<String, Map<Object, Object>>> diff = QueryGenerationUtils.findDiff(oldParameters, newParameters);
+    if (diff.isPresent()) {
+      Map<String, Map<Object, Object>> diffMap = diff.get();
+      Map<Object, Object> added = diffMap.get(QueryGenerationUtils.ADDED);
+      Map<Object, Object> modified = diffMap.get(QueryGenerationUtils.MODIFIED);
+      Map<Object, Object> deleted = diffMap.get(QueryGenerationUtils.DELETED);
+
+      // TODO : how to handle deleted? actually I cannot find anything in hive alter table that will remove existing property
+      Map addedOrModified = new HashMap<>(added);
+      addedOrModified.putAll(modified);
+
+      if (serdeChanged) {
+        query += " WITH SERDEPROPERTIES ";
+      } else {
+        query += " SET SERDEPROPERTIES ";
+      }
+      query += " ( " + QueryGenerationUtils.getPropertiesAsKeyValues(addedOrModified) + " ) ";
+    }
+
+    if (!query.trim().isEmpty()) {
+      return Optional.of(query);
+    }
+
+    return Optional.absent();
+  }
+
+  Optional<String> generateTablePropertiesQuery(Map oldProps, Map newProps) {
+    Optional<String> query = createTablePropertiesQuery(oldProps, newProps);
+    if (query.isPresent()) return Optional.of(getQueryPerfix() + query.get());
+    else return Optional.absent();
+  }
+
+
+  static Optional<String> createTablePropertiesQuery(Map oldProps, Map newProps) {
+    if (null == newProps) {
+      newProps = new HashMap();
+    }
+// TODO ignore system generated table properties during comparison
+    if (!QueryGenerationUtils.isEqual(oldProps, newProps)) {
+      return Optional.of(" SET TBLPROPERTIES (" + QueryGenerationUtils.getPropertiesAsKeyValues(newProps) + ")");
+    }
+
+    return Optional.absent();
+  }
+
+  Optional<String> generateTableRenameQuery(String oldDatabaseName, String oldTableName, String newDatabaseName, String newTableName) {
+    Optional<String> query = createTableRenameQuery(oldDatabaseName, oldTableName, newDatabaseName, newTableName);
+    if (query.isPresent()) return Optional.of(getQueryPerfix() + query.get());
+    else return Optional.absent();
+  }
+
+  static Optional<String> createTableRenameQuery(String oldDatabaseName, String oldTableName, String newDatabaseName, String newTableName) {
+    if (Strings.isNullOrEmpty(oldTableName) || Strings.isNullOrEmpty(newTableName)) {
+      LOG.error("oldTableName or newTableName is empty : {}, {} ", oldTableName, newTableName);
+      throw new IllegalArgumentException("oldTableName and newTableName both should be non empty.");
+    }
+
+    String oldName = (null != oldDatabaseName ? oldDatabaseName.trim() + "." : "") + oldTableName.trim();
+    String newName = (null != newDatabaseName ? newDatabaseName.trim() + "." : "") + newTableName.trim();
+
+    if (!oldName.equals(newName)) {
+      return Optional.of(" RENAME TO " + newName);
+    }
+
+    return Optional.absent();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateTableQueryGenerator.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateTableQueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateTableQueryGenerator.java
new file mode 100644
index 0000000..eab3a4b
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateTableQueryGenerator.java
@@ -0,0 +1,165 @@
+/*
+* 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.ambari.view.hive20.internal.query.generators;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.view.hive20.internal.dto.ColumnInfo;
+import org.apache.ambari.view.hive20.internal.dto.ColumnOrder;
+import org.apache.ambari.view.hive20.internal.dto.TableMeta;
+
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+
+public class CreateTableQueryGenerator implements QueryGenerator{
+  private static final String COMMENT = "COMMENT";
+  public static final String ESCAPE_DELIM = "escape.delim";
+  public static final String FIELD_DELIM = "field.delim";
+  public static final String COLELCTION_DELIM = "colelction.delim";
+  public static final String MAPKEY_DELIM = "mapkey.delim";
+  public static final String LINE_DELIM = "line.delim";
+  public static final String SERIALIZATION_NULL_FORMAT = "serialization.null.format";
+  private TableMeta tableMeta;
+  public CreateTableQueryGenerator(TableMeta tableMeta) {
+    this.tableMeta = tableMeta;
+  }
+
+  @Override
+  public Optional<String> getQuery(){
+    StringBuffer query = new StringBuffer();
+    query.append("CREATE TABLE ");
+    query.append(tableMeta.getDatabase()).append(".");
+    query.append(tableMeta.getTable()).append(" ");
+    query.append("(").append(getColumnQuery(tableMeta.getColumns())).append(") ");
+    if(null != tableMeta.getDetailedInfo() && null != tableMeta.getDetailedInfo().getParameters()){
+      String tableComment = tableMeta.getDetailedInfo().getParameters().get(COMMENT);
+      if(!Strings.isNullOrEmpty(tableComment)){
+        query.append(" COMMENT ").append(tableComment);
+      }
+    }
+    if(null != tableMeta.getPartitionInfo() ) {
+      if (tableMeta.getPartitionInfo().getColumns() != null && !tableMeta.getPartitionInfo().getColumns().isEmpty()) {
+        query.append(" PARTITIONED BY ( ").append(getColumnQuery(tableMeta.getPartitionInfo().getColumns())).append(")");
+      }
+    }
+    if(null != tableMeta.getStorageInfo()) {
+      if (!QueryGenerationUtils.isNullOrEmpty(tableMeta.getStorageInfo().getBucketCols())) {
+        query.append(" CLUSTERED BY (").append(Joiner.on(",").join(tableMeta.getStorageInfo().getBucketCols())).append(")");
+      }
+      if (!QueryGenerationUtils.isNullOrEmpty(tableMeta.getStorageInfo().getSortCols())) {
+        query.append(" SORTED BY (").append(getSortColQuery(tableMeta.getStorageInfo().getSortCols())).append(")");
+      }
+      if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getNumBuckets())) {
+        query.append(" INTO ").append(tableMeta.getStorageInfo().getNumBuckets()).append(" BUCKETS ");
+      }
+      // TODO : Skewed information not available right now.
+
+      if(!isNullOrEmpty(tableMeta.getStorageInfo().getParameters())) {
+        if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(ESCAPE_DELIM)) ||
+          !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(FIELD_DELIM)) ||
+          !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(COLELCTION_DELIM)) ||
+          !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(MAPKEY_DELIM)) ||
+          !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(LINE_DELIM)) ||
+          !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(SERIALIZATION_NULL_FORMAT))
+          ) {
+          query.append(" ROW FORMAT DELIMITED ");
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(FIELD_DELIM))) {
+            query.append(" FIELDS TERMINATED BY '").append(tableMeta.getStorageInfo().getParameters().get(FIELD_DELIM)).append("'");
+          }
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(ESCAPE_DELIM))) {
+            query.append(" ESCAPED BY '").append(tableMeta.getStorageInfo().getParameters().get(ESCAPE_DELIM)).append("'");
+          }
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(COLELCTION_DELIM))) {
+            query.append(" COLLECTION ITEMS TERMINATED BY '").append(tableMeta.getStorageInfo().getParameters().get(COLELCTION_DELIM)).append("'");
+          }
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(MAPKEY_DELIM))) {
+            query.append(" MAP KEYS TERMINATED BY '").append(tableMeta.getStorageInfo().getParameters().get(MAPKEY_DELIM)).append("'");
+          }
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(LINE_DELIM))) {
+            query.append(" LINES TERMINATED BY '").append(tableMeta.getStorageInfo().getParameters().get(LINE_DELIM)).append("'");
+          }
+          if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getParameters().get(SERIALIZATION_NULL_FORMAT))) {
+            query.append(" NULL DEFINED AS '").append(tableMeta.getStorageInfo().getParameters().get(SERIALIZATION_NULL_FORMAT)).append("'");
+          }
+        }
+      }
+
+      // STORED AS file_format
+      if(!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getFileFormat()) && !tableMeta.getStorageInfo().getFileFormat().trim().isEmpty()){
+        query.append(" STORED AS ").append(tableMeta.getStorageInfo().getFileFormat().trim());
+      }else if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getInputFormat()) ||
+        !Strings.isNullOrEmpty(tableMeta.getStorageInfo().getOutputFormat())
+        ) {
+        query.append(" STORED AS ");
+        if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getInputFormat())) {
+          query.append(" INPUTFORMAT '").append(tableMeta.getStorageInfo().getInputFormat()).append("'");
+        }
+        if (!Strings.isNullOrEmpty(tableMeta.getStorageInfo().getOutputFormat())) {
+          query.append(" OUTPUTFORMAT '").append(tableMeta.getStorageInfo().getOutputFormat()).append("'");
+        }
+      }
+    }
+
+    if(null != tableMeta.getDetailedInfo()) {
+      if (!Strings.isNullOrEmpty(tableMeta.getDetailedInfo().getLocation())) {
+        query.append(" LOCATION '").append(tableMeta.getDetailedInfo().getLocation()).append("'");
+      }
+
+      if (QueryGenerationUtils.isNullOrEmpty(tableMeta.getDetailedInfo().getParameters())) {
+        String props = QueryGenerationUtils.getPropertiesAsKeyValues(tableMeta.getDetailedInfo().getParameters());
+
+        query.append(" TBLPROPERTIES (").append(props).append(")");
+      }
+    }
+
+    return Optional.of(query.toString());
+  }
+
+  private boolean isNullOrEmpty(Map map) {
+    return null == map || map.isEmpty();
+  }
+
+  private String getSortColQuery(List<ColumnOrder> sortCols) {
+    List<String> sortColsList = FluentIterable.from(sortCols).transform(new Function<ColumnOrder, String>() {
+      @Nullable
+      @Override
+      public String apply(@Nullable ColumnOrder input) {
+        return input.getColumnName() + " " + input.getOrder().name();
+      }
+    }).toList();
+    return Joiner.on(",").join(sortColsList);
+  }
+
+  private String getColumnQuery(List<ColumnInfo> columns) {
+    List<String> columnQuery = FluentIterable.from(columns).transform(new Function<ColumnInfo, String>() {
+      @Nullable
+      @Override
+      public String apply(@Nullable ColumnInfo column) {
+        return QueryGenerationUtils.getColumnRepresentation(column);
+      }
+    }).toList();
+
+    return Joiner.on(",").join(columnQuery);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteTableQueryGenerator.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteTableQueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteTableQueryGenerator.java
new file mode 100644
index 0000000..09b12b6
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteTableQueryGenerator.java
@@ -0,0 +1,67 @@
+/*
+* 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.ambari.view.hive20.internal.query.generators;
+
+import com.google.common.base.Optional;
+import org.apache.ambari.view.hive20.exceptions.ServiceException;
+import org.apache.parquet.Strings;
+
+public class DeleteTableQueryGenerator implements QueryGenerator{
+  private final String databaseName;
+  private final String tableName;
+  private Boolean purge = Boolean.FALSE;
+
+  public DeleteTableQueryGenerator(String databaseName, String tableName) {
+    this(databaseName, tableName, Boolean.FALSE);
+  }
+
+  public DeleteTableQueryGenerator(String databaseName, String tableName, Boolean purge) {
+    this.databaseName = databaseName;
+    this.tableName = tableName;
+    if( null != purge ) this.purge = purge;
+  }
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  public String getTableName() {
+    return tableName;
+  }
+
+  public Boolean getPurge() {
+    return purge;
+  }
+
+  public void setPurge(Boolean purge) {
+    this.purge = purge;
+  }
+
+  /**
+   * @return
+   * @throws ServiceException
+   */
+  @Override
+  public Optional<String> getQuery() throws ServiceException {
+    if(Strings.isNullOrEmpty(this.getDatabaseName()) || Strings.isNullOrEmpty(this.getTableName()))
+      throw new ServiceException("databaseName or tableName was null.");
+
+    return Optional.of("DROP TABLE `" + databaseName + "`.`" + tableName + "`" + (this.getPurge() ? " PURGE " : ""));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerationUtils.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerationUtils.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerationUtils.java
new file mode 100644
index 0000000..d9dc6e1
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerationUtils.java
@@ -0,0 +1,151 @@
+/*
+* 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.ambari.view.hive20.internal.query.generators;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
+import org.apache.ambari.view.hive20.internal.dto.ColumnInfo;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class QueryGenerationUtils {
+
+  public static final String ADDED = "ADDED";
+  public static final String DELETED = "DELETED";
+  public static final String MODIFIED = "MODIFIED";
+
+  public static boolean isNullOrEmpty(Map map) {
+    return null != map && !map.isEmpty();
+  }
+
+  public static boolean isNullOrEmpty(Collection collection) {
+    return null == collection || collection.isEmpty();
+  }
+
+  public static boolean isEqual(Map oldProps, Map newProps) {
+    if(oldProps == null && newProps == null) return true;
+
+    if(oldProps != null && newProps != null){
+      if(oldProps.size() != newProps.size()) return false;
+
+      Set<Map.Entry> entrySet = oldProps.entrySet();
+      for(Map.Entry e : entrySet){
+        Object key = e.getKey();
+        if(oldProps.get(key) == null){
+          if(newProps.get(key) != null) return false;
+        }else {
+          if (newProps.get(key) == null || !newProps.get(key).equals(oldProps.get(key))) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * return a map with 3 keys "DELETED" and "ADDED" and "MODIFIED" to show the different between oldProps and newProps
+   * for "ADDED" and "MODIFIED" the values in map are of newProps
+   * @param oldProps
+   * @param newProps
+   * @return
+   */
+  public static Optional<Map<String, Map<Object,Object>>> findDiff(Map oldProps, Map newProps) {
+    Map<String, Map<Object, Object>> ret = new HashMap<>();
+    Map<Object, Object> added = new HashMap<>();
+    Map<Object, Object> modified = new HashMap<>();
+    Map<Object, Object> deleted = new HashMap<>();
+
+    if(oldProps == null && newProps == null) return Optional.of(ret);
+
+    if(oldProps != null && newProps != null){
+      Set<Map.Entry> entrySet = oldProps.entrySet();
+      for(Map.Entry e : entrySet){
+        Object key = e.getKey();
+        Object newValue = newProps.get(key);
+        if(e.getValue() == null){
+          if( newValue != null){
+            added.put(key, newValue);
+          }
+        }else {
+          if (newValue == null) {
+            deleted.put(key, newValue);
+          }else if (!e.getValue().equals(newValue)){
+            modified.put(key, newValue);
+          }
+        }
+      }
+
+      Set<Map.Entry> newEntrySet = newProps.entrySet();
+      for(Map.Entry e : newEntrySet){
+        if(e.getValue() != null && oldProps.get(e.getKey()) == null){
+          added.put(e.getKey(), e.getValue());
+        }
+      }
+    }
+    ret.put(ADDED, added);
+    ret.put(DELETED, deleted);
+    ret.put(MODIFIED, modified);
+
+    return Optional.of(ret);
+  }
+
+  public static String getPropertiesAsKeyValues(Map<String, String> parameters) {
+    List<String> props = (List<String>) FluentIterable.from(parameters.entrySet())
+            .transform(new Function<Map.Entry<String, String>, String>() {
+              @Nullable
+              @Override
+              public String apply(@Nullable Map.Entry<String, String> entry) {
+                return "'" + entry.getKey() + "'='" + entry.getValue() + "'";
+              }
+            }).toList();
+
+    return Joiner.on(",").join(props);
+  }
+
+  public static String getColumnRepresentation(ColumnInfo column) {
+    StringBuilder colQuery = new StringBuilder().append("`").append(column.getName()).append("`");
+    colQuery.append(" ").append(column.getType());
+    if(!QueryGenerationUtils.isNullOrZero(column.getPrecision())){
+      if(!QueryGenerationUtils.isNullOrZero(column.getScale())){
+        colQuery.append("(").append(column.getPrecision()).append(",").append(column.getScale()).append(")");
+      }else{
+        colQuery.append("(").append(column.getPrecision()).append(")");
+      }
+    }
+    if(!Strings.isNullOrEmpty(column.getComment())) {
+      colQuery.append(" COMMENT '").append(column.getComment()).append("'");
+    }
+
+    return colQuery.toString();
+  }
+
+  public static boolean isNullOrZero(Integer integer) {
+    return null == integer || 0 == integer;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerator.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerator.java
new file mode 100644
index 0000000..0d8f350
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/QueryGenerator.java
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.apache.ambari.view.hive20.internal.query.generators;
+
+import com.google.common.base.Optional;
+import org.apache.ambari.view.hive20.exceptions.ServiceException;
+
+public interface QueryGenerator {
+  Optional<String> getQuery() throws ServiceException;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/DataStoreStorage.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/DataStoreStorage.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/DataStoreStorage.java
new file mode 100644
index 0000000..133ff08
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/DataStoreStorage.java
@@ -0,0 +1,140 @@
+/**
+ * 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.ambari.view.hive20.persistence;
+
+import org.apache.ambari.view.PersistenceException;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.persistence.utils.FilteringStrategy;
+import org.apache.ambari.view.hive20.persistence.utils.Indexed;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.persistence.utils.OnlyOwnersFilteringStrategy;
+import org.apache.ambari.view.hive20.utils.ServiceFormattedException;
+import org.apache.commons.beanutils.BeanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.beans.Transient;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Engine for storing objects to context DataStore storage
+ */
+public class DataStoreStorage implements Storage {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(DataStoreStorage.class);
+
+  protected ViewContext context;
+
+  /**
+   * Constructor
+   * @param context View Context instance
+   */
+  public DataStoreStorage(ViewContext context) {
+    this.context = context;
+  }
+
+  @Override
+  public synchronized void store(Class model, Indexed obj) {
+
+    try {
+      Indexed newBean = (Indexed) BeanUtils.cloneBean(obj);
+      preprocessEntity(newBean);
+      context.getDataStore().store(newBean);
+      obj.setId(newBean.getId());
+    } catch (Exception e) {
+      throw new ServiceFormattedException("S020 Data storage error", e);
+    }
+  }
+
+  private void preprocessEntity(Indexed obj) {
+    cleanTransientFields(obj);
+  }
+
+  private void cleanTransientFields(Indexed obj) {
+    for (Method m : obj.getClass().getMethods()) {
+      Transient aTransient = m.getAnnotation(Transient.class);
+      if (aTransient != null && m.getName().startsWith("set")) {
+        try {
+          m.invoke(obj, new Object[]{ null });
+        } catch (IllegalAccessException e) {
+          throw new ServiceFormattedException("S030 Data storage error", e);
+        } catch (InvocationTargetException e) {
+          throw new ServiceFormattedException("S030 Data storage error", e);
+        }
+      }
+    }
+  }
+
+  @Override
+  public synchronized <T extends Indexed> T load(Class<T> model, Object id) throws ItemNotFound {
+    LOG.debug(String.format("Loading %s #%s", model.getName(), id));
+    try {
+      T obj = context.getDataStore().find(model, id);
+      if (obj != null) {
+        return obj;
+      } else {
+        throw new ItemNotFound();
+      }
+    } catch (PersistenceException e) {
+      throw new ServiceFormattedException("S040 Data storage error", e);
+    }
+  }
+
+  @Override
+  public synchronized <T extends Indexed> List<T> loadAll(Class<? extends T> model, FilteringStrategy filter) {
+    LinkedList<T> list = new LinkedList<T>();
+    LOG.debug(String.format("Loading all %s-s", model.getName()));
+    try {
+      for(T item: context.getDataStore().findAll(model, filter.whereStatement())) {
+        list.add(item);
+      }
+    } catch (PersistenceException e) {
+      throw new ServiceFormattedException("S050 Data storage error", e);
+    }
+    return list;
+  }
+
+  @Override
+  public synchronized <T extends Indexed> List<T> loadAll(Class<T> model) {
+    return loadAll(model, new OnlyOwnersFilteringStrategy(this.context.getUsername()));
+  }
+
+  @Override
+  public synchronized void delete(Class model, Object id) throws ItemNotFound {
+    LOG.debug(String.format("Deleting %s:%s", model.getName(), id));
+    Object obj = load(model, id);
+    try {
+      context.getDataStore().remove(obj);
+    } catch (PersistenceException e) {
+      throw new ServiceFormattedException("S060 Data storage error", e);
+    }
+  }
+
+  @Override
+  public boolean exists(Class model, Object id) {
+    try {
+      return context.getDataStore().find(model, id) != null;
+    } catch (PersistenceException e) {
+      throw new ServiceFormattedException("S070 Data storage error", e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/IStorageFactory.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/IStorageFactory.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/IStorageFactory.java
new file mode 100644
index 0000000..eaad7ba
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/IStorageFactory.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.ambari.view.hive20.persistence;
+
+public interface IStorageFactory {
+  Storage getStorage();
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/InstanceKeyValueStorage.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/InstanceKeyValueStorage.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/InstanceKeyValueStorage.java
new file mode 100644
index 0000000..f02b35d
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/InstanceKeyValueStorage.java
@@ -0,0 +1,132 @@
+/**
+ * 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.ambari.view.hive20.persistence;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.persistence.utils.ContextConfigurationAdapter;
+import org.apache.ambari.view.hive20.utils.ServiceFormattedException;
+import org.apache.commons.configuration.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.WebApplicationException;
+
+
+/**
+ * Persistent storage engine for storing java beans to
+ * instance data
+ */
+@Deprecated
+public class InstanceKeyValueStorage extends KeyValueStorage {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(InstanceKeyValueStorage.class);
+
+  private ContextConfigurationAdapter config = null;
+  private int VALUE_LENGTH_LIMIT = 254;
+
+  /**
+   * Constructor.
+   * @param context View Context instance
+   */
+  public InstanceKeyValueStorage(ViewContext context) {
+    super(context);
+  }
+
+  /**
+   * Returns config instance, adapter to Persistence API
+   * @return config instance
+   */
+  @Override
+  protected synchronized Configuration getConfig() {
+    if (config == null) {
+      config = new ContextConfigurationAdapter(context);
+    }
+    return config;
+  }
+
+  /**
+   * Value is limited to 256 symbols, this code splits value into chunks and saves them as <key>#<chunk_id>
+   * @param modelPropName key
+   * @param json value
+   */
+  protected void write(String modelPropName, String json) {
+    int saved = 0;
+    int page = 1;
+    while (saved < json.length()) {
+      int end = Math.min(saved + VALUE_LENGTH_LIMIT, json.length());
+      String substring = json.substring(saved, end);
+      getConfig().setProperty(modelPropName + "#" + page, substring);
+      saved += VALUE_LENGTH_LIMIT;
+      page += 1;
+      LOG.debug("Chunk saved: " + modelPropName + "#" + page + "=" + substring);
+    }
+    getConfig().setProperty(modelPropName, page - 1);
+    LOG.debug("Write finished: " + modelPropName + " pages:" + (page - 1));
+  }
+
+  /**
+   * Read chunked value (keys format <key>#<chunk_id>)
+   * @param modelPropName key
+   * @return value
+   */
+  protected String read(String modelPropName) {
+    StringBuilder result = new StringBuilder();
+    int pages = getConfig().getInt(modelPropName);
+    LOG.debug("Read started: " + modelPropName + " pages:" + pages);
+
+    for(int page = 1; page <= pages; page++) {
+      String substring = getConfig().getString(modelPropName + "#" + page);
+      LOG.debug("Chunk read: " + modelPropName + "#" + page + "=" + substring);
+      if (substring != null) {
+        result.append(substring);
+      }
+    }
+
+    return result.toString();
+  }
+
+  /**
+   * Remove chunked value (keys format <key>#<chunk_id>)
+   * @param modelPropName key
+   */
+  protected void clear(String modelPropName) {
+    int pages = getConfig().getInt(modelPropName);
+    LOG.debug("Clean started: " + modelPropName + " pages:" + pages);
+
+    for(int page = 1; page <= pages; page++) {
+      getConfig().clearProperty(modelPropName + "#" + page);
+      LOG.debug("Chunk clean: " + modelPropName + "#" + page);
+    }
+    getConfig().clearProperty(modelPropName);
+  }
+
+  public static void storageSmokeTest(ViewContext context) {
+    try {
+      final String property = "test.smoke.property";
+      context.putInstanceData(property, "42");
+      boolean status = context.getInstanceData(property).equals("42");
+      context.removeInstanceData(property);
+      if (!status) throw new ServiceFormattedException("Ambari Views instance data DB doesn't work properly", null);
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/KeyValueStorage.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/KeyValueStorage.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/KeyValueStorage.java
new file mode 100644
index 0000000..e3ed2b4
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/KeyValueStorage.java
@@ -0,0 +1,163 @@
+/**
+ * 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.ambari.view.hive20.persistence;
+
+import com.google.gson.Gson;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.persistence.utils.FilteringStrategy;
+import org.apache.ambari.view.hive20.persistence.utils.Indexed;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.persistence.utils.OnlyOwnersFilteringStrategy;
+import org.apache.commons.configuration.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Engine for storing objects to key-value storage
+ */
+public abstract class KeyValueStorage implements Storage {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(KeyValueStorage.class);
+  protected final Gson gson = new Gson();
+  protected ViewContext context;
+
+  /**
+   * Constructor
+   * @param context View Context instance
+   */
+  public KeyValueStorage(ViewContext context) {
+    this.context = context;
+  }
+
+  /**
+   * Returns config instance, adapter to Persistence API
+   * @return config instance
+   */
+  protected abstract Configuration getConfig();
+
+  @Override
+  public <T extends Indexed> void store(Class<T> model, Indexed obj) {
+    String modelIndexingPropName = getIndexPropertyName(model);
+
+    if (obj.getId() == null) {
+      int lastIndex = getConfig().getInt(modelIndexingPropName, 0);
+      lastIndex ++;
+      getConfig().setProperty(modelIndexingPropName, lastIndex);
+      obj.setId(String.valueOf(lastIndex));
+    }
+
+    String modelPropName = getItemPropertyName(model, obj.getId());
+    String json = serialize(obj);
+    write(modelPropName, json);
+  }
+
+  @Override
+  public <T extends Indexed> T load(Class<T> model, Object id) throws ItemNotFound {
+    String modelPropName = getItemPropertyName(model, id);
+    LOG.debug(String.format("Loading %s", modelPropName));
+    if (getConfig().containsKey(modelPropName)) {
+      String json = read(modelPropName);
+      LOG.debug(String.format("json: %s", json));
+
+      return deserialize(model, json);
+    } else {
+      throw new ItemNotFound();
+    }
+  }
+
+  /**
+   * Write json to storage
+   * @param modelPropName key
+   * @param json value
+   */
+  protected void write(String modelPropName, String json) {
+    getConfig().setProperty(modelPropName, json);
+  }
+
+  /**
+   * Read json from storage
+   * @param modelPropName key
+   * @return value
+   */
+  protected String read(String modelPropName) {
+    return getConfig().getString(modelPropName);
+  }
+
+  /**
+   * Remove line from storage
+   * @param modelPropName key
+   */
+  protected void clear(String modelPropName) {
+    getConfig().clearProperty(modelPropName);
+  }
+
+  protected String serialize(Indexed obj) {
+    return gson.toJson(obj);
+  }
+
+  protected <T extends Indexed> T deserialize(Class<T> model, String json) {
+    return gson.fromJson(json, model);
+  }
+
+  @Override
+  public synchronized <T extends Indexed> List<T> loadAll(Class<? extends T> model, FilteringStrategy filter) {
+    ArrayList<T> list = new ArrayList<T>();
+    String modelIndexingPropName = getIndexPropertyName(model);
+    LOG.debug(String.format("Loading all %s-s", model.getName()));
+    int lastIndex = getConfig().getInt(modelIndexingPropName, 0);
+    for(int i=1; i<=lastIndex; i++) {
+      try {
+        T item = load(model, i);
+        if ((filter == null) || filter.isConform(item)) {
+          list.add(item);
+        }
+      } catch (ItemNotFound ignored) {
+      }
+    }
+    return list;
+  }
+
+  @Override
+  public synchronized <T extends Indexed> List<T> loadAll(Class<T> model) {
+    return loadAll(model, new OnlyOwnersFilteringStrategy(this.context.getUsername()));
+  }
+
+  @Override
+  public synchronized void delete(Class model, Object id) {
+    LOG.debug(String.format("Deleting %s:%s", model.getName(), id));
+    String modelPropName = getItemPropertyName(model, id);
+    clear(modelPropName);
+  }
+
+  @Override
+  public boolean exists(Class model, Object id) {
+    return getConfig().containsKey(getItemPropertyName(model, id));
+  }
+
+  private String getIndexPropertyName(Class model) {
+    return String.format("%s:index", model.getName());
+  }
+
+  private String getItemPropertyName(Class model, Object id) {
+    return String.format("%s.%s", model.getName(), id);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/LocalKeyValueStorage.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/LocalKeyValueStorage.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/LocalKeyValueStorage.java
new file mode 100644
index 0000000..9aee9d2
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/LocalKeyValueStorage.java
@@ -0,0 +1,69 @@
+/**
+ * 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.ambari.view.hive20.persistence;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.utils.MisconfigurationFormattedException;
+import org.apache.commons.configuration.ConfigurationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Persistent storage engine for storing java beans to
+ * properties file
+ * Path to file should be in 'dataworker.storagePath' parameter
+ */
+@Deprecated
+public class LocalKeyValueStorage extends KeyValueStorage {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(LocalKeyValueStorage.class);
+
+  private PersistentConfiguration config = null;
+
+  /**
+   * Constructor
+   * @param context View Context instance
+   */
+  public LocalKeyValueStorage(ViewContext context) {
+    super(context);
+  }
+
+  /**
+   * Returns config instance
+   * @return config instance
+   */
+  @Override
+  protected synchronized PersistentConfiguration getConfig() {
+    if (config == null) {
+      String fileName = context.getProperties().get("dataworker.storagePath");
+      if (fileName == null) {
+        String msg = "dataworker.storagePath is not configured!";
+        LOG.error(msg);
+        throw new MisconfigurationFormattedException("dataworker.storagePath");
+      }
+      try {
+        config = new PersistentConfiguration(fileName);
+      } catch (ConfigurationException e) {
+        e.printStackTrace();
+      }
+    }
+    return config;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/PersistentConfiguration.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/PersistentConfiguration.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/PersistentConfiguration.java
new file mode 100644
index 0000000..c9d7bb7
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/persistence/PersistentConfiguration.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view.hive20.persistence;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+
+import java.io.File;
+
+/**
+ * Configuration enables all necessary options for PropertiesConfiguration:
+ * auto-save, auto-reloading, no delimiter parsing and other
+ */
+@Deprecated
+public class PersistentConfiguration extends PropertiesConfiguration {
+  /**
+   * Constructor
+   * @param fileName path to data file
+   * @throws ConfigurationException
+   */
+  public PersistentConfiguration(String fileName) throws ConfigurationException {
+    super();
+
+    File config = new File(fileName);
+    setFile(config);
+    this.setAutoSave(true);
+    this.setReloadingStrategy(new FileChangedReloadingStrategy());
+    this.setDelimiterParsingDisabled(true);
+    this.setListDelimiter((char) 0);
+
+    if (config.exists()) {
+      this.load();
+    }
+  }
+}