Repository: ambari Updated Branches: refs/heads/trunk 9550b870b -> f8257e587
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/f8257e58 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f8257e58 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f8257e58 Branch: refs/heads/trunk Commit: f8257e587368210edaff267e012ef2bd82e240c4 Parents: 9550b87 Author: Dipayan Bhowmick <[email protected]> Authored: Thu Jun 30 18:01:04 2016 +0530 Committer: Dipayan Bhowmick <[email protected]> Committed: Thu Jun 30 18:01:04 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/f8257e58/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/f8257e58/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/f8257e58/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/f8257e58/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/f8257e58/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/f8257e58/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/f8257e58/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/f8257e58/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")); + } +}
