/*
* This file is part of the GeoLatte project.
*
* GeoLatte is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GeoLatte 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GeoLatte. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2010 - 2012 and Ownership of code is shared by:
* Qmino bvba - Romeinsestraat 18 - 3001 Heverlee (http://www.qmino.com)
* Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
*/
package org.geolatte.common.automapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
class TableMetaDataReader {
final private static Logger LOGGER = LoggerFactory.getLogger(TableMetaDataReader.class);
final private GeometryColumnTest geomTest;
TableMetaDataReader(GeometryColumnTest geomTest) {
this.geomTest = geomTest;
}
TableMetaData read(TableConfiguration cfg, DatabaseMetaData dmd) throws TableNotFoundException, MissingIdentifierException {
LOGGER.info("Reading metadata for table " + cfg.getTableName());
TableMetaData metaData = new TableMetaData(cfg.getTableRef());
readColums(cfg, dmd, metaData);
setIdentifier(cfg, dmd, metaData);
setGeometry(cfg, metaData);
return metaData;
}
private void setIdentifier(TableConfiguration cfg, DatabaseMetaData dmd, TableMetaData cInfo) throws MissingIdentifierException {
String configuredColumn = cfg.getIdentifierColumn();
if (configuredColumn != null) {
setAsIdentifier(cInfo, cfg.getIdentifierColumn());
return;
}
String column = determinePrimaryKey(cfg.getTableRef(), dmd);
if (column != null) {
setAsIdentifier(cInfo, column);
return;
}
throw new MissingIdentifierException(cfg.getTableRef().toString());
}
private void setGeometry(TableConfiguration cfg, TableMetaData cInfo) throws MissingIdentifierException {
String configuredColumn = cfg.getGeometryColumn();
if (configuredColumn != null) {
setAsGeometry(cInfo, cfg.getIdentifierColumn());
return;
}
String column = determineGeometry(cInfo);
if (column != null) {
setAsGeometry(cInfo, column);
}
return;
}
private String determineGeometry(TableMetaData cInfo) {
for (ColumnMetaData columnMetaData : cInfo.getColumnMetaData()) {
if (this.geomTest.isGeometry(columnMetaData)) return columnMetaData.getColumnName();
}
return null;
}
private String determinePrimaryKey(TableRef tableRef, DatabaseMetaData dmd) {
String pkn = null;
ResultSet rs = null;
try {
rs = dmd.getPrimaryKeys(tableRef.getCatalog(), tableRef.getSchema(), tableRef.getTableName());
if (!rs.next()) return null;
pkn = rs.getString("COLUMN_NAME");
//check whether the primary key is non-composite
if (rs.next()) return null;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if (rs != null) rs.close();
} catch (SQLException e) {
//do nothing
}
}
return pkn;
}
private void readColums(TableConfiguration cfg, DatabaseMetaData dmd, TableMetaData tableMetaData) throws TableNotFoundException {
ResultSet rs = null;
boolean empty = true;
try {
rs = dmd.getColumns(cfg.getCatalog(), cfg.getSchema(), cfg.getTableName(), null);
while (rs.next()) {
empty = false;
String colName = rs.getString("COLUMN_NAME");
String dbType = rs.getString("TYPE_NAME");
int javaType = rs.getInt("DATA_TYPE");
if (columnToSkip(cfg, colName)) {
LOGGER.info(String.format("Column %s in exclude list of configuration, so excluded.", colName));
continue;
}
addAttribute(tableMetaData, colName, dbType, javaType);
}
} catch (SQLException ex) {
throw new RuntimeException(ex);
} finally {
try {
if (rs != null) rs.close();
} catch (SQLException e) {
// do nothing
}
}
if (empty) {
throw new TableNotFoundException(cfg.getTableRef());
}
}
private boolean columnToSkip(TableConfiguration cfg, String colName) {
for (String toExclude : cfg.getExcludedColumns()) {
if (colName.equalsIgnoreCase(toExclude)) return true;
}
return false;
}
private boolean setAsIdentifier(TableMetaData metaData, String column) {
for (ColumnMetaData ai : metaData.getColumnMetaData()) {
if (ai.getColumnName().equals(column)) {
ai.setAsIdentifier(true);
return true;
}
}
LOGGER.warn("Attempted to set columns " + column + " as identifier, but no corresponding field in class found.");
return false;
}
private boolean setAsGeometry(TableMetaData metaData, String column) {
for (ColumnMetaData ai : metaData.getColumnMetaData()) {
if (ai.getColumnName().equals(column)) {
ai.setAsGeometry(true);
return true;
}
}
LOGGER.warn("Attempted to set columns " + column + " as geometry, but no corresponding field in class found.");
return false;
}
private void addAttribute(TableMetaData metaData, String colName, String dbType, int javaType) {
metaData.addColumnMetaData(new ColumnMetaData(colName, javaType, dbType));
}
}