ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dbhowm...@apache.org
Subject ambari git commit: AMBARI-17487: porting changes of AMBARI-17081 and AMBARI-16427 in hive2 view AMBARI-17081 : hive view upload table adding support for date and time format as per hive. AMBARI-16427. Hive view : Upload Table- Tries to upload file, when
Date Thu, 30 Jun 2016 12:31:47 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.4 cd9e14908 -> e4dcce6bc


AMBARI-17487: porting changes of AMBARI-17081 and AMBARI-16427 in hive2 view AMBARI-17081
: hive view upload table adding support for date and time format as per hive. AMBARI-16427.
Hive view : Upload Table- Tries to upload file, when no file is mentioned in hdfs path. (Nitiraj
Rathore via dipayanb)


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

Branch: refs/heads/branch-2.4
Commit: e4dcce6bccb5e690f5f1ed9c901fc0c7889e2d27
Parents: cd9e149
Author: Dipayan Bhowmick <dipayan.bhowmick@gmail.com>
Authored: Thu Jun 30 18:01:04 2016 +0530
Committer: Dipayan Bhowmick <dipayan.bhowmick@gmail.com>
Committed: Thu Jun 30 18:01:31 2016 +0530

----------------------------------------------------------------------
 .../resources/uploads/parsers/ParseUtils.java   |  60 ++++++---
 .../hive2/resources/uploads/parsers/Parser.java |   4 +-
 .../app/components/validated-text-field.js      |   2 +
 .../ui/hive-web/app/controllers/upload-table.js | 124 +++++++++++--------
 .../ui/hive-web/app/initializers/i18n.js        |   3 +
 .../resources/ui/hive-web/app/styles/app.scss   |   5 -
 .../ui/hive-web/app/templates/upload-table.hbs  |   8 +-
 .../hive2/resources/upload/ParseUtilsTest.java  |  54 ++++++++
 8 files changed, 182 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/ParseUtils.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/ParseUtils.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/ParseUtils.java
index d00dc24..1c8fb70 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/ParseUtils.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/ParseUtils.java
@@ -18,9 +18,11 @@
 
 package org.apache.ambari.view.hive2.resources.uploads.parsers;
 
+import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
@@ -32,9 +34,12 @@ public class ParseUtils {
   protected final static Logger LOG =
     LoggerFactory.getLogger(ParseUtils.class);
 
-  final public static String[] DATE_FORMATS = {"mm/dd/yyyy", "dd/mm/yyyy", "mm-dd-yyyy" /*add
more formatss*/};
+  final public static DataTypes[] dataTypeList = {DataTypes.BOOLEAN, DataTypes.INT, DataTypes.BIGINT,
DataTypes.DOUBLE, DataTypes.CHAR, DataTypes.TIMESTAMP, DataTypes.DATE, DataTypes.STRING};
+  private static final String HIVE_DATE_FORMAT = "yyyy-MM-dd";
+
+  // no strict checking required as it is done by Date parsing
+  private static final String HIVE_DATE_FORMAT_REGEX = "^[0-9]{4}-[0-9]?[1-9]-[0-9]?[0-9]$";
 
-  final public static DataTypes [] dataTypeList = {DataTypes.BOOLEAN,DataTypes.INT,DataTypes.BIGINT,DataTypes.DOUBLE,DataTypes.CHAR,DataTypes.DATE,DataTypes.STRING};
 
   public static boolean isInteger(Object object) {
     if (object == null)
@@ -59,16 +64,11 @@ public class ParseUtils {
       return true;
 
     String strValue = object.toString();
-    if (strValue.equalsIgnoreCase("true") || strValue.equalsIgnoreCase("false"))
-      return true;
-    else
-      return false;
+    return strValue.equalsIgnoreCase("true") || strValue.equalsIgnoreCase("false");
   }
 
   public static boolean isString(Object object) {
-    if (object == null)
-      return false;
-    else return true; // any non null can always be interpreted as a string
+    return object != null;
   }
 
   public static boolean isLong(Object object) {
@@ -109,10 +109,8 @@ public class ParseUtils {
       return true;
 
     String str = object.toString().trim();
-    if (str.length() == 1)
-      return true;
+    return str.length() == 1;
 
-    return false;
   }
 
   public static boolean isDate(Object object) {
@@ -123,13 +121,36 @@ public class ParseUtils {
       return true;
 
     String str = object.toString();
-    for (String format : DATE_FORMATS) {
-      try {
-        Date i = new SimpleDateFormat(format).parse(str);
-        return true;
-      } catch (Exception e) {
+    if (Strings.isNotEmpty(str)) {
+      str = str.trim();
+      if (str.matches(HIVE_DATE_FORMAT_REGEX)) {
+        try {
+          SimpleDateFormat sdf = new SimpleDateFormat(HIVE_DATE_FORMAT);
+          sdf.setLenient(false);
+          Date date = sdf.parse(str);
+          return true;
+        } catch (Exception e) {
+          LOG.debug("error while parsing as date string {}, format {}", str, HIVE_DATE_FORMAT,
e);
+        }
       }
     }
+    return false;
+  }
+
+  public static boolean isTimeStamp(Object object) {
+    if (object == null)
+      return false;
+
+    if (object instanceof Date)
+      return true;
+
+    String str = object.toString();
+    try {
+      Timestamp ts = Timestamp.valueOf(str);
+      return true;
+    } catch (Exception e) {
+      LOG.debug("error while parsing as timestamp string {}", str, e);
+    }
 
     return false;
   }
@@ -141,6 +162,7 @@ public class ParseUtils {
     if (isLong(object)) return DataTypes.BIGINT;
     if (isDouble(object)) return DataTypes.DOUBLE;
     if (isChar(object)) return DataTypes.CHAR;
+    if (isTimeStamp(object)) return DataTypes.TIMESTAMP;
     if (isDate(object)) return DataTypes.DATE;
 
     return DataTypes.STRING;
@@ -161,6 +183,8 @@ public class ParseUtils {
         return isChar(object);
       case DATE:
         return isDate(object);
+      case TIMESTAMP:
+        return isTimeStamp(object);
       case STRING:
         return isString(object);
 
@@ -171,7 +195,7 @@ public class ParseUtils {
   }
 
   public static DataTypes detectHiveColumnDataType(List<Object> colValues) {
-    boolean found = true;
+    boolean found;
     for(DataTypes datatype : dataTypeList){
       found = true;
       for(Object object : colValues){

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/Parser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/Parser.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/Parser.java
index 847a4b8..2623c4c 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/Parser.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/uploads/parsers/Parser.java
@@ -88,7 +88,7 @@ public abstract class Parser implements IParser {
     }
 
     int numberOfRows = numberOfPreviewRows;
-    previewRows = new ArrayList<Row>(numberOfPreviewRows + 1); // size including the
header.
+    previewRows = new ArrayList<>(numberOfPreviewRows + 1); // size including the header.
 
     Row headerRow = null;
     Integer numOfCols = null;
@@ -119,8 +119,6 @@ public abstract class Parser implements IParser {
 
       for (int colNum = 0; colNum < numOfCols; colNum++) {
         if(colNum < values.length) {
-          // detect type
-          ColumnDescription.DataTypes type = ParseUtils.detectHiveDataType(values[colNum]);
           newValues[colNum] = values[colNum];
         }else{
           newValues[colNum] = null;

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/components/validated-text-field.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/components/validated-text-field.js
b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/components/validated-text-field.js
index 50cea36..2379a15 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/components/validated-text-field.js
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/components/validated-text-field.js
@@ -26,6 +26,8 @@ import Ember from 'ember';
  * {{/validated-text-field}}
  */
 export default Ember.Component.extend({
+  classNameBindings: ['tagClassName'],
+  tagClassName : false, // set it to non false value if you want a specific class to be assigned
   allowEmpty: true,
   valid: true,
   setValid: function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
index 84637e5..6fa6cfd 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
@@ -24,6 +24,7 @@ import constants from 'hive/utils/constants';
 export default Ember.Controller.extend({
   COLUMN_NAME_REGEX: "^[a-zA-Z]{1}[a-zA-Z0-9_]*$",
   TABLE_NAME_REGEX: "^[a-zA-Z]{1}[a-zA-Z0-9_]*$",
+  HDFS_PATH_REGEX: "^[/]{1}.+",  // unix path allows everything but here we have to mention
full path so starts with /
   isLocalUpload: Ember.computed.equal("uploadSource", "local"),
   uploadSource: "local",
   COLUMN_NAME_PREFIX : "column",
@@ -118,7 +119,7 @@ export default Ember.Controller.extend({
           this.get('rows').unshiftObject({row: this.get('firstRow')});
           this._setHeaderElements(this.get('header'),this.get('defaultColumnNames'));
         }
-      } else if( this.get('header') ) { // headers are available
+      } else if (this.get('header')) { // headers are available
         // take first row of
         this._setHeaderElements(this.get('header'),this.get('firstRow'));
         this.get('rows').removeAt(0);
@@ -128,7 +129,7 @@ export default Ember.Controller.extend({
     }
   }.observes('isFirstRowHeader'),
 
-  popUploadProgressInfos : function(){
+  popUploadProgressInfos: function () {
     var msg = this.get('uploadProgressInfos').popObject();
   },
 
@@ -177,11 +178,11 @@ export default Ember.Controller.extend({
       "firstRow : ", this.get('firstRow'));
   },
 
-  generateTempTableName : function(){
+  generateTempTableName: function () {
     var text = "";
     var possible = "abcdefghijklmnopqrstuvwxyz";
 
-    for( var i=0; i < 30; i++ )
+    for (var i = 0; i < 30; i++)
       text += possible.charAt(Math.floor(Math.random() * possible.length));
 
     return text;
@@ -214,29 +215,52 @@ export default Ember.Controller.extend({
   uploadForPreview: function (files) {
     console.log("uploaderForPreview called.");
     var self = this;
-    return this.get('uploader').uploadFiles('preview', files, {"isFirstRowHeader" : self.get("isFirstRowHeader"),
"inputFileType" : self.get("inputFileType").id});
+    return this.get('uploader').uploadFiles('preview', files, {
+      "isFirstRowHeader": self.get("isFirstRowHeader"),
+      "inputFileType": self.get("inputFileType").id
+    });
   },
 
-  uploadForPreviewFromHDFS : function(){
+  uploadForPreviewFromHDFS: function () {
     console.log("uploadForPreviewFromHDFS called.");
-    return this.get('uploader').previewFromHDFS({"isFirstRowHeader" : this.get("isFirstRowHeader"),"inputFileType"
: this.get("inputFileType").id , "hdfsPath" : this.get("hdfsPath") });
+    var hdfsPath = this.get("hdfsPath");
+    this.validateHDFSPath(hdfsPath);
+    return this.get('uploader').previewFromHDFS({
+      "isFirstRowHeader": this.get("isFirstRowHeader"),
+      "inputFileType": this.get("inputFileType").id,
+      "hdfsPath": hdfsPath
+    });
   },
 
-  generatePreview : function(files){
+  generatePreview: function (files) {
     var self = this;
     var promise = null;
-    this.waitForGeneratingPreview();
-    if(this.get('isLocalUpload')){
-      promise = this.uploadForPreview(files);
-    }else{
-      promise = this.uploadForPreviewFromHDFS();
-    }
+    try {
+      this.waitForGeneratingPreview();
+      if (this.get('isLocalUpload')) {
+        promise = this.uploadForPreview(files);
+      } else {
+        promise = this.uploadForPreviewFromHDFS();
+      }
 
-    return promise.then(function (data) {
+      return promise.then(function (data) {
         self.onGeneratePreviewSuccess(data);
-    }, function (error) {
+      }, function (error) {
         self.onGeneratePreviewFailure(error);
-    });
+      }).catch(function (error) {
+        console.log("inside catch : ", error);
+      }).finally(function () {
+        console.log("finally hide the modal always after preview.");
+        self.hideUploadModal();
+      });
+    }catch(e){
+      // exception before promise will be caught here.
+      console.log("exception before promise : ", e);
+      self.setError(e);
+    }finally{
+      console.log("finally hide the modal always after preview.");
+      self.hideUploadModal();
+    }
   },
 
   waitForGeneratingPreview: function () {
@@ -255,9 +279,9 @@ export default Ember.Controller.extend({
     this.set("header", data.header);
     this.set("firstRow", data.rows[0].row);
     this.set('isFirstRowHeader', data.isFirstRowHeader);
-    this.set('tableName',data.tableName);
-    if(data.isFirstRowHeader == true){
-        data.rows = data.rows.slice(1);
+    this.set('tableName', data.tableName);
+    if (data.isFirstRowHeader == true) {
+      data.rows = data.rows.slice(1);
     }
     this.set("rows", data.rows);
   },
@@ -276,7 +300,7 @@ export default Ember.Controller.extend({
     this.setError(error);
   },
 
-  createActualTable : function(){
+  createActualTable: function () {
     console.log("createActualTable");
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.startingToCreateActualTable'));
     var headers = this.get('header');
@@ -315,30 +339,30 @@ export default Ember.Controller.extend({
     return p;
   },
 
-  onCreateActualTableSuccess : function(){
+  onCreateActualTableSuccess: function () {
     console.log("onCreateTableSuccess");
     this.popUploadProgressInfos();
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.successfullyCreatedActualTable'));
   },
 
-  onCreateActualTableFailure : function(error){
+  onCreateActualTableFailure: function (error) {
     console.log("onCreateActualTableFailure");
     this.popUploadProgressInfos();
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.failedToCreateActualTable'));
     this.setError(error);
   },
 
-  createTempTable : function(){
+  createTempTable: function () {
     console.log("createTempTable");
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.startingToCreateTemporaryTable'));
     var tempTableName = this.generateTempTableName();
-    this.set('tempTableName',tempTableName);
+    this.set('tempTableName', tempTableName);
     return this.get('uploader').createTable({
       "isFirstRowHeader": this.get("isFirstRowHeader"),
       "header": this.get("header"),
       "tableName": tempTableName,
       "databaseName": this.get('databaseName'),
-      "fileType":"TEXTFILE"
+      "fileType": "TEXTFILE"
     });
   },
 
@@ -354,7 +378,7 @@ export default Ember.Controller.extend({
     return p;
   },
 
-  onCreateTempTableSuccess : function(){
+  onCreateTempTableSuccess: function () {
     console.log("onCreateTempTableSuccess");
     this.popUploadProgressInfos();
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.successfullyCreatedTemporaryTable'));
@@ -369,20 +393,20 @@ export default Ember.Controller.extend({
     });
   },
 
-  deleteTableOnError : function(databaseName,tableName, tableLabel){
-      //delete table and wait for delete job
+  deleteTableOnError: function (databaseName, tableName, tableLabel) {
+    //delete table and wait for delete job
     var self = this;
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.deletingTable',{table:tableLabel}));
 
-    return this.deleteTable(databaseName,tableName).then(function(data){
-      return new Ember.RSVP.Promise(function(resolve,reject){
-        self.waitForJobStatus(data.jobId,resolve,reject);
+    return this.deleteTable(databaseName, tableName).then(function (data) {
+      return new Ember.RSVP.Promise(function (resolve, reject) {
+        self.waitForJobStatus(data.jobId, resolve, reject);
       });
-    }).then(function(){
+    }).then(function () {
       self.popUploadProgressInfos();
       self.pushUploadProgressInfos(this.formatMessage('hive.messages.succesfullyDeletedTable',{table:tableLabel}));
       return Ember.RSVP.Promise.resolve();
-    },function(err){
+    }, function (err) {
       self.popUploadProgressInfos();
       self.pushUploadProgressInfos(this.formatMessage('hive.messages.failedToDeleteTable',{table:tableLabel}));
       self.setError(err);
@@ -404,15 +428,15 @@ export default Ember.Controller.extend({
     console.log("onCreateTempTableFailure");
     this.setError(error);
     this.popUploadProgressInfos();
-    this.pushUploadProgressInfos();
+    this.pushUploadProgressInfos(this.formatMessage('hive.messages.failedToCreateTemporaryTable'));
     return this.rollBackActualTableCreation().then(function(data){
       return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
-    },function(err){
+    }, function (err) {
       return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
     });
   },
 
-  uploadFile : function(){
+  uploadFile: function () {
     console.log("uploadFile");
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.startingToUploadFile'));
     if( this.get("isLocalUpload")){
@@ -443,7 +467,7 @@ export default Ember.Controller.extend({
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.successfullyUploadedFile')
);
   },
 
-  rollBackTempTableCreation : function(){
+  rollBackTempTableCreation: function () {
     var self = this;
     return this.deleteTableOnError(this.get("databaseName"),this.get("tempTableName"),this.translate('hive.words.temporary')).then(function(data){
       return self.rollBackActualTableCreation();
@@ -473,7 +497,7 @@ export default Ember.Controller.extend({
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.startingToInsertRows'));
 
     return this.get('uploader').insertIntoTable({
-      "fromDatabase":  this.get("databaseName"),
+      "fromDatabase": this.get("databaseName"),
       "fromTable": this.get("tempTableName"),
       "toDatabase": this.get("databaseName"),
       "toTable": this.get("tableName")
@@ -492,13 +516,13 @@ export default Ember.Controller.extend({
     return p;
   },
 
-  onInsertIntoTableSuccess : function(){
+  onInsertIntoTableSuccess: function () {
     console.log("onInsertIntoTableSuccess");
     this.popUploadProgressInfos();
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.successfullyInsertedRows'));
   },
 
-  onInsertIntoTableFailure : function(error){
+  onInsertIntoTableFailure: function (error) {
     console.log("onInsertIntoTableFailure");
     this.setError(error);
     this.popUploadProgressInfos();
@@ -532,20 +556,20 @@ export default Ember.Controller.extend({
     return p;
   },
 
-  onDeleteTempTableSuccess : function(){
+  onDeleteTempTableSuccess: function () {
     console.log("onDeleteTempTableSuccess");
     this.popUploadProgressInfos();
     this.pushUploadProgressInfos(this.formatMessage('hive.messages.successfullyDeletedTemporaryTable'));
     this.onUploadSuccessfull();
   },
 
-  onDeleteTempTableFailure : function(error){
+  onDeleteTempTableFailure: function (error) {
     console.log("onDeleteTempTableFailure");
     this.setError(error);
     this.setError(this.formatMessage('hive.messages.manuallyDeleteTable',{databaseName:this.get('databaseName'),
tableName: this.get("tempTableName")}));
   },
 
-  createTableAndUploadFile : function(){
+  createTableAndUploadFile: function () {
     var self = this;
     self.setError();
     self.createActualTable()
@@ -746,20 +770,20 @@ export default Ember.Controller.extend({
       var self = this;
       return this.generatePreview(files)
     },
-    previewFromHdfs : function(){
+    previewFromHdfs: function () {
       return this.generatePreview();
     },
-    uploadTable : function(){
-      try{
+    uploadTable: function () {
+      try {
         this.createTableAndUploadFile();
-      }catch(e){
+      } catch (e) {
         console.log("exception occured : ", e);
         this.setError(e);
         this.hideUploadModal();
       }
     },
-    uploadFromHDFS : function(){
-      this.set("isLocalUpload",false);
+    uploadFromHDFS: function () {
+      this.set("isLocalUpload", false);
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
index 578101f..a00f0b4 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
@@ -304,6 +304,9 @@ TRANSLATIONS = {
       'isFirstRowHeader':"Is first row header ?",
       'columnNameTooltip':"Enter valid (alphanumeric + underscore) column name.",
       'columnNameErrorMessage':"Only alphanumeric and underscore characters are allowed in
column names.",
+      'hdfsFieldTooltip':"Enter full HDFS path",
+      'hdfsFieldPlaceholder':"Enter full HDFS path",
+      'hdfsFieldErrorMessage':"Please enter complete path of hdfs file to upload."
 
     }
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/styles/app.scss
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/styles/app.scss b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/styles/app.scss
index d72ae8c..f0c9a4c 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/styles/app.scss
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/styles/app.scss
@@ -650,11 +650,6 @@ td.data-upload-form-field {
   display: inline;
 }
 
-#hdfs-param input {
-  width: 80%;
-  display: inline;
-}
-
 #visualization{
     .max-rows {
       float: right;

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/templates/upload-table.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/templates/upload-table.hbs
b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/templates/upload-table.hbs
index f334a3d..5e3a519 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/templates/upload-table.hbs
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/templates/upload-table.hbs
@@ -69,13 +69,17 @@
           }}
         </td>
 
-
         {{#if isLocalUpload }}
           <td class="data-upload-form-label"><label>{{t "hive.ui.selectFromLocal"}}</label></td>
           <td class="data-upload-form-field">{{file-upload  filesUploaded="filesUploaded"
 uploadFiles=files}}</td>
         {{else}}
           <td class="data-upload-form-label"><label>{{t "hive.ui.hdfsPath"}}</label></td>
-          <td class="data-upload-form-field" id="hdfs-param">{{input type="text" class="form-control"
placeholder="Enter full HDFS path" value=hdfsPath }}
+          <td class="data-upload-form-field" id="hdfs-param">
+            {{#validated-text-field inputValue=hdfsPath allowEmpty=false tagClassName="hdfsPath"
+            tooltip=(t "hive.ui.hdfsFieldTooltip") placeholder=(t "hive.ui.hdfsFieldPlaceholder")
+            invalidClass='form-control hdfsPath red-border' validClass='form-control hdfsPath'
regex=HDFS_PATH_REGEX
+            errorMessage=(t "hive.ui.hdfsFieldErrorMessage")  }}
+            {{/validated-text-field}}
             <button style="margin-left: 5px; padding-top: 6px;padding-bottom: 6px; padding-right:
10px; padding-left: 10px;" type="button" {{action "previewFromHdfs"}}
             {{bind-attr class=":btn :btn-sm :btn-default"}}>{{t "buttons.showPreview"}}</button></td>
         {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e4dcce6b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/resources/upload/ParseUtilsTest.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/resources/upload/ParseUtilsTest.java
b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/resources/upload/ParseUtilsTest.java
new file mode 100644
index 0000000..e540879
--- /dev/null
+++ b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/resources/upload/ParseUtilsTest.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <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.hive2.resources.upload;
+
+import org.apache.ambari.view.hive2.resources.uploads.parsers.ParseUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ParseUtilsTest {
+  @Test
+  public void testDateFormats() {
+    Assert.assertTrue(ParseUtils.isDate("1970-01-01"));
+    Assert.assertTrue(ParseUtils.isDate("1970-01-01 "));
+    Assert.assertTrue(ParseUtils.isDate("0001-1-3"));
+    Assert.assertTrue(ParseUtils.isDate("1996-1-03"));
+    Assert.assertTrue(ParseUtils.isDate("1996-01-3"));
+    Assert.assertFalse(ParseUtils.isDate("1970-01-01 01:01:01"));
+    Assert.assertFalse(ParseUtils.isDate("1970-01-01 23:59:59.999999"));
+    Assert.assertFalse(ParseUtils.isDate("1970/01/01"));
+    Assert.assertFalse(ParseUtils.isDate("01-01-1970"));
+    Assert.assertFalse(ParseUtils.isDate("1970-13-01"));
+    Assert.assertFalse(ParseUtils.isDate("1970-01-32"));
+    Assert.assertFalse(ParseUtils.isDate("01/01/1970"));
+    Assert.assertFalse(ParseUtils.isDate("001-1-3"));
+  }
+
+  @Test
+  public void testTimestampFormats() {
+    Assert.assertFalse(ParseUtils.isTimeStamp("1999-11-30"));
+    Assert.assertFalse(ParseUtils.isTimeStamp("1999-12-31 23:59"));
+    Assert.assertTrue(ParseUtils.isTimeStamp("1999-12-31 23:59:59"));
+    Assert.assertTrue(ParseUtils.isTimeStamp("1999-12-31 23:59:59.100"));
+    Assert.assertTrue(ParseUtils.isTimeStamp("1999-12-31 23:59:59.999999"));
+    Assert.assertTrue(ParseUtils.isTimeStamp("1999-12-31 23:59:59.99999999"));
+    Assert.assertTrue(ParseUtils.isTimeStamp("1999-12-31 23:59:59.999999999"));
+    Assert.assertFalse(ParseUtils.isTimeStamp("1999-12-31 23:59:59.9999999999"));
+    Assert.assertFalse(ParseUtils.isTimeStamp("1999/12/31 23:59:59.9999999999"));
+  }
+}


Mime
View raw message