sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mlebi...@apache.org
Subject svn commit: r1643155 [4/6] - in /sis/branches/JDK8: core/sis-utility/src/main/java/org/apache/sis/util/logging/ storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/ storage/sis-shapefile/src/main/java/org/apache/sis/internal/shap...
Date Fri, 05 Dec 2014 05:53:24 GMT
Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/DBFRecordBasedResultSet.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,485 @@
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.nio.charset.Charset;
+import java.sql.Date;
+import java.sql.ResultSetMetaData;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.logging.Level;
+
+import org.apache.sis.internal.shapefile.jdbc.SQLConnectionClosedException;
+import org.apache.sis.internal.shapefile.jdbc.metadata.DBFResultSetMataData;
+import org.apache.sis.internal.shapefile.jdbc.sql.*;
+import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement;
+import org.apache.sis.storage.shapefile.FieldDescriptor;
+
+/**
+ * A ResultSet based on a record.
+ * @author Marc LE BIHAN
+ */
+public class DBFRecordBasedResultSet extends AbstractResultSet {
+    /** The current record. */
+    private Map<String, Object> m_record;
+    
+    /** Condition of where clause (currently, only one is handled). */
+    private ConditionalClauseResolver m_singleConditionOfWhereClause;
+
+    /** UTF-8 charset. */
+    private static Charset UTF8 = Charset.forName("UTF-8");
+    
+    /**
+     * Constructs a result set.
+     * @param stmt Parent statement.
+     * @param sqlQuery SQL Statment that produced this ResultSet.
+     * @throws SQLInvalidStatementException if the SQL Statement is invalid.
+     */
+    public DBFRecordBasedResultSet(final DBFStatement stmt, String sqlQuery) throws SQLInvalidStatementException {
+        super(stmt, sqlQuery);
+        m_singleConditionOfWhereClause = new CrudeSQLParser(this).parse();
+    }
+    
+    /**
+     * @see org.apache.sis.internal.shapefile.jdbc.resultset.AbstractUnimplementedFeaturesOfResultSet#getBigDecimal(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Override
+    public BigDecimal getBigDecimal(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getBigDecimal", columnLabel);
+        
+        assertNotClosed();
+        
+        // Act as if we were a double, but store the result in a pre-created BigDecimal at the end.
+        FieldDescriptor field = getField(columnLabel); // Ensure that the field queried exists.
+        
+        MathContext mc = new MathContext(field.getDecimalCount(), RoundingMode.HALF_EVEN);
+        Double doubleValue = getDouble(columnLabel);
+        
+        if (doubleValue != null) {
+            BigDecimal number = new BigDecimal(doubleValue, mc);
+            m_wasNull = false;
+            return number;
+        }
+        else {
+            m_wasNull = true;
+            return null;
+        }
+    }
+
+    /**
+     * @see java.sql.ResultSet#getBigDecimal(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public BigDecimal getBigDecimal(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getBigDecimal", columnIndex);
+        return getBigDecimal(getField(columnIndex).getName());
+    }
+
+    /**
+     * @see java.sql.ResultSet#getBigDecimal(java.lang.String, int)
+     * @deprecated Deprecated API (from ResultSet Interface)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Deprecated @Override
+    public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getBigDecimal", columnLabel, scale);
+        assertNotClosed();
+        
+        // Act as if we were a double, but store the result in a pre-created BigDecimal at the end.
+        MathContext mc = new MathContext(scale, RoundingMode.HALF_EVEN);
+        Double doubleValue = getDouble(columnLabel);
+        
+        if (doubleValue != null) {
+            BigDecimal number = new BigDecimal(getDouble(columnLabel), mc);
+            m_wasNull = false;
+            return number;
+        }
+        else {
+            m_wasNull = true;
+            return null;
+        }
+    }
+
+    /**
+     * @see java.sql.ResultSet#getDate(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotDateException if the field is not a date. 
+     */
+    @Override
+    public Date getDate(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotDateException {
+        logStep("getDate", columnLabel);
+        assertNotClosed();
+        
+        String value = getString(columnLabel);
+        
+        if (value == null || value.equals("00000000")) { // "00000000" is stored in Database to represent a null value too.
+            m_wasNull = true;
+            return null; // The ResultSet:getDate() contract is to return null when a null date is encountered.
+        }
+        else {
+            m_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.SEVERE, "excp.field_is_not_a_date", columnLabel, m_sql, value);
+            throw new SQLNotDateException(message, m_sql, getDatabase().getFile(), columnLabel, value);
+        }
+
+        // Extract the date parts.
+        int year, month, dayOfMonth;
+        
+        try {
+            year = Integer.parseInt(value.substring(0, 4));
+            month = Integer.parseInt(value.substring(5, 7));
+            dayOfMonth = Integer.parseInt(value.substring(7));
+        }
+        catch(NumberFormatException e) {
+            String message = format(Level.SEVERE, "excp.field_is_not_a_date", columnLabel, m_sql, value);
+            throw new SQLNotDateException(message, m_sql, getDatabase().getFile(), columnLabel, value);
+        }
+        
+        // Create a date.
+        Calendar calendar = new GregorianCalendar(year, month-1, dayOfMonth, 0, 0, 0);
+        Date sqlDate = new Date(calendar.getTimeInMillis());
+        return sqlDate;
+    }
+
+    /**
+     * @see java.sql.ResultSet#getDate(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotDateException if the field is not a date. 
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public Date getDate(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotDateException, SQLIllegalColumnIndexException {
+        logStep("getDate", columnIndex);
+        return getDate(getField(columnIndex).getName());
+    }
+
+    /**
+     * @see java.sql.ResultSet#getDouble(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Override
+    public double getDouble(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getDouble", columnLabel);
+        
+        Double value = getNumeric(columnLabel, Double::parseDouble);
+        m_wasNull = (value == null);
+        return value != null ? value : 0.0; // The ResultSet contract for numbers is to return 0 when a null value is encountered.
+    }
+
+    /**
+     * @see java.sql.ResultSet#getDouble(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public double getDouble(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getDouble", columnIndex);
+        return getDouble(getField(columnIndex).getName());
+    }
+
+    /**
+     * @see java.sql.ResultSet#getFloat(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Override
+    public float getFloat(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getFloat", columnLabel);
+        
+        Float value = getNumeric(columnLabel, Float::parseFloat);
+        m_wasNull = (value == null);
+        return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered.
+    }
+
+    /**
+     * @see java.sql.ResultSet#getFloat(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public float getFloat(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getFloat", columnIndex);
+        return getFloat(getField(columnIndex).getName());
+    }
+
+    /**
+     * @see org.apache.sis.internal.shapefile.jdbc.resultset.AbstractUnimplementedFeaturesOfResultSet#getInt(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Override
+    public int getInt(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getInt", columnLabel);
+        
+        Integer value = getNumeric(columnLabel, Integer::parseInt);
+        m_wasNull = (value == null);
+        return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered.
+    }
+
+    /**
+     * @see java.sql.ResultSet#getInt(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public int getInt(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getInt", columnIndex);
+        return getInt(getField(columnIndex).getName());
+    }
+
+    /**
+     * @see java.sql.ResultSet#getLong(java.lang.String)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     */
+    @Override
+    public long getLong(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getLong", columnLabel);
+        
+        Long value = getNumeric(columnLabel, Long::parseLong);
+        m_wasNull = (value == null);
+        return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered.
+    }
+
+    /**
+     * @see java.sql.ResultSet#getLong(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override public long getLong(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getLong", columnIndex);
+        return getLong(getField(columnIndex).getName());
+    }
+    
+    /**
+     * @see java.sql.ResultSet#getMetaData()
+     */
+    @Override
+    public ResultSetMetaData getMetaData() {
+        logStep("getMetaData");
+        
+        DBFResultSetMataData meta = new DBFResultSetMataData(this); 
+        return meta;
+    }
+
+    /**
+     * @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.
+     * @throws SQLNotNumericException if the field value is not numeric or has a NULL value.
+     */
+    @Override
+    public short getShort(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        logStep("getShort", columnLabel);
+        
+        Short value = getNumeric(columnLabel, Short::parseShort);
+        m_wasNull = (value == null);
+        return value != null ? value : 0; // The ResultSet contract for numbers is to return 0 when a null value is encountered.
+    }
+
+    /**
+     * @see java.sql.ResultSet#getShort(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric or has a NULL value.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public short getShort(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLIllegalColumnIndexException {
+        logStep("getShort", columnIndex);
+        return getShort(getField(columnIndex).getName());
+    }
+
+    /**
+     * Returns the value in the current row for the given column.
+     * @param columnLabel Column name.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field does not exist.
+     */
+    @Override
+    public String getString(String columnLabel) throws SQLConnectionClosedException, SQLNoSuchFieldException {
+        logStep("getString", columnLabel);
+        assertNotClosed();
+        
+        getField(columnLabel); // Ensure that the field queried exists, else a null value here can be interpreted as "not existing" or "has a null value".
+        String withoutCharset = (String)m_record.get(columnLabel);
+        
+        if (withoutCharset == null) {
+            m_wasNull = true;
+            return withoutCharset;
+        } 
+        else {
+            m_wasNull = false;
+        }
+        
+        // If a non null value has been readed, convert it to the wished Charset.
+        String withDatabaseCharset = new String(withoutCharset.getBytes(), getDatabase().getCharset()); 
+        log(Level.FINER, "log.string_field_charset", columnLabel, withoutCharset, withDatabaseCharset, getDatabase().getCharset());
+        
+        // Because the Database is old (end of 1980's), it has not been made to support UTF-8 encoding.
+        // But must users of DBase 3 don't know this, and sometimes a String field may carry such characters.
+        // Attempt to determine if the string could be an UTF-8 String instead.
+        String withUtf8Encoding = new String(withoutCharset.getBytes(), UTF8);
+
+        // If conversion contains a not convertible character, it's not an UTF-8 string.
+        // If the UTF-8 string is shorter than the one that would have given the database charset, it's a good sign : it has chances to be better.
+        boolean unsureResult = withUtf8Encoding.indexOf('\ufffd') != -1 || withUtf8Encoding.length() >= withDatabaseCharset.length();
+        
+        if (unsureResult)
+            return withDatabaseCharset;
+        else {
+            log(Level.FINER, "log.string_field_charset", columnLabel, withoutCharset, withUtf8Encoding, UTF8);
+            return withUtf8Encoding;
+        }
+    }
+    
+    /**
+     * @see java.sql.ResultSet#getString(int)
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLIllegalColumnIndexException if the column index has an illegal value.
+     */
+    @Override
+    public String getString(int columnIndex) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLIllegalColumnIndexException {
+        logStep("getString", columnIndex);
+        return(getString(getField(columnIndex).getName()));
+    }
+
+    /**
+     * Moves the cursor forward one row from its current position.
+     * @throws SQLInvalidStatementException if the SQL statement is invalid.
+     * @throws SQLIllegalParameterException if the value of one parameter of a condition is invalid.
+     * @throws SQLNoSuchFieldException if a field mentionned in the condition doesn't exist.
+     * @throws SQLUnsupportedParsingFeatureException if the caller asked for a not yet supported feature of the driver.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNotNumericException if a value or data expected to be numeric isn't.
+     * @throws SQLNotDateException if a value or data expected to be a date isn't.
+     */
+    @Override
+    public boolean next() throws SQLNoResultException, SQLConnectionClosedException, SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLNotNumericException, SQLNotDateException {
+        logStep("next");
+        assertNotClosed();
+
+        // Check that we aren't at the end of the Database file.
+        final int remaining = getDatabase().getRecordCount() - getDatabase().getRowNum();
+        
+        if (remaining <= 0) {
+            throw new SQLNoResultException(format(Level.SEVERE, "excp.no_more_results", m_sql, getDatabase().getFile().getName()), m_sql, getDatabase().getFile());
+        }
+
+        //m_record = getDatabase().readNextRowAsObjects();
+        return nextRecordMatchingConditions();
+    }
+    
+    /**
+     * Find the next record that match the where condition.
+     * @return true if a record has been found.
+     * @throws SQLInvalidStatementException if the SQL statement is invalid.
+     * @throws SQLIllegalParameterException if the value of one parameter of a condition is invalid.
+     * @throws SQLNoSuchFieldException if a field mentionned in the condition doesn't exist.
+     * @throws SQLUnsupportedParsingFeatureException if the caller asked for a not yet supported feature of the driver.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNotNumericException if a value or data expected to be numeric isn't.
+     * @throws SQLNotDateException if a value or data expected to be a date isn't.
+     */
+    private boolean nextRecordMatchingConditions() throws SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLConnectionClosedException, SQLNotNumericException, SQLNotDateException {
+        boolean recordMatchesConditions = false;
+        
+        while(getDatabase().getRecordCount() - getDatabase().getRowNum() > 0 && recordMatchesConditions == false) {
+            m_record = getDatabase().readNextRowAsObjects();
+            recordMatchesConditions = m_singleConditionOfWhereClause == null || m_singleConditionOfWhereClause.isVerified(this);
+        }
+        
+        return recordMatchesConditions && 
+               (getDatabase().getRecordCount() - getDatabase().getRowNum() > 0); // Beware of the end of database !
+    }
+    
+    /**
+     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
+     */
+    @Override
+    public boolean isWrapperFor(Class<?> iface) {
+        logStep("isWrapperFor", iface);
+        return iface.isAssignableFrom(getInterface());
+    }
+
+    /**
+     * @see java.sql.ResultSet#wasNull()
+     */
+    @Override
+    public boolean wasNull() {
+        logStep("wasNull");
+        return m_wasNull;
+    }
+
+    /**
+     * Get a numeric value.
+     * @param <T> Type of the number.
+     * @param columnLabel Column Label.
+     * @param parse Parsing function : Integer.parseInt, Float.parseFloat, Long.parseLong, ...
+     * @return The expected value or null if null was encountered.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLNoSuchFieldException if the field looked for doesn't exist.
+     * @throws SQLNotNumericException if the field value is not numeric or has a NULL value.
+     */
+    private <T extends Number> T getNumeric(String columnLabel, Function<String, T> parse) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException {
+        assertNotClosed();
+        
+        FieldDescriptor field = getField(columnLabel); // Ensure that the field queried exists, else, a null value here can be interpreted as "not existing" or "has a null value".
+        String textValue = (String)m_record.get(columnLabel); 
+        
+        if (textValue == null) {
+            return null;
+        }
+        
+        try {
+            textValue = textValue.trim(); // Field must be trimed before being converted.
+            T value = parse.apply(textValue);
+            return(value);
+        } 
+        catch(NumberFormatException e) {
+            String message = format(Level.SEVERE, "excp.field_is_not_numeric", columnLabel, field.getType(), m_sql, textValue);
+            throw new SQLNotNumericException(message, m_sql, getDatabase().getFile(), columnLabel, textValue);
+        }
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return format("toString", m_statement != null ? m_statement.toString() : null, m_sql, isClosed() == false);
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLIllegalColumnIndexException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,60 @@
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a column index is invalid.
+ * @author Marc LE BIHAN
+ */
+public class SQLIllegalColumnIndexException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = 7525295716068215255L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /** Column Index that is invalid. */
+    private int m_columnIndex;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     * @param columnIndex The column index that is invalid.
+     */
+    public SQLIllegalColumnIndexException(String message, String sql, File database, int columnIndex) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+        m_columnIndex = columnIndex;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the column index.
+     * @return Column index.
+     */
+    public int getColumnIndex() {
+        return m_columnIndex;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoResultException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when there is no more result.
+ * @author Marc LE BIHAN
+ */
+public class SQLNoResultException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = -6685966109486353932L;
+
+    /** The SQL Statement that whas attempted. */
+    private String m_sql;
+    
+    /** The database that was queried. */
+    private File m_database;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble.
+     * @param database The database that was queried.
+     */
+    public SQLNoResultException(String message, String sql, File database) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+    }
+    
+    /**
+     * Returns the SQL statement who encountered the "end of data" alert.
+     * @return SQL statement.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the database file that was queried.
+     * @return The database that was queried.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNoSuchFieldException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a column name is not found in a request or in the database structure.
+ * @author Marc LE BIHAN
+ */
+public class SQLNoSuchFieldException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = 1118679516090878177L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /** Column name that doesn't exist. */
+    private String m_columnName;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     * @param columnName The column name that doesn't exist.
+     */
+    public SQLNoSuchFieldException(String message, String sql, File database, String columnName) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+        m_columnName = columnName;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the column name that doesn't exist.
+     * @return Column name.
+     */
+    public String getColumnName() {
+        return m_columnName;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotDateException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a column value was expected to be a date but wasn't.
+ * @author Marc LE BIHAN
+ */
+public class SQLNotDateException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = 848673127131548693L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /** Column name. */
+    private String m_columnName;
+    
+    /** The value that is not numeric. */
+    private String m_value;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     * @param columnName The column name that has a non numeric value.
+     * @param value The wrong value.
+     */
+    public SQLNotDateException(String message, String sql, File database, String columnName, String value) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+        m_columnName = columnName;
+        m_value = value;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the column name.
+     * @return Column name.
+     */
+    public String getColumnName() {
+        return m_columnName;
+    }
+    
+    /**
+     * Returns the value that is not numeric.
+     * @return Value.
+     */
+    public String getValue() {
+        return m_value;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/SQLNotNumericException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.resultset;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a column value was expected numeric but wasn't.
+ * @author Marc LE BIHAN
+ */
+public class SQLNotNumericException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = -1065338463289030584L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /** Column name. */
+    private String m_columnName;
+    
+    /** The value that is not numeric. */
+    private String m_value;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     * @param columnName The column name that has a non numeric value.
+     * @param value The wrong value.
+     */
+    public SQLNotNumericException(String message, String sql, File database, String columnName, String value) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+        m_columnName = columnName;
+        m_value = value;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the column name.
+     * @return Column name.
+     */
+    public String getColumnName() {
+        return m_columnName;
+    }
+    
+    /**
+     * Returns the value that is not numeric.
+     * @return Value.
+     */
+    public String getValue() {
+        return m_value;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/package-info.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/package-info.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/resultset/package-info.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Result sets for SQL statements and DB Metadata querying. 
+ */
+package org.apache.sis.internal.shapefile.jdbc.resultset;
\ No newline at end of file

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/AbstractClauseResolver.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/AbstractClauseResolver.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/AbstractClauseResolver.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/AbstractClauseResolver.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.logging.Level;
+
+import org.apache.sis.internal.shapefile.jdbc.*;
+import org.apache.sis.internal.shapefile.jdbc.resultset.*;
+import org.apache.sis.storage.shapefile.FieldDescriptor;
+import org.apache.sis.util.logging.AbstractAutoChecker;
+
+/**
+ * Base class for clause resolver.
+ * @author Marc LE BIHAN
+ */
+public abstract class AbstractClauseResolver extends AbstractAutoChecker {
+    /** First comparand. */
+    private Object m_comparand1;
+    
+    /** Second comparand. */
+    private Object m_comparand2;
+    
+    /** Operator. */
+    private String m_operator;
+    
+    /**
+     * Construct a where clause resolver.
+     * @param comparand1 The first comparand that might be a primitive or a FieldDescriptor.
+     * @param comparand2 The second comparand that might be a primitive or a FieldDescriptor.
+     * @param operator The operator to apply.
+     */
+    public AbstractClauseResolver(Object comparand1, Object comparand2, String operator) {
+        m_comparand1 = comparand1;
+        m_comparand2 = comparand2;
+        m_operator = operator;
+    }
+
+    /**
+     * Returns first comparand.
+     * @return First comparand.
+     */
+    public Object getComparand1() {
+        return m_comparand1;
+    }
+
+    /**
+     * Returns second comparand.
+     * @return Second comparand.
+     */
+    public Object getComparand2() {
+        return m_comparand2;
+    }
+
+    /**
+     * Returns operator.
+     * @return Operator.
+     */
+    public String getOperator() {
+        return m_operator;
+    }
+
+    /**
+     * Set the first comparand.
+     * @param comparand First comparand.
+     */
+    public void setComparand1(Object comparand) {
+        m_comparand1 = comparand;
+    }
+
+    /**
+     * Set the second comparand.
+     * @param comparand Second comparand.
+     */
+    public void setComparand2(Object comparand) {
+        m_comparand2 = comparand;
+    }
+
+    /**
+     * Set the operator.
+     * @param operator Operator.
+     */
+    public void setOperator(String operator) {
+        m_operator = operator;
+    }
+    
+    /**
+     * Check if a condition is verified.
+     * @param rs ResultSet where the value shall be taken.
+     * @return true if the current record of the ResultSet matches this condition. 
+     * @throws SQLInvalidStatementException if the operator is not valid.
+     * @throws SQLIllegalParameterException if a parameter has a value that is not parsable.
+     * @throws SQLNoSuchFieldException if a field name doesn't exist in the query.
+     * @throws SQLUnsupportedParsingFeatureException if our implementation of the driver still not handle this data type.
+     * @throws SQLNotDateException if a field announced being a date isn't.
+     * @throws SQLUnsupportedParsingFeatureException if the driver encounter a type it cannot handle.
+     * @throws SQLNotNumericException if a field doesn't carry a numeric value when expected to.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     */
+    public boolean isVerified(DBFRecordBasedResultSet rs) throws SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLConnectionClosedException, SQLNotNumericException, SQLNotDateException {
+        switch(getOperator()) {
+            case "=" :
+                return compare(rs) == 0;
+                
+            case ">" :
+                return compare(rs) > 0;
+                
+            case ">=" :
+                return compare(rs) >= 0;
+                
+            case "<" :
+                return compare(rs) < 0;
+                
+            case "<=" :
+                return compare(rs) <= 0;
+                
+            default :
+                 String message = format(Level.SEVERE, "excp.invalid_statement_operator", getOperator(), rs.getSQL());
+                 throw new SQLInvalidStatementException(message, rs.getSQL(), rs.getDatabase().getFile());
+        }
+    }
+    
+    /**
+     * Returns true if this condition is verified.
+     * @param rs The record containing the values to extract, if needed.
+     * @return true if it is the case.
+     * @throws SQLIllegalParameterException if a parameter has a value that is not parsable.
+     * @throws SQLNoSuchFieldException if a field name doesn't exist in the query.
+     * @throws SQLUnsupportedParsingFeatureException if our implementation of the driver still not handle this data type.
+     * @throws SQLNotDateException if a field announced being a date isn't.
+     * @throws SQLUnsupportedParsingFeatureException if the driver encounter a type it cannot handle.
+     * @throws SQLNotNumericException if a field doesn't carry a numeric value when expected to.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     */
+    private int compare(DBFRecordBasedResultSet rs) throws SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLConnectionClosedException, SQLNotNumericException, SQLNotDateException {
+        Object value1 = valueOf(rs, getComparand1());
+        Object value2 = valueOf(rs, getComparand2());
+        
+        // Handle NULL value cases.
+        if (value1 == null && value2 == null)
+            return 0;
+        else
+        {
+            if (value1 == null)
+                return -1;
+            else
+            {
+                if (value2 == null)
+                    return 1;
+            }
+        }
+        
+        assert(value1 != null && value2 != null) : "Null values should have been handled in comparison.";
+        
+        // If comparands have already the same type, compare them immediately.
+        if (value1.getClass().equals(value2.getClass())) {
+            return compare(rs, value1, value2);
+        }
+        else {
+            // Else, attempt to promote their types to something equivalent on the two sides.
+
+            // Promote Short to Integer, Long, Float or Double.
+            Integer compare = compareIfPromoted(rs, value1, value2, Short.class, Integer.class, Integer::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Short.class, Long.class, Long::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Short.class, Float.class, Float::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Short.class, Double.class, Double::valueOf);
+            
+            // Promote Integer to Long, Float or Double.
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Integer.class, Long.class, Long::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Integer.class, Float.class, Float::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Integer.class, Double.class, Double::valueOf);
+            
+            // Promote Long to Float or Double.
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Long.class, Float.class, Float::valueOf);
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Long.class, Double.class, Double::valueOf);
+            
+            // Promote Float to Double.
+            compare = compare != null ? compare : compareIfPromoted(rs, value1, value2, Float.class, Double.class, Double::valueOf);
+
+            // if we are here with still a null value in comparison result, we have found no matching at all.
+            // Default to String comparison.
+            if (compare == null) {
+                String default1 = value1.toString();
+                String default2 = value2.toString();
+                return compare(rs, default1, default2);
+            }
+            else
+                return compare;
+        }
+    }
+    
+    /**
+     * Perform a comparison after having attempted to promote compared types : one of the parameter must belongs to one class and the other
+     * one to the second one to allow the conversion and comparison to be done, else a null value will be returned, meaning that no promotion were possible.
+     * @param <W> the worst class expected, the one that will be promoted to the best class through the mean of the promoter function.
+     * @param <B> the best class expected : one of the parameter will be promoted to this class to allow comparison to be done.
+     * @param rs ResultSet where field values has been taken.
+     * @param value1 First value.
+     * @param value2 Second value.
+     * @param worstHas The worst class expected.
+     * @param bestHas The best class expected.
+     * @param promoter Promoting function.
+     * @return Comparison result, or null if no comparison can be done because a parameter value cannot be promoted.
+     * @throws SQLUnsupportedParsingFeatureException if a comparison fails eventually on a Java type not belonging to {link #java.lang.Comparable}.
+     */
+    private <W, B> Integer compareIfPromoted(DBFRecordBasedResultSet rs, Object value1, Object value2, Class<W> worstHas, Class<B> bestHas, Function<W, B> promoter) throws SQLUnsupportedParsingFeatureException {
+        boolean w1 = value1.getClass().equals(worstHas);
+        boolean b1 = value1.getClass().equals(bestHas);
+        boolean w2 = value2.getClass().equals(worstHas); 
+        boolean b2 = value2.getClass().equals(bestHas);
+        
+        // if the values has the same class, they should have been already compared. But let's to it.
+        if ((w1 && w2) || (b1 && b2))
+            return compare(rs, value1, value2);
+        else
+        {
+            // if one value doesn't match to a type, we can't perform the comparison.
+            if ((w1 == false && b1 == false) || (w2 == false && b2 == false))
+               return null;
+            else {
+                assert((w1 != b1 && w2 != b2) && (w1 != w2 && b1 != b2)) : "Parameters are not of different types.";
+                
+                // Suppress the warnings because we have done the checkings before.
+                @SuppressWarnings("unchecked") B sameType1 = w1 ? promoter.apply((W)value1) : (B)value1;
+                @SuppressWarnings("unchecked") B sameType2 = w2 ? promoter.apply((W)value2) : (B)value2;
+                return compare(rs, sameType1, sameType2);
+            }
+        }
+    }
+    
+    /**
+     * Compare two values of the same type.
+     * @param <T> Class of their type.
+     * @param rs ResultSet where field values has been taken.
+     * @param value1 First comparand.
+     * @param value2 Second comparand.
+     * @return Result of the comparison.
+     * @throws SQLUnsupportedParsingFeatureException if this type doesn't implements {link #java.lang.Comparable} and cannot be handled by this driver. 
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"}) // Wished : Types are checked by the caller.
+    private <T> int compare(DBFRecordBasedResultSet rs, T value1, T value2) throws SQLUnsupportedParsingFeatureException {
+        Comparable comparable1 = null;
+        Comparable comparable2 = null;
+        
+        if (value1 instanceof Comparable<?>) {
+            comparable1 = (Comparable)value1;
+        }
+        
+        if (value2 instanceof Comparable<?>) {
+            comparable2 = (Comparable)value2;
+        }
+        
+        // If one of the comparands doesn't belong to java.lang.Comparable, our driver is taken short.
+        if (comparable1 == null) {
+            String message = format(Level.SEVERE, "excp.uncomparable_type", value1, value1.getClass().getName(), rs.getSQL());
+            throw new SQLUnsupportedParsingFeatureException(message, rs.getSQL(), rs.getDatabase().getFile());
+        }
+        
+        if (comparable2 == null) {
+            String message = format(Level.SEVERE, "excp.uncomparable_type", value2, value2.getClass().getName(), rs.getSQL());
+            throw new SQLUnsupportedParsingFeatureException(message, rs.getSQL(), rs.getDatabase().getFile());
+        }
+
+        return comparable1.compareTo(comparable2);
+    }
+    
+    /**
+     * Returns the value of a comparand.
+     * @param rs ResultSet.
+     * @param comparand Comparand.
+     * @return Value of that comparand : 
+     * <br>- itself, it is a primitive type or an enclosed string.
+     * <br>-a field value if the given string is not enclosed by ' characters : the parser see it a field name, then.
+     * @throws SQLIllegalParameterException if a literal string value is not well enclosed by '...'. 
+     * @throws SQLNoSuchFieldException if the comparand designs a field name that doesn't exist.
+     * @throws SQLNotDateException if a field announced being a date isn't.
+     * @throws SQLUnsupportedParsingFeatureException if the driver encounter a type it cannot handle.
+     * @throws SQLNotNumericException if a field doesn't carry a numeric value when expected to.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     */
+    private Object valueOf(DBFRecordBasedResultSet rs, Object comparand) throws SQLIllegalParameterException, SQLNoSuchFieldException, SQLConnectionClosedException, SQLNotNumericException, SQLUnsupportedParsingFeatureException, SQLNotDateException {
+        Objects.requireNonNull(rs, "ResultSet cannot be null when taking the value of a ResultSet comparand.");
+        Objects.requireNonNull(comparand, "Comparand cannot be null.");
+        
+        // All comparands that are litterals are returned as they are.
+        if (comparand instanceof String == false)
+            return comparand;
+
+        String text = (String)comparand;
+        text = text.trim();
+
+        // If the field is enclosed by ' characters, it is considered a litteral too, but these ' are removed before returning the string.
+        boolean wannaBeLiteral = text.startsWith("'") || text.endsWith("'"); // A ' at the beginning or the end.
+        boolean uncompleteLiteral = text.startsWith("'") == false || text.endsWith("'") == false || text.length() < 2; // But not at the two sides, or a string made of a single one. 
+        
+        if (wannaBeLiteral) {
+            if (wannaBeLiteral && uncompleteLiteral) {
+                String message = format(Level.SEVERE, "excp.illegal_parameter_where", text, rs.getSQL());
+                throw new SQLIllegalParameterException(message, rs.getSQL(), rs.getDatabase().getFile(), "literal", text);
+            }
+            
+            assert(text.indexOf("'") == 0 && text.indexOf("'") < text.lastIndexOf("'") && text.lastIndexOf("'") == text.length()-1 && text.length() >= 2) : "The litteral string is not enclosed into '...'"; 
+            
+            String literal = text.substring(1, text.length()-1);
+            return literal;
+        }
+        else {
+            // The string designs a field name, return it.
+            FieldDescriptor field = rs.getDatabase().getFieldsDescriptor().get(rs.findColumn(text)-1); // Columns indexes start at 1. 
+            return valueOf(rs, field);
+        }
+    }
+    
+    /**
+     * Returns the field value in a ResultSet.
+     * @param rs ResultSet.
+     * @param field Field.
+     * @return Field value.
+     * @throws SQLNotNumericException if the value of a numeric field queried isn't numeric.
+     * @throws SQLNoSuchFieldException if a field name doesn't exist in the query.
+     * @throws SQLConnectionClosedException if the connection is closed.
+     * @throws SQLUnsupportedParsingFeatureException if our implementation of the driver still not handle this data type.
+     * @throws SQLNotDateException if the value of a date field is not a date.
+     */
+    private Object valueOf(DBFRecordBasedResultSet rs, FieldDescriptor field) throws SQLConnectionClosedException, SQLNoSuchFieldException, SQLNotNumericException, SQLUnsupportedParsingFeatureException, SQLNotDateException {
+        switch(field.getType()) {
+            case AutoIncrement:
+                return rs.getInt(field.getName());
+                
+            case Character:
+                return rs.getString(field.getName());
+                
+            case Date:
+                return rs.getDate(field.getName());
+                
+            case Double:
+                return rs.getDouble(field.getName());
+                
+            case FloatingPoint:
+                return rs.getFloat(field.getName());
+                
+            case Integer:
+                return rs.getInt(field.getName());
+                
+            case Number:
+                // Choose Integer or Long type, if no decimal and that the field is not to big.
+                if (field.getDecimalCount() == 0 && field.getLength() <= 18)
+                {
+                    if (field.getLength() <= 9)
+                        return rs.getInt(field.getName());
+                    else
+                        return rs.getLong(field.getName());
+                }
+                
+                return rs.getDouble(field.getName());
+
+            // Unhandled types.
+            case Currency:
+            case DateTime:
+            case Logical:
+            case Memo:
+            case Picture:
+            case TimeStamp:
+            case Variant:
+            case VariField:
+                String message = format(Level.SEVERE, "excp.unparsable_field_type", field.getName(), field.getType(), rs.getSQL());
+                throw new SQLUnsupportedParsingFeatureException(message, rs.getSQL(), rs.getDatabase().getFile());
+                
+            default:
+                throw new RuntimeException(format("assert.unknown_field_type", field.getType()));
+        }
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ConditionalClauseResolver.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ConditionalClauseResolver.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ConditionalClauseResolver.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/ConditionalClauseResolver.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+/**
+ * Conditional Clause resolver : resolves a single part of an expression :
+ * <br>- Only resolve comparison of simple statements like F = 2, not those involving intermediate calculations (F + 4 = 6).
+ * <br>- Only resolve a part of an expression : in "A = 5 and (B = 3 or C = 6)" will treat A = 5, for example.
+ * <br>- If many clauseResolvers are chained, operator precedence checking has to be done by the caller.
+ * <br>- This class is only here temporary, and will be replaced by a good SQL parser as soon as possible. 
+ * @author Marc LE BIHAN
+ */
+public class ConditionalClauseResolver extends AbstractClauseResolver
+{
+    /**
+     * Construct a where clause resolver.
+     * @param comparand1 The first comparand that might be a primitive or a FieldDescriptor.
+     * @param comparand2 The second comparand that might be a primitive or a FieldDescriptor.
+     * @param operator The operator to apply.
+     */
+    public ConditionalClauseResolver(Object comparand1, Object comparand2, String operator) {
+        super(comparand1, comparand2, operator);
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/CrudeSQLParser.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,112 @@
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+import java.util.Objects;
+
+import org.apache.sis.internal.shapefile.jdbc.AbstractJDBC;
+import org.apache.sis.internal.shapefile.jdbc.resultset.DBFRecordBasedResultSet;
+
+/**
+ * Simple and temporary SQL parser.
+ * @author Marc LE BIHAN 
+ */
+public class CrudeSQLParser extends AbstractJDBC {
+    /** ResultSet followed straight forward. */
+    private DBFRecordBasedResultSet m_rs;
+    
+    /**
+     * Construct a crude SQL parser.
+     * @param rs Target ResultSet.
+     */
+    public CrudeSQLParser(DBFRecordBasedResultSet rs) {
+        Objects.requireNonNull(rs, "The ResultSet given to the SQL parser cannot be null.");
+        m_rs = rs;
+    }
+    
+    /**
+     * Get the unique conditional statement contained in an SQL statement.
+     * @return Conditional clause or null if the statement wasn't accompanied by a where clause.
+     * @throws SQLInvalidStatementException if the SQL statement is invalid. 
+     */
+    public ConditionalClauseResolver parse() throws SQLInvalidStatementException {
+        logStep("parse");
+        
+        String sql = m_rs.getSQL().trim();
+        
+        if (sql.toLowerCase().startsWith("select * from ") == false) {
+            String message = format("excp.limited_feature_syntax", sql);
+            throw new SQLInvalidStatementException(message, m_rs.getSQL(), m_rs.getDatabase().getFile());
+        }
+        
+        final String whereWord = " where ";
+        int whereIndex = sql.toLowerCase().indexOf(whereWord);
+
+        // If the where clause has not been found, its not an error : there is no condition to set, that's all.
+        if (whereIndex == -1)
+            return null;
+
+        // Get the conditions.
+        int endOfwhereClause = whereIndex + whereWord.length();
+        String whereCondition = sql.substring(endOfwhereClause).trim();
+        
+        // If the condition is empty, it's a syntax error because a WHERE clause went before.
+        if (whereCondition.isEmpty()) {
+            String message = format("excp.where_without_conditions", sql);            
+            throw new SQLInvalidStatementException(message, m_rs.getSQL(), m_rs.getDatabase().getFile());
+        }
+        
+        // Currently, all the condition are made of three parts :
+        // <Comparand 1> <operator> <Comparand 2>
+        // i.e. : A < 5, CITY = 'Kratie', B >= 15.3
+        // Spaces are currently expected between parts of the conditional expression.
+        String[] parts = whereCondition.split(" ");
+        
+        if (parts.length != 3) {
+            String message = format("excp.limited_feature_conditional_parsing", whereCondition, sql);
+            throw new SQLInvalidStatementException(message, m_rs.getSQL(), m_rs.getDatabase().getFile());
+        }
+        
+        // Detect and promote litterals in parameters to their best types.
+        Object comparand1 = convertToNearestParameterType(parts[0]);
+        Object comparand2 = convertToNearestParameterType(parts[2]);
+        String operand = parts[1];
+        
+        ConditionalClauseResolver resolver = new ConditionalClauseResolver(comparand1, comparand2, operand);
+        return resolver;
+    }
+
+    /**
+     * Promote a value to the best parameter available : Integer, then Double, then String.
+     * TODO Convert to Date, and admit null values.
+     * @param value Value.
+     * @return Converted value or value kept as String if no convertion applies.
+     */
+    private Object convertToNearestParameterType(String value) {
+        try {
+            return Integer.parseInt(value);
+        }
+        catch(NumberFormatException e) {
+            try {
+                return Double.parseDouble(value);
+            }
+            catch(NumberFormatException ex) {
+                return value;
+            }
+        }
+    }
+    
+    /**
+     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
+     */
+    @Override public boolean isWrapperFor(Class<?> iface) {
+        logStep("isWrapperFor", iface);
+        return false;
+    }
+
+    /**
+     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getInterface()
+     */
+    @Override protected Class<?> getInterface() {
+        logStep("getInterface");
+        return getClass();
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLIllegalParameterException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a parameter is invalid.
+ * @author Marc LE BIHAN
+ */
+public class SQLIllegalParameterException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = -3173798942882143448L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /** Parameter name (if known) that is invalid. */
+    private String m_parameterName;
+    
+    /** Parameter value that is invalid. */
+    private String m_parameterValue;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     * @param parameterName The parameter name that is invalid.
+     * @param parameterValue The parameter value that is invalid.
+     */
+    public SQLIllegalParameterException(String message, String sql, File database, String parameterName, String parameterValue) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+        m_parameterName = parameterName;
+        m_parameterValue = parameterValue;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the parameter name that is invalid, if known.
+     * @return Parameter name.
+     */
+    public String geParameterName() {
+        return m_parameterName;
+    }
+    
+    /**
+     * Returns the parameter value that is invalid.
+     * @return Parameter name.
+     */
+    public String geParameterValue() {
+        return m_parameterValue;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLInvalidStatementException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a statement is invalid.
+ * @author Marc LE BIHAN
+ */
+public class SQLInvalidStatementException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = -1807300055143449480L;
+
+    /** The SQL Statement (if known). */
+    private String m_sql;
+    
+    /** The database file. */
+    private File m_database;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble, if known.
+     * @param database The database that was queried.
+     */
+    public SQLInvalidStatementException(String message, String sql, File database) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+    }
+    
+    /**
+     * Returns the SQL statement.
+     * @return SQL statement or null.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the database file.
+     * @return Database file.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/SQLUnsupportedParsingFeatureException.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
+
+import java.io.File;
+import java.sql.SQLException;
+
+/**
+ * Exception thrown when a parsing feature is not supported.
+ * @author Marc LE BIHAN
+ */
+public class SQLUnsupportedParsingFeatureException extends SQLException {
+    /** Serial ID. */
+    private static final long serialVersionUID = 6944940576163675495L;
+
+    /** The SQL Statement that whas attempted. */
+    private String m_sql;
+    
+    /** The database that was queried. */
+    private File m_database;
+    
+    /**
+     * Build the exception.
+     * @param message Exception message.
+     * @param sql SQL Statement who encountered the trouble.
+     * @param database The database that was queried.
+     */
+    public SQLUnsupportedParsingFeatureException(String message, String sql, File database) {
+        super(message);
+        m_sql = sql;
+        m_database = database;
+    }
+    
+    /**
+     * Returns the SQL statement who encountered the "end of data" alert.
+     * @return SQL statement.
+     */
+    public String getSQL() {
+        return m_sql;
+    }
+    
+    /**
+     * Returns the database file that was queried.
+     * @return The database that was queried.
+     */
+    public File getDatabase() {
+        return m_database;
+    }
+}

Added: sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/package-info.java?rev=1643155&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/package-info.java (added)
+++ sis/branches/JDK8/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/sql/package-info.java Fri Dec  5 05:53:23 2014
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * SQL Parser.
+ */
+package org.apache.sis.internal.shapefile.jdbc.sql;
\ No newline at end of file



Mime
View raw message