/* Copyright 2013 The jeo project. All rights reserved. * * 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 io.jeo.sql; import java.math.BigDecimal; import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; /** * Contains mappings between database types and java types. * * @author Justin Deoliveira, OpenGeo */ public class DbTypes { /** * sql type to class mappings. */ Map<Integer,Class<?>> sql; /** * name to class mappings */ Map<String,Class<?>> name; public DbTypes() { sql = createSqlTypeMappings(); name = createNameMappings(); } /** * Creates sql type (defined by {@link Types}) to class mappings. * <p> * Subclasses should override/extend this method to customize mappings. * </p> */ protected Map<Integer, Class<?>> createSqlTypeMappings() { Map<Integer, Class<?>> sql = new LinkedHashMap<Integer, Class<?>>(); sql.put(Types.VARCHAR, String.class); sql.put(Types.CHAR, String.class); sql.put(Types.LONGVARCHAR, String.class); sql.put(Types.NVARCHAR, String.class); sql.put(Types.NCHAR, String.class); sql.put(Types.BIT, Boolean.class); sql.put(Types.BOOLEAN, Boolean.class); sql.put(Types.TINYINT, Short.class); sql.put(Types.SMALLINT, Short.class); sql.put(Types.INTEGER, Integer.class); sql.put(Types.BIGINT, Long.class); sql.put(Types.REAL, Float.class); sql.put(Types.DOUBLE, Double.class); sql.put(Types.FLOAT, Double.class); sql.put(Types.DECIMAL, BigDecimal.class); sql.put(Types.NUMERIC, BigDecimal.class); sql.put(Types.DATE, Date.class); sql.put(Types.TIME, Time.class); sql.put(Types.TIMESTAMP, Timestamp.class); sql.put(Types.BLOB, byte[].class); sql.put(Types.BINARY, byte[].class); sql.put(Types.CLOB, String.class); sql.put(Types.VARBINARY, byte[].class); return sql; } /** * Creates sql type name to class mappings. * <p> * Subclasses should override/extend this method to customize mappings. * </p> */ protected Map<String, Class<?>> createNameMappings() { Map<String,Class<?>> name = new LinkedHashMap<String, Class<?>>(); name.put("GEOMETRY", Geometry.class); name.put("POINT", Point.class); name.put("LINESTRING", LineString.class); name.put("POLYGON", Polygon.class); name.put("POLYGONM", Polygon.class); name.put("MULTIPOINT", MultiPoint.class); name.put("MULTILINESTRING", MultiLineString.class); name.put("MULTIPOLYGON", MultiPolygon.class); name.put("GEOMETRYCOLLECTION", GeometryCollection.class); return name; } /** * Returns the class mapped to the specified type. * * @param type Type defined by {@link Types}. * * @return The mapped class or <code>null</code> if no such mapping exists. */ public Class<?> fromSQL(int type) { return sql.get(type); } /** * Returns the class mapped to the specified type name. * * @param typename The name of the type. * * @return The mapped class or <code>null</code> if no such mapping exists. */ public Class<?> fromName(String typename) { return name.get(typename.toUpperCase(Locale.ROOT)); } /** * Returns the sql type (from {@link Types}) for the specified class. * <p> * This method will first try a direct match. If no such mapping exists for the exact class * then a loose match is done by returning the first mapped class that is assignable from the * specified class. * </p> * @param clazz The mapped class. * * @return The sql type or <code>null</code> if no such mapping exists. */ public Integer toSQL(Class<?> clazz) { for (Map.Entry<Integer,Class<?>> e : sql.entrySet()) { if (e.getValue() == clazz) { return e.getKey(); } } //no match, do a loose match for (Map.Entry<Integer,Class<?>> e : sql.entrySet()) { if (e.getValue().isAssignableFrom(clazz)) { return e.getKey(); } } return null; } /** * Returns the sql type name for the specified class. * <p> * This method will first try a direct match. If no such mapping exists for the exact class * then a loose match is done by returning the first mapped class that is assignable from the * specified class. * </p> * @param clazz The mapped class. * * @return The sql type name or <code>null</code> if no such mapping exists. */ public String toName(Class<?> clazz) { for (Map.Entry<String,Class<?>> e : name.entrySet()) { if (e.getValue() == clazz) { return e.getKey(); } } //no match, do a loose match for (Map.Entry<String,Class<?>> e : name.entrySet()) { if (e.getValue().isAssignableFrom(clazz)) { return e.getKey(); } } return null; } }