001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.gps.device.jdbc.mapping;
018:
019: import java.sql.Connection;
020: import java.sql.DatabaseMetaData;
021: import java.sql.ResultSet;
022: import java.sql.SQLException;
023: import java.util.Iterator;
024: import javax.sql.DataSource;
025: import org.compass.gps.device.jdbc.JdbcGpsDeviceException;
026: import org.compass.gps.device.jdbc.JdbcUtils;
027:
028: /**
029: * A specialized form of
030: * {@link org.compass.gps.device.jdbc.mapping.ResultSetToResourceMapping},
031: * mapping a specfic database table to a resource.
032: * <p>
033: * Since the mapping works against a table, most of the parameters can be
034: * automatically generated. The required mappings are the alias name and the
035: * table name. The settings that can be generated are the id mappings
036: * (based on the table primary keys), the select query (based on the table
037: * name), and the version query (based on the table name and the version column
038: * mappings).
039: * <p>
040: * If no data column mappings are provided, the
041: * <code>indexUnMappedColumns</code> from
042: * {@link org.compass.gps.device.jdbc.mapping.ResultSetToResourceMapping} can be
043: * user to auto map all the table columns as data columns.
044: * <p>
045: * For real time mirroring, at least one version column mapping ({@link org.compass.gps.device.jdbc.mapping.VersionColumnMapping})
046: * is required. And the version query can be auto generated.
047: * <p>
048: * Note that the mapping will auto generate only settings that have not been
049: * set. If, for example, the select query was set, it will not be generated.
050: *
051: * @author kimchy
052: */
053: public class TableToResourceMapping extends ResultSetToResourceMapping
054: implements AutoGenerateMapping {
055:
056: private String tableName;
057:
058: /**
059: * Creates a new table to <code>Resource</code> mapping. Must set the
060: * alias, and the table name.
061: * <p>
062: * Indexing of unmapped columns is diasabled by default.
063: *
064: */
065: public TableToResourceMapping() {
066:
067: }
068:
069: /**
070: * Creates a new table to {@link org.compass.core.Resource} mapping with the given
071: * table name and alias.
072: * <p>
073: * Indexing of unmapped columns is disabled by default.
074: *
075: * @param tableName The table name
076: * @param alias The {@link org.compass.core.Resource} alias
077: */
078: public TableToResourceMapping(String tableName, String alias) {
079: setAlias(alias);
080: this .tableName = tableName;
081: }
082:
083: /**
084: * Generates the unset mappings.
085: * <p>
086: * Generates the id mappings based on the table primary keys if no id column
087: * mappings are set.
088: * <p>
089: * Generates the select query based on the table name if no select query is
090: * set.
091: * <p>
092: * Generates the version query based on the table name and the version
093: * column mappings if no version query is set and at least one version
094: * column mapping is set.
095: */
096: public void generateMappings(DataSource dataSource)
097: throws JdbcGpsDeviceException {
098: if (idMappingsSize() == 0) {
099: generateIdMappings(dataSource);
100: }
101: if (getSelectQuery() == null) {
102: generateSelectQuery(dataSource);
103: }
104: if (getVersionQuery() == null && supportsVersioning()) {
105: generateVersionQuery(dataSource);
106: }
107: }
108:
109: private void generateIdMappings(DataSource dataSource)
110: throws JdbcGpsDeviceException {
111: Connection con = JdbcUtils.getConnection(dataSource);
112: ResultSet pks = null;
113: try {
114: DatabaseMetaData metaData = con.getMetaData();
115: pks = metaData.getPrimaryKeys(null, null, getTableName()
116: .toUpperCase());
117: while (pks.next()) {
118: String pkColumnName = pks.getString("COLUMN_NAME");
119: addIdMapping(new IdColumnToPropertyMapping(
120: pkColumnName, pkColumnName));
121: }
122: } catch (SQLException e) {
123: throw new JdbcGpsDeviceException(
124: "Failed to fetch primary keys for table ["
125: + getTableName() + "]", e);
126: } finally {
127: JdbcUtils.closeResultSet(pks);
128: JdbcUtils.closeConnection(con);
129: }
130: }
131:
132: private void generateSelectQuery(DataSource dataSource) {
133: if (isIndexUnMappedColumns()) {
134: setSelectQuery("select * from " + getTableName());
135: } else {
136: StringBuffer sb = new StringBuffer();
137: sb.append("select ");
138: boolean first = true;
139: for (Iterator idIt = idMappingsIt(); idIt.hasNext();) {
140: ColumnToPropertyMapping idMapping = (ColumnToPropertyMapping) idIt
141: .next();
142: if (first) {
143: first = false;
144: } else {
145: sb.append(", ");
146: }
147: if (idMapping.isUsingColumnIndex()) {
148: throw new IllegalArgumentException(
149: "When mapping and not using the indexUnMappedColumns, must specify id column name and not column index");
150: }
151: sb.append(idMapping.getColumnName());
152: }
153: for (Iterator dataIt = dataMappingsIt(); dataIt.hasNext();) {
154: ColumnToPropertyMapping dataMapping = (ColumnToPropertyMapping) dataIt
155: .next();
156: sb.append(", ");
157: if (dataMapping.isUsingColumnIndex()) {
158: throw new IllegalArgumentException(
159: "When mapping and not using the indexUnMappedColumns, must specify id column name and not column index");
160: }
161: sb.append(dataMapping.getColumnName());
162: }
163: for (Iterator verIt = versionMappingsIt(); verIt.hasNext();) {
164: VersionColumnMapping verMapping = (VersionColumnMapping) verIt
165: .next();
166: sb.append(", ");
167: if (verMapping.isUsingColumnIndex()) {
168: throw new IllegalArgumentException(
169: "When mapping version column to a table, must specify version column name and not column index");
170: }
171: sb.append(verMapping.getColumnName());
172: }
173: sb.append(" from ");
174: sb.append(getTableName());
175: setSelectQuery(sb.toString());
176: }
177: }
178:
179: private void generateVersionQuery(DataSource dataSource) {
180: StringBuffer sb = new StringBuffer();
181: sb.append("select ");
182: boolean first = true;
183: for (Iterator idIt = idMappingsIt(); idIt.hasNext();) {
184: IdColumnToPropertyMapping idMapping = (IdColumnToPropertyMapping) idIt
185: .next();
186: if (first) {
187: first = false;
188: } else {
189: sb.append(", ");
190: }
191: sb.append(idMapping.getColumnNameForVersion());
192: }
193: for (Iterator verIt = versionMappingsIt(); verIt.hasNext();) {
194: VersionColumnMapping verMapping = (VersionColumnMapping) verIt
195: .next();
196: sb.append(", ");
197: if (verMapping.isUsingColumnIndex()) {
198: throw new IllegalArgumentException(
199: "When mapping version column to a table, must specify version column name and not column index");
200: }
201: sb.append(verMapping.getColumnName());
202: }
203: sb.append(" from ");
204: sb.append(getTableName());
205: setVersionQuery(sb.toString());
206: }
207:
208: /**
209: * Returns the table name that the mappings maps to.
210: */
211: public String getTableName() {
212: return tableName;
213: }
214:
215: /**
216: * Sets the table name that the mappings maps to.
217: */
218: public void setTableName(String tableName) {
219: this .tableName = tableName;
220: }
221:
222: public String toString() {
223: return "Table[" + tableName + "] " + super.toString();
224: }
225: }
|