/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* 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 org.drools.workbench.screens.dtablexls.backend.server.conversion;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.drools.workbench.models.datamodel.oracle.DataType;
import org.drools.workbench.models.guided.dtable.shared.model.DTCellValue52;
import org.kie.workbench.common.services.shared.preferences.ApplicationPreferences;
/**
* Utilities relating to the use of DTCellValue's
*/
public class DTCellValueUtilities {
private static final String DATE_FORMAT = ApplicationPreferences.getDroolsDateFormat();
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat(DATE_FORMAT);
/**
* Callback to record data-type conversion errors.
*/
public interface ConversionErrorCallback {
/**
* Called when a conversion error occurred.
* @param value The value being converted.
* @param dataType The target data-type to which the value is being converted.
*/
void onConversionError(final String value,
final DataType.DataTypes dataType);
}
/**
* The column-data type is looked up from the SuggestionCompletionEngine and
* represents the *true* data-type that the column represents. The data-type
* associated with the Cell Value can be incorrect for legacy models. For
* pre-5.2 they will always be String and for pre-5.4 numerical fields are
* always Numeric
* @param type
* @param dcv
*/
public static void assertDTCellValue(final String type,
final DTCellValue52 dcv,
final ConversionErrorCallback callback) {
if (dcv == null) {
return;
}
//If already converted exit
final DataType.DataTypes dataType = convertToTypeSafeType(type);
if (dataType.equals(dcv.getDataType())) {
return;
}
switch (dcv.getDataType()) {
case NUMERIC:
convertDTCellValueFromNumeric(dataType,
dcv);
break;
default:
convertDTCellValueFromString(dataType,
dcv,
callback);
}
}
private static DataType.DataTypes convertToTypeSafeType(final String type) {
if (type.equals(DataType.TYPE_NUMERIC)) {
return DataType.DataTypes.NUMERIC;
} else if (type.equals(DataType.TYPE_NUMERIC_BIGDECIMAL)) {
return DataType.DataTypes.NUMERIC_BIGDECIMAL;
} else if (type.equals(DataType.TYPE_NUMERIC_BIGINTEGER)) {
return DataType.DataTypes.NUMERIC_BIGINTEGER;
} else if (type.equals(DataType.TYPE_NUMERIC_BYTE)) {
return DataType.DataTypes.NUMERIC_BYTE;
} else if (type.equals(DataType.TYPE_NUMERIC_DOUBLE)) {
return DataType.DataTypes.NUMERIC_DOUBLE;
} else if (type.equals(DataType.TYPE_NUMERIC_FLOAT)) {
return DataType.DataTypes.NUMERIC_FLOAT;
} else if (type.equals(DataType.TYPE_NUMERIC_INTEGER)) {
return DataType.DataTypes.NUMERIC_INTEGER;
} else if (type.equals(DataType.TYPE_NUMERIC_LONG)) {
return DataType.DataTypes.NUMERIC_LONG;
} else if (type.equals(DataType.TYPE_NUMERIC_SHORT)) {
return DataType.DataTypes.NUMERIC_SHORT;
} else if (type.equals(DataType.TYPE_BOOLEAN)) {
return DataType.DataTypes.BOOLEAN;
} else if (type.equals(DataType.TYPE_DATE)) {
return DataType.DataTypes.DATE;
}
return DataType.DataTypes.STRING;
}
//If the Decision Table model has been converted from the legacy text based
//class then all values are held in the DTCellValue's StringValue. This
//function attempts to set the correct DTCellValue property based on
//the DTCellValue's data type.
private static void convertDTCellValueFromString(final DataType.DataTypes dataType,
final DTCellValue52 dcv,
final ConversionErrorCallback callback) {
String text = dcv.getStringValue();
switch (dataType) {
case BOOLEAN:
dcv.setBooleanValue((text == null ? Boolean.FALSE : Boolean.valueOf(text)));
break;
case DATE:
Date d = null;
try {
if (!(text == null || text.isEmpty())) {
d = FORMATTER.parse(stripQuotes(text));
}
} catch (ParseException e) {
callback.onConversionError(text,
dataType);
}
dcv.setDateValue(d);
break;
case NUMERIC:
BigDecimal numericValue = null;
try {
if (!(text == null || text.isEmpty())) {
numericValue = new BigDecimal(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(numericValue);
break;
case NUMERIC_BIGDECIMAL:
BigDecimal bigDecimalValue = null;
try {
if (!(text == null || text.isEmpty())) {
bigDecimalValue = new BigDecimal(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(bigDecimalValue);
break;
case NUMERIC_BIGINTEGER:
BigInteger bigIntegerValue = null;
try {
if (!(text == null || text.isEmpty())) {
bigIntegerValue = new BigInteger(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(bigIntegerValue);
break;
case NUMERIC_BYTE:
Byte byteValue = null;
try {
if (!(text == null || text.isEmpty())) {
byteValue = Byte.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(byteValue);
break;
case NUMERIC_DOUBLE:
Double doubleValue = null;
try {
if (!(text == null || text.isEmpty())) {
doubleValue = Double.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(doubleValue);
break;
case NUMERIC_FLOAT:
Float floatValue = null;
try {
if (!(text == null || text.isEmpty())) {
floatValue = Float.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(floatValue);
break;
case NUMERIC_INTEGER:
Integer integerValue = null;
try {
if (!(text == null || text.isEmpty())) {
integerValue = Integer.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(integerValue);
break;
case NUMERIC_LONG:
Long longValue = null;
try {
if (!(text == null || text.isEmpty())) {
longValue = Long.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(longValue);
break;
case NUMERIC_SHORT:
Short shortValue = null;
try {
if (!(text == null || text.isEmpty())) {
shortValue = Short.valueOf(stripQuotes(text));
}
} catch (Exception e) {
callback.onConversionError(text,
dataType);
}
dcv.setNumericValue(shortValue);
break;
}
}
static String stripQuotes(String text) {
if (text == null || text.isEmpty()) {
return text;
}
if (text.startsWith("\"")) {
text = text.substring(1);
}
if (text.endsWith("\"")) {
text = text.substring(0,
text.length() - 1);
}
return text;
}
//If the Decision Table model was pre-5.4 Numeric data-types were always stored as
//BigDecimals. This function attempts to set the correct DTCellValue property based
//on the *true* data type.
private static void convertDTCellValueFromNumeric(final DataType.DataTypes dataType,
final DTCellValue52 dcv) {
//Generic type NUMERIC was always stored as a BigDecimal
final BigDecimal value = (BigDecimal) dcv.getNumericValue();
switch (dataType) {
case NUMERIC_BIGDECIMAL:
dcv.setNumericValue(value == null ? null : value);
break;
case NUMERIC_BIGINTEGER:
dcv.setNumericValue(value == null ? null : value.toBigInteger());
break;
case NUMERIC_BYTE:
dcv.setNumericValue(value == null ? null : value.byteValue());
break;
case NUMERIC_DOUBLE:
dcv.setNumericValue(value == null ? null : value.doubleValue());
break;
case NUMERIC_FLOAT:
dcv.setNumericValue(value == null ? null : value.floatValue());
break;
case NUMERIC_INTEGER:
dcv.setNumericValue(value == null ? null : value.intValue());
break;
case NUMERIC_LONG:
dcv.setNumericValue(value == null ? null : value.longValue());
break;
case NUMERIC_SHORT:
dcv.setNumericValue(value == null ? null : value.shortValue());
break;
}
}
}