/** * 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 * * 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.apache.metamodel.schema; import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; import java.sql.Time; import java.sql.Timestamp; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.metamodel.util.NumberComparator; import org.apache.metamodel.util.ObjectComparator; import org.apache.metamodel.util.TimeComparator; import org.apache.metamodel.util.ToStringComparator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Default implementation of ColumnType */ public class ColumnTypeImpl implements ColumnType { private static final long serialVersionUID = 1L; public static final Logger logger = LoggerFactory.getLogger(ColumnTypeImpl.class); private final String _name; private final SuperColumnType _superColumnType; private final Class<?> _javaType; private final boolean _largeObject; public ColumnTypeImpl(String name, SuperColumnType superColumnType) { this(name, superColumnType, null); } public ColumnTypeImpl(String name, SuperColumnType superColumnType, Class<?> javaType) { this(name, superColumnType, javaType, false); } public ColumnTypeImpl(String name, SuperColumnType superColumnType, Class<?> javaType, boolean largeObject) { if (name == null) { throw new IllegalArgumentException("Name cannot be null"); } if (superColumnType == null) { throw new IllegalArgumentException("SuperColumnType cannot be null"); } _name = name; _superColumnType = superColumnType; if (javaType == null) { _javaType = superColumnType.getJavaEquivalentClass(); } else { _javaType = javaType; } _largeObject = largeObject; } @Override public String getName() { return _name; } @Override public Comparator<Object> getComparator() { if (isTimeBased()) { return TimeComparator.getComparator(); } if (isNumber()) { return NumberComparator.getComparator(); } if (isLiteral()) { return ToStringComparator.getComparator(); } return ObjectComparator.getComparator(); } @Override public boolean isBoolean() { return _superColumnType == SuperColumnType.BOOLEAN_TYPE; } @Override public boolean isBinary() { return _superColumnType == SuperColumnType.BINARY_TYPE; } @Override public boolean isNumber() { return _superColumnType == SuperColumnType.NUMBER_TYPE; } @Override public boolean isTimeBased() { return _superColumnType == SuperColumnType.TIME_TYPE; } @Override public boolean isLiteral() { return _superColumnType == SuperColumnType.LITERAL_TYPE; } @Override public boolean isLargeObject() { return _largeObject; } @Override public Class<?> getJavaEquivalentClass() { return _javaType; } @Override public SuperColumnType getSuperType() { return _superColumnType; } @Override public int getJdbcType() throws IllegalStateException { final String name = this.toString(); try { // We assume that the JdbcTypes class only consists of constant // integer types, so we make no assertions here final Field[] fields = JdbcTypes.class.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String fieldName = field.getName(); if (fieldName.equals(name)) { int value = (Integer) field.getInt(null); return value; } } throw new IllegalStateException("No JdbcType found with field name: " + name); } catch (Exception e) { throw new IllegalStateException("Could not access fields in JdbcTypes", e); } } @Override public String toString() { return _name; } /** * Finds the ColumnType enum corresponding to the incoming JDBC * type-constant */ public static ColumnType convertColumnType(int jdbcType) { try { Field[] fields = JdbcTypes.class.getFields(); // We assume that the JdbcTypes class only consists of constant // integer types, so we make no assertions here for (int i = 0; i < fields.length; i++) { Field field = fields[i]; int value = (Integer) field.getInt(null); if (value == jdbcType) { String fieldName = field.getName(); return valueOf(fieldName); } } } catch (Exception e) { throw new IllegalStateException("Could not access fields in JdbcTypes", e); } return OTHER; } /** * Finds the ColumnType enum corresponding to the incoming Java class. * * @param cls * @return */ public static ColumnType convertColumnType(Class<?> cls) { if (cls == null) { throw new IllegalArgumentException("Class cannot be null"); } final ColumnType type; if (cls == String.class) { type = ColumnType.STRING; } else if (cls == Boolean.class || cls == boolean.class) { type = ColumnType.BOOLEAN; } else if (cls == Character.class || cls == char.class || cls == Character[].class || cls == char[].class) { type = ColumnType.CHAR; } else if (cls == Byte.class || cls == byte.class) { type = ColumnType.TINYINT; } else if (cls == Short.class || cls == short.class) { type = ColumnType.SMALLINT; } else if (cls == Integer.class || cls == int.class) { type = ColumnType.INTEGER; } else if (cls == Long.class || cls == long.class || cls == BigInteger.class) { type = ColumnType.BIGINT; } else if (cls == Float.class || cls == float.class) { type = ColumnType.FLOAT; } else if (cls == Double.class || cls == double.class) { type = ColumnType.DOUBLE; } else if (cls == BigDecimal.class) { type = ColumnType.DECIMAL; } else if (Number.class.isAssignableFrom(cls)) { type = ColumnType.NUMBER; } else if (Map.class.isAssignableFrom(cls)) { type = ColumnType.MAP; } else if (List.class.isAssignableFrom(cls)) { type = ColumnType.LIST; } else if (Set.class.isAssignableFrom(cls)) { type = ColumnType.SET; } else if (cls == java.sql.Date.class) { type = ColumnType.DATE; } else if (cls == Timestamp.class) { type = ColumnType.TIMESTAMP; } else if (cls == Time.class) { type = ColumnType.TIME; } else if (Date.class.isAssignableFrom(cls)) { type = ColumnType.TIMESTAMP; } else if (cls == UUID.class) { type = ColumnType.UUID; } else if (cls == InetAddress.class) { type = ColumnType.INET; } else { type = ColumnType.OTHER; } return type; } public static ColumnType valueOf(String fieldName) { try { Field columnTypeField = ColumnType.class.getField(fieldName); if (columnTypeField != null) { columnTypeField.setAccessible(true); Object columnType = columnTypeField.get(ColumnType.class); return (ColumnType) columnType; } } catch (Exception e) { logger.error("Failed to resolve JDBC type in ColumnType constants: " + fieldName, e); } return null; } }