001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.postgis.fidmapper;
017:
018: import java.io.IOException;
019: import java.sql.Connection;
020: import java.sql.Types;
021: import java.util.Arrays;
022: import java.util.HashSet;
023: import java.util.Set;
024:
025: import org.geotools.data.jdbc.fidmapper.BasicFIDMapper;
026: import org.geotools.data.jdbc.fidmapper.DefaultFIDMapperFactory;
027: import org.geotools.data.jdbc.fidmapper.FIDMapper;
028: import org.geotools.data.jdbc.fidmapper.FIDMapperFactory;
029: import org.geotools.data.jdbc.fidmapper.TypedFIDMapper;
030: import org.geotools.data.postgis.VersionedPostgisDataStore;
031:
032: /**
033: * A fid mapper factory that makes sure the revision attribute does not become part of the key
034: * (since users outside are unaware of it).
035: *
036: * @author aaime
037: * @since 2.4
038: */
039: public class VersionedFIDMapperFactory extends DefaultFIDMapperFactory {
040:
041: Set versionedTypes = new HashSet();
042:
043: private FIDMapperFactory unversionedFactory;
044:
045: public VersionedFIDMapperFactory(FIDMapperFactory unversionedFactory) {
046: super ();
047: this .unversionedFactory = unversionedFactory;
048: returnFIDColumnsAsAttributes = true;
049: returningTypedFIDMapper = false;
050: }
051:
052: public void setVersionedTypes(String[] versionedTypes) {
053: this .versionedTypes.clear();
054: this .versionedTypes.addAll(Arrays.asList(versionedTypes));
055: }
056:
057: /**
058: * Gets the appropriate FIDMapper for the specified table.
059: *
060: * @param catalog
061: * @param schema
062: * @param tableName
063: * @param connection
064: * the active database connection to get table key information
065: *
066: * @return the appropriate FIDMapper for the specified table.
067: *
068: * @throws IOException
069: * if any error occurs.
070: */
071: public FIDMapper getMapper(String catalog, String schema,
072: String tableName, Connection connection) throws IOException {
073: // handle changesets as a special one
074: if (VersionedPostgisDataStore.TBL_CHANGESETS.equals(tableName)) {
075: PostGISAutoIncrementFIDMapper mapper = new PostGISAutoIncrementFIDMapper(
076: VersionedPostgisDataStore.TBL_CHANGESETS,
077: "revision", Types.NUMERIC, true);
078: return new TypedFIDMapper(mapper,
079: VersionedPostgisDataStore.TBL_CHANGESETS);
080: }
081:
082: // for non versioned types we're good with the standard mappers, but we
083: // must remember that versioned data store uses typed fids externally
084: // (only internal ones are non typed)
085: if (!versionedTypes.contains(tableName)) {
086: if (tableName.endsWith("_vfc_view")) {
087: try {
088: String otn = VersionedPostgisDataStore
089: .getVFCTableName(tableName);
090: // let's see if the original feature table is there and versioned
091: VersionedFIDMapper mapper = (VersionedFIDMapper) getMapper(
092: catalog, schema, otn, connection);
093: return new VersionedFeatureCollectionFidMapper(
094: mapper);
095: // return new VersionedFeatureCollectionFidMapper(mapper);
096: } catch (Exception e) {
097: // ok, it wasn't a versioned feature collection view
098: }
099: }
100:
101: return unversionedFactory.getMapper(catalog, schema,
102: tableName, connection);
103:
104: }
105:
106: ColumnInfo[] colInfos = getPkColumnInfo(catalog, schema,
107: tableName, connection);
108: if (colInfos.length <= 1)
109: throw new IOException("Versioned type (" + tableName
110: + ") with a primary key with less than 2 columns,"
111: + " this cannot be, there's a error");
112:
113: // assume revision is the last column
114: if (colInfos.length == 2) {
115: return buildSingleColumnVersionedFidMapper(schema,
116: tableName, connection, colInfos);
117: } else {
118: return buildMultiColumnFIDMapper(schema, tableName,
119: connection, colInfos);
120: }
121: }
122:
123: protected FIDMapper buildSingleColumnVersionedFidMapper(
124: String schema, String tableName, Connection connection,
125: ColumnInfo[] colInfos) {
126: if (colInfos[1].isAutoIncrement() && colInfos.length == 2) {
127: return new VersionedAutoincrementFIDMapper(schema,
128: tableName, colInfos[1].colName,
129: colInfos[1].dataType, colInfos[0].decimalDigits);
130: } else if (isIntegralType(colInfos[1].dataType)) {
131: return buildMultiColumnFIDMapper(schema, tableName,
132: connection, colInfos);
133: } else {
134: return buildMultiColumnFIDMapper(schema, tableName,
135: connection, colInfos);
136: }
137: }
138:
139: protected FIDMapper buildMultiColumnFIDMapper(String schema,
140: String tableName, Connection connection,
141: ColumnInfo[] colInfos) {
142: String[] colNames = new String[colInfos.length];
143: int[] colTypes = new int[colInfos.length];
144: int[] colSizes = new int[colInfos.length];
145: int[] colDecimalDigits = new int[colInfos.length];
146: boolean[] autoIncrement = new boolean[colInfos.length];
147:
148: for (int i = 0; i < colInfos.length; i++) {
149: ColumnInfo ci = colInfos[i];
150: colNames[i] = ci.colName;
151: colTypes[i] = ci.dataType;
152: colSizes[i] = ci.size;
153: colDecimalDigits[i] = ci.decimalDigits;
154: autoIncrement[i] = ci.autoIncrement;
155: }
156:
157: return new VersionedMulticolumnFIDMapper(schema, tableName,
158: colNames, colTypes, colSizes, colDecimalDigits,
159: autoIncrement);
160: }
161: }
|