zeppelin-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject [5/6] incubator-zeppelin git commit: ZEPPELIN-179: Cassandra Interpreter
Date Wed, 05 Aug 2015 06:17:06 GMT
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/helpMenu.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/helpMenu.ssp b/cassandra/src/main/resources/scalate/helpMenu.ssp
new file mode 100644
index 0000000..1c793ec
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/helpMenu.ssp
@@ -0,0 +1,901 @@
+<%--
+/*
+* 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.
+*/
+--%>
+
+#import(java.util.UUID)
+
+#import(com.datastax.driver.core.utils.UUIDs)
+
+<%@ val basicCommandsId: UUID = UUIDs.random() %>
+<%@ val schemaDiscoveryId: UUID = UUIDs.random() %>
+<%@ val queryParamsId: UUID = UUIDs.random() %>
+<%@ val preparedStatementsId: UUID = UUIDs.random() %>
+<%@ val dynamicFormsId: UUID = UUIDs.random() %>
+<%@ val configurationId: UUID = UUIDs.random() %>
+<%@ val miscId: UUID = UUIDs.random() %>
+
+<br/>
+<br/>
+<nav class="navbar navbar-default">
+    <ul class="nav navbar-nav">
+        <li role="presentation" class="dropdown">
+            <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
+                <span class="text-info"><i class="glyphicon glyphicon-book"/>&nbsp;<strong>Please select ...</strong></span>
+                <span class="text-info caret"></span>
+                <ul class="dropdown-menu">
+                    <li class="dropdown-header"><span class="text-info">Topics</span></li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${basicCommandsId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Basic Commands</span>
+                        </a>
+                    </li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${schemaDiscoveryId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Schema Discovery</span>
+                        </a>
+                    </li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${queryParamsId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Query Parameters</span>
+                        </a>
+                    </li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${preparedStatementsId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Prepared Statements</span>
+                        </a>
+                    </li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${dynamicFormsId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Dynamic Forms</span>
+                        </a>
+                    </li>
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${configurationId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Interpreter Configuration</span>
+                        </a>
+                    </li>                    
+                    <li>
+                        <a role="button" data-toggle="collapse" data-target="#${miscId}">
+                            <span class="text-info"><i class="glyphicon glyphicon-bookmark"/>&nbsp;&nbsp;Misc</span>
+                        </a>
+                    </li>                    
+                </ul>
+            </a>
+        </li>
+
+        <li>
+            <a><span class="text-info"><strong>CASSANDRA INTERPRETER DOCUMENTATION</strong></span></a>
+        </li>
+    </ul>
+    <ul class="nav navbar-nav navbar-right">
+        <li class="dropdown">
+            <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
+                <span class="text-info"><strong>About ...</strong></span>
+                <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+                <li>
+                    <a role="button">
+                        <span class="text-info">Version <strong>1.0</strong></span>
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <span class="text-info">Java Driver Version <strong>2.1.7.1</strong></span>
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <span class="text-info">Author <strong>@doanduyhai</strong></span>
+                    </a>
+                </li>
+            </ul>
+        </li>
+        <li>
+            <a href="#"></a>
+        </li>    
+</nav>
+<br/><br/>
+<div class="container">
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${basicCommandsId}" aria-expanded="false">
+                    <span class="text-info"><strong>Basic Commands</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${basicCommandsId}" class="panel-collapse collapse in" role="tabpanel">
+            <div class="panel-body">
+
+                <div class="panel panel-default">
+                  <div class="panel-body">
+                    <h3>I CQL Statements</h3>
+                    <p>This interpreter is compatible with any CQL statement supported by Cassandra. Ex:
+                        <br/><br/>
+                        <div class="row">
+                            <div class="col-md-6 col-md-offset-3">
+                                <pre>
+
+    INSERT INTO users(login,name) VALUES('jdoe','John DOE');
+    SELECT * FROM users WHERE login='jdoe';
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+                        Each statement should be separated by a <strong>semi-colon</strong> (;).
+                        <br/>
+                        <strong>Multi-line</strong> statements as well as multiple statements on the <strong>same line</strong>
+                        are also supported as long as they are separated by a semi-colon. Ex:
+                        <br/>
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-8 col-md-offset-2">
+                                <pre>
+
+    USE spark_demo;
+
+    SELECT * FROM albums_by_country LIMIT 1; SELECT * FROM countries LIMIT 1;
+
+    SELECT *
+    FROM artists
+    WHERE login='jlennon';
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+                        <strong>Batch</strong> statements are supported and can span multiple lines, as well as
+                        <strong>DDL</strong>(CREATE/ALTER/DROP) statements:
+                        <br/>
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-8 col-md-offset-2">
+                                <pre>
+
+    BEGIN BATCH
+        INSERT INTO users(login,name) VALUES('jdoe','John DOE');
+        INSERT INTO users_preferences(login,account_type) VALUES('jdoe','BASIC');
+    APPLY BATCH;
+
+    CREATE TABLE IF NOT EXISTS test(
+        key int PRIMARY KEY,
+        value text
+    );
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+                        CQL statements are <strong>case-insensitive</strong> (except for column names and values).
+                        This means that the following statements are equivalent and valid:
+                        <br/>
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-8 col-md-offset-2">
+                                <pre>
+
+    INSERT INTO users(login,name) VALUES('jdoe','John DOE');
+    Insert into users(login,name) vAlues('hsue','Helen SUE');
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+                        The complete list of all CQL statements and versions can be found below:
+                        <br/><br/>
+                        <div class="row">
+                            <div class="col-md-6 col-md-offset-3">
+                               <table class="table table-bordered">
+                                    <thead>
+                                        <tr><th>Cassandra version</th><th>Documentation</th></tr>
+                                    </thead>
+                                    <tbody>
+                                        <tr>
+                                            <td><strong>2.2</strong></td>
+                                            <td>
+                                                <a href="http://docs.datastax.com/en/cql/3.3/cql/cqlIntro.html" target="_blank">
+                                                    http://docs.datastax.com/en/cql/3.3/cql/cqlIntro.html
+                                                </a>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td><strong>2.1 & 2.0</strong></td>
+                                            <td>
+                                                <a href="http://docs.datastax.com/en/cql/3.1/cql/cql_intro_c.html" target="_blank">
+                                                    http://docs.datastax.com/en/cql/3.1/cql/cql_intro_c.html
+                                                </a>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td><strong>1.2</strong></td>
+                                            <td>
+                                                <a href="http://docs.datastax.com/en/cql/3.0/cql/aboutCQL.html" target="_blank">
+                                                    http://docs.datastax.com/en/cql/3.0/cql/aboutCQL.html
+                                                </a>
+                                            </td>
+                                        </tr>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+
+
+                    </p>
+                    <h3>II Comments</h3>
+                    <p>
+                        It is possible to add comments between statements. Single line comments start with the
+                        <strong>hash</strong> sign (#). Multi-line comments are enclosed between
+                        <strong>&sol;&ast;&ast;</strong> and <strong>&ast;&ast;&sol;</strong>. Ex:
+
+                        <br/>
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-8 col-md-offset-2">
+                                <pre>
+
+    #First comment
+    INSERT INTO users(login,name) VALUES('jdoe','John DOE');
+
+    /**
+     Multi line
+     comments
+     **/
+    Insert into users(login,name) vAlues('hsue','Helen SUE');
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+
+                    </p>
+                    <h3>III Syntax Validation</h3>
+                    <p>
+                        The interpreters is shipped with a <em>built-in syntax validator</em>. This validator only
+                        checks for <strong>basic syntax errors</strong>. All CQL-related syntax validation is delegated
+                        directly to <strong>Cassandra</strong>
+                        <br/><br/>
+                        Most of the time, syntax errors are due to missing semi-colons between statements or typo errors.
+
+                    </p>
+
+                  </div>
+                </div>
+
+
+
+            </div>
+        </div>
+    </div>    
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${schemaDiscoveryId}" aria-expanded="false">
+                    <span class="text-info"><strong>Schema Discovery</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${schemaDiscoveryId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+
+                <div class="panel panel-default">
+                  <div class="panel-body">
+                    <h3>I Commands For Discovery</h3>
+                    <p>
+                        To make schema discovery easier and more interactive, the following commands are supported:
+                        <br/><br/>
+                        <table class="table table-bordered">
+                            <thead>
+                                <tr><th>Command</th><th>Description</th></tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td><strong>DESCRIBE CLUSTER;</strong></td>
+                                    <td>Show the current cluster name and its partitioner</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>DESCRIBE KEYSPACES;</strong></td>
+                                    <td>List all existing keyspaces in the cluster and their configuration
+                                    (replication factor, durable write ...)</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>DESCRIBE TABLES;</strong></td>
+                                    <td>List all existing keyspaces in the cluster and for each, all the tables name</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>DESCRIBE KEYSPACE &lt;keyspace name&gt;;</strong></td>
+                                    <td>Describe the given keyspace configuration and all its table details (name, columns, ...)</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>DESCRIBE TABLE <em>(&lt;keyspace name&gt;).</em>&lt;table name&gt;;</strong></td>
+                                    <td>
+                                        Describe the given table. If the keyspace is not provided, the current
+                                        <strong>logged in</strong> keyspace is used. If there is no logged in keyspace,
+                                        the default <em>system</em> keyspace is used. If no table is found, an error message is raised
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td><strong>DESCRIBE TYPE <em>(&lt;keyspace name&gt;).</em>&lt;type name&gt;;</strong></td>
+                                    <td>
+                                        Describe the given type(UDT). If the keyspace is not provided, the current
+                                        <strong>logged in</strong> keyspace is used. If there is no logged in keyspace,
+                                        the default <em>system</em> keyspace is used. If no type is found, an error message is raised
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <br/>
+                        <div class="alert alert-danger" role="alert">
+                            Please note that each <strong>DESCRIBE</strong> command should be ended by <strong>a semi-colon</strong>.
+                        </div>
+                    </p>
+                    <h3>II Schema Display</h3>
+                    <p>
+                        The schema objects (cluster, keyspace, table &amp; type) are displayed in a tabular format.
+                        There is a <strong>drop-down</strong> menu on the top left corner to expand objects details.
+                        On the top right menu is shown the Icon legend.
+
+                    </p>
+                  </div>
+                </div>
+
+            </div>
+        </div>
+    </div>    
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${queryParamsId}" aria-expanded="false">
+                    <span class="text-info"><strong>Query Parameters</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${queryParamsId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+
+                <div class="panel panel-default">
+                  <div class="panel-body">
+                    <p>
+                        Sometimes you want to be able to pass runtime query parameters to your statements.
+                        Those parameters are <strong>not</strong> part of the CQL specs and are specific to the interpreter.
+                        Below is the list of all parameters:
+
+                        <br/><br/>
+                        <table class="table table-bordered">
+                            <caption>
+                                <h4>Query Parameters</h4>
+                            </caption>
+                            <thead>
+                                <tr>
+                                    <th>Parameter</th>
+                                    <th>Syntax</th>
+                                    <th>Description</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td>Consistency Level</td>
+                                    <td><strong>@consistency=<em>value</em></strong></td>
+                                    <td>Apply the given consistency level to all queries in the paragraph</td>
+                                </tr>
+                                <tr>
+                                    <td>Serial Consistency Level</td>
+                                    <td><strong>@serialConsistency=<em>value</em></strong></td>
+                                    <td>Apply the given serial consistency level to all queries in the paragraph</td>
+                                </tr>
+                                <tr>
+                                    <td>Timestamp</td>
+                                    <td><strong>@timestamp=<em>long value</em></strong></td>
+                                    <td>Apply the given timestamp to all queries in the paragraph.<br/>
+                                        Please note that timestamp value passed directly in CQL statement will override this value
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>Retry Policy</td>
+                                    <td><strong>@retryPolicy=<em>value</em></strong></td>
+                                    <td>Apply the given retry policy to all queries in the paragraph</td>
+                                </tr>
+                                <tr>
+                                    <td>Fetch Size</td>
+                                    <td><strong>@fetchSize=<em>int value</em></strong></td>
+                                    <td>Apply the given fetch size to all queries in the paragraph</td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <br/>
+                        Some parameters only accept restricted values:
+
+                        <br/><br/>
+                        <table class="table table-bordered">
+                            <caption>
+                                <h4>Allowed Values</h4>
+                            </caption>
+                            <thead>
+                                <tr>
+                                    <th>Parameter</th>
+                                    <th>Possible Values</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td>Consistency Level</td>
+                                    <td><strong>ALL, ANY, ONE, TWO, THREE, QUORUM, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM</strong></td>
+                                </tr>
+                                <tr>
+                                    <td>Serial Consistency Level</td>
+                                    <td><strong>SERIAL, LOCAL_SERIAL</strong></td>
+                                </tr>
+                                <tr>
+                                    <td>Timestamp</td>
+                                    <td>Any long value</td>
+                                </tr>
+                                <tr>
+                                    <td>Retry Policy</td>
+                                    <td>
+                                        <strong>
+                                            DEFAULT, DOWNGRADING_CONSISTENCY, FALLTHROUGH, LOGGING_DEFAULT,
+                                            LOGGING_DOWNGRADING, LOGGING_FALLTHROUGH
+                                        </strong>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>Fetch Size</td>
+                                    <td>Any integer value</td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <br/>
+
+                        <div class="alert alert-danger" role="alert">
+                            Please note that you <strong>should not add semi-colon (;)</strong> at the end of each parameter statement
+                        </div>
+
+                        Some example:
+                        <br/><br/>
+                        <div class="row">
+                            <div class="col-md-8 col-md-offset-2">
+                                <pre>
+
+    CREATE TABLE IF NOT EXISTS spark_demo.ts(
+        key int PRIMARY KEY,
+        value text
+    );
+    TRUNCATE spark_demo.ts;
+
+    # Timestamp in the past
+    @timestamp=10
+
+    # Force timestamp directly in the first insert
+    INSERT INTO spark_demo.ts(key,value) VALUES(1,'first insert') USING TIMESTAMP 100;
+
+    # Select some data to make the clock turn
+    SELECT * FROM spark_demo.albums LIMIT 100;
+
+    # Now insert using the timestamp parameter set at the beginning(10)
+    INSERT INTO spark_demo.ts(key,value) VALUES(1,'second insert');
+
+    # Check for the result. You should see 'first insert'
+    SELECT value FROM spark_demo.ts WHERE key=1;
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+
+                        Some remarks about query parameters:
+                        <br/><br/>
+                        <div class="alert alert-info" role="alert">
+                            <ul>
+                                <li><strong>many</strong> query parameters can be set in the same paragraph</li>
+                                <li>if the <strong>same</strong> query parameter is set many time with different values,
+                                    the interpreter only take into account the first value
+                                </li>
+                                <li>each query parameter applies to <strong>all</strong> CQL statement in the same paragraph,
+                                    unless you override the option using plain CQL text (like forcing timestamp with the USING clause)
+                                </li>
+                                <li>the order of each query parameter with regard to CQL statement does not matter</li>
+                            </ul>
+                        </div>
+                    </p>
+                    </div>
+                </div>
+
+
+            </div>
+        </div>
+    </div>        
+    
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${preparedStatementsId}" aria-expanded="false">
+                    <span class="text-info"><strong>Prepared Statements</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${preparedStatementsId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+                <div class="panel panel-default">
+                  <div class="panel-body">
+                    <h3>I Syntax</h3>
+                    <br/>
+                    <p>
+                        For performance reason, it is better to <strong>prepare statements</strong> before-hand and reuse
+                        them later by providing bound values. This interpreter provides 3 commands to handle prepared and
+                        bound statements:
+                        <br/><br/>
+                        <ol>
+                            <li><strong>@prepare</strong></li>
+                            <li><strong>@bind</strong></li>
+                            <li><strong>@remove_prepared</strong></li>
+                        </ol>
+                        <br/>
+                        Example:
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-10 col-md-offset-1">
+                                <pre>
+
+    @prepare[statement_name]=...
+
+    @bind[statement_name]=’text’, 1223, ’2015-07-30 12:00:01’, null, true, [‘list_item1’, ’list_item2’]
+
+    @bind[statement_name_with_no_bound_value]
+
+    @remove_prepare[statement_name]
+
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+
+                    <h3>II @prepare</h3>
+                    <br/>
+                    <p>
+                        You can use the syntax "<strong>@prepare[statement_name]=SELECT ...</strong>" to create a prepared statement.
+                        The <em>statement_name</em> is mandatory because the interpreter prepares the given statement with the
+                        Java driver and saves the generated prepared statement in an internal map, using the provided
+                        <em>statement_name</em> as search key.
+                        <br/><br/>
+                        <div class="alert alert-info">
+                            Please note that this internal prepared statement map is shared with <strong>all notebooks</strong>
+                            and <strong>all paragraphs</strong> because there is only one instance of the interpreter for Cassandra
+                        </div>
+                        <br/>
+                        <div class="alert alert-warning">
+                            If the interpreter encounters many @prepare for the <strong>same statement_name</strong> (key),
+                            only the <strong>first</strong> statement will be taken into account.
+                        </div>
+                        <br/>
+                        Example:
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-10 col-md-offset-1">
+                                <pre>
+
+    @prepare[select]=SELECT * FROM spark_demo.albums LIMIT ?
+
+    @prepare[select]=SELECT * FROM spark_demo.artists LIMIT ?
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+
+                        For the above example, the prepared statement is <strong>"SELECT * FROM spark_demo.albums LIMIT ?"</strong>.
+                        <em>"SELECT * FROM spark_demo.artists LIMIT ?"</em> is ignored because an entry already exists in the
+                        prepared statements map with the key <strong>select</strong>.
+                        <br/><br/>
+                        In the context of Zeppelin, a notebook can be scheduled to be executed at regular interval,
+                        thus it is necessary to avoid re-preparing many time the same statement (considered an anti-pattern).
+                    </p>
+                    <h3>III @bind</h3>
+                    <br/>
+                    <p>
+                        Once the statement is prepared (possibly in a separated notebook/paragraph). You can bind values to it:
+                        <br/><br/>
+                        <div class="row">
+                            <div class="col-md-10 col-md-offset-1">
+                                <pre>
+
+    @bind[select_first]=10
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+                        Bound values are not mandatory for the <strong>@bind</strong> statement.
+                        However if you provide bound values, they need to comply to some syntax:
+
+                        <ul>
+                            <li>String values should be enclosed between simple quotes ( ‘ )</li>
+                            <li>Date values should be enclosed between simple quotes ( ‘ ) and respect the formats:
+                                <ol>
+                                    <li>yyyy-MM-dd HH:MM:ss</li>
+                                    <li>yyyy-MM-dd HH:MM:ss.SSS</li>
+                                </ol>
+                            </li>
+                            <li><strong>null</strong> is parsed as-is</li>
+                            <li><strong>boolean</strong> (true|false) are parsed as-is </li>
+                            <li>collection values must follow the
+                                <a href="http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_collections_c.html" target="_blank">standard CQL syntax</a>:
+                                <ul>
+                                    <li>list:  [‘list_item1’, ’list_item2’, ...]</li>
+                                    <li>set: {‘set_item1’, ‘set_item2’, …}</li>
+                                    <li>map: {‘key1’: ‘val1’, ‘key2’: ‘val2’, …}</li>
+                                </ul>
+                            </li>
+                            <li>
+                                tuple values should be enclosed between parenthesis
+                                (see <a href="http://docs.datastax.com/en/cql/3.1/cql/cql_reference/tupleType.html" target="_blank">tuple CQL syntax</a>):
+                                (‘text’, 123, true)
+                            </li>
+                            <li>
+                                udt values should be enclosed between brackets
+                                (see <a href="http://docs.datastax.com/en/cql/3.1/cql/cql_using/cqlUseUDT.html" target="_blank">udt CQL syntax</a>):
+                                {stree_name: ‘Beverly Hills’,  number: 104, zip_code: 90020, state: ‘California’, …}
+                            </li>
+                        </ul>
+                        <br/>
+                        <div class="alert alert-info">
+                            It is possible to use the <strong>@bind</strong> statement inside a batch: <br/>
+                            <pre>
+    BEGIN BATCH
+        @bind[insert_user]='jdoe','John DOE'
+        UPDATE users SET age = 27 WHERE login='hsue';
+    APPLY BATCH;
+                            </pre>
+                        </div>
+                        <br/>
+                    </p>
+                    <h3>IV @remove_prepare</h3>
+                    <br/>
+                    <p>
+                        To avoid for a prepared statement to stay forever in the prepared statement map, you can use the <strong>@remove_prepare[statement_name]</strong> syntax
+                        to remove it. Removing a non-existing prepared statement yields no error.
+                    </p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>  
+    
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${dynamicFormsId}" aria-expanded="false">
+                    <span class="text-info"><strong>Dynamic Forms</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${dynamicFormsId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+
+                <div class="panel panel-default">
+                  <div class="panel-body">
+                    <p>
+                        Instead of hard-coding your CQL queries, it is possible to use the mustache syntax (<strong>{{ }}</strong>)
+                        to inject simple value or multiple choices forms.
+                        <br/><br/>
+
+                        The syntax for simple parameter is: <strong>{{input_Label=default value}}</strong>.
+                        The default value is mandatory because the first time the paragraph is executed,
+                        we launch the CQL query before rendering the form so at least one value should be provided.
+                        <br/><br/>
+                        The syntax for multiple choices parameter is: <strong>{{input_Label=value1 | value2 | … | valueN }}</strong>.
+                        By default the first choice is used for CQL query the first time the paragraph is executed.
+                        <br/><br/>
+                        Example:
+                        <br/>
+                        <div class="row">
+                            <div class="col-md-10 col-md-offset-1">
+                                <pre>
+
+    #Secondary index on performer style
+    SELECT name, country, performer
+    FROM spark_demo.performers
+    WHERE name='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}'
+    AND styles CONTAINS '{{style=Rock}}';
+
+                                </pre>
+                            </div>
+                        </div>
+                        <br/>
+
+                        In the above example, the first CQL query will be executed for <em>performer='Sheryl Crow'</em>
+                        AND <em>style='Rock'</em>. For subsequent queries, you can change the value directly using the form.
+                        Please note that we enclosed the {{ }} block between simple quotes (') because Cassandra expects a String here.
+                        We could have also use the <strong>{{style='Rock'}}</strong> syntax but this time, the value
+                        displayed on the form is <em>'Rock'</em> and not <em>Rock</em>.
+
+                        <br/><br/>
+                        <div class="alert alert-info">
+                            It is also possible to use dynamic forms for <strong>prepared statements</strong>: <br/>
+                            <strong>@bind[select]=='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}', '{{style=Rock}}'</strong>
+                        </div>
+                       </pre>
+                    </p>
+                    </div>
+                </div>
+
+            </div>
+        </div>
+    </div>  
+    
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${configurationId}" aria-expanded="false">
+                    <span class="text-info"><strong>Interpreter Configuration</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${configurationId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+                The <strong>Cassandra</strong> interpreter comes with some some configuration values for the Java driver:
+
+                 <table class="table table-bordered">
+                    <caption>
+                        <h4>Interpreter Configuration</h4>
+                    </caption>
+                     <thead>
+                        <tr>
+                            <th>Parameter</th>
+                            <th>Default Value</th>
+                        </tr>
+                     </thead>
+                     <tbody>
+                        <tr>
+                            <td>cassandra.cluster</td>
+                            <td><strong>Test Cluster</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.compression.protocol</td>
+                            <td><strong>NONE</strong>, possible values: LZ4, SNAPPY</td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.credentials.password</td>
+                            <td><strong>none</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.credentials.username</td>
+                            <td><strong>none</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.hosts</td>
+                            <td><strong>localhost</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.interpreter.parallelism</td>
+                            <td><strong>10</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.keyspace</td>
+                            <td><strong>system</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.load.balancing.policy</td>
+                            <td><strong>DEFAULT</strong>, or a FQCN of a custom class</td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.max.schema.agreement.wait.second</td>
+                            <td><strong>10</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.native.port</td>
+                            <td><strong>9042</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.core.connection.per.host.local</td>
+                            <td><strong>Protocol V2 and below: 2, V3 and above: 1</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.core.connection.per.host.remote</td>
+                            <td><strong>Protocol V2 and below: 1, V3 and above: 1</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.heartbeat.interval.seconds</td>
+                            <td><strong>30</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.idle.timeout.seconds</td>
+                            <td><strong>Test Cluster</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.max.connection.per.host.local</td>
+                            <td><strong>Protocol V2 and below: 8, V3 and above: 1</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.max.connection.per.host.remote</td>
+                            <td><strong>Protocol V2 and below: 2, V3 and above: 1</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.max.request.per.connection.local</td>
+                            <td><strong>Protocol V2 and below: 128, V3 and above: 1024</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.max.request.per.connection.remote</td>
+                            <td><strong>Protocol V2 and below: 128, V3 and above: 256</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.new.connection.threshold.local</td>
+                            <td><strong>Protocol V2 and below: 100, V3 and above: 800</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.new.connection.threshold.remote</td>
+                            <td><strong>Protocol V2 and below: 100, V3 and above: 200</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.pooling.pool.timeout.millisecs</td>
+                            <td><strong>5000</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.protocol.version</td>
+                            <td><strong>3</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.query.default.consistency</td>
+                            <td><strong>ONE</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.query.default.fetchSize</td>
+                            <td><strong>5000</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.query.default.serial.consistency</td>
+                            <td><strong>SERIAL</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.reconnection.policy</td>
+                            <td><strong>DEFAULT</strong>, or a FQCN of a custom class</td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.retry.policy</td>
+                            <td><strong>DEFAULT</strong>, or a FQCN of a custom class</td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.socket.connection.timeout.millisecs</td>
+                            <td><strong>500</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.socket.read.timeout.millisecs</td>
+                            <td><strong>12000</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.socket.tcp.no_delay</td>
+                            <td><strong>true</strong></td>
+                        </tr>
+                        <tr>
+                            <td>cassandra.speculative.execution.policy</td>
+                            <td><strong>DEFAULT</strong>, or a FQCN of a custom class</td>
+                        </tr>
+                     </tbody>
+                 </table>
+            </div>
+        </div>
+    </div>    
+
+    <div class="panel panel-default">
+        <div class="panel-heading" role="tab">
+            <h4 class="panel-title">
+                <a role="button" data-toggle="collapse" data-target="#${miscId}" aria-expanded="false">
+                    <span class="text-info"><strong>Miscellaneous</strong></span>
+                </a>
+            </h4>
+        </div>
+        <div id="${miscId}" class="panel-collapse collapse" role="tabpanel">
+            <div class="panel-body">
+               <h3>Execution parallelism</h3>
+               It is possible to execute many paragraphs in parallel. However, at the back-end side, we’re still using <strong>synchronous</strong> queries. Asynchronous execution is only possible when it is possible to return a Future value in the <strong>InterpreterResult</strong>. It may be an interesting proposal for the Zeppelin project.
+            </div>
+        </div>
+    </div>    
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/keyspaceContent.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/keyspaceContent.ssp b/cassandra/src/main/resources/scalate/keyspaceContent.ssp
new file mode 100644
index 0000000..5139069
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/keyspaceContent.ssp
@@ -0,0 +1,91 @@
+<%--
+/*
+* 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.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+<%@ val ksContent: KeyspaceContent %>
+<div class="container">
+    <!-- Keyspace -->
+    ${unescape(ksContent.keyspaceDetails)}
+
+    <!-- Tables -->
+    <div class="row"></div>
+    #if (ksContent.tables.nonEmpty)
+
+    <table width="100%">
+        <td><hr /></td>
+        <td style="width:1px; padding: 0 10px; white-space: nowrap;"><strong class="text-primary">Tables</strong></td>
+        <td><hr /></td>
+    </table>
+    <div class="row">
+        <div class="panel-group" role="tablist" aria-multiselectable="true">
+            #for((id,name,tableHTML) <- ksContent.tables)
+
+            <div class="panel panel-default">
+                <div class="panel-heading" role="tab">
+                    <h4 class="panel-title">
+                        <a role="button" data-toggle="collapse" data-target="#${id}" aria-expanded="false">
+                            <span class="text-primary">
+                                <i class="glyphicon glyphicon-th-list"/>&nbsp;${name}
+                            </span>
+                        </a>
+                    </h4>
+                </div>
+                <div id="${id}" class="panel-collapse collapse" role="tabpanel">
+                    <div class="panel-body">
+                        ${unescape(tableHTML)}
+                    </div>
+                 </div>
+            </div>
+            #end
+
+        </div>
+    </div>
+    #end
+
+    #if (ksContent.udts.nonEmpty)
+    <!-- UDTs -->
+    <table width="100%">
+        <td><hr /></td>
+        <td style="width:1px; padding: 0 10px; white-space: nowrap;"><strong class="text-warning">User Defined Types</strong></td>
+        <td><hr /></td>
+    </table>
+    <div class="row">
+        <div class="panel-group" role="tablist" aria-multiselectable="true">
+            #for((id,name,udtHTML) <- ksContent.udts)
+
+            <div class="panel panel-default">
+                <div class="panel-heading" role="tab">
+                    <h4 class="panel-title">
+                        <a role="button" data-toggle="collapse" data-target="#${id}" aria-expanded="false">
+                            <span class="text-warning"><i class="glyphicon glyphicon-copyright-mark"/>&nbsp;${name}</span>
+                        </a>
+                    </h4>
+                </div>
+                <div id="${id}" class="panel-collapse collapse" role="tabpanel">
+                    <div class="panel-body">
+                        ${unescape(udtHTML)}
+                    </div>
+                </div>
+            </div>
+            #end
+
+        </div>
+    </div>
+    #end
+
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/keyspaceDetails.ssp b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
new file mode 100644
index 0000000..beaf182
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
@@ -0,0 +1,61 @@
+<%--
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+#import(scala.util.parsing.json.JSONObject)
+<%@ val ksDetails: KeyspaceDetails %>
+<%@ val withCaption: Boolean%>
+<div class="row">
+    <div class="col-md-2"></div>
+    <div class="col-md-8 col-offset-md-2">
+        <div class="panel panel-default table-responsive table-bordered">
+            <table class="table">
+                #if (withCaption)
+                <caption>
+                    <h4 class="text-danger">
+                        <i class="glyphicon glyphicon-folder-open"/>&nbsp;&nbsp;${ksDetails.name}
+                    </h4>
+                </caption>
+                #end
+                <thead>
+                <tr>
+                    <th class="col-md-10">Replication</th>
+                    <th class="col-md-2">Durable Writes</th>
+                </tr>
+                </thead>
+                <tbody>
+                    <tr>
+                        <td class="col-md-10">${ksDetails.getReplicationMap}</td>
+                        <td class="col-md-2">${ksDetails.durableWrites}</td>
+                    </tr>
+                <tbody>
+            </table>
+            <div class="panel-footer">
+                <a data-toggle="collapse" data-target="#${ksDetails.uniqueId}_asCQL">
+                    <strong>As CQL statement</strong>
+                    <span class="caret"></span>
+                </a>
+                <br/><br/>
+                <div class="collapse" id="${ksDetails.uniqueId}_asCQL">
+                    <pre class="well">${ksDetails.asCQL}</pre>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="col-md-2"></div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/menu.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/menu.ssp b/cassandra/src/main/resources/scalate/menu.ssp
new file mode 100644
index 0000000..91afc8b
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/menu.ssp
@@ -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.
+*/
+--%>
+<%@ val statement: String %>
+<%@ val dropDownMenu: String = "" %>
+<br/>
+<br/>
+<nav class="navbar navbar-default">
+    <ul class="nav navbar-nav">
+        ${unescape(dropDownMenu)}
+        <li>
+            <a><strong>${statement}</strong></a>
+        </li>
+    </ul>
+    <ul class="nav navbar-nav navbar-right">
+        <li class="dropdown">
+            <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
+                <strong>Legend</strong>
+                <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+                <li>
+                    <a role="button">
+                        <i class="glyphicon glyphicon-dashboard text-muted" />&nbsp;Cluster
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <i class="glyphicon glyphicon-folder-open text-danger" />&nbsp;&nbsp;Keyspace
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <i class="glyphicon glyphicon-copyright-mark text-warning" />&nbsp;&nbsp;UDT
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <i class="glyphicon glyphicon-th-list text-primary" />&nbsp;&nbsp;Table
+                    </a>
+                </li>
+                <li class="bg-info">
+                    <a role="button">
+                        <i class="glyphicon glyphicon-fullscreen" />&nbsp;&nbsp;Partition Key
+                    </a>
+                </li>
+                <li class="bg-warning">
+                    <a role="button">
+                        <i class="glyphicon glyphicon-pushpin" />&nbsp;&nbsp;Static Column
+                    </a>
+                </li>
+                <li class="bg-success">
+                    <a role="button">
+                        <i class="glyphicon glyphicon-sort" />&nbsp;&nbsp;Clustering Column
+                    </a>
+                </li>
+                <li class="bg-success">
+                    <a role="button">
+                        <i class="glyphicon glyphicon-sort-by-attributes" />&nbsp;&nbsp;Clustering Order ASC
+                    </a>
+                </li>
+                <li class="bg-success">
+                    <a role="button">
+                        <i class="glyphicon glyphicon-sort-by-attributes-alt" />&nbsp;&nbsp;Clustering Order DESC
+                    </a>
+                </li>
+                <li>
+                    <a role="button">
+                        <i class="glyphicon glyphicon-info-sign" />&nbsp;&nbsp;Indexed Column
+                    </a>
+                </li>
+            </ul>
+        </li>
+        <li>
+            <a href="#"></a>
+        </li>
+    </ul>
+</nav>
+<hr/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/noResult.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/noResult.ssp b/cassandra/src/main/resources/scalate/noResult.ssp
new file mode 100644
index 0000000..a3dc4b6
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/noResult.ssp
@@ -0,0 +1,24 @@
+<%--
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+<div class="container">
+    <div class="row text-center">
+        <h4>No Result</h4>
+    </div>
+    <br>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/noResultWithExecutionInfo.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/noResultWithExecutionInfo.ssp b/cassandra/src/main/resources/scalate/noResultWithExecutionInfo.ssp
new file mode 100644
index 0000000..1f709a4
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/noResultWithExecutionInfo.ssp
@@ -0,0 +1,65 @@
+<%--
+/*
+* 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.
+*/
+--%>
+<%@ val query: String%>
+<%@ val consistency: String%>
+<%@ val triedHosts: String%>
+<%@ val queriedHosts: String%>
+<%@ val schemaInAgreement: String%>
+<div class="container">
+<div class="row text-center">
+<h4>No Result</h4>
+</div>
+<br/>
+    <div class="row">
+    <div class="col-md-3"></div>
+    <div class="col-md-6 col-offset-md-3 table-responsive table-bordered">
+        <table class="table">
+            <caption><h5>Last query execution info</h5></caption>
+            <thead>
+                <tr>
+                    <th>Info</th>
+                    <th>Value</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td>Statement</td>
+                    <td>${query}</td>
+                </tr>
+                <tr>
+                    <td>Achieved Consistency</td>
+                    <td>${consistency}</td>
+                </tr>
+                <tr>
+                    <td>Tried Hosts</td>
+                    <td>${triedHosts}</td>
+                </tr>
+                <tr>
+                    <td>Queried Hosts</td>
+                    <td>${queriedHosts}</td>
+                </tr>
+                <tr>
+                    <td>Schema In Agreement</td>
+                    <td>${schemaInAgreement}</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/tableDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/tableDetails.ssp b/cassandra/src/main/resources/scalate/tableDetails.ssp
new file mode 100644
index 0000000..6cfbc49
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/tableDetails.ssp
@@ -0,0 +1,147 @@
+<%--
+/*
+* 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.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+<%@ val tableDetails: TableDetails %>
+<%@ val withCaption: Boolean%>
+<div class="row">
+    <div class="col-md-2"/>
+    <div class="col-md-8 col-offset-md-2">
+        <div class="panel panel-default table-responsive table-bordered">
+            <table class="table">
+                #if(withCaption)
+                <caption><h4 class="text-primary"><i class="glyphicon glyphicon-th-list"/>&nbsp;${tableDetails.tableName}</h4></caption>
+                #end
+                <thead>
+                    <tr>
+                        <th class="col-md-4">Column Type</th>
+                        <th class="col-md-4">Column Name</th>
+                        <th class="col-md-4">Data Type</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    #for (column <- tableDetails.columns)
+                        #match (column.columnType)
+                        #case(PartitionKey)
+
+                    <tr class="info">
+                        <td class="col-md-4">
+                            <i class="glyphicon glyphicon-fullscreen" title="Partition Key"/>
+                            #match (column.index)
+                            #case (Some(index))
+
+                            &nbsp;<i class="glyphicon glyphicon-info-sign" title="Indexed Column"/>
+                            <em>${index.name}</em> <strong>${index.info}</strong>
+                            #case (None)
+                            <span></span>
+                            #end
+
+                        </td>
+                        <td class="col-md-4">${column.name}</td>
+                        <td class="col-md-4">${column.dataType}</td>
+                    </tr>
+                        #case(StaticColumn)
+                    <tr class="warning">
+                        <td class="col-md-4">
+                            <i class="glyphicon glyphicon-pushpin" title="Static Column"/>
+                            #match (column.index)
+                            #case (Some(index))
+
+                            &nbsp;<i class="glyphicon glyphicon-info-sign" title="Indexed Column"/>
+                            <em>${index.name}</em> <strong>${index.info}</strong>
+                            #case (None)
+                            <span></span>
+                            #end
+
+                        </td>
+                        <td class="col-md-4">${column.name}</td>
+                        <td class="col-md-4">${column.dataType}</td>
+                    </tr>
+                        #case(ClusteringColumn(ASC))
+                    <tr class="success">
+                        <td class="col-md-4">
+                            <i class="glyphicon glyphicon-sort" title="Clustering Column"/>
+                            &nbsp;
+                            <i class="glyphicon glyphicon-sort-by-attributes" title="Sort ASC"/>
+                            #match (column.index)
+                            #case (Some(index))
+
+                            &nbsp;<i class="glyphicon glyphicon-info-sign" title="Indexed Column"/>
+                            <em>${index.name}</em> <strong>${index.info}</strong>
+                            #case (None)
+                            <span></span>
+                            #end
+
+                        </td>
+                        <td class="col-md-4">${column.name}</td>
+                        <td class="col-md-4">${column.dataType}</td>
+                    </tr>
+                        #case(ClusteringColumn(DESC))
+                    <tr class="success">
+                        <td class="col-md-4">
+                            <i class="glyphicon glyphicon-sort" title="Clustering Column"/>
+                            &nbsp;
+                            <i class="glyphicon glyphicon-sort-by-attributes-alt" title="Sort DESC"/>
+                            #match (column.index)
+                            #case (Some(index))
+
+                            &nbsp;<i class="glyphicon glyphicon-info-sign" title="Indexed Column"/>
+                            <em>${index.name}</em> <strong>${index.info}</strong>
+                            #case (None)
+                            <span></span>
+                            #end
+
+                        </td>
+                        <td class="col-md-4">${column.name}</td>
+                        <td class="col-md-4">${column.dataType}</td>
+                    </tr>
+                        #otherwise
+                    <tr>
+                        <td class="col-md-4">
+                            #match (column.index)
+                            #case (Some(index))
+
+                            <i class="glyphicon glyphicon-info-sign" title="Indexed Column"/>
+                            <em>${index.name}</em> <strong>${index.info}</strong>
+                            #case (None)
+                            <span></span>
+                            #end
+
+                        </td>
+                        <td class="col-md-4">${column.name}</td>
+                        <td class="col-md-4">${column.dataType}</td>
+                    </tr>
+                        #end
+                    #end
+
+                </tbody>
+            </table>
+            <div class="panel-footer">
+                <a data-toggle="collapse" data-target="#${tableDetails.uniqueId}_asCQL">
+                    <strong>As CQL statement</strong>
+                    <span class="caret"></span>
+                </a>
+                <br/><br/>
+                <div class="collapse" id="${tableDetails.uniqueId}_asCQL">
+                    <pre class="well">${tableDetails.asCQL}</pre>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="col-md-2"></div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/resources/scalate/udtDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/udtDetails.ssp b/cassandra/src/main/resources/scalate/udtDetails.ssp
new file mode 100644
index 0000000..80380a4
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/udtDetails.ssp
@@ -0,0 +1,61 @@
+<%--
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+<%@ val udtDetails: UDTDetails %>
+<%@ val withCaption: Boolean%>
+<div class="row">
+    <div class="col-md-3"></div>
+    <div class="col-md-6 col-offset-md-3">
+        <div class="panel panel-default table-responsive table-bordered">
+            <table class="table">
+                #if(withCaption)
+                <caption><h4 class="text-warning"><i class="glyphicon glyphicon-copyright-mark"/>&nbsp;${udtDetails.typeName}</h4></caption>
+                #end
+
+                <thead>
+                    <tr>
+                        <th class="col-md-6">Column Name</th>
+                        <th class="col-md-6">Data Type</th>
+                    </tr>
+                </thead>
+                <tbody>
+                #for (column <- udtDetails.columns )
+
+                <tr>
+                    <td class="col-md-6">${column.name}</td>
+                    <td class="col-md-6">${column.dataType}</td>
+                </tr>
+                #end
+
+                <tbody>
+            </table>
+            <div class="panel-footer">
+                <a data-toggle="collapse" data-target="#${udtDetails.uniqueId}_asCQL">
+                    <strong>As CQL statement</strong>
+                    <span class="caret"></span>
+                </a>
+                <br/><br/>
+                <div class="collapse" id="${udtDetails.uniqueId}_asCQL">
+                    <pre class="well">${udtDetails.asCQL}</pre>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="col-md-3"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/BoundValuesParser.scala
----------------------------------------------------------------------
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/BoundValuesParser.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/BoundValuesParser.scala
new file mode 100644
index 0000000..3268650
--- /dev/null
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/BoundValuesParser.scala
@@ -0,0 +1,65 @@
+/*
+ * 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.zeppelin.cassandra
+
+import java.text.SimpleDateFormat
+import java.util.{Date}
+
+import scala.util.parsing.combinator._
+
+/**
+ * Parser of bound values passed into @bind parameters
+ */
+class BoundValuesParser extends RegexParsers with JavaTokenParsers {
+
+  val STANDARD_DATE_PATTERN = """(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})""".r
+  val ACCURATE_DATE_PATTERN = """(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})""".r
+
+  def value : Parser[String] = "null" | "true" | "false" | zeppelinVariable |
+    map | list | set | tuple| udt |
+    decimal | integer | standardDate | quotedString
+
+
+  def integer: Parser[String] = """\d+""".r ^^{_.toLong.toString}
+
+  def decimal: Parser[String] = """[+-]?(?:(?:\d+\.(?:\d*)?)|(?:\.\d+))""".r ^^{_.toDouble.toString}
+
+  def standardDate: Parser[String] = s"""'${STANDARD_DATE_PATTERN.toString}(?:\\.\\d{3})?'""".r ^^{_.replaceAll("'","")}
+
+  def quotedString: Parser[String] = """'[^']+'""".r //^^ {_.replaceAll("(?<!')'","")}
+
+  def list: Parser[String] = "["~>repsep(value, ",")<~"]" ^^ {_.mkString("[",",","]")}
+
+  def set: Parser[String] = "{"~>repsep(value, ",")<~"}" ^^ {_.mkString("{",",","}")}
+
+  def map: Parser[String] = "{"~>repsep(member, ",")<~"}" ^^{_.mkString("{",", ","}")}
+
+  def tuple: Parser[String] = "(" ~> repsep(value, ",") <~ ")" ^^{_.mkString("(",",",")")}
+
+  def udt: Parser[String] = "{"~>repsep(udtMember, ",")<~"}" ^^{_.mkString("{",", ","}")}
+
+  def member: Parser[String] = quotedString ~ ":" ~ value ^^{ case name~sep~mapVal => name+": "+mapVal}
+
+  def udtColumnName: Parser[String] = """(?:(?:[a-zA-Z][a-zA-Z0-9_]*)|(?:"[^"]+"))""".r
+
+  def udtMember: Parser[String] = udtColumnName ~ ":" ~ value ^^{ case name~sep~mapVal => name+": "+mapVal}
+
+  def zeppelinVariable: Parser[String] = "{{"~"""\w+=[^}]+""".r~"}}" ^^{case prefix~variable~suffix => prefix+variable+suffix}
+
+  def values: Parser[List[String]] = repsep(value, ",")
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/b9583c6e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
----------------------------------------------------------------------
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
new file mode 100644
index 0000000..2881b4b
--- /dev/null
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
@@ -0,0 +1,298 @@
+/*
+ * 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.zeppelin.cassandra
+
+import java.util.UUID
+
+import com.datastax.driver.core.ColumnMetadata.IndexMetadata
+import com.datastax.driver.core.utils.UUIDs
+import org.apache.zeppelin.cassandra.MetaDataHierarchy._
+import org.fusesource.scalate.TemplateEngine
+
+import scala.collection.JavaConverters._
+
+import com.datastax.driver.core._
+
+import scala.collection.immutable.ListMap
+
+/**
+ * Format and display
+ * schema meta data
+ */
+object DisplaySystem {
+
+  val engine = new TemplateEngine
+
+  val CLUSTER_DETAILS_TEMPLATE = "scalate/clusterDetails.ssp"
+  val KEYSPACE_DETAILS_TEMPLATE = "scalate/keyspaceDetails.ssp"
+  val TABLE_DETAILS_TEMPLATE = "scalate/tableDetails.ssp"
+  val UDT_DETAILS_TEMPLATE = "scalate/udtDetails.ssp"
+
+  val MENU_TEMPLATE = "scalate/menu.ssp"
+  val CLUSTER_DROPDOWN_TEMPLATE = "scalate/dropDownMenuForCluster.ssp"
+  val KEYSPACE_DROPDOWN_TEMPLATE = "scalate/dropDownMenuForKeyspace.ssp"
+
+  val CLUSTER_CONTENT_TEMPLATE = "scalate/clusterContent.ssp"
+  val KEYSPACE_CONTENT_TEMPLATE = "scalate/keyspaceContent.ssp"
+  val ALL_TABLES_TEMPLATE = "scalate/allTables.ssp"
+
+  object TableDisplay {
+
+    def format(statement: String, meta: TableMetadata, withCaption: Boolean): String = {
+      MenuDisplay.formatMenu(statement) + formatWithoutMenu(meta, withCaption)
+    }
+
+    protected[DisplaySystem] def formatWithoutMenu(meta: TableMetadata, withCaption: Boolean): String = {
+      val tableName: String = meta.getName
+      val columnsDetails = MetaDataConverter.tableMetaToColumnDetails(meta)
+
+      engine.layout(TABLE_DETAILS_TEMPLATE,
+        Map[String, Any]("tableDetails" -> TableDetails(tableName, columnsDetails, meta.exportAsString), "withCaption" -> withCaption))
+    }
+  }
+
+  object UDTDisplay {
+    def format(statement: String, userType: UserType, withCaption: Boolean): String = {
+      MenuDisplay.formatMenu(statement) ++ formatWithoutMenu(userType, withCaption)
+    }
+
+    protected[DisplaySystem] def formatWithoutMenu(userType: UserType, withCaption: Boolean): String = {
+      val udtName: String = userType.getTypeName
+      val columnsDetails = MetaDataConverter.userTypeToColumnDetails(userType)
+
+      engine.layout(UDT_DETAILS_TEMPLATE,
+        Map[String, Any]("udtDetails" -> UDTDetails(udtName, columnsDetails, userType.exportAsString), "withCaption" -> withCaption))
+    }
+  }
+  
+  object KeyspaceDisplay {
+
+    private def formatCQLQuery(cql: String): String = {
+      cql.replaceAll(""" WITH REPLICATION = \{"""," WITH REPLICATION = \\{")
+        .replaceAll("('[^']+'\\s*:\\s+'[^']+',?)","\n\t$1")
+        .replaceAll(""" \} AND DURABLE_WRITES = """," \\}\nAND DURABLE_WRITES = ")
+    }
+
+    protected[cassandra] def formatKeyspaceOnly(meta: KeyspaceMetadata, withCaption: Boolean): String = {
+      val ksDetails = KeyspaceDetails(meta.getName,
+        meta.getReplication.asScala.toMap,
+        meta.isDurableWrites,
+        formatCQLQuery(meta.asCQLQuery()))
+
+      engine.layout(KEYSPACE_DETAILS_TEMPLATE,
+        Map[String, Any]("ksDetails" -> ksDetails, "withCaption" -> withCaption))
+    }
+
+    def formatKeyspaceContent(statement: String, meta: KeyspaceMetadata): String = {
+      val ksName: String = meta.getName
+      val ksDetails = formatKeyspaceOnly(meta, false)
+
+      val tableDetails: List[(UUID, String, String)] = meta.getTables.asScala.toList
+        .sortBy(meta => meta.getName)
+        .map(meta => (UUIDs.timeBased(), meta.getName, TableDisplay.formatWithoutMenu(meta, false)))
+
+      val udtDetails: List[(UUID, String, String)] = meta.getUserTypes.asScala.toList
+        .sortBy(udt => udt.getTypeName)
+        .map(udt => (UUIDs.timeBased(), udt.getTypeName, UDTDisplay.formatWithoutMenu(udt, false)))
+
+      val ksContent: KeyspaceContent = KeyspaceContent(ksName, ksDetails, tableDetails, udtDetails)
+
+      MenuDisplay.formatMenuForKeyspace(statement, ksContent) +
+        engine.layout(KEYSPACE_CONTENT_TEMPLATE,
+          Map[String, Any]("statement" -> statement, "ksContent" -> ksContent))
+    }
+  }
+
+  object ClusterDisplay {
+
+    def formatClusterOnly(statement: String, meta: Metadata, withMenu: Boolean = true): String = {
+      val clusterDetails: ClusterDetails = ClusterDetails(meta.getClusterName, meta.getPartitioner)
+      val content: String = engine.layout(CLUSTER_DETAILS_TEMPLATE,
+        Map[String, Any]("clusterDetails" -> clusterDetails))
+
+      if(withMenu) MenuDisplay.formatMenu(statement) + content else content
+    }
+
+    def formatClusterContent(statement: String, meta: Metadata): String = {
+      val clusterName: String = meta.getClusterName
+      val clusterDetails: String = formatClusterOnly(statement, meta, false)
+
+      val keyspaceDetails: List[(UUID, String, String)] = meta.getKeyspaces.asScala.toList
+        .sortBy(ks => ks.getName)
+        .map(ks => (UUIDs.timeBased(), ks.getName, KeyspaceDisplay.formatKeyspaceOnly(ks, false)))
+
+      val clusterContent: ClusterContent = ClusterContent(clusterName, clusterDetails, keyspaceDetails)
+
+      MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+        engine.layout(CLUSTER_CONTENT_TEMPLATE,
+          Map[String, Any]("clusterContent" -> clusterContent))
+    }
+
+    def formatAllTables(statement: String, meta: Metadata): String = {
+      val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .sortBy(ks => ks.getName)
+
+      val allTables: Map[(UUID, String), List[String]] = ListMap.empty ++
+        ksMetas
+        .map(ks => {
+          ((UUIDs.timeBased(), ks.getName),
+            ks.getTables.asScala.toList.map(table => table.getName).sortBy(name => name))
+         })
+        .sortBy{case ((id,name), _) => name}
+
+
+      val keyspaceDetails: List[(UUID, String, String)] = allTables
+        .keySet.toList.sortBy{case(id,ksName) => ksName}
+        .map{case(id,ksName) => (id,ksName, "")}
+
+      val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+      MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+        engine.layout(ALL_TABLES_TEMPLATE,
+          Map[String, Any]("allTables" -> allTables))
+    }
+  }
+
+  object HelpDisplay {
+
+    def formatHelp(): String = {
+      engine.layout("/scalate/helpMenu.ssp")
+    }
+  }
+
+  object NoResultDisplay {
+
+    val formatNoResult: String = engine.layout("/scalate/noResult.ssp")
+
+    def noResultWithExecutionInfo(lastQuery: String, execInfo: ExecutionInfo): String = {
+      val consistency = Option(execInfo.getAchievedConsistencyLevel).getOrElse("N/A")
+      val queriedHosts = execInfo.getQueriedHost.toString.replaceAll("/","").replaceAll("""\[""","").replaceAll("""\]""","")
+      val triedHosts = execInfo.getTriedHosts.toString.replaceAll("/","").replaceAll("""\[""","").replaceAll("""\]""","")
+      val schemaInAgreement = Option(execInfo.isSchemaInAgreement).map(_.toString).getOrElse("N/A")
+
+      engine.layout("/scalate/noResultWithExecutionInfo.ssp",
+        Map[String,Any]("query" -> lastQuery, "consistency" -> consistency,
+                        "triedHosts" -> triedHosts, "queriedHosts" -> queriedHosts,
+                        "schemaInAgreement" -> schemaInAgreement))
+    }
+  }
+
+
+  private object MenuDisplay {
+    def formatMenu(statement: String, dropDownMenu: String = ""): String = {
+      engine.layout(MENU_TEMPLATE,
+        Map[String, Any]("statement" -> statement, "dropDownMenu" -> dropDownMenu))
+    }
+
+    def formatMenuForKeyspace(statement: String, ksContent: KeyspaceContent): String = {
+      val dropDownMenu: String = engine.layout(KEYSPACE_DROPDOWN_TEMPLATE,
+        Map[String, Any]("ksContent" -> ksContent))
+
+      formatMenu(statement, dropDownMenu)
+    }
+
+    def formatMenuForCluster(statement: String, clusterContent: ClusterContent): String = {
+      val dropDownMenu: String = engine.layout(CLUSTER_DROPDOWN_TEMPLATE,
+        Map[String, Any]("clusterContent" -> clusterContent))
+
+      formatMenu(statement, dropDownMenu)
+    }
+  }
+}
+
+class ColumnMetaWrapper(val columnMeta: ColumnMetadata) {
+  def canEqual(other: Any): Boolean = other.isInstanceOf[ColumnMetaWrapper]
+
+  override def equals(other: Any): Boolean = other match {
+    case that: ColumnMetaWrapper => (that canEqual this) &&
+      (columnMeta.getName == that.columnMeta.getName)
+    case _ => false
+  }
+
+  override def hashCode: Int = columnMeta.getName.hashCode
+}
+
+/**
+ * Convert Java driver
+ * meta data structure
+ * to our own structure
+ */
+object MetaDataConverter {
+
+  def tableMetaToColumnDetails(meta: TableMetadata): List[ColumnDetails] = {
+    val partitionKeys: List[ColumnMetaWrapper] = meta.getPartitionKey.asScala.toList.map(new ColumnMetaWrapper(_))
+    val clusteringColumns: List[ColumnMetaWrapper] = meta.getClusteringColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+    val columns: List[ColumnMetaWrapper] = meta.getColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+      .diff(partitionKeys).diff(clusteringColumns)
+    val clusteringOrders = meta.getClusteringOrder.asScala.toList
+
+    convertPartitionKeys(partitionKeys):::
+      extractStaticColumns(columns):::
+      convertClusteringColumns(clusteringColumns, clusteringOrders):::
+      extractNormalColumns(columns)
+  }
+  
+  def userTypeToColumnDetails(userType: UserType): List[ColumnDetails] = {
+    userType.getFieldNames.asScala.toList
+      .map(name => new ColumnDetails(name, NormalColumn, userType.getFieldType(name), None))
+  }
+
+  private def extractNormalColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+    columns
+      .filter(_.columnMeta.isStatic == false)
+      .map(c => new ColumnDetails(c.columnMeta.getName, NormalColumn, c.columnMeta.getType, extractIndexDetail(c)))
+  }
+
+  private def extractIndexDetail(column: ColumnMetaWrapper): Option[IndexDetails] = {
+    val indexOption = Option(column.columnMeta.getIndex)
+
+    def buildIndexInfo(indexMeta: IndexMetadata): String = {
+      if(indexMeta.isKeys) "KEYS"
+      if(indexMeta.isEntries) "ENTRIES"
+      if(indexMeta.isFull) "FULL"
+      if(indexMeta.isCustomIndex) s"Class = ${indexMeta.getIndexClassName}"
+      else ""
+    }
+
+    indexOption.map(index => IndexDetails(index.getName, buildIndexInfo(index)))
+  }
+
+  private def extractStaticColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+    columns
+      .filter(_.columnMeta.isStatic == true)
+      .map(c => new ColumnDetails(c.columnMeta.getName, StaticColumn, c.columnMeta.getType, extractIndexDetail(c)))
+  }
+
+  private def convertClusteringColumns(columns: List[ColumnMetaWrapper], orders: List[TableMetadata.Order]): List[ColumnDetails] = {
+    columns
+      .zip(orders)
+      .map{case(c,order) => new ColumnDetails(c.columnMeta.getName,
+      new ClusteringColumn(OrderConverter.convert(order)),
+      c.columnMeta.getType, extractIndexDetail(c))}
+
+  }
+
+  private def convertPartitionKeys(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+    columns
+      .map(c => new ColumnDetails(c.columnMeta.getName, PartitionKey, c.columnMeta.getType, extractIndexDetail(c)))
+  }
+}
+
+
+
+
+


Mime
View raw message