001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.cache; 019 020import java.sql.DatabaseMetaData; 021import java.sql.SQLException; 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027import java.util.Map.Entry; 028 029import net.sf.hajdbc.DatabaseProperties; 030import net.sf.hajdbc.QualifiedName; 031import net.sf.hajdbc.QualifiedNameFactory; 032import net.sf.hajdbc.SequenceProperties; 033import net.sf.hajdbc.TableProperties; 034import net.sf.hajdbc.dialect.Dialect; 035 036/** 037 * @author Paul Ferraro 038 * 039 */ 040public abstract class AbstractDatabaseProperties implements DatabaseProperties 041{ 042 protected final QualifiedNameFactory nameFactory; 043 private final boolean supportsSelectForUpdate; 044 private final boolean locatorsUpdateCopy; 045 046 public AbstractDatabaseProperties(DatabaseMetaData metaData, Dialect dialect) throws SQLException 047 { 048 this.supportsSelectForUpdate = metaData.supportsSelectForUpdate(); 049 this.locatorsUpdateCopy = metaData.locatorsUpdateCopy(); 050 this.nameFactory = dialect.createQualifiedNameFactory(metaData, dialect.createIdentifierNormalizer(metaData)); 051 } 052 053 /** 054 * @see net.sf.hajdbc.DatabaseProperties#supportsSelectForUpdate() 055 */ 056 @Override 057 public final boolean supportsSelectForUpdate() 058 { 059 return this.supportsSelectForUpdate; 060 } 061 062 /** 063 * {@inheritDoc} 064 * @see net.sf.hajdbc.DatabaseProperties#locatorsUpdateCopy() 065 */ 066 @Override 067 public boolean locatorsUpdateCopy() 068 { 069 return this.locatorsUpdateCopy; 070 } 071 072 /** 073 * @see net.sf.hajdbc.DatabaseProperties#getTables() 074 */ 075 @Override 076 public final Collection<TableProperties> getTables() throws SQLException 077 { 078 return this.tables().values(); 079 } 080 081 protected abstract Map<QualifiedName, TableProperties> tables() throws SQLException; 082 083 /** 084 * @see net.sf.hajdbc.DatabaseProperties#getSequences() 085 */ 086 @Override 087 public final Collection<SequenceProperties> getSequences() throws SQLException 088 { 089 return this.sequences().values(); 090 } 091 092 protected abstract Map<QualifiedName, SequenceProperties> sequences() throws SQLException; 093 094 /** 095 * @see net.sf.hajdbc.DatabaseProperties#findTable(java.lang.String) 096 */ 097 @Override 098 public final TableProperties findTable(String table) throws SQLException 099 { 100 return this.find(this.tables(), table, this.defaultSchemas()); 101 } 102 103 /** 104 * @see net.sf.hajdbc.DatabaseProperties#findSequence(java.lang.String) 105 */ 106 @Override 107 public final SequenceProperties findSequence(String sequence) throws SQLException 108 { 109 return this.find(this.sequences(), sequence, this.defaultSchemas()); 110 } 111 112 private <T> T find(Map<QualifiedName, T> map, String raw, List<String> defaultSchemaList) 113 { 114 QualifiedName name = this.nameFactory.parse(raw); 115 116 T properties = map.get(name); 117 118 if ((properties == null) && (name.getSchema() == null)) 119 { 120 Iterator<String> schemas = defaultSchemaList.iterator(); 121 while ((properties == null) && schemas.hasNext()) 122 { 123 properties = map.get(this.nameFactory.createQualifiedName(schemas.next(), raw)); 124 } 125 } 126 127 return properties; 128 } 129 130 protected abstract List<String> defaultSchemas() throws SQLException; 131 132 /** 133 * {@inheritDoc} 134 * @see net.sf.hajdbc.DatabaseProperties#findType(int, int[]) 135 */ 136 @Override 137 public String findType(int precision, int... types) throws SQLException 138 { 139 Map<Integer, Map.Entry<String, Integer>> map = this.types(); 140 141 for (int type: types) 142 { 143 Map.Entry<String, Integer> entry = map.get(type); 144 if (entry != null) 145 { 146 String name = entry.getKey(); 147 Integer maxPrecision = entry.getValue(); 148 if (maxPrecision != null) 149 { 150 String qualifier = "(" + ((precision == 0) ? maxPrecision : precision) + ")"; 151 return name.contains("()") ? name.replace("()", qualifier) : name + qualifier; 152 } 153 154 return name; 155 } 156 } 157 throw new SQLException("No native type found for " + Arrays.asList(types)); 158 } 159 160 protected abstract Map<Integer, Entry<String, Integer>> types() throws SQLException; 161}