/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* 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.jkiss.dbeaver.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ModelPreferences;
import org.jkiss.dbeaver.model.data.DBDBinaryFormatter;
import org.jkiss.dbeaver.model.data.DBDDataFormatter;
import org.jkiss.dbeaver.model.data.DBDDisplayFormat;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.struct.DBSDataType;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import org.jkiss.dbeaver.model.struct.DBSTypedObjectEx;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
/**
* DB value formatting utilities
*/
public final class DBValueFormatting {
public static final DecimalFormat NATIVE_DECIMAL_FORMATTER = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
private static final Log log = Log.getLog(DBValueFormatting.class);
static {
DBValueFormatting.NATIVE_DECIMAL_FORMATTER.setMaximumFractionDigits(340);
}
@NotNull
public static DBPImage getTypeImage(@NotNull DBSTypedObject typedObject)
{
if (typedObject instanceof DBSTypedObjectEx) {
DBSDataType dataType = ((DBSTypedObjectEx) typedObject).getDataType();
if (dataType instanceof DBPImageProvider) {
DBPImage image = ((DBPImageProvider) dataType).getObjectImage();
if (image != null) {
return image;
}
}
}
return getDefaultTypeImage(typedObject);
}
@NotNull
public static DBPImage getDefaultTypeImage(DBSTypedObject typedObject) {
String typeName = typedObject.getTypeName();
switch (typedObject.getDataKind()) {
case BOOLEAN:
return DBIcon.TYPE_BOOLEAN;
case STRING:
return DBIcon.TYPE_STRING;
case NUMERIC:
return DBIcon.TYPE_NUMBER;
case DATETIME:
return DBIcon.TYPE_DATETIME;
case BINARY:
return DBIcon.TYPE_BINARY;
case CONTENT:
if (typeName.contains("XML") || typeName.contains("xml")) {
return DBIcon.TYPE_XML;
} else if (typeName.contains("CHAR") || typeName.contains("char")) {
return DBIcon.TYPE_TEXT;
}
return DBIcon.TYPE_LOB;
case ARRAY:
return DBIcon.TYPE_ARRAY;
case STRUCT:
return DBIcon.TYPE_STRUCT;
case DOCUMENT:
return DBIcon.TYPE_DOCUMENT;
case REFERENCE:
return DBIcon.TYPE_REFERENCE;
case ROWID:
return DBIcon.TYPE_ROWID;
case OBJECT:
if (typeName != null && (typeName.contains(DBConstants.TYPE_NAME_UUID) || typeName.contains(DBConstants.TYPE_NAME_UUID2))) {
return DBIcon.TYPE_UUID;
}
return DBIcon.TYPE_OBJECT;
case ANY:
return DBIcon.TYPE_ANY;
default:
return DBIcon.TYPE_UNKNOWN;
}
}
@NotNull
public static DBPImage getObjectImage(DBPObject object)
{
return getObjectImage(object, true);
}
@Nullable
public static DBPImage getObjectImage(DBPObject object, boolean useDefault)
{
DBPImage image = null;
if (object instanceof DBPImageProvider) {
image = ((DBPImageProvider)object).getObjectImage();
}
if (image == null) {
if (object instanceof DBSTypedObject) {
image = getTypeImage((DBSTypedObject) object);
}
if (image == null && useDefault) {
image = DBIcon.TYPE_OBJECT;
}
}
return image;
}
@NotNull
public static DBDBinaryFormatter getBinaryPresentation(@NotNull DBPDataSource dataSource)
{
String id = dataSource.getContainer().getPreferenceStore().getString(ModelPreferences.RESULT_SET_BINARY_PRESENTATION);
if (id != null) {
DBDBinaryFormatter formatter = getBinaryPresentation(id);
if (formatter != null) {
return formatter;
}
}
return DBConstants.BINARY_FORMATS[0];
}
@Nullable
public static DBDBinaryFormatter getBinaryPresentation(String id)
{
for (DBDBinaryFormatter formatter : DBConstants.BINARY_FORMATS) {
if (formatter.getId().equals(id)) {
return formatter;
}
}
return null;
}
public static String getDefaultBinaryFileEncoding(@NotNull DBPDataSource dataSource)
{
DBPPreferenceStore preferenceStore = dataSource.getContainer().getPreferenceStore();
String fileEncoding = preferenceStore.getString(ModelPreferences.CONTENT_HEX_ENCODING);
if (CommonUtils.isEmpty(fileEncoding)) {
fileEncoding = GeneralUtils.getDefaultFileEncoding();
}
return fileEncoding;
}
@Nullable
public static Number convertStringToNumber(String text, Class<?> hintType, @NotNull DBDDataFormatter formatter)
{
if (text == null || text.length() == 0) {
return null;
}
try {
if (hintType == Long.class) {
try {
return Long.valueOf(text);
} catch (NumberFormatException e) {
return new BigInteger(text);
}
} else if (hintType == Integer.class) {
return Integer.valueOf(text);
} else if (hintType == Short.class) {
return Short.valueOf(text);
} else if (hintType == Byte.class) {
return Byte.valueOf(text);
} else if (hintType == Float.class) {
return Float.valueOf(text);
} else if (hintType == Double.class) {
return Double.valueOf(text);
} else if (hintType == BigInteger.class) {
return new BigInteger(text);
} else {
return new BigDecimal(text);
}
} catch (NumberFormatException e) {
try {
return (Number)formatter.parseValue(text, hintType);
} catch (ParseException e1) {
log.debug("Can't parse numeric value [" + text + "] using formatter: " + e.getMessage());
return null;
}
}
}
public static String convertNumberToNativeString(Number value) {
if (value instanceof BigDecimal) {
return ((BigDecimal) value).toPlainString();
} else if (value instanceof Float || value instanceof Double) {
return NATIVE_DECIMAL_FORMATTER.format(value);
} else {
return value.toString();
}
}
public static String getBooleanString(boolean propertyValue) {
return propertyValue ? DBConstants.BOOLEAN_PROP_YES : DBConstants.BOOLEAN_PROP_NO;
}
public static String formatBinaryString(@NotNull DBPDataSource dataSource, @NotNull byte[] data, @NotNull DBDDisplayFormat format) {
return formatBinaryString(dataSource, data, format, false);
}
public static String formatBinaryString(@NotNull DBPDataSource dataSource, @NotNull byte[] data, @NotNull DBDDisplayFormat format, boolean forceLimit) {
DBDBinaryFormatter formatter;
if (format == DBDDisplayFormat.NATIVE && dataSource instanceof SQLDataSource) {
formatter = ((SQLDataSource) dataSource).getSQLDialect().getNativeBinaryFormatter();
} else {
formatter = getBinaryPresentation(dataSource);
}
// Convert bytes to string
int length = data.length;
if (format == DBDDisplayFormat.UI || forceLimit) {
int maxLength = dataSource.getContainer().getPreferenceStore().getInt(ModelPreferences.RESULT_SET_BINARY_STRING_MAX_LEN);
if (length > maxLength) {
length = maxLength;
}
}
String string = formatter.toString(data, 0, length);
if (format == DBDDisplayFormat.NATIVE || length == data.length) {
// Do not append ... for native formatter - it may contain expressions
return string;
}
return string + "..." + " [" + data.length + "]";
}
@NotNull
public static String getDefaultValueDisplayString(@Nullable Object value, @NotNull DBDDisplayFormat format)
{
if (DBUtils.isNullValue(value)) {
if (format == DBDDisplayFormat.UI) {
return DBConstants.NULL_VALUE_LABEL;
} else {
return "";
}
}
if (value instanceof CharSequence) {
return value.toString();
}
if (value.getClass().isArray()) {
if (value.getClass().getComponentType() == Byte.TYPE) {
byte[] bytes = (byte[]) value;
int length = bytes.length;
if (length > 2000) length = 2000;
String string = CommonUtils.toHexString(bytes, 0, length);
return bytes.length > 2000 ? string + "..." : string;
} else {
return GeneralUtils.makeDisplayString(value).toString();
}
}
String className = value.getClass().getName();
if (className.startsWith("java.lang") || className.startsWith("java.util")) {
// Standard types just use toString
return value.toString();
}
// Unknown types print their class name
boolean hasToString;
try {
hasToString = value.getClass().getMethod("toString").getDeclaringClass() != Object.class;
} catch (Throwable e) {
log.debug(e);
hasToString = false;
}
if (hasToString) {
return value.toString();
} else {
return "[" + value.getClass().getSimpleName() + "]";
}
}
}