/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * */ package org.geotools.arcsde.session; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.arcsde.ArcSdeException; import org.geotools.arcsde.logging.Loggers; import com.esri.sde.sdk.client.SeColumnDefinition; import com.esri.sde.sdk.client.SeException; import com.esri.sde.sdk.client.SeRow; import com.esri.sde.sdk.client.SeShape; import com.esri.sde.sdk.geom.GeometryFactory; /** * Wrapper for an SeRow so it allows asking multiple times for the same property. * * @author Gabriel Roldan, Axios Engineering * @version $Id$ * * @source $URL$ * http://svn.geotools.org/geotools/trunk/gt/modules/plugin/arcsde/datastore/src/main/java * /org/geotools/arcsde/data/SdeRow.java $ * @since 2.4.0 */ public class SdeRow { private static final Logger LOGGER = Loggers.getLogger("org.geotools.arcsde.session"); /** cached SeRow values */ private Object[] values; private int[] colStatusIndicator; private int nCols; /** * A possible non set SDE geometry factory that provides the means for geometry fetching other * than SeRow.getShape(). That is, if this geometryFactory is non null, it will be used to fetch * the geometric attributes. Otherwise SeRow.getShape():SeShape will be used */ private GeometryFactory geometryFactory; private int geometryIndex = -1; public SdeRow(GeometryFactory geometryFactory) { this.geometryFactory = geometryFactory; } public SdeRow(SeRow row) throws IOException { this(row, null); } public SdeRow(SeRow row, GeometryFactory geometryFactory) throws IOException { this.geometryFactory = geometryFactory; setRow(row); } public void setRow(SeRow row) throws IOException { final int ncols = row.getNumColumns(); if (this.nCols != ncols) { this.nCols = ncols; values = new Object[nCols]; colStatusIndicator = new int[nCols]; } int i = 0; int statusIndicator = 0; try { for (i = 0; i < nCols; i++) { statusIndicator = row.getIndicator(i); colStatusIndicator[i] = statusIndicator; if (statusIndicator == SeRow.SE_IS_ALREADY_FETCHED || statusIndicator == SeRow.SE_IS_REPEATED_FEATURE || statusIndicator == SeRow.SE_IS_NULL_VALUE) { // ignore, will use previous values } else { if (this.geometryFactory != null && this.geometryIndex == i) { values[i] = row.getGeometry(geometryFactory, i); } else { values[i] = row.getObject(i); } /* * ML: I'm adding checks here for the [n] clob object that are returned as null * by getObject, but are reported as Strings. We can suck those out of * ByteArrayStreams */ if (values[i] == null) { ByteArrayInputStream clobIn = null; BufferedReader reader = null; try { int type = row.getColumnDef(i).getType(); if (type == SeColumnDefinition.TYPE_NCLOB) { clobIn = row.getNClob(i); } else if (type == SeColumnDefinition.TYPE_CLOB) { /* * Warning! this line throws an NPE with the 9.2 java api, but works * with the 9.3 jars */ clobIn = row.getClob(i); } if (clobIn != null) { reader = new BufferedReader(new InputStreamReader(clobIn, "UTF-16")); StringBuffer buf = new StringBuffer(); String snip = reader.readLine(); while (snip != null) { if (buf.length() != 0) buf.append('\n'); buf.append(snip); snip = reader.readLine(); } if (buf.length() > 0) values[i] = buf.toString(); } } catch (IOException e) { LOGGER.log(Level.FINEST, "Issue decoding CLOB/NCLOB into a String:" + e, e); // value will remain null } finally { if (reader != null) { try { reader.close(); } catch (IOException ignore) { LOGGER.log(Level.FINEST, "Issue cleaning up after CLOB/NCLOB:" + ignore, ignore); } } } } } } } catch (SeException e) { throw new ArcSdeException("getting property #" + i, e); } } public void setPreviousValues(Object[] previousValues) { int statusIndicator; for (int i = 0; i < nCols; i++) { statusIndicator = colStatusIndicator[i]; if (statusIndicator == SeRow.SE_IS_ALREADY_FETCHED || statusIndicator == SeRow.SE_IS_REPEATED_FEATURE) { values[i] = previousValues[i]; } } } /** * DOCUMENT ME! * * @param index * DOCUMENT ME! * @return DOCUMENT ME! * @throws IOException * DOCUMENT ME! */ public Object getObject(int index) throws IOException { return values[index]; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Object[] getAll() { return values; } /** * DOCUMENT ME! * * @param index * DOCUMENT ME! * @return DOCUMENT ME! * @throws IOException * DOCUMENT ME! */ public Long getLong(int index) throws IOException { return (Long) getObject(index); } /** * DOCUMENT ME! * * @param index * DOCUMENT ME! * @return DOCUMENT ME! * @throws IOException * DOCUMENT ME! */ public SeShape getShape(int index) throws IOException { return (SeShape) getObject(index); } /** * @param columnIndex * @return one of {@link SeRow#SE_IS_ALREADY_FETCHED}, {@link SeRow#SE_IS_NOT_NULL_VALUE}, * {@link SeRow#SE_IS_NULL_VALUE}, {@link SeRow#SE_IS_REPEATED_FEATURE} */ public int getIndicator(int columnIndex) { return colStatusIndicator[columnIndex]; } public Integer getInteger(int index) throws IOException { return (Integer) getObject(index); } /** * @param geometryIndex * a value >= 0 indicates which index in the row contains the geometry attribute. If * not set, geometryFactory will be ignored */ public void setGeometryIndex(int geometryIndex) { this.geometryIndex = geometryIndex; } }