Newer
Older
/*
* _____________________________________________________________________________
*
* INAF - OATS National Institute for Astrophysics - Astronomical Observatory of
* Trieste INAF - IA2 Italian Center for Astronomical Archives
* _____________________________________________________________________________
*
* Copyright (C) 2017 Istituto Nazionale di Astrofisica
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License Version 3 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package it.inaf.ia2.tsm.model;
import it.inaf.ia2.tsm.datalayer.ADQL;
Sonia Zorba
committed
import it.inaf.ia2.tsm.datalayer.DataTypeMode;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Utility class for converting data types having different syntaxes.
* <p>
* It parses the sql_type_mapping.xml resource file.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
*
* @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
*/
public class TypesMapping {
@XmlRootElement(name = "sql_type_mapping")
static class TypesWrapper {
private List<TypeMapping> types;
@XmlElements({
@XmlElement(name = "type")
})
public List<TypeMapping> getTypes() {
return types;
}
public void setTypes(List<TypeMapping> types) {
this.types = types;
}
}
private static final List<TypeMapping> TYPES;
static {
try (InputStream is = TypeMapping.class.getClassLoader().getResourceAsStream("sql_type_mapping.xml")) {
TypesWrapper typesWrapper = JAXB.unmarshal(is, TypesWrapper.class);
TYPES = typesWrapper.types;
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
private static TypeMapping getTypeMappingFromADQLType(String adqlType) {
for (TypeMapping typeMapping : TYPES) {
if (adqlType.equals(typeMapping.getAdqlType())) {
return typeMapping;
}
}
/**
* Converts an ADQL datatype into a Java type.
*/
public static Class getClassFromAdqlType(String adqlType) {
TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType);
if (typeMapping == null) {
return String.class;
}
return typeMapping.getJavaType();
/**
* Converts an ADQL datatype to MySQL datatype.
*/
public static String getMySQLTypeFromADQLType(String adqlType) {
TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType);
if (typeMapping == null) {
return "VARCHAR";
}
Sonia Zorba
committed
return typeMapping.getMySQLMapping().getTypes().get(0);
/**
* Converts an ADQL datatype to PostgreSQL datatype.
*/
public static String getPostgresSQLTypeFromADQLType(String adqlType) {
TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType);
if (typeMapping == null) {
return "character varying";
}
Sonia Zorba
committed
return typeMapping.getPgsqlMapping().getTypes().get(0);
/**
* Returns the correct datatype according to the {@link DataTypeMode} used
* by a TAP_SCHEMA.
*
* @param adqlType the datatype in ADQL format; this format is used in XML
* configuration files contained into the {@code schema_definition}
* resources folder.
* @param mode the {@code DataTypeMode} used by the TAP_SCHEMA.
*/
Sonia Zorba
committed
public static String getDataType(String adqlType, DataTypeMode mode) {
switch (mode) {
case ADQL:
return adqlType;
case VOTABLE:
return getTypeMappingFromADQLType(adqlType).getVoTableType();
default:
throw new UnsupportedOperationException("DataTypeMode " + mode + " not supported yet");
/**
* Retrieves the {@code TypeMapping} for a datatype expressed in the mode
* used by a given TAP_SCHEMA.
*
* @param dataType the datatype, as exposed by the TAP_SCHEMA.
* @param mode the {@code DataTypeMode} used by the TAP_SCHEMA.
*/
public static TypeMapping getTypeMapping(String dataType, DataTypeMode mode) {
for (TypeMapping typeMapping : TYPES) {
switch (mode) {
case ADQL:
if (dataType.equals(typeMapping.getAdqlType())) {
return typeMapping;
}
break;
case VOTABLE:
if (dataType.equals(typeMapping.getVoTableType())) {
return typeMapping;
}
break;
default:
throw new UnsupportedOperationException("DataTypeMode " + mode + " not supported yet");
}
}
throw new RuntimeException("Unable to get TypeMapping for datatype " + dataType + " [" + mode + "]");
}
Sonia Zorba
committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
private static abstract class DataTypeFromDBTypeMapper {
private final DataTypeMode mode;
DataTypeFromDBTypeMapper(DataTypeMode mode) {
this.mode = mode;
}
abstract DBTypeMapping getDBTypeMapping(TypeMapping typeMapping);
private String getDataType(TypeMapping mapping) {
switch (mode) {
case ADQL:
return mapping.getAdqlType();
case VOTABLE:
return mapping.getVoTableType();
default:
throw new UnsupportedOperationException("DataTypeMode " + mode + " not supported yet");
}
}
private String getDefaultDataType(String dbType) {
switch (mode) {
case ADQL:
return ADQL.getDataType(dbType);
case VOTABLE:
return "char";
default:
throw new UnsupportedOperationException("DataTypeMode " + mode + " not supported yet");
}
}
String getDataTypeFromDBType(String dbType) {
String dbTypeWithoutSize = dbType.toUpperCase().replaceAll("\\(.+\\)", "");
for (TypeMapping typeMapping : TYPES) {
DBTypeMapping dbMapping = getDBTypeMapping(typeMapping);
if (dbMapping.isInverse()) {
for (String type : dbMapping.getTypes()) {
if (dbTypeWithoutSize.toLowerCase().startsWith(type.toLowerCase())) {
return getDataType(typeMapping);
}
}
}
}
return getDefaultDataType(dbTypeWithoutSize);
}
/**
* Retrieves a datatype having the format required by a given TAP_SCHEMA
* from a MySQL datatype.
*
* @param mode the {@code DataTypeMode} used by the TAP_SCHEMA.
*/
public static String getDataTypeFromMySQLType(String mysqlType, DataTypeMode mode) {
return (new DataTypeFromDBTypeMapper(mode) {
@Override
DBTypeMapping getDBTypeMapping(TypeMapping typeMapping) {
return typeMapping.getMySQLMapping();
}
}).getDataTypeFromDBType(mysqlType);
}
/**
* Retrieves a datatype having the format required by a given TAP_SCHEMA
* from a PostrgreSQL datatype.
*
* @param mode the {@code DataTypeMode} used by the TAP_SCHEMA.
*/
Sonia Zorba
committed
public static String getDataTypeFromPostgresType(String pgsqlType, DataTypeMode mode) {
return (new DataTypeFromDBTypeMapper(mode) {
@Override
DBTypeMapping getDBTypeMapping(TypeMapping typeMapping) {
return typeMapping.getPgsqlMapping();
Sonia Zorba
committed
}).getDataTypeFromDBType(pgsqlType);
}
/**
* Converts a MySQL datatype to an ADQL datatype.
*
* @param mysqlDBType the datatype, as read from MySQL information_schema.
*/
public static ADQL getADQLFromMySQLType(String mysqlDBType) {
return ADQL.parse(getDataTypeFromMySQLType(mysqlDBType, DataTypeMode.ADQL));
/**
* Converts a PostgreSQL datatype to an ADQL datatype.
*
* @param postgresDBType the datatype, as read from PostgreSQL
* information_schema.
*/
public static ADQL getADQLFromPostgresType(String postgresDBType) {
return ADQL.parse(getDataTypeFromPostgresType(postgresDBType, DataTypeMode.ADQL));
/**
* Parses a string converting it in a typed object according to the datatype
* specified in ADQL format.
*
* @param type datatype in ADQL format
*/
public static Object parseTypedValue(String value, String type) {
switch (ADQL.valueOf(type)) {
Sonia Zorba
committed
case BOOLEAN:
return Boolean.parseBoolean(value);
return Short.parseShort(value);
Sonia Zorba
committed
case INTEGER:
return Integer.parseInt(value);
return Long.parseLong(value);
return Float.parseFloat(value);
return Double.parseDouble(value);