/*
* Copyright 2002-2005 the original author or authors.
*
* 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.springmodules.datamap.jdbc.sqlmap.support;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.support.DatabaseMetaDataCallback;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
import org.springmodules.datamap.jdbc.sqlmap.PersistentField;
import org.springmodules.datamap.jdbc.sqlmap.PersistentObject;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* Suppport functionality used by ActiveMapper.
*
* @author Thomas Risberg
* @since 0.3
*/
public class ActiveMapperUtils {
public static String underscoreName(String name) {
return name.substring(0,1).toLowerCase() + name.substring(1).replaceAll("([A-Z])", "_$1").toLowerCase();
}
public static String getterName(String fieldName) {
return "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
}
public static String setterName(String columnName) {
StringTokenizer tokenizer = new StringTokenizer(columnName, "_");
StringBuffer propertyName = new StringBuffer();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
propertyName.append(token.substring(0, 1).toUpperCase());
propertyName.append(token.substring(1));
}
return "set" + propertyName.toString();
}
public static PersistentObject getPersistenceMetaData(Class clazz, final DataSource dataSource, Map pluralExceptions) {
final PersistentObject newPo = new PersistentObject();
String baseName = clazz.getName();
baseName = baseName.substring(baseName.lastIndexOf(".") + 1);
String tableName;
if (pluralExceptions.containsKey(baseName)) {
tableName = underscoreName((String)pluralExceptions.get(baseName));
}
else {
tableName = underscoreName(baseName + "s");
}
newPo.setBaseName(baseName);
newPo.setTableName(tableName);
final String sqlTableName = tableName;
final Map newMetaData = new HashMap(10);
Field[] f = clazz.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
PersistentField pf = new PersistentField();
pf.setFieldName(f[i].getName());
pf.setColumnName(ActiveMapperUtils.underscoreName(f[i].getName()));
pf.setJavaType(f[i].getType());
if ("id".equals(f[i].getName())) {
if (!pf.isIdField())
pf.setIdField(true);
}
newMetaData.put(pf.getColumnName(), pf);
}
try {
JdbcUtils.extractDatabaseMetaData(dataSource, new DatabaseMetaDataCallback() {
public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
newPo.setUsingLowerCaseIdentifiers(databaseMetaData.storesLowerCaseIdentifiers());
newPo.setDatabaseProductName(databaseMetaData.getDatabaseProductName());
if ("PostgreSQL".equals(newPo.getDatabaseProductName())) {
newPo.setUsingGeneratedKeysStrategy(false);
newPo.setIncrementer(new PostgreSQLSequenceMaxValueIncrementer(dataSource, newPo.getBaseName() + "_seq"));
}
else if ("HSQL Database Engine".equals(newPo.getDatabaseProductName())) {
newPo.setUsingGeneratedKeysStrategy(false);
newPo.setIncrementer(new HsqlMaxValueIncrementer(dataSource, newPo.getBaseName() + "_seq", "value"));
}
else if ("Oracle".equals(newPo.getDatabaseProductName())) {
newPo.setUsingGeneratedKeysStrategy(false);
newPo.setIncrementer(new OracleSequenceMaxValueIncrementer(dataSource, newPo.getBaseName() + "_seq"));
}
else {
newPo.setUsingGeneratedKeysStrategy(true);
}
String metaDataTableName;
if (newPo.isUsingLowerCaseIdentifiers())
metaDataTableName = sqlTableName.toLowerCase();
else
metaDataTableName = sqlTableName.toUpperCase();
ResultSet pkrs = databaseMetaData.getPrimaryKeys(null, null, metaDataTableName);
Set primaryKeys = new HashSet();
while (pkrs.next()) {
primaryKeys.add(pkrs.getString(4));
}
pkrs.close();
newPo.setPrimaryKeyColumns(primaryKeys);
int unmappedKey = primaryKeys.size();
ResultSet crs = databaseMetaData.getColumns(null, null, metaDataTableName, null);
while (crs.next()) {
PersistentField pf = (PersistentField)newMetaData.get(crs.getString(4).toLowerCase());
if (pf != null) {
pf.setSqlType(crs.getInt(5));
if (primaryKeys.contains(pf.getColumnName())) {
pf.setIdField(true);
unmappedKey--;
}
}
}
crs.close();
if (primaryKeys.size() > 1 || unmappedKey > 0) {
newPo.setDependentObject(true);
}
return null;
}
});
} catch (MetaDataAccessException e) {
throw new DataAccessResourceFailureException("Error retreiving metadata", e);
}
newPo.setPersistentFields(newMetaData);
return newPo;
}
}