001: /*
002: * Geotools2 - 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: */
017: package org.geotools.arcsde.data;
018:
019: import java.io.IOException;
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.logging.Logger;
025:
026: import org.geotools.arcsde.pool.ArcSDEPooledConnection;
027: import org.geotools.data.DataSourceException;
028: import org.geotools.feature.AttributeType;
029: import org.geotools.feature.FeatureType;
030:
031: import com.esri.sde.sdk.client.SeException;
032: import com.esri.sde.sdk.client.SeLayer;
033: import com.esri.sde.sdk.client.SeRegistration;
034: import com.esri.sde.sdk.client.SeShape;
035:
036: /**
037: * Strategy object used to manage the different ways an ArcSDE server handles
038: * row identity.
039: * <p>
040: * The supported strategies are:
041: * <ul>
042: * <li>SDE managed mode: a column is assigned by the sde engine to be the
043: * feature id (it uses to be called OBJECTID)
044: * <li>User managed: a user specified row is used as the fid column.
045: * <li>Shape fid: if none of the above, the fid happens to be the identifier of
046: * the geometry column
047: * </ul>
048: * </p>
049: *
050: * @author Gabriel Roldan, Axios Engineering
051: * @version $Id: FIDReader.java 25949 2007-06-20 16:07:37Z desruisseaux $
052: */
053: public abstract class FIDReader {
054:
055: protected String layerName;
056:
057: /** column name holding the feature id attribute */
058: private String fidColumn;
059:
060: private int columnIndex;
061:
062: /**
063: * Creates a new FIDStrategy object.
064: *
065: * @param fidColumns
066: * DOCUMENT ME!
067: */
068: private FIDReader(String layerName, String fidColumn) {
069: this .layerName = layerName;
070: this .fidColumn = fidColumn;
071: }
072:
073: public String getFidColumn() {
074: return fidColumn;
075: }
076:
077: public void setColumnIndex(int fidIndex) {
078: this .columnIndex = fidIndex;
079: }
080:
081: public int getColumnIndex() {
082: return this .columnIndex;
083: }
084:
085: public long readFid(SdeRow row) throws IOException {
086: Object fid = row.getObject(this .columnIndex);
087: return ((Number) fid).longValue();
088: }
089:
090: /**
091: * Returns the attribute names of the FeatureType passed to the constructor.
092: *
093: * @return DOCUMENT ME!
094: *
095: * @throws IOException
096: * if the SeLayer can't be obtained (only if the geomety
097: * attribute was not included in the request).
098: */
099: public String[] getPropertiesToFetch(FeatureType schema)
100: throws IOException {
101:
102: List attNames = new ArrayList(schema.getAttributeCount() + 1);
103:
104: // /List attDescriptors = Descriptors.nodes(schema.getDescriptor());
105: List attDescriptors = Arrays.asList(schema.getAttributeTypes());
106:
107: int i = 0;
108: for (Iterator it = attDescriptors.iterator(); it.hasNext(); i++) {
109: AttributeType property = (AttributeType) it.next();
110: // /attNames.add( property.getName().getLocalPart() );
111: attNames.add(property.getName());
112: }
113:
114: String fidColumn = getFidColumn();
115: int fidIndex = attNames.indexOf(fidColumn);
116: if (fidColumn != null && fidIndex == -1) {
117: attNames.add(fidColumn);
118: fidIndex = attNames.size() - 1;
119: }
120: setColumnIndex(fidIndex);
121:
122: return (String[]) attNames.toArray(new String[attNames.size()]);
123: }
124:
125: /**
126: * Returns a FID strategy appropriate for the given SeLayer
127: *
128: * @param conn
129: * DOCUMENT ME!
130: * @param tableName
131: * DOCUMENT ME!
132: *
133: * @return DOCUMENT ME!
134: *
135: * @throws IOException
136: * DOCUMENT ME!
137: * @throws DataSourceException
138: * DOCUMENT ME!
139: */
140: public static FIDReader getFidReader(ArcSDEPooledConnection conn,
141: SeLayer layer) throws IOException {
142: FIDReader fidReader = null;
143:
144: final String tableName;
145: try {
146: tableName = layer.getQualifiedName();
147: } catch (SeException e) {
148: throw new DataSourceException("asking qualified name of "
149: + layer.getName(), e);
150: }
151: try {
152: SeRegistration reg = new SeRegistration(conn, tableName);
153:
154: // final int rowIdAllocationType = reg.getRowIdAllocation();
155: final int rowIdColumnType = reg.getRowIdColumnType();
156: final String rowIdColumnName = reg.getRowIdColumnName();
157:
158: if (rowIdColumnType == SeRegistration.SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE) {
159: // use column name, value maintained by sde
160: fidReader = new SdeManagedFidReader(tableName,
161: rowIdColumnName);
162: } else if (rowIdColumnType == SeRegistration.SE_REGISTRATION_ROW_ID_COLUMN_TYPE_USER) {
163: // use column name, value maintained by user
164: fidReader = new UserManagedFidReader(tableName,
165: rowIdColumnName);
166: } else if (rowIdColumnType == SeRegistration.SE_REGISTRATION_ROW_ID_COLUMN_TYPE_NONE) {
167: // use geometry id
168: String shapeColName = layer.getSpatialColumn();
169: String shapeIdColName = layer
170: .getShapeAttributeName(SeLayer.SE_SHAPE_ATTRIBUTE_FID);
171: fidReader = new ShapeFidReader(tableName, shapeColName,
172: shapeIdColName);
173: } else {
174: // may have been returned 0, meaning there is no registered
175: // column id
176: throw new IllegalStateException(
177: "Unkown ArcSDE row ID registration type: "
178: + rowIdColumnType + " for layer "
179: + tableName);
180: }
181: return fidReader;
182: } catch (SeException e) {
183: throw new DataSourceException("Obtaining FID strategy for "
184: + layer, e);
185: }
186: }
187:
188: public static class ShapeFidReader extends FIDReader {
189: private final String shapeColName;
190:
191: private int shapeIndex;
192:
193: public ShapeFidReader(final String layerName,
194: final String shapeColName, final String shapeIdColName) {
195: super (layerName, shapeIdColName);
196: this .shapeColName = shapeColName;
197: this .shapeIndex = -1;
198: }
199:
200: public long readFid(SdeRow row) throws IOException {
201: if (shapeIndex != -1) {
202: // we have the shape, so SHAPE.fid couldn't be retrieved
203: // at the same time, need to get the shape and ask it for the id
204: try {
205: SeShape shape = row.getShape(shapeIndex);
206: if (shape == null) {
207: throw new NullPointerException(
208: "Can't get FID from "
209: + layerName
210: + " as it has SHAPE fid reading strategy and got a null shape");
211: }
212: return shape.getFeatureId().longValue();
213: } catch (SeException e) {
214: throw new DataSourceException(
215: "Getting fid from shape", e);
216: }
217: } else {
218: int shapeIdIndex = getColumnIndex();
219: Integer id = (Integer) row.getObject(shapeIdIndex);
220: return id.longValue();
221: }
222: }
223:
224: public String[] getPropertiesToFetch(FeatureType schema)
225: throws IOException {
226: List attNames = new ArrayList(
227: schema.getAttributeCount() + 1);
228:
229: // /List attDescriptors = Descriptors.nodes(schema.getDescriptor());
230: List attDescriptors = Arrays.asList(schema
231: .getAttributeTypes());
232:
233: int i = 0;
234: for (Iterator it = attDescriptors.iterator(); it.hasNext(); i++) {
235: AttributeType property = (AttributeType) it.next();
236: attNames.add(property.getName());
237: }
238:
239: shapeIndex = attNames.indexOf(shapeColName);
240: if (shapeIndex == -1) {
241: String fidColumn = getFidColumn();
242: int fidIndex = attNames.indexOf(shapeColName);
243: if (fidIndex == -1) {
244: attNames.add(fidColumn);
245: fidIndex = attNames.size() - 1;
246: }
247: setColumnIndex(fidIndex);
248: }
249: return (String[]) attNames.toArray(new String[attNames
250: .size()]);
251: }
252:
253: }
254:
255: public static class SdeManagedFidReader extends FIDReader {
256:
257: public SdeManagedFidReader(final String layerName,
258: final String rowIdColName) {
259: super (layerName, rowIdColName);
260: }
261: }
262:
263: public static class UserManagedFidReader extends FIDReader {
264:
265: public UserManagedFidReader(final String layerName,
266: final String rowIdColName) {
267: super (layerName, rowIdColName);
268: }
269: }
270:
271: public static final FIDReader NULL_READER = new FIDReader(null,
272: null) {
273: public long readFid(SdeRow row) throws IOException {
274: return (long) (10000 * Math.random());
275: }
276: };
277: }
|