Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -49,6 +49,12 @@ public class DBFRecordBasedResultSet ext /** Condition of where clause (currently, only one is handled). */ private ConditionalClauseResolver singleConditionOfWhereClause; + /** Indicates that the last result set record matching conditions has already been returned, and a further call of next() shall throw a "no more record" exception. */ + private boolean lastResultSetRecordAlreadyReturned; + + /** The record number of this record. */ + private int recordNumber; + /** * Constructs a result set. * @param stmt Parent statement. @@ -57,7 +63,7 @@ public class DBFRecordBasedResultSet ext */ public DBFRecordBasedResultSet(final DBFStatement stmt, String sqlQuery) throws SQLInvalidStatementException { super(stmt, sqlQuery); - singleConditionOfWhereClause = new CrudeSQLParser(this).parse(); + this.singleConditionOfWhereClause = new CrudeSQLParser(this).parse(); } /** @@ -79,11 +85,11 @@ public class DBFRecordBasedResultSet ext if (doubleValue != null) { BigDecimal number = new BigDecimal(doubleValue, mc); - wasNull = false; + this.wasNull = false; return number; } else { - wasNull = true; + this.wasNull = true; return null; } } @@ -99,7 +105,7 @@ public class DBFRecordBasedResultSet ext @Override public BigDecimal getBigDecimal(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getBigDecimal", columnIndex); - return getBigDecimal(getFieldName(columnIndex, sql)); + return getBigDecimal(getFieldName(columnIndex, this.sql)); } /** @@ -120,11 +126,11 @@ public class DBFRecordBasedResultSet ext if (doubleValue != null) { BigDecimal number = new BigDecimal(getDouble(columnLabel), mc); - wasNull = false; + this.wasNull = false; return number; } else { - wasNull = true; + this.wasNull = true; return null; } } @@ -143,18 +149,18 @@ public class DBFRecordBasedResultSet ext String value = getString(columnLabel); if (value == null || value.equals("00000000")) { // "00000000" is stored in Database to represent a null value too. - wasNull = true; + this.wasNull = true; return null; // The ResultSet:getDate() contract is to return null when a null date is encountered. } else { - wasNull = false; + this.wasNull = false; } // The DBase 3 date format is "YYYYMMDD". // if the length of the string isn't eight characters, the field format is incorrect. if (value.length() != 8) { - String message = format(Level.WARNING, "excp.field_is_not_a_date", columnLabel, sql, value); - throw new SQLNotDateException(message, sql, getFile(), columnLabel, value); + String message = format(Level.WARNING, "excp.field_is_not_a_date", columnLabel, this.sql, value); + throw new SQLNotDateException(message, this.sql, getFile(), columnLabel, value); } // Extract the date parts. @@ -166,8 +172,8 @@ public class DBFRecordBasedResultSet ext dayOfMonth = Integer.parseInt(value.substring(7)); } catch(NumberFormatException e) { - String message = format(Level.WARNING, "excp.field_is_not_a_date", columnLabel, sql, value); - throw new SQLNotDateException(message, sql, getFile(), columnLabel, value); + String message = format(Level.WARNING, "excp.field_is_not_a_date", columnLabel, this.sql, value); + throw new SQLNotDateException(message, this.sql, getFile(), columnLabel, value); } // Create a date. @@ -186,7 +192,7 @@ public class DBFRecordBasedResultSet ext @Override public Date getDate(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotDateException, SQLIllegalColumnIndexException { logStep("getDate", columnIndex); - return getDate(getFieldName(columnIndex, sql)); + return getDate(getFieldName(columnIndex, this.sql)); } /** @@ -204,7 +210,7 @@ public class DBFRecordBasedResultSet ext return Double.parseDouble(value); } }); - wasNull = (value == null); + this.wasNull = (value == null); return value != null ? value : 0.0; // The ResultSet contract for numbers is to return 0 when a null value is encountered. } @@ -218,7 +224,7 @@ public class DBFRecordBasedResultSet ext @Override public double getDouble(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getDouble", columnIndex); - return getDouble(getFieldName(columnIndex, sql)); + return getDouble(getFieldName(columnIndex, this.sql)); } /** @@ -236,7 +242,7 @@ public class DBFRecordBasedResultSet ext return Float.parseFloat(value); } }); - wasNull = (value == null); + this.wasNull = (value == null); return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered. } @@ -250,7 +256,7 @@ public class DBFRecordBasedResultSet ext @Override public float getFloat(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getFloat", columnIndex); - return getFloat(getFieldName(columnIndex, sql)); + return getFloat(getFieldName(columnIndex, this.sql)); } /** @@ -268,7 +274,7 @@ public class DBFRecordBasedResultSet ext return Integer.parseInt(value); } }); - wasNull = (value == null); + this.wasNull = (value == null); return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered. } @@ -282,7 +288,7 @@ public class DBFRecordBasedResultSet ext @Override public int getInt(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getInt", columnIndex); - return getInt(getFieldName(columnIndex, sql)); + return getInt(getFieldName(columnIndex, this.sql)); } /** @@ -300,7 +306,7 @@ public class DBFRecordBasedResultSet ext return Long.parseLong(value); } }); - wasNull = (value == null); + this.wasNull = (value == null); return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered. } @@ -313,7 +319,7 @@ public class DBFRecordBasedResultSet ext */ @Override public long getLong(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getLong", columnIndex); - return getLong(getFieldName(columnIndex, sql)); + return getLong(getFieldName(columnIndex, this.sql)); } /** @@ -332,7 +338,7 @@ public class DBFRecordBasedResultSet ext */ @Override public Object getObject(int column) throws SQLConnectionClosedException, SQLIllegalColumnIndexException, SQLFeatureNotSupportedException, SQLNoSuchFieldException, SQLNotNumericException, SQLNotDateException { - try(DBFBuiltInMemoryResultSetForColumnsListing field = (DBFBuiltInMemoryResultSetForColumnsListing)getFieldDesc(column, sql)) { + try(DBFBuiltInMemoryResultSetForColumnsListing field = (DBFBuiltInMemoryResultSetForColumnsListing)getFieldDesc(column, this.sql)) { String fieldType; try { @@ -421,6 +427,14 @@ public class DBFRecordBasedResultSet ext } /** + * Return the record number of this record. + * @return Record number of this record. + */ + public int getRowNum() { + return this.recordNumber; + } + + /** * @see java.sql.ResultSet#getShort(java.lang.String) * @throws SQLConnectionClosedException if the connection is closed. * @throws SQLNoSuchFieldException if the field looked for doesn't exist. @@ -435,7 +449,7 @@ public class DBFRecordBasedResultSet ext return Short.parseShort(value); } }); - wasNull = (value == null); + this.wasNull = (value == null); return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered. } @@ -449,7 +463,7 @@ public class DBFRecordBasedResultSet ext @Override public short getShort(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException { logStep("getShort", columnIndex); - return getShort(getFieldName(columnIndex, sql)); + return getShort(getFieldName(columnIndex, this.sql)); } /** @@ -464,15 +478,15 @@ public class DBFRecordBasedResultSet ext logStep("getString", columnLabel); assertNotClosed(); - getFieldDesc(columnLabel, sql); // Ensure that the field queried exists, else a null value here can be interpreted as "not existing" or "has a null value". - byte[] bytes = record.get(columnLabel); + getFieldDesc(columnLabel, this.sql); // Ensure that the field queried exists, else a null value here can be interpreted as "not existing" or "has a null value". + byte[] bytes = this.record.get(columnLabel); if (bytes == null) { - wasNull = true; + this.wasNull = true; return null; } else { - wasNull = false; + this.wasNull = false; } // If a non null value has been readed, convert it to the wished Charset (provided one has been given). @@ -498,7 +512,7 @@ public class DBFRecordBasedResultSet ext @Override public String getString(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLIllegalColumnIndexException { logStep("getString", columnIndex); - return(getString(getFieldName(columnIndex, sql))); + return(getString(getFieldName(columnIndex, this.sql))); } /** @@ -521,7 +535,13 @@ public class DBFRecordBasedResultSet ext // Check that we aren't at the end of the Database file. if (cnt.nextRowAvailable() == false) { - throw new SQLNoResultException(format(Level.WARNING, "excp.no_more_results", sql, getFile().getName()), sql, getFile()); + if (this.lastResultSetRecordAlreadyReturned) { + throw new SQLNoResultException(format(Level.WARNING, "excp.no_more_results", this.sql, getFile().getName()), this.sql, getFile()); + } + else { + this.lastResultSetRecordAlreadyReturned = true; + return false; + } } return nextRecordMatchingConditions(); @@ -544,11 +564,12 @@ public class DBFRecordBasedResultSet ext DBFConnection cnt = (DBFConnection)((DBFStatement)getStatement()).getConnection(); while(cnt.nextRowAvailable() && recordMatchesConditions == false) { - record = cnt.readNextRowAsObjects(); - recordMatchesConditions = singleConditionOfWhereClause == null || singleConditionOfWhereClause.isVerified(this); + this.record = cnt.readNextRowAsObjects(); + this.recordNumber = cnt.getRowNum(); + recordMatchesConditions = this.singleConditionOfWhereClause == null || this.singleConditionOfWhereClause.isVerified(this); } - return recordMatchesConditions && cnt.nextRowAvailable(); // Beware of the end of database ! + return recordMatchesConditions; } /** @@ -566,7 +587,7 @@ public class DBFRecordBasedResultSet ext @Override public boolean wasNull() { logStep("wasNull"); - return wasNull; + return this.wasNull; } /** @@ -582,7 +603,7 @@ public class DBFRecordBasedResultSet ext private <T extends Number> T getNumeric(String columnLabel, Function<String, T> parse) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException { assertNotClosed(); - try(DBFBuiltInMemoryResultSetForColumnsListing rs = (DBFBuiltInMemoryResultSetForColumnsListing)getFieldDesc(columnLabel, sql)) { + try(DBFBuiltInMemoryResultSetForColumnsListing rs = (DBFBuiltInMemoryResultSetForColumnsListing)getFieldDesc(columnLabel, this.sql)) { String textValue = getString(columnLabel); if (textValue == null) { @@ -595,8 +616,8 @@ public class DBFRecordBasedResultSet ext return(value); } catch(NumberFormatException e) { - String message = format(Level.WARNING, "excp.field_is_not_numeric", columnLabel, rs.getString("TYPE_NAME"), sql, textValue); - throw new SQLNotNumericException(message, sql, getFile(), columnLabel, textValue); + String message = format(Level.WARNING, "excp.field_is_not_numeric", columnLabel, rs.getString("TYPE_NAME"), this.sql, textValue); + throw new SQLNotNumericException(message, this.sql, getFile(), columnLabel, textValue); } } } @@ -606,6 +627,6 @@ public class DBFRecordBasedResultSet ext */ @Override public String toString() { - return format("toString", statement != null ? statement.toString() : null, sql, isClosed() == false); + return format("toString", this.statement != null ? this.statement.toString() : null, this.sql, isClosed() == false); } }
Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFResultSet.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFResultSet.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFResultSet.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFResultSet.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -56,8 +56,8 @@ public abstract class DBFResultSet exten public DBFResultSet(final DBFStatement stmt, String sqlQuery) { Objects.requireNonNull(stmt, "the statement referred by the ResultSet cannot be null."); - statement = stmt; - sql = sqlQuery; + this.statement = stmt; + this.sql = sqlQuery; } /** @@ -73,10 +73,10 @@ public abstract class DBFResultSet exten * @throws SQLConnectionClosedException if one of them is closed. */ protected void assertNotClosed() throws SQLConnectionClosedException { - statement.assertNotClosed(); + this.statement.assertNotClosed(); - if (isClosed) { - throw new SQLConnectionClosedException(format(Level.WARNING, "excp.closed_resultset", sql, getFile().getName()), sql, getFile()); + if (this.isClosed) { + throw new SQLConnectionClosedException(format(Level.WARNING, "excp.closed_resultset", this.sql, getFile().getName()), this.sql, getFile()); } } @@ -96,8 +96,8 @@ public abstract class DBFResultSet exten if (isClosed()) return; - statement.notifyCloseResultSet(this); - isClosed = true; + this.statement.notifyCloseResultSet(this); + this.isClosed = true; } /** @@ -111,7 +111,7 @@ public abstract class DBFResultSet exten @Override @SuppressWarnings("resource") // The connection is only used to get the column index. public int findColumn(String columnLabel) throws SQLNoSuchFieldException, SQLConnectionClosedException { - DBFConnection cnt = (DBFConnection)statement.getConnection(); + DBFConnection cnt = (DBFConnection)this.statement.getConnection(); return cnt.findColumn(columnLabel, getSQL()); } @@ -231,7 +231,7 @@ public abstract class DBFResultSet exten */ @SuppressWarnings("resource") // Only use the current connection to get the field name. public String getFieldName(int columnIndex, String sqlStatement) throws SQLIllegalColumnIndexException, SQLConnectionClosedException { - DBFConnection cnt = (DBFConnection)statement.getConnection(); + DBFConnection cnt = (DBFConnection)this.statement.getConnection(); return cnt.getFieldName(columnIndex, sqlStatement); } @@ -241,7 +241,7 @@ public abstract class DBFResultSet exten */ @Override public File getFile() { - return statement.getFile(); + return this.statement.getFile(); } /** @@ -391,7 +391,7 @@ public abstract class DBFResultSet exten * @return SQL query. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -410,7 +410,7 @@ public abstract class DBFResultSet exten @Override public Statement getStatement() throws SQLConnectionClosedException { assertNotClosed(); - return statement; + return this.statement; } /** @@ -445,7 +445,7 @@ public abstract class DBFResultSet exten */ @Override public boolean isClosed() { - return isClosed || statement.isClosed(); + return this.isClosed || this.statement.isClosed(); } /** @@ -928,7 +928,7 @@ public abstract class DBFResultSet exten */ @Override public boolean wasNull() { - return wasNull; + return this.wasNull; } /** @@ -960,6 +960,6 @@ public abstract class DBFResultSet exten */ @Override public String toString() { - return format("toString", statement != null ? statement.toString() : null, sql, isClosed() == false); + return format("toString", this.statement != null ? this.statement.toString() : null, this.sql, isClosed() == false); } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -45,9 +45,9 @@ public class SQLIllegalColumnIndexExcept */ public SQLIllegalColumnIndexException(String message, String sqlStatement, File dbf, int colIndex) { super(message); - sql = sqlStatement; - database = dbf; - columnIndex = colIndex; + this.sql = sqlStatement; + this.database = dbf; + this.columnIndex = colIndex; } /** @@ -55,7 +55,7 @@ public class SQLIllegalColumnIndexExcept * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -63,7 +63,7 @@ public class SQLIllegalColumnIndexExcept * @return Column index. */ public int getColumnIndex() { - return columnIndex; + return this.columnIndex; } /** @@ -71,6 +71,6 @@ public class SQLIllegalColumnIndexExcept * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,8 +41,8 @@ public class SQLNoResultException extend */ public SQLNoResultException(String message, String sqlStatement, File dbf) { super(message); - sql = sqlStatement; - database = dbf; + this.sql = sqlStatement; + this.database = dbf; } /** @@ -50,7 +50,7 @@ public class SQLNoResultException extend * @return SQL statement. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -58,6 +58,6 @@ public class SQLNoResultException extend * @return The database that was queried. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -45,9 +45,9 @@ public class SQLNoSuchFieldException ext */ public SQLNoSuchFieldException(String message, String sqlStatement, File dbf, String colName) { super(message); - sql = sqlStatement; - database = dbf; - columnName = colName; + this.sql = sqlStatement; + this.database = dbf; + this.columnName = colName; } /** @@ -55,7 +55,7 @@ public class SQLNoSuchFieldException ext * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -63,7 +63,7 @@ public class SQLNoSuchFieldException ext * @return Column name. */ public String getColumnName() { - return columnName; + return this.columnName; } /** @@ -71,6 +71,6 @@ public class SQLNoSuchFieldException ext * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -49,10 +49,10 @@ public class SQLNotDateException extends */ public SQLNotDateException(String message, String sqlStatement, File dbf, String colName, String wrongValue) { super(message); - sql = sqlStatement; - database = dbf; - columnName = colName; - value = wrongValue; + this.sql = sqlStatement; + this.database = dbf; + this.columnName = colName; + this.value = wrongValue; } /** @@ -60,7 +60,7 @@ public class SQLNotDateException extends * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -68,7 +68,7 @@ public class SQLNotDateException extends * @return Column name. */ public String getColumnName() { - return columnName; + return this.columnName; } /** @@ -76,7 +76,7 @@ public class SQLNotDateException extends * @return Value. */ public String getValue() { - return value; + return this.value; } /** @@ -84,6 +84,6 @@ public class SQLNotDateException extends * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -49,10 +49,10 @@ public class SQLNotNumericException exte */ public SQLNotNumericException(String message, String sqlStatement, File dbf, String colName, String wrongValue) { super(message); - sql = sqlStatement; - database = dbf; - columnName = colName; - value = wrongValue; + this.sql = sqlStatement; + this.database = dbf; + this.columnName = colName; + this.value = wrongValue; } /** @@ -60,7 +60,7 @@ public class SQLNotNumericException exte * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -68,7 +68,7 @@ public class SQLNotNumericException exte * @return Column name. */ public String getColumnName() { - return columnName; + return this.columnName; } /** @@ -76,7 +76,7 @@ public class SQLNotNumericException exte * @return Value. */ public String getValue() { - return value; + return this.value; } /** @@ -84,6 +84,6 @@ public class SQLNotNumericException exte * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ClauseResolver.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ClauseResolver.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ClauseResolver.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ClauseResolver.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -49,9 +49,9 @@ public abstract class ClauseResolver ext * @param op The operator to apply. */ public ClauseResolver(Object cmp1, Object cmp2, String op) { - comparand1 = cmp1; - comparand2 = cmp2; - operator = op; + this.comparand1 = cmp1; + this.comparand2 = cmp2; + this.operator = op; } /** @@ -59,7 +59,7 @@ public abstract class ClauseResolver ext * @return First comparand. */ public Object getComparand1() { - return comparand1; + return this.comparand1; } /** @@ -67,7 +67,7 @@ public abstract class ClauseResolver ext * @return Second comparand. */ public Object getComparand2() { - return comparand2; + return this.comparand2; } /** @@ -75,7 +75,7 @@ public abstract class ClauseResolver ext * @return Operator. */ public String getOperator() { - return operator; + return this.operator; } /** @@ -83,7 +83,7 @@ public abstract class ClauseResolver ext * @param comparand First comparand. */ public void setComparand1(Object comparand) { - comparand1 = comparand; + this.comparand1 = comparand; } /** @@ -91,7 +91,7 @@ public abstract class ClauseResolver ext * @param comparand Second comparand. */ public void setComparand2(Object comparand) { - comparand2 = comparand; + this.comparand2 = comparand; } /** @@ -99,7 +99,7 @@ public abstract class ClauseResolver ext * @param op Operator. */ public void setOperator(String op) { - operator = op; + this.operator = op; } /** Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -37,7 +37,7 @@ public class CrudeSQLParser extends Abst */ public CrudeSQLParser(DBFRecordBasedResultSet resultset) { Objects.requireNonNull(resultset, "The ResultSet given to the SQL parser cannot be null."); - rs = resultset; + this.rs = resultset; } /** @@ -48,11 +48,11 @@ public class CrudeSQLParser extends Abst public ConditionalClauseResolver parse() throws SQLInvalidStatementException { logStep("parse"); - String sql = rs.getSQL().trim(); + String sql = this.rs.getSQL().trim(); if (sql.toLowerCase().startsWith("select * from ") == false) { String message = format(Level.WARNING, "excp.limited_feature_syntax", sql); - throw new SQLInvalidStatementException(message, rs.getSQL(), rs.getFile()); + throw new SQLInvalidStatementException(message, this.rs.getSQL(), this.rs.getFile()); } final String whereWord = " where "; @@ -69,7 +69,7 @@ public class CrudeSQLParser extends Abst // If the condition is empty, it's a syntax error because a WHERE clause went before. if (whereCondition.isEmpty()) { String message = format(Level.WARNING, "excp.where_without_conditions", sql); - throw new SQLInvalidStatementException(message, rs.getSQL(), rs.getFile()); + throw new SQLInvalidStatementException(message, this.rs.getSQL(), this.rs.getFile()); } // Currently, all the condition are made of three parts : @@ -80,7 +80,7 @@ public class CrudeSQLParser extends Abst if (parts.length != 3) { String message = format(Level.WARNING, "excp.limited_feature_conditional_parsing", whereCondition, sql); - throw new SQLInvalidStatementException(message, rs.getSQL(), rs.getFile()); + throw new SQLInvalidStatementException(message, this.rs.getSQL(), this.rs.getFile()); } // Detect and promote litterals in parameters to their best types. @@ -124,7 +124,7 @@ public class CrudeSQLParser extends Abst * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getFile() */ @Override protected File getFile() { - return rs.getFile(); + return this.rs.getFile(); } /** Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -49,10 +49,10 @@ public class SQLIllegalParameterExceptio */ public SQLIllegalParameterException(String message, String sqlStatement, File dbf, String name, String value) { super(message); - sql = sqlStatement; - database = dbf; - parameterName = name; - parameterValue = value; + this.sql = sqlStatement; + this.database = dbf; + this.parameterName = name; + this.parameterValue = value; } /** @@ -60,7 +60,7 @@ public class SQLIllegalParameterExceptio * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -68,7 +68,7 @@ public class SQLIllegalParameterExceptio * @return Parameter name. */ public String geParameterName() { - return parameterName; + return this.parameterName; } /** @@ -76,7 +76,7 @@ public class SQLIllegalParameterExceptio * @return Parameter name. */ public String geParameterValue() { - return parameterValue; + return this.parameterValue; } /** @@ -84,6 +84,6 @@ public class SQLIllegalParameterExceptio * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,8 +41,8 @@ public class SQLInvalidStatementExceptio */ public SQLInvalidStatementException(String message, String sqlStatement, File dbf) { super(message); - sql = sqlStatement; - database = dbf; + this.sql = sqlStatement; + this.database = dbf; } /** @@ -50,7 +50,7 @@ public class SQLInvalidStatementExceptio * @return SQL statement or null. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -58,6 +58,6 @@ public class SQLInvalidStatementExceptio * @return Database file. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,8 +41,8 @@ public class SQLUnsupportedParsingFeatur */ public SQLUnsupportedParsingFeatureException(String message, String sqlStatement, File dbf) { super(message); - sql = sqlStatement; - database = dbf; + this.sql = sqlStatement; + this.database = dbf; } /** @@ -50,7 +50,7 @@ public class SQLUnsupportedParsingFeatur * @return SQL statement. */ public String getSQL() { - return sql; + return this.sql; } /** @@ -58,6 +58,6 @@ public class SQLUnsupportedParsingFeatur * @return The database that was queried. */ public File getDatabase() { - return database; + return this.database; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/statement/DBFStatement.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/statement/DBFStatement.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/statement/DBFStatement.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/statement/DBFStatement.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -66,7 +66,7 @@ public class DBFStatement extends Abstra @Override public Connection getConnection() throws SQLConnectionClosedException { assertNotClosed(); - return connection; + return this.connection; } /** @@ -75,7 +75,7 @@ public class DBFStatement extends Abstra */ @Override public File getFile() { - return connection.getFile(); + return this.connection.getFile(); } /** @@ -132,7 +132,7 @@ public class DBFStatement extends Abstra @Override public ResultSet getResultSet() throws SQLConnectionClosedException { assertNotClosed(); - return currentResultSet; + return this.currentResultSet; } /** @@ -151,23 +151,23 @@ public class DBFStatement extends Abstra if (isClosed()) return; - if (currentResultSet != null) { + if (this.currentResultSet != null) { // Inform that this ResultSet could have been closed but that we are handling this : // Some developpers may expect their ResultSet should have been closed before in their program. - format(Level.FINE, "log.closing_underlying_resultset", currentResultSet); - currentResultSet.close(); + log(Level.FINE, "log.closing_underlying_resultset", this.currentResultSet); + this.currentResultSet.close(); - currentResultSet = null; + this.currentResultSet = null; } // Check if all the underlying ResultSets that has been opened with this statement has been closed. // If not, we log a warning to help the developper. - if (openedResultSets.size() > 0) { - format(Level.WARNING, "log.resultsets_left_opened", openedResultSets.size(), openedResultSets.toString()); + if (this.openedResultSets.size() > 0) { + log(Level.WARNING, "log.resultsets_left_opened", this.openedResultSets.size(), openedResultSets.toString()); } - isClosed = true; - connection.notifyCloseStatement(this); + this.isClosed = true; + this.connection.notifyCloseStatement(this); } /** @@ -176,7 +176,7 @@ public class DBFStatement extends Abstra */ @Override public boolean isClosed() { - return isClosed || connection.isClosed(); + return this.isClosed || this.connection.isClosed(); } /** @@ -184,11 +184,11 @@ public class DBFStatement extends Abstra * @throws SQLConnectionClosedException if one of them is closed. */ public void assertNotClosed() throws SQLConnectionClosedException { - connection.assertNotClosed(); // First, the underlying shall not be closed. + this.connection.assertNotClosed(); // First, the underlying shall not be closed. // Then, this statement shouldn't be closed too. - if (isClosed) { - throw new SQLConnectionClosedException(format(Level.WARNING, "excp.closed_statement", connection.getFile().getName()), null, connection.getFile()); + if (this.isClosed) { + throw new SQLConnectionClosedException(format(Level.WARNING, "excp.closed_statement", this.connection.getFile().getName()), null, this.connection.getFile()); } } @@ -208,10 +208,10 @@ public class DBFStatement extends Abstra Objects.requireNonNull(rs, "The ResultSet notified being closed cannot be null."); // If this ResultSet was the current ResultSet, now there is no more current ResultSet. - if (currentResultSet == rs) - currentResultSet = null; + if (this.currentResultSet == rs) + this.currentResultSet = null; - if (openedResultSets.remove(rs) == false) { + if (this.openedResultSets.remove(rs) == false) { throw new RuntimeException(format(Level.SEVERE, "assert.resultset_not_opened_by_me", rs, toString())); } } @@ -221,8 +221,8 @@ public class DBFStatement extends Abstra * @param rs Result Set. */ public void registerResultSet(DBFResultSet rs) { - currentResultSet = rs; - openedResultSets.add(rs); + this.currentResultSet = rs; + this.openedResultSets.add(rs); } /** @@ -238,6 +238,6 @@ public class DBFStatement extends Abstra */ @Override public String toString() { - return format("toString", connection != null ? connection.toString() : null, isClosed() == false); + return format("toString", this.connection != null ? this.connection.toString() : null, isClosed() == false); } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/InputFeatureStream.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -22,11 +22,12 @@ import java.sql.SQLFeatureNotSupportedEx import java.text.DecimalFormat; import java.text.MessageFormat; import java.util.List; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.sis.feature.DefaultFeatureType; -import org.apache.sis.internal.shapefile.SQLShapefileNotFoundException; -import org.apache.sis.internal.shapefile.ShapefileByteReader; -import org.apache.sis.internal.shapefile.ShapefileDescriptor; +import org.apache.sis.internal.shapefile.*; import org.apache.sis.internal.shapefile.jdbc.*; import org.apache.sis.internal.shapefile.jdbc.connection.DBFConnection; import org.apache.sis.internal.shapefile.jdbc.metadata.DBFDatabaseMetaData; @@ -36,6 +37,7 @@ import org.apache.sis.internal.shapefile import org.apache.sis.internal.shapefile.jdbc.sql.SQLUnsupportedParsingFeatureException; import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement; import org.apache.sis.storage.DataStoreClosedException; +import org.apache.sis.util.logging.Logging; import org.opengis.feature.Feature; /** @@ -47,6 +49,12 @@ import org.opengis.feature.Feature; * @module */ public class InputFeatureStream extends InputStream { + /** Logger. */ + private static Logger LOGGER = Logging.getLogger(InputFeatureStream.class.getSimpleName()); + + /** Resource bundle. */ + private ResourceBundle rsc = ResourceBundle.getBundle(InputFeatureStream.class.getName()); + /** Dedicated connection to DBF. */ private DBFConnection connection; @@ -67,6 +75,12 @@ public class InputFeatureStream extends /** Database file. */ private File databaseFile; + + /** Shapefile index. */ + private File shapefileIndex; + + /** Indicates that the shape file has a valid index provided with it. */ + private boolean hasShapefileIndex; /** Type of the features contained in this shapefile. */ private DefaultFeatureType featuresType; @@ -78,20 +92,37 @@ public class InputFeatureStream extends * Create an input stream of features over a connection. * @param shpfile Shapefile. * @param dbaseFile Database file. + * @param shpfileIndex Shapefile index, null if none provided, will be checked for existence. + * @param sqlStatement SQL Statement to run, if null, a SELECT * FROM DBF will occurs. * @throws InvalidShapefileFormatException if the shapefile format is invalid. * @throws InvalidDbaseFileFormatException if the Dbase file format is invalid. * @throws ShapefileNotFoundException if the shapefile has not been found. * @throws DbaseFileNotFoundException if the database file has not been found. */ - public InputFeatureStream(File shpfile, File dbaseFile) throws InvalidDbaseFileFormatException, InvalidShapefileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException { + public InputFeatureStream(File shpfile, File dbaseFile, File shpfileIndex, String sqlStatement) throws InvalidDbaseFileFormatException, InvalidShapefileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException { try { - connection = (DBFConnection)new DBFDriver().connect(dbaseFile.getAbsolutePath(), null); - sql = MessageFormat.format("SELECT * FROM {0}", dbaseFile.getName()); - shapefile = shpfile; - databaseFile = dbaseFile; + this.connection = (DBFConnection)new DBFDriver().connect(dbaseFile.getAbsolutePath(), null); + + if (sqlStatement == null) { + this.sql = MessageFormat.format("SELECT * FROM {0}", dbaseFile.getName()); + } + else { + this.sql = sqlStatement; + } + + this.shapefile = shpfile; + this.databaseFile = dbaseFile; + + if (shpfileIndex != null && (shpfileIndex.exists() && shpfileIndex.isFile())) { + this.shapefileIndex = shpfileIndex; + this.hasShapefileIndex = true; + } + else { + this.hasShapefileIndex = false; + } - shapefileReader = new ShapefileByteReader(shapefile, databaseFile); - featuresType = shapefileReader.getFeaturesType(); + this.shapefileReader = new ShapefileByteReader(this.shapefile, this.databaseFile, this.shapefileIndex); + this.featuresType = this.shapefileReader.getFeaturesType(); try { executeQuery(); @@ -118,8 +149,35 @@ public class InputFeatureStream extends throw new ShapefileNotFoundException(ex.getMessage(), ex); } } + + /** + * Create an input stream of features over a connection, responding to a SELECT * FROM DBF statement. + * @param shpfile Shapefile. + * @param dbaseFile Database file. + * @param shpfileIndex Shapefile index, null if none provided, will be checked for existence. + * @throws InvalidShapefileFormatException if the shapefile format is invalid. + * @throws InvalidDbaseFileFormatException if the Dbase file format is invalid. + * @throws ShapefileNotFoundException if the shapefile has not been found. + * @throws DbaseFileNotFoundException if the database file has not been found. + */ + public InputFeatureStream(File shpfile, File dbaseFile, File shpfileIndex) throws InvalidDbaseFileFormatException, InvalidShapefileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException { + this(shpfile, dbaseFile, shpfileIndex, null); + } /** + * Create an input stream of features over a connection, responding to a SELECT * FROM DBF statement. + * @param shpfile Shapefile. + * @param dbaseFile Database file. + * @throws InvalidShapefileFormatException if the shapefile format is invalid. + * @throws InvalidDbaseFileFormatException if the Dbase file format is invalid. + * @throws ShapefileNotFoundException if the shapefile has not been found. + * @throws DbaseFileNotFoundException if the database file has not been found. + */ + public InputFeatureStream(File shpfile, File dbaseFile) throws InvalidDbaseFileFormatException, InvalidShapefileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException { + this(shpfile, dbaseFile, null); + } + + /** * @see java.io.InputStream#read() */ @Override @@ -140,16 +198,16 @@ public class InputFeatureStream extends */ @Override public void close() { - rs.close(); - stmt.close(); - connection.close(); + this.rs.close(); + this.stmt.close(); + this.connection.close(); } /** * Read next feature responding to the SQL query. * @return Feature, null if no more feature is available. * @throws DataStoreClosedException if the current connection used to query the shapefile has been closed. - * @throws DataStoreQueryException if the statement used to query the shapefile content is incorrect. + * @throws DataStoreQueryException if the statement used to query the shapefile content is incorrect, or requires a shapefile index to be executed and none is available. * @throws DataStoreQueryResultException if the shapefile results cause a trouble (wrong format, for example). * @throws InvalidShapefileFormatException if the shapefile structure shows a problem. */ @@ -166,14 +224,16 @@ public class InputFeatureStream extends catch(SQLNotNumericException | SQLNotDateException e) { throw new DataStoreQueryResultException(e.getMessage(), e); } + catch(SQLNoDirectAccessAvailableException e) { + throw new DataStoreQueryException(e.getMessage(), e); + } } /** * Return the features type. * @return Features type. */ - public DefaultFeatureType getFeaturesType() - { + public DefaultFeatureType getFeaturesType() { return this.featuresType; } @@ -181,8 +241,7 @@ public class InputFeatureStream extends * Returns the shapefile descriptor. * @return Shapefile descriptor. */ - public ShapefileDescriptor getShapefileDescriptor() - { + public ShapefileDescriptor getShapefileDescriptor() { return this.shapefileReader.getShapefileDescriptor(); } @@ -190,12 +249,19 @@ public class InputFeatureStream extends * Returns the database fields descriptors. * @return List of fields descriptors. */ - public List<DBase3FieldDescriptor> getDatabaseFieldsDescriptors() - { + public List<DBase3FieldDescriptor> getDatabaseFieldsDescriptors() { return this.shapefileReader.getFieldsDescriptors(); } /** + * Checks if the shapefile has an index provided with it. + * @return true if an index file (.shx) has been given with the shapefile. + */ + public boolean hasShapefileIndex() { + return this.hasShapefileIndex; + } + + /** * Read next feature responding to the SQL query. * @return Feature, null if no more feature is available. * @throws SQLNotNumericException if a field expected numeric isn't. @@ -207,26 +273,55 @@ public class InputFeatureStream extends * @throws SQLUnsupportedParsingFeatureException if a SQL ability is not currently available through this driver. * @throws SQLFeatureNotSupportedException if a SQL ability is not currently available through this driver. * @throws InvalidShapefileFormatException if the shapefile format is invalid. + * @throws SQLNoDirectAccessAvailableException if the underlying SQL statement requires a direct access in the shapefile, but the shapefile cannot allow it. */ - private Feature internalReadFeature() throws SQLConnectionClosedException, SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLNotNumericException, SQLNotDateException, SQLFeatureNotSupportedException, InvalidShapefileFormatException { + private Feature internalReadFeature() throws SQLConnectionClosedException, SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLNotNumericException, SQLNotDateException, SQLFeatureNotSupportedException, InvalidShapefileFormatException, SQLNoDirectAccessAvailableException { try { - if (endOfFile) { + if (this.endOfFile) { return null; } - if (rs.next() == false) { - endOfFile = true; + int previousRecordNumber = this.rs.getRowNum(); + + if (this.rs.next() == false) { + this.endOfFile = true; return null; } - - Feature feature = featuresType.newInstance(); - shapefileReader.completeFeature(feature); - DBFDatabaseMetaData metadata = (DBFDatabaseMetaData)connection.getMetaData(); + + int currentRecordNumber = this.rs.getRowNum(); + + // On the shapefile, only jump in another place if a direct access is needed. + boolean directAccesRequired = currentRecordNumber != (previousRecordNumber + 1); + + if (directAccesRequired) { + try { + if (LOGGER.isLoggable(Level.FINER)) { + MessageFormat format = new MessageFormat(this.rsc.getString("log.shapefile_reading_with_direct_access")); + LOGGER.finer(format.format(new Object[] {previousRecordNumber, currentRecordNumber})); + } + + this.shapefileReader.setRowNum(currentRecordNumber); + } + catch(SQLInvalidRecordNumberForDirectAccessException e) { + // This would be an internal API problem, because as soon as we handle a shapefile index, we shall go through its relative shape feature file correctly. + throw new RuntimeException(e.getMessage(), e); + } + } + else { + if (LOGGER.isLoggable(Level.FINER)) { + MessageFormat format = new MessageFormat(this.rsc.getString("log.shapefile_reading_with_sequential_access")); + LOGGER.finer(format.format(new Object[] {previousRecordNumber, currentRecordNumber})); + } + } + + Feature feature = this.featuresType.newInstance(); + this.shapefileReader.completeFeature(feature); + DBFDatabaseMetaData metadata = (DBFDatabaseMetaData)this.connection.getMetaData(); try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = (DBFBuiltInMemoryResultSetForColumnsListing)metadata.getColumns(null, null, null, null)) { while(rsDatabase.next()) { String fieldName = rsDatabase.getString("COLUMN_NAME"); - Object fieldValue = rs.getObject(fieldName); + Object fieldValue = this.rs.getObject(fieldName); // FIXME To allow features to be filled again, the values are converted to String again : feature should allow any kind of data. String stringValue; @@ -272,7 +367,7 @@ public class InputFeatureStream extends * @throws SQLInvalidStatementException if the given SQL Statement is invalid. */ private void executeQuery() throws SQLConnectionClosedException, SQLInvalidStatementException { - stmt = (DBFStatement)connection.createStatement(); - rs = (DBFRecordBasedResultSet)stmt.executeQuery(sql); + this.stmt = (DBFStatement)this.connection.createStatement(); + this.rs = (DBFRecordBasedResultSet)this.stmt.executeQuery(this.sql); } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/ShapeFile.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/ShapeFile.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/ShapeFile.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/main/java/org/apache/sis/storage/shapefile/ShapeFile.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,6 +41,9 @@ public class ShapeFile { /** Database file. */ private File databaseFile; + + /** Shapefile index, if any. */ + private File shapeFileIndex; /** Type of the features contained in this shapefile. */ private DefaultFeatureType featuresType; @@ -58,12 +61,55 @@ public class ShapeFile { public ShapeFile(String shpfile) { Objects.requireNonNull(shpfile, "The shapefile to load cannot be null."); - shapeFile = new File(shpfile); + this.shapeFile = new File(shpfile); - // Deduct database file name. + // Deduct database file name by suffixing it by dbf (trying to respect the same case). StringBuilder dbfFileName = new StringBuilder(shpfile); - dbfFileName.replace(shpfile.length() - 3, shpfile.length(), "dbf"); - databaseFile = new File(dbfFileName.toString()); + + String dbfSuffix = null; + dbfSuffix = shpfile.endsWith("shp") ? "dbf" : dbfSuffix; + dbfSuffix = shpfile.endsWith("SHP") ? "DBF" : dbfSuffix; + dbfSuffix = shpfile.endsWith("Shp") ? "Dbf" : dbfSuffix; + dbfSuffix = (dbfSuffix == null) ? "dbf" : dbfSuffix; + + dbfFileName.replace(shpfile.length() - 3, shpfile.length(), dbfSuffix); + this.databaseFile = new File(dbfFileName.toString()); + + // Deduct shapefile index file name by suffixing it by shx (trying to respect the same case). + StringBuilder shapeFileIndexName = new StringBuilder(shpfile); + + String shapeFileIndexSuffix = null; + shapeFileIndexSuffix = shpfile.endsWith("shp") ? "shx" : shapeFileIndexSuffix; + shapeFileIndexSuffix = shpfile.endsWith("SHP") ? "SHX" : shapeFileIndexSuffix; + shapeFileIndexSuffix = shpfile.endsWith("Shp") ? "Shx" : shapeFileIndexSuffix; + shapeFileIndexSuffix = (shapeFileIndexSuffix == null) ? "shx" : shapeFileIndexSuffix; + + shapeFileIndexName.replace(shpfile.length() - 3, shpfile.length(), shapeFileIndexSuffix); + this.shapeFileIndex = new File(shapeFileIndexName.toString()); + } + + /** + * Construct a Shapefile from a file. + * @param shpfile file to read. + * @param dbasefile Associated DBase file. + */ + public ShapeFile(String shpfile, String dbasefile) { + Objects.requireNonNull(shpfile, "The shapefile to load cannot be null."); + Objects.requireNonNull(dbasefile, "The DBase III file to load cannot be null."); + + this.shapeFile = new File(shpfile); + this.databaseFile = new File(dbasefile); + } + + /** + * Construct a Shapefile from a file. + * @param shpfile file to read. + * @param dbasefile Associated DBase file. + * @param shpfileIndex Associated Shapefile index, may be null. + */ + public ShapeFile(String shpfile, String dbasefile, String shpfileIndex) { + this(shpfile, dbasefile); + this.shapeFileIndex = new File(shpfileIndex); } /** @@ -91,6 +137,30 @@ public class ShapeFile { } /** + * Returns the underlying DBase file used by this Shapefile. + * @return Dbase file. + */ + public File getFileDatabase() { + return this.databaseFile; + } + + /** + * Returns the shape file designed by this shapefile object. + * @return Shape file. + */ + public File getFileShapefile() { + return this.shapeFile; + } + + /** + * Return the shapefile Index provided with the shapefile, if any. + * @return Shapefile Index file or null if none given. + */ + public File getFileShapefileIndex() { + return this.shapeFileIndex; + } + + /** * Find features corresponding to an SQL request SELECT * FROM database. * @return Features * @throws DbaseFileNotFoundException if the database file has not been found. @@ -99,7 +169,20 @@ public class ShapeFile { * @throws InvalidShapefileFormatException if the shapefile format is invalid. */ public InputFeatureStream findAll() throws InvalidDbaseFileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException, InvalidShapefileFormatException { - InputFeatureStream is = new InputFeatureStream(shapeFile, databaseFile); + return find(null); + } + + /** + * Find features corresponding to an SQL request SELECT * FROM database. + * @param sqlStatement SQL Statement to run, if null, will default to SELECT * FROM database. + * @return Features + * @throws DbaseFileNotFoundException if the database file has not been found. + * @throws ShapefileNotFoundException if the shapefile has not been found. + * @throws InvalidDbaseFileFormatException if the database file format is invalid. + * @throws InvalidShapefileFormatException if the shapefile format is invalid. + */ + public InputFeatureStream find(String sqlStatement) throws InvalidDbaseFileFormatException, ShapefileNotFoundException, DbaseFileNotFoundException, InvalidShapefileFormatException { + InputFeatureStream is = new InputFeatureStream(this.shapeFile, this.databaseFile, this.shapeFileIndex, sqlStatement); this.featuresType = is.getFeaturesType(); this.shapefileDescriptor = is.getShapefileDescriptor(); this.databaseFieldsDescriptors = is.getDatabaseFieldsDescriptors(); Modified: sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/AbstractTestBaseForInternalJDBC.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/AbstractTestBaseForInternalJDBC.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/AbstractTestBaseForInternalJDBC.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/AbstractTestBaseForInternalJDBC.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -51,7 +51,7 @@ public abstract class AbstractTestBaseFo */ public Connection connect() throws SQLException { final Driver driver = new DBFDriver(); - return driver.connect(dbfFile.getAbsolutePath(), null); + return driver.connect(this.dbfFile.getAbsolutePath(), null); } /** @@ -62,7 +62,7 @@ public abstract class AbstractTestBaseFo public void setup() throws URISyntaxException { final URL url = ShapeFileTest.class.getResource("SignedBikeRoute_4326_clipped.dbf"); assertNotNull("The database file used for testing doesn't exist.", url); - dbfFile = new File(url.toURI()); - assertTrue(dbfFile.isFile()); + this.dbfFile = new File(url.toURI()); + assertTrue(this.dbfFile.isFile()); } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFConnectionTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFConnectionTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFConnectionTest.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFConnectionTest.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,7 +41,7 @@ public class DBFConnectionTest extends A @Test public void openCloseConnection() throws SQLException { final Driver driver = new DBFDriver(); - final Connection connection = driver.connect(dbfFile.getAbsolutePath(), null); + final Connection connection = driver.connect(this.dbfFile.getAbsolutePath(), null); assertFalse("Connection should be opened", connection.isClosed()); assertTrue ("Connection should be valid", connection.isValid(0)); @@ -60,7 +60,7 @@ public class DBFConnectionTest extends A info.put("record_charset", "UTF-8"); final Driver driver = new DBFDriver(); - final Connection connection = driver.connect(dbfFile.getAbsolutePath(), info); + final Connection connection = driver.connect(this.dbfFile.getAbsolutePath(), info); assertFalse("Connection should be opened", connection.isClosed()); assertTrue ("Connection should be valid", connection.isValid(0)); @@ -78,14 +78,14 @@ public class DBFConnectionTest extends A public void connectionClosed() throws SQLException { // Open and close an connection. final Driver driver = new DBFDriver(); - final Connection connection = driver.connect(dbfFile.getAbsolutePath(), null); + final Connection connection = driver.connect(this.dbfFile.getAbsolutePath(), null); connection.close(); // Then, attempt to use it. try { connection.createStatement(); } catch(SQLConnectionClosedException e) { - assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); throw e; } } Modified: sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFResultSetTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFResultSetTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFResultSetTest.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFResultSetTest.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -125,7 +125,8 @@ public class DBFResultSetTest extends Ab record.add(rs.getBigDecimal("SHAPE_LEN")); // Type : Number, Field length : 19, Decimal positions : 11 count ++; - log.info(MessageFormat.format("Record {0,number} : {1}\n", count, record)); + assertEquals("The record number returned by the ResultSet is not the same of the manual counting we are doing." , count, ((DBFRecordBasedResultSet)rs).getRowNum()); + this.log.info(MessageFormat.format("Record {0,number} : {1}\n", count, record)); } assertTrue("Less than one record was readed.", count > 1); @@ -148,7 +149,7 @@ public class DBFResultSetTest extends Ab rs.close(); } catch(SQLConnectionClosedException e) { - assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); assertEquals("The SQL Query is exception is not well set.", e.getSQL(), sql); } catch(SQLException e) { @@ -168,7 +169,7 @@ public class DBFResultSetTest extends Ab rs.next(); } catch(SQLConnectionClosedException e) { - assertEquals("The database name is exception message is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name is exception message is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); } catch(SQLException e) { fail("Not the expected exception for using a closed ResultSet."); @@ -190,7 +191,7 @@ public class DBFResultSetTest extends Ab rs.next(); } catch(SQLConnectionClosedException e) { - assertEquals("The database name is exception message is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name is exception message is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); } catch(SQLException e) { fail("Not the expected exception for using a closed ResultSet."); Modified: sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFStatementTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFStatementTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFStatementTest.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/internal/shapefile/jdbc/DBFStatementTest.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -41,7 +41,7 @@ public class DBFStatementTest extends Ab public void openCloseStatement() throws SQLException { final Driver driver = new DBFDriver(); - try(Connection connection = driver.connect(dbfFile.getAbsolutePath(), null)) { + try(Connection connection = driver.connect(this.dbfFile.getAbsolutePath(), null)) { final Statement stmt = connection.createStatement(); assertFalse("Statement should be opened", stmt.isClosed()); @@ -67,7 +67,7 @@ public class DBFStatementTest extends Ab stmt.executeQuery("Must detect that the statement is closed, and not try to parse this query."); } catch(SQLConnectionClosedException e) { - assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); } catch(SQLException e) { fail("Not the expected exception for using a closed statement."); @@ -85,7 +85,7 @@ public class DBFStatementTest extends Ab stmt.executeQuery("Must detect that the statement is closed, and not try to parse this query."); } catch(SQLConnectionClosedException e) { - assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), dbfFile.getName()); + assertEquals("The database name in this exception is not well set.", e.getDatabase().getName(), this.dbfFile.getName()); } catch(SQLException e) { fail("Not the expected exception for using a closed statement."); Modified: sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/storage/shapefile/ShapeFileTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/storage/shapefile/ShapeFileTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/storage/shapefile/ShapeFileTest.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-shapefile/src/test/java/org/apache/sis/storage/shapefile/ShapeFileTest.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -16,6 +16,7 @@ */ package org.apache.sis.storage.shapefile; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.File; @@ -25,6 +26,7 @@ import java.util.logging.Logger; import org.apache.sis.storage.DataStoreException; import org.apache.sis.test.TestCase; +import org.junit.Ignore; import org.junit.Test; import org.opengis.feature.Feature; @@ -106,6 +108,85 @@ public final strictfp class ShapeFileTes readAll(shp); } + /** + * Checks that the reader is able to detect EoF signs in the DBase file. + * @throws URISyntaxException if the resource name is incorrect. + * @throws DataStoreException if a general file reading trouble occurs. + */ + @Test @Ignore // TODO Adapt with another shapefile. + public void testHandleEofNotification() throws URISyntaxException, DataStoreException { + ShapeFile shp = new ShapeFile(path("DEPARTEMENT.SHP")); + Feature first = null, last = null; + + Logger log = org.apache.sis.util.logging.Logging.getLogger(ShapeFileTest.class.getName()); + + try(InputFeatureStream is = shp.findAll()) { + Feature feature = is.readFeature(); + + // Read and retain the first and the last feature. + while(feature != null) { + if (first == null) { + first = feature; + } + + // Advice : To debug just before the last record, put a conditional breakpoint on department name "MEURTHE-ET-MOSELLE". + String deptName = (String)feature.getProperty("NOM_DEPT").getValue(); + log.info(deptName); + + last = feature; + feature = is.readFeature(); + } + } + + assertNotNull("No record has been found in the DBase file or Shapefile.", first); + assertNotNull("This test is not working well : last feature should always be set if any feature has been found.", last); + assertEquals("The first record red must be JURA department.", "JURA", first.getProperty("NOM_DEPT").getValue()); + assertEquals("The last record red must be DEUX-SEVRES department.", "DEUX-SEVRES", last.getProperty("NOM_DEPT").getValue()); + } + + /** + * Testing direct access in the shapefile. + * @throws URISyntaxException if the resource name is incorrect. + * @throws DataStoreException if a general file reading trouble occurs. + */ + @Test + public void testDirectAcces() throws DataStoreException, URISyntaxException { + ShapeFile shp = new ShapeFile(path("ABRALicenseePt_4326_clipped.shp")); + + // 1) Find the third record, sequentially. + Feature thirdFeature; + + try(InputFeatureStream isSequential = shp.findAll()) { + isSequential.readFeature(); + isSequential.readFeature(); + thirdFeature = isSequential.readFeature(); + } + + // Take one of its key fields and another field for reference, and its geometry. + Double sequentialAddressId = Double.valueOf((String)(thirdFeature.getProperty("ADDRID")).getValue()); + String sequentialAddress = (String)(thirdFeature.getProperty("ADDRESS")).getValue(); + Object sequentialGeometry = thirdFeature.getPropertyValue("geometry"); + + // 2) Now attempt a direct access to this feature. + Feature directFeature; + String sql = MessageFormat.format("SELECT * FROM ABRALicenseePt_4326_clipped WHERE ADDRID = {0,number,#0}", sequentialAddressId); + + try(InputFeatureStream isDirect = shp.find(sql)) { + directFeature = isDirect.readFeature(); + assertNotNull("The direct access feature returned should not be null", directFeature); + } + + assertNotNull("The field ADDRID in the direct access feature has not been found again.", directFeature.getProperty("ADDRID")); + + Double directAddressId = Double.valueOf((String)(directFeature.getProperty("ADDRID")).getValue()); + String directAddress = (String)(directFeature.getProperty("ADDRESS")).getValue(); + Object directGeometry = directFeature.getPropertyValue("geometry"); + + assertEquals("DBase part : direct access didn't returned the same address id than sequential access.", sequentialAddressId, directAddressId); + assertEquals("DBase part : direct access didn't returned the same address than sequential access.", sequentialAddress, directAddress); + assertEquals("Shapefile part : direct access didn't returned the same geometry than sequential access.", sequentialGeometry, directGeometry); + } + /** * Read all the shapefile content. * @param shp Shapefile to read. Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java?rev=1723780&r1=1723779&r2=1723780&view=diff ============================================================================== --- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java [UTF-8] (original) +++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelImageInputStream.java [UTF-8] Fri Jan 8 18:29:04 2016 @@ -289,7 +289,7 @@ loop: while ((c = read()) >= 0) { */ @Override public final long skipBytes(final long n) throws IOException { - return skipBytes(Math.min((int) n, Integer.MAX_VALUE)); + return skipBytes((int) Math.min(n, Integer.MAX_VALUE)); } /**