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: */package org.geotools.arcsde.data;
017:
018: import java.io.IOException;
019: import java.util.logging.Level;
020: import java.util.logging.Logger;
021:
022: import org.geotools.data.AttributeReader;
023: import org.geotools.data.DataSourceException;
024: import org.geotools.feature.AttributeType;
025: import org.geotools.feature.FeatureType;
026: import org.geotools.feature.GeometryAttributeType;
027: import org.geotools.feature.type.GeometricAttributeType;
028:
029: import com.esri.sde.sdk.client.SeException;
030: import com.esri.sde.sdk.client.SeShape;
031:
032: /**
033: * Implements an attribute reader that is aware of the particulars of ArcSDE.
034: * This class sends its logging to the log named "org.geotools.data".
035: *
036: * @author Gabriel Roldan, Axios Engineering
037: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/arcsde/datastore/src/main/java/org/geotools/arcsde/data/ArcSDEAttributeReader.java $
038: * @version $Id: ArcSDEAttributeReader.java 27863 2007-11-12 20:34:34Z desruisseaux $
039: */
040: class ArcSDEAttributeReader implements AttributeReader {
041: /** Shared package's logger */
042: private static final Logger LOGGER = org.geotools.util.logging.Logging
043: .getLogger("org.geotools.data");
044:
045: /** query passed to the constructor */
046: private ArcSDEQuery query;
047:
048: /** schema of the features this attribute reader iterates over */
049: private FeatureType schema;
050:
051: /** current sde java api row being read */
052: private SdeRow currentRow;
053:
054: /**
055: * the unique id of the current feature. -1 means the feature id was not
056: * retrieved
057: */
058: private long currentFid = -1;
059:
060: /**
061: * the builder for the geometry type of the schema's default geometry, or
062: * null if the geometry attribute is not included in the schema
063: */
064: private ArcSDEGeometryBuilder geometryBuilder;
065:
066: /**
067: * holds the "<DATABASE_NAME>.<USER_NAME>." string and is used
068: * to efficiently create String FIDs from the SeShape feature id, which is a
069: * long number.
070: */
071: private StringBuffer fidPrefix;
072:
073: /**
074: * lenght of the prefix string for creating string based feature ids, used
075: * to truncate the <code>fidPrefix</code> and append it the SeShape's
076: * feature id number
077: */
078: private int fidPrefixLen;
079:
080: /**
081: * Strategy to read FIDs
082: */
083: private FIDReader fidReader;
084:
085: /**
086: * flag to avoid the processing done in <code>hasNext()</code> if next()
087: * was not called between calls to hasNext()
088: */
089: private boolean hasNextAlreadyCalled = false;
090:
091: /**
092: * The query that defines this readers interaction with an ArcSDE instance.
093: *
094: * @param query
095: *
096: * @throws IOException
097: * DOCUMENT ME!
098: */
099: public ArcSDEAttributeReader(ArcSDEQuery query) throws IOException {
100: this .query = query;
101: this .fidReader = query.getFidReader();
102: this .schema = query.getSchema();
103:
104: String typeName = schema.getTypeName();
105:
106: this .fidPrefix = new StringBuffer(typeName).append('.');
107: this .fidPrefixLen = this .fidPrefix.length();
108:
109: final GeometryAttributeType geomType = schema
110: .getDefaultGeometry();
111:
112: if (geomType != null) {
113: Class geometryClass = geomType.getType();
114: this .geometryBuilder = ArcSDEGeometryBuilder
115: .builderFor(geometryClass);
116: }
117: }
118:
119: /**
120: *
121: */
122: public int getAttributeCount() {
123: return this .schema.getAttributeCount();
124: }
125:
126: /**
127: *
128: */
129: public AttributeType getAttributeType(int index)
130: throws ArrayIndexOutOfBoundsException {
131: return this .schema.getAttributeType(index);
132: }
133:
134: /**
135: * Closes the associated query object.
136: *
137: * @throws IOException
138: * DOCUMENT ME!
139: */
140: public void close() throws IOException {
141: this .query.close();
142: }
143:
144: /**
145: *
146: */
147: public boolean hasNext() throws IOException {
148: if (!this .hasNextAlreadyCalled) {
149: try {
150: currentRow = query.fetch();
151: if (currentRow == null) {
152: this .query.close();
153: } else {
154: this .currentFid = fidReader.readFid(currentRow);
155: }
156: hasNextAlreadyCalled = true;
157: } catch (IOException dse) {
158: this .hasNextAlreadyCalled = true;
159: this .query.close();
160: LOGGER
161: .log(Level.SEVERE, dse.getLocalizedMessage(),
162: dse);
163: throw dse;
164: } catch (RuntimeException ex) {
165: this .hasNextAlreadyCalled = true;
166: this .query.close();
167: throw new DataSourceException("Fetching row:"
168: + ex.getMessage(), ex);
169: }
170: }
171:
172: return this .currentRow != null;
173: }
174:
175: /**
176: * Retrieves the next row, or throws a DataSourceException if not more rows
177: * are available.
178: *
179: * @throws IOException
180: * DOCUMENT ME!
181: * @throws DataSourceException
182: * DOCUMENT ME!
183: */
184: public void next() throws IOException {
185: if (this .currentRow == null) {
186: throw new DataSourceException("There are no more rows");
187: }
188:
189: this .hasNextAlreadyCalled = false;
190: }
191:
192: /**
193: * DOCUMENT ME!
194: *
195: * @param index
196: * DOCUMENT ME!
197: *
198: * @return DOCUMENT ME!
199: *
200: * @throws IOException
201: * never, since the feature retrieve was done in
202: * <code>hasNext()</code>
203: * @throws ArrayIndexOutOfBoundsException
204: * if <code>index</code> is outside the bounds of the schema
205: * attribute's count
206: */
207: public Object read(int index) throws IOException,
208: ArrayIndexOutOfBoundsException {
209: Object value = currentRow.getObject(index);
210:
211: if (schema.getAttributeType(index) instanceof GeometricAttributeType) {
212: try {
213: SeShape shape = (SeShape) value;
214: /**
215: Class geomClass = ArcSDEAdapter.getGeometryType(shape.getType());
216: geometryBuilder = GeometryBuilder.builderFor(geomClass);
217: */
218: value = geometryBuilder.construct(shape);
219: } catch (SeException e) {
220: throw new DataSourceException(e);
221: }
222: }
223:
224: return value;
225: }
226:
227: public Object[] readAll() throws ArrayIndexOutOfBoundsException,
228: IOException {
229: int size = schema.getAttributeCount();
230: Object[] all = new Object[size];
231: for (int i = 0; i < size; i++) {
232: all[i] = read(i);
233: }
234: return all;
235: }
236:
237: /**
238: *
239: */
240: public String readFID() throws IOException {
241: if (this .currentFid == -1) {
242: throw new DataSourceException(
243: "The feature id was not fetched");
244: }
245: this.fidPrefix.setLength(this.fidPrefixLen);
246: this.fidPrefix.append(this.currentFid);
247:
248: return this.fidPrefix.toString();
249: }
250: }
|