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.lazy; 019 020import java.sql.SQLException; 021import java.util.Collection; 022import java.util.Map; 023import java.util.concurrent.atomic.AtomicReference; 024 025import net.sf.hajdbc.ColumnProperties; 026import net.sf.hajdbc.ColumnPropertiesFactory; 027import net.sf.hajdbc.ForeignKeyConstraint; 028import net.sf.hajdbc.ForeignKeyConstraintFactory; 029import net.sf.hajdbc.IdentifierNormalizer; 030import net.sf.hajdbc.QualifiedName; 031import net.sf.hajdbc.QualifiedNameFactory; 032import net.sf.hajdbc.UniqueConstraint; 033import net.sf.hajdbc.UniqueConstraintFactory; 034import net.sf.hajdbc.cache.AbstractTableProperties; 035import net.sf.hajdbc.cache.DatabaseMetaDataProvider; 036import net.sf.hajdbc.dialect.Dialect; 037 038/** 039 * @author Paul Ferraro 040 * 041 */ 042public class LazyTableProperties extends AbstractTableProperties 043{ 044 private final DatabaseMetaDataProvider metaDataProvider; 045 private final Dialect dialect; 046 private final UniqueConstraintFactory uniqueConstraintFactory; 047 private final ForeignKeyConstraintFactory foreignKeyConstraintFactory; 048 private final ColumnPropertiesFactory columnPropertiesFactory; 049 050 private final AtomicReference<Map<String, ColumnProperties>> columnsRef = new AtomicReference<Map<String, ColumnProperties>>(); 051 private final AtomicReference<UniqueConstraint> primaryKeyRef = new AtomicReference<UniqueConstraint>(); 052 private final AtomicReference<Collection<UniqueConstraint>> uniqueConstraintsRef = new AtomicReference<Collection<UniqueConstraint>>(); 053 private final AtomicReference<Collection<ForeignKeyConstraint>> foreignKeyConstraintsRef = new AtomicReference<Collection<ForeignKeyConstraint>>(); 054 private final AtomicReference<Collection<String>> identityColumnsRef = new AtomicReference<Collection<String>>(); 055 056 public LazyTableProperties(QualifiedName table, DatabaseMetaDataProvider metaDataProvider, Dialect dialect, QualifiedNameFactory nameFactory) 057 { 058 super(table); 059 060 this.metaDataProvider = metaDataProvider; 061 this.dialect = dialect; 062 IdentifierNormalizer normalizer = nameFactory.getIdentifierNormalizer(); 063 this.uniqueConstraintFactory = dialect.createUniqueConstraintFactory(normalizer); 064 this.foreignKeyConstraintFactory = dialect.createForeignKeyConstraintFactory(nameFactory); 065 this.columnPropertiesFactory = dialect.createColumnPropertiesFactory(normalizer); 066 } 067 068 @Override 069 protected Map<String, ColumnProperties> getColumnMap() throws SQLException 070 { 071 Map<String, ColumnProperties> columns = this.columnsRef.get(); 072 073 if (columns == null) 074 { 075 columns = this.dialect.getColumns(this.metaDataProvider.getDatabaseMetaData(), this.getName(), this.columnPropertiesFactory); 076 077 if (!this.columnsRef.compareAndSet(null, columns)) 078 { 079 return this.columnsRef.get(); 080 } 081 } 082 083 return columns; 084 } 085 086 /** 087 * @see net.sf.hajdbc.TableProperties#getPrimaryKey() 088 */ 089 @Override 090 public UniqueConstraint getPrimaryKey() throws SQLException 091 { 092 UniqueConstraint primaryKey = this.primaryKeyRef.get(); 093 094 if (primaryKey == null) 095 { 096 primaryKey = this.dialect.getPrimaryKey(this.metaDataProvider.getDatabaseMetaData(), this.getName(), this.uniqueConstraintFactory); 097 098 if (!this.primaryKeyRef.compareAndSet(null, primaryKey)) 099 { 100 return this.primaryKeyRef.get(); 101 } 102 } 103 104 return primaryKey; 105 } 106 107 /** 108 * @see net.sf.hajdbc.TableProperties#getForeignKeyConstraints() 109 */ 110 @Override 111 public Collection<ForeignKeyConstraint> getForeignKeyConstraints() throws SQLException 112 { 113 Collection<ForeignKeyConstraint> foreignKeyConstraints = this.foreignKeyConstraintsRef.get(); 114 115 if (foreignKeyConstraints == null) 116 { 117 foreignKeyConstraints = this.dialect.getForeignKeyConstraints(this.metaDataProvider.getDatabaseMetaData(), this.getName(), this.foreignKeyConstraintFactory); 118 119 if (!this.foreignKeyConstraintsRef.compareAndSet(null, foreignKeyConstraints)) 120 { 121 return this.foreignKeyConstraintsRef.get(); 122 } 123 } 124 125 return foreignKeyConstraints; 126 } 127 128 /** 129 * @see net.sf.hajdbc.TableProperties#getUniqueConstraints() 130 */ 131 @Override 132 public Collection<UniqueConstraint> getUniqueConstraints() throws SQLException 133 { 134 Collection<UniqueConstraint> uniqueConstraints = this.uniqueConstraintsRef.get(); 135 136 if (uniqueConstraints == null) 137 { 138 uniqueConstraints = this.dialect.getUniqueConstraints(this.metaDataProvider.getDatabaseMetaData(), this.getName(), this.getPrimaryKey(), this.uniqueConstraintFactory); 139 140 if (!this.uniqueConstraintsRef.compareAndSet(null, uniqueConstraints)) 141 { 142 return this.uniqueConstraintsRef.get(); 143 } 144 } 145 146 return uniqueConstraints; 147 } 148 149 /** 150 * @see net.sf.hajdbc.TableProperties#getIdentityColumns() 151 */ 152 @Override 153 public Collection<String> getIdentityColumns() throws SQLException 154 { 155 Collection<String> identityColumns = this.identityColumnsRef.get(); 156 157 if (identityColumns == null) 158 { 159 identityColumns = this.dialect.getIdentityColumns(this.getColumnMap().values()); 160 161 if (!this.identityColumnsRef.compareAndSet(null, identityColumns)) 162 { 163 return this.identityColumnsRef.get(); 164 } 165 } 166 167 return identityColumns; 168 } 169}