/*******************************************************************************
* Copyright 2017 Capital One Services, LLC and Bitwise, Inc.
* Licensed 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 hydrograph.ui.propertywindow.widgets.utility;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.slf4j.Logger;
import hydrograph.ui.common.util.Constants;
import hydrograph.ui.common.util.CustomColorRegistry;
import hydrograph.ui.datastructure.property.FixedWidthGridRow;
import hydrograph.ui.datastructure.property.GenerateRecordSchemaGridRow;
import hydrograph.ui.datastructure.property.GridRow;
import hydrograph.ui.datastructure.property.MixedSchemeGridRow;
import hydrograph.ui.datastructure.property.XPathGridRow;
import hydrograph.ui.logging.factory.LogFactory;
public class SchemaRowValidation{
private static final Logger logger = LogFactory.INSTANCE.getLogger(SchemaRowValidation.class);
private static final String NONE = "none";
private static final String REGULAR_EXPRESSION_FOR_NUMBER = "\\d+";
private static final String PARQUET = "parquet";
private static final String HIVE = "hive";
private static final String JAVA_MATH_BIG_DECIMAL = "java.math.BigDecimal";
private static final String JAVA_UTIL_DATE = "java.util.Date";
private static final String JAVA_LANG_INTEGER = "java.lang.Integer";
private static final String JAVA_LANG_DOUBLE = "java.lang.Double";
private static final String JAVA_LANG_FLOAT = "java.lang.Float";
private static final String JAVA_LANG_SHORT = "java.lang.Short";
private static final String JAVA_LANG_LONG = "java.lang.Long";
private boolean invalidDateFormat = false;
private boolean invalidLength = false;
private boolean isRowInvalid;
public static final SchemaRowValidation INSTANCE = new SchemaRowValidation();
private SchemaRowValidation(){
}
/**
* @param gridRow
* @param item
* @param table
* @param componentType
*
* This method highlight invalid data row with red color.
*
*/
public void highlightInvalidRowWithRedColor(GridRow gridRow,TableItem item,Table table,String componentType ){
if(item==null){
for(TableItem tableItem:table.getItems()){
setRedColorOnTableRowBasedOnInvalidData((GridRow)tableItem.getData(), componentType, tableItem);
}
}else{
setRedColorOnTableRowBasedOnInvalidData(gridRow, componentType, item);
gridRow=null;
}
}
private void setRedColorOnTableRowBasedOnInvalidData(GridRow gridRow,
String componentType, TableItem tableItem){
if(!gridRow.getFieldName().matches(Constants.REGEX)){
setRedColor(tableItem);
}
else if(gridRow instanceof FixedWidthGridRow){
if(gridRow instanceof GenerateRecordSchemaGridRow){
executeIfObjectIsGenerateRecordRow(gridRow, componentType, tableItem);
}else{
executeIfObjectIsFixedWidthRow(gridRow, componentType, tableItem);
}
}
else if(gridRow instanceof GridRow){
validationCheckForBigDecimalAndDateDatatype(gridRow, componentType, tableItem);
if(!isRowInvalid)
{
if(gridRow instanceof XPathGridRow){
validationCheckForXpathGridRow(gridRow,tableItem);
}
}
}
}
private void validationCheckForXpathGridRow(GridRow gridRow,TableItem tableItem) {
if(StringUtils.isBlank(((XPathGridRow)gridRow).getXPath())){
setRedColor(tableItem);
}
else{
setBlackColor(tableItem);
}
}
private void validationCheckForBigDecimalAndDateDatatype(GridRow gridRow, String componentType, TableItem tableItem){
if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(), JAVA_MATH_BIG_DECIMAL)){
validationCheckForBigDecimalDatatype(gridRow, componentType, tableItem);
}else if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(),JAVA_UTIL_DATE)){
validationCheckForDateDatatype(gridRow, tableItem);
}
else{
setBlackColor(tableItem);
}
}
private void executeIfObjectIsFixedWidthRow(GridRow gridRow,
String componentType, TableItem tableItem){
if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(), JAVA_MATH_BIG_DECIMAL)){
if(validationCheckForBigDecimalDatatype(gridRow, componentType, tableItem))
return;
}else if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(),JAVA_UTIL_DATE)){
validationCheckForDateDatatype(gridRow, tableItem);
return;
}
FixedWidthGridRow fixedWidthGridRow=(FixedWidthGridRow)gridRow;
if(fixedWidthGridRow instanceof MixedSchemeGridRow){
if((StringUtils.isBlank(fixedWidthGridRow.getDelimiter()) && StringUtils.isBlank(fixedWidthGridRow.getLength()))
||(StringUtils.isNotBlank(fixedWidthGridRow.getDelimiter()) && StringUtils.isNotBlank(fixedWidthGridRow.getLength()))
||(StringUtils.isNotBlank(fixedWidthGridRow.getLength()) && (fixedWidthGridRow.getLength().equals("0") ))
||(StringUtils.isNotBlank(fixedWidthGridRow.getLength())&& !(fixedWidthGridRow.getLength().matches(REGULAR_EXPRESSION_FOR_NUMBER)))
){
setRedColor(tableItem);
invalidLength = true;
}else{
setBlackColor(tableItem);
invalidLength = false;
}
}else{
if(StringUtils.isBlank(fixedWidthGridRow.getLength())||!(fixedWidthGridRow.getLength().matches(REGULAR_EXPRESSION_FOR_NUMBER))|| (fixedWidthGridRow.getLength().equals("0"))){
setRedColor(tableItem);
invalidLength = true;
}else{
setBlackColor(tableItem);
invalidLength = false;
}
}
}
private boolean validateSchemaRangeForDate(GenerateRecordSchemaGridRow generateRecordSchemaGridRow){
Date rangeFromDate = null, rangeToDate = null;
SimpleDateFormat formatter = new SimpleDateFormat(generateRecordSchemaGridRow.getDateFormat());
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeFrom())){
try{
rangeFromDate = formatter.parse(generateRecordSchemaGridRow.getRangeFrom());
}catch (ParseException e){
return true;
}
}
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeTo())){
try{
rangeToDate = formatter.parse(generateRecordSchemaGridRow.getRangeTo());
}catch (ParseException e){
return true;
}
}
if (rangeFromDate != null && rangeToDate != null && rangeFromDate.after(rangeToDate)){
return true;
}
return false;
}
private boolean validateSchemaRangeForBigDecimal(GenerateRecordSchemaGridRow generateRecordSchemaGridRow){
BigDecimal rangeFrom = null, rangeTo = null;
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeFrom()) && generateRecordSchemaGridRow.getRangeFrom().matches(REGULAR_EXPRESSION_FOR_NUMBER)){
rangeFrom = new BigDecimal(generateRecordSchemaGridRow.getRangeFrom());
}
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeTo()) && generateRecordSchemaGridRow.getRangeTo().matches(REGULAR_EXPRESSION_FOR_NUMBER)){
rangeTo = new BigDecimal(generateRecordSchemaGridRow.getRangeTo());
}
if (rangeFrom != null && rangeTo != null){
if (rangeFrom.compareTo(rangeTo) > 0){
return true;
}
}
if (!generateRecordSchemaGridRow.getLength().isEmpty()){
int fieldLength = 0, scaleLength = 0;
fieldLength = Integer.parseInt(generateRecordSchemaGridRow.getLength());
if (!generateRecordSchemaGridRow.getScale().isEmpty()){
scaleLength = Integer.parseInt(generateRecordSchemaGridRow.getScale());
}
if (fieldLength < 0){
return true;
}else if (scaleLength < 0){
return true;
}else if (scaleLength >= fieldLength){
return true;
}else{
String minPermissibleRangeValue = "", maxPermissibleRangeValue = "";
for (int i = 1; i <= fieldLength; i++){
maxPermissibleRangeValue = maxPermissibleRangeValue.concat("9");
if (minPermissibleRangeValue.trim().length() == 0){
minPermissibleRangeValue = minPermissibleRangeValue.concat("-");
}else{
minPermissibleRangeValue = minPermissibleRangeValue.concat("9");
}
}
if(minPermissibleRangeValue.equals("-")){
minPermissibleRangeValue = "0";
}
if (scaleLength != 0){
int decimalPosition = fieldLength - scaleLength;
if (decimalPosition == 1){
minPermissibleRangeValue = "0";
maxPermissibleRangeValue = maxPermissibleRangeValue.replaceFirst("9", ".");
}else{
minPermissibleRangeValue = minPermissibleRangeValue.substring(0, decimalPosition - 1)
+ "." + minPermissibleRangeValue.substring(decimalPosition);
}
maxPermissibleRangeValue = maxPermissibleRangeValue.substring(0, decimalPosition - 1)
+ "." + maxPermissibleRangeValue.substring(decimalPosition);
}
if(fieldLength == 0){
minPermissibleRangeValue = "0";
maxPermissibleRangeValue = "0";
}
BigDecimal minRangeValue = new BigDecimal(minPermissibleRangeValue);
BigDecimal maxRangeValue = new BigDecimal(maxPermissibleRangeValue);
if(checkIfSchemaRangeAndLengethIsInvalid(rangeFrom, fieldLength, rangeTo, minRangeValue, maxRangeValue)){
return true;
}
}
}
return false;
}
private boolean checkIfSchemaRangeAndLengethIsInvalid(BigDecimal rangeFrom, int fieldLength, BigDecimal rangeTo,
BigDecimal minRangeValue, BigDecimal maxRangeValue) {
if (rangeFrom != null && fieldLength > 0 && rangeTo != null){
if (rangeFrom.compareTo(minRangeValue) < 0){
return true;
}else if(rangeTo.compareTo(maxRangeValue) > 0){
return true;
}
}else if(rangeFrom != null && fieldLength > 0 && rangeTo == null){
if (rangeFrom.compareTo(maxRangeValue) > 0){
return true;
}
}else if(rangeFrom == null && fieldLength > 0 && rangeTo != null){
if (rangeTo.compareTo(minRangeValue) < 0){
return true;
}
}
return false;
}
private boolean validateSchemaRangeForDoubleFloatIntegerLongShort(GenerateRecordSchemaGridRow generateRecordSchemaGridRow) {
BigDecimal rangeFrom = null, rangeTo = null;
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeFrom())){
rangeFrom = new BigDecimal(generateRecordSchemaGridRow.getRangeFrom());
}
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeTo())){
rangeTo = new BigDecimal(generateRecordSchemaGridRow.getRangeTo());
}
if (rangeFrom != null && rangeTo != null){
if (rangeFrom.compareTo(rangeTo) > 0){
return true;
}
}
if (!generateRecordSchemaGridRow.getLength().isEmpty()){
int fieldLength = Integer.parseInt(generateRecordSchemaGridRow.getLength());
if (fieldLength < 0){
return true;
}else{
String minPermissibleRangeValue = "", maxPermissibleRangeValue = "";
for (int i = 1; i <= fieldLength; i++){
maxPermissibleRangeValue = maxPermissibleRangeValue.concat("9");
if (minPermissibleRangeValue.trim().length() == 0){
minPermissibleRangeValue = minPermissibleRangeValue.concat("-");
}else{
minPermissibleRangeValue = minPermissibleRangeValue.concat("9");
}
}
if(fieldLength == 0){
minPermissibleRangeValue = "0";
maxPermissibleRangeValue = "0";
}
if(minPermissibleRangeValue.equals("-")){
minPermissibleRangeValue = "0";
}
BigDecimal minRangeValue = new BigDecimal(minPermissibleRangeValue);
BigDecimal maxRangeValue = new BigDecimal(maxPermissibleRangeValue);
if(checkIfSchemaRangeAndLengethIsInvalid(rangeFrom, fieldLength, rangeTo, minRangeValue, maxRangeValue)){
return true;
}
}
}
return false;
}
private void executeIfObjectIsGenerateRecordRow(GridRow gridRow, String componentType, TableItem tableItem){
GenerateRecordSchemaGridRow generateRecordSchemaGridRow = (GenerateRecordSchemaGridRow) gridRow;
boolean isRedColor = false;
if (StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeFrom())
|| StringUtils.isNotBlank(generateRecordSchemaGridRow.getRangeTo())){
if (StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_UTIL_DATE)){
isRedColor = validateSchemaRangeForDate(generateRecordSchemaGridRow);
}else if (StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_MATH_BIG_DECIMAL)){
isRedColor = validateSchemaRangeForBigDecimal(generateRecordSchemaGridRow);
}else if (StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_LANG_DOUBLE)
|| StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_LANG_FLOAT)
|| StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_LANG_INTEGER)
|| StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_LANG_LONG)
|| StringUtils.equalsIgnoreCase(generateRecordSchemaGridRow.getDataTypeValue(), JAVA_LANG_SHORT)){
isRedColor = validateSchemaRangeForDoubleFloatIntegerLongShort(generateRecordSchemaGridRow);
}
}
if (isRedColor){
setRedColor(tableItem);
}else{
if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(), JAVA_MATH_BIG_DECIMAL)){
validationCheckForBigDecimalDatatype(gridRow, componentType, tableItem);
}else if(StringUtils.equalsIgnoreCase(gridRow.getDataTypeValue(),JAVA_UTIL_DATE)){
validationCheckForDateDatatype(gridRow, tableItem);
}else{
setBlackColor(tableItem);
}
}
}
private void setBlackColor(TableItem tableItem){
tableItem.setForeground(CustomColorRegistry.INSTANCE.getColorFromRegistry( 0, 0, 0));
isRowInvalid=false;
}
private void setRedColor(TableItem tableItem){
tableItem.setForeground(CustomColorRegistry.INSTANCE.getColorFromRegistry( 255, 0, 0));
isRowInvalid=true;
}
private void validationCheckForDateDatatype(GridRow gridRow, TableItem tableItem){
if((StringUtils.isBlank(gridRow.getDateFormat()))){
setRedColor(tableItem);
invalidDateFormat = true;
}else{
setBlackColor(tableItem);
invalidDateFormat = false;
}
}
private boolean validationCheckForBigDecimalDatatype(GridRow gridRow,
String componentType, TableItem tableItem){
int precision = 0 , scale = 0 ;
if(StringUtils.isNotBlank(gridRow.getPrecision()) && StringUtils.isNotBlank(gridRow.getScale())){
try{
precision = Integer.parseInt(gridRow.getPrecision());
}
catch(NumberFormatException exception){
logger.debug("Failed to parse the precision ", exception);
return false;
}
try{
scale = Integer.parseInt(gridRow.getScale());
}
catch(NumberFormatException exception){
logger.debug("Failed to parse the scale ", exception);
return false;
}
}
if(StringUtils.containsIgnoreCase(componentType, HIVE)||StringUtils.containsIgnoreCase(componentType, PARQUET)){
if(StringUtils.isBlank(gridRow.getPrecision())|| StringUtils.isBlank(gridRow.getScale()) ||
StringUtils.equalsIgnoreCase(gridRow.getScaleTypeValue(), NONE)||
!(gridRow.getScale().matches(REGULAR_EXPRESSION_FOR_NUMBER))||!(gridRow.getPrecision().matches(REGULAR_EXPRESSION_FOR_NUMBER))
|| precision <= scale){
setRedColor(tableItem);
return true;
}else{
setBlackColor(tableItem);
return false;
}
}else if(StringUtils.isBlank(gridRow.getScale()) ||
StringUtils.equalsIgnoreCase(gridRow.getScaleTypeValue(), NONE)||
!(gridRow.getScale().matches(REGULAR_EXPRESSION_FOR_NUMBER))||(!(gridRow.getPrecision().matches(REGULAR_EXPRESSION_FOR_NUMBER))&&
StringUtils.isNotBlank(gridRow.getPrecision()))){
setRedColor(tableItem);
return true;
}else{
setBlackColor(tableItem);
return false;
}
}
}