diff --git a/.idea/inspectionProfiles/SWAGD.xml b/.idea/inspectionProfiles/SWAGD.xml
index 31dc846b..e1d2419d 100644
--- a/.idea/inspectionProfiles/SWAGD.xml
+++ b/.idea/inspectionProfiles/SWAGD.xml
@@ -78,7 +78,9 @@
-
+
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 8f96fd28..f43837a9 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,19 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/GeoPackage.java b/GeoPackage/src/main/java/com/rgi/geopackage/GeoPackage.java
index a0e268a3..e80851e8 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/GeoPackage.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/GeoPackage.java
@@ -204,7 +204,7 @@ public GeoPackage(final File file, final VerificationLevel verificationLevel, fi
DatabaseUtility.setPragmaForeignKeys(this.databaseConnection, true);
DatabaseUtility.setPragmaJournalModeMemory(this.databaseConnection);
- // this was moved below setting the pragmas because is starts a transaction and causes setPragmaSynchronousOff to throw an exception
+ // This was moved below the pragmas because it starts a transaction and causes setPragmaSynchronousOff to throw an exception
this.databaseConnection.setAutoCommit(false);
this.core = new GeoPackageCore (this.databaseConnection, isNewFile);
@@ -465,5 +465,5 @@ public enum OpenMode
private final GeoPackageMetadata metadata;
private final GeoPackageExtensions extensions;
- private static final byte[] GeoPackageSqliteApplicationId = {(byte) 'G', (byte) 'P', (byte) '1', (byte) '0'};
+ private static final byte[] GeoPackageSqliteApplicationId = {(byte) 'G', (byte) 'P', (byte) '1', (byte) '2'};
}
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/core/CoreVerifier.java b/GeoPackage/src/main/java/com/rgi/geopackage/core/CoreVerifier.java
index 4dd83e9e..734d8440 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/core/CoreVerifier.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/core/CoreVerifier.java
@@ -39,7 +39,6 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -153,25 +152,26 @@ public void requirement1() throws IOException, AssertionError
* Requirement 2
*
*
- * A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII)
- * in the application id field of the SQLite database header
- * to indicate a GeoPackage version 1.0 file.
+ * A GeoPackage SHALL contain an appropriate value in the application ID
+ * field of the SQLite database header to indicate that it is a GeoPackage.
+ * The value SHALL have a prefix of 0x4750 ("GP" in ASCII). A value of
+ * 0x47503132 ("GP12" in ASCII) SHALL indicate a GeoPackage version 1.2 file.
*
- * @throws AssertionError throws if it fails to meet the specified requirement;
+ * @throws AssertionError throws if it fails to meet the specified requirement
*/
@Requirement(reference = "Requirement 2",
- text = "A GeoPackage SHALL contain 0x47503130 ('GP10' in ASCII) in the application id field of the SQLite database header to indicate a GeoPackage version 1.0 file.")
+ text = "A GeoPackage SHALL contain an appropriate value in the application ID field of the SQLite database header to indicate that it is a GeoPackage. The value SHALL have a prefix of 0x4750 (\"GP\" in ASCII). A value of 0x47503132 (\"GP12\" in ASCII) SHALL indicate a GeoPackage version 1.2 file.")
public void requirement2() throws AssertionError
{
- final int sizeOfInt = 4;
- final byte[] data = new byte[sizeOfInt]; // 4 bytes in an int
+ final int sizeOfPrefix = 2;
+ final byte[] data = new byte[sizeOfPrefix]; // 4 bytes in an int
try(RandomAccessFile randomAccessFile = new RandomAccessFile(this.file, "r"))
{
final long applicationIdByteOffset = 68;
randomAccessFile.seek(applicationIdByteOffset);
assertTrue("The file does not have enough bytes to contain a GeoPackage.",
- randomAccessFile.read(data, 0, sizeOfInt) == sizeOfInt,
+ randomAccessFile.read(data, 0, sizeOfPrefix) == sizeOfPrefix,
Severity.Warning);
}
catch(final Exception ex)
@@ -179,19 +179,11 @@ public void requirement2() throws AssertionError
throw new AssertionError(ex, Severity.Error);
}
- // application id
- // http://www.sqlite.org/fileformat2.html
- // http://www.geopackage.org/spec/#_sqlite_container
- // A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the
- // application id field of the SQLite database header to indicate a
- // GeoPackage version 1.0 file.
- // The bytes 'G', 'P', '1', '0' are equivalent to 0x47503130
- final int expectedAppId = 0x47503130;
-
- final int applicationId = ByteBuffer.wrap(data).asIntBuffer().get();
-
- assertTrue(String.format("Bad Application ID: 0x%08x Expected: 0x%08x", applicationId, expectedAppId),
- applicationId == expectedAppId,
+ assertTrue(String.format("Bad Application ID prefix: \"%c%c\" Expected: \"GP\"",
+ data[0],
+ data[1]),
+ data[0] == 'G' &&
+ data[1] == 'P',
Severity.Warning);
}
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/core/GeoPackageCore.java b/GeoPackage/src/main/java/com/rgi/geopackage/core/GeoPackageCore.java
index 7507c647..1ba78a1a 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/core/GeoPackageCore.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/core/GeoPackageCore.java
@@ -646,7 +646,7 @@ protected void createDefaultTables() throws SQLException
// Add the default entries to the spatial reference system table
// See: http://www.geopackage.org/spec/#spatial_ref_sys -> 1.1.2.1.2. Table Data Values, Requirement 11
this.addSpatialReferenceSystemNoCommit("World Geodetic System (WGS) 1984",
- 1,
+ 4326,
"EPSG",
4326,
"GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]", // http://spatialreference.org/ref/epsg/wgs-84/ogcwkt/
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/extensions/GeoPackageExtensions.java b/GeoPackage/src/main/java/com/rgi/geopackage/extensions/GeoPackageExtensions.java
index e3f78cc6..84cc8ae1 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/extensions/GeoPackageExtensions.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/extensions/GeoPackageExtensions.java
@@ -23,16 +23,6 @@
package com.rgi.geopackage.extensions;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import com.rgi.common.util.jdbc.JdbcUtility;
import com.rgi.geopackage.GeoPackage;
import com.rgi.geopackage.core.GeoPackageCore;
@@ -43,6 +33,16 @@
import com.rgi.geopackage.verification.VerificationIssue;
import com.rgi.geopackage.verification.VerificationLevel;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* 'Extensions' subsystem of the {@link GeoPackage} implementation
*
@@ -372,7 +372,7 @@ protected String getExtensionsTableCreationSql()
"(table_name TEXT, -- Name of the table that requires the extension. When NULL, the extension is required for the entire GeoPackage. SHALL NOT be NULL when the column_name is not NULL.\n" +
" column_name TEXT, -- Name of the column that requires the extension. When NULL, the extension is required for the entire table.\n" +
" extension_name TEXT NOT NULL, -- The case sensitive name of the extension that is required, in the form _.\n" +
- " definition TEXT NOT NULL, -- Definition of the extension in the form specfied by the template in GeoPackage Extension Template (Normative) or reference thereto.\n" +
+ " definition TEXT NOT NULL, -- Definition of the extension in the form specified by the template in GeoPackage Extension Template (Normative) or reference thereto.\n" +
" scope TEXT NOT NULL, -- Indicates scope of extension effects on readers / writers: read-write or write-only in lowercase.\n" +
" CONSTRAINT ge_tce UNIQUE (table_name, column_name, extension_name))";
}
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/features/ColumnDefault.java b/GeoPackage/src/main/java/com/rgi/geopackage/features/ColumnDefault.java
index aac4eb1d..96c5099f 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/features/ColumnDefault.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/features/ColumnDefault.java
@@ -83,7 +83,7 @@ static ColumnDefault from(final double value)
}
/**
- * Creates a string literal of the form ''. Single quotes in the
+ * Creates a string literal of the form '<string>'. Single quotes in the
* string value will be escaped with an additional single quote e.g. '
* becomes ''
*
@@ -102,7 +102,7 @@ static ColumnDefault from(final String value)
}
/**
- * Creates a blob literal in the form X''
+ * Creates a blob literal in the form X'<hex digits>'
*
* @param value
* Array of bytes representing a binary blob
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/features/FeaturesVerifier.java b/GeoPackage/src/main/java/com/rgi/geopackage/features/FeaturesVerifier.java
index 72572b27..d56a21ee 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/features/FeaturesVerifier.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/features/FeaturesVerifier.java
@@ -113,7 +113,7 @@ public void requirement18() throws AssertionError
{
final List missingFeatureTables = this.contentsFeatureTableNames
.stream()
- .filter(this::hasPrimaryKey)
+ .filter(tableName -> !this.hasPrimaryKey(tableName))
.collect(Collectors.toList());
assertTrue(String.format("The following feature table entries in the gpkg_contents table are missing or are missing a primary key column: %s",
@@ -364,9 +364,9 @@ private boolean isValidGeometry(final byte[] geoPackageBinaryBlob)
{
try
{
- final BinaryHeader binaryHeader = new BinaryHeader(geoPackageBinaryBlob);
+ final BinaryHeader binaryHeader = new BinaryHeader(geoPackageBinaryBlob); // This will throw if the array length is too short to contain a header (or if it's not long enough to contain the envelope type specified)
- final Geometry geometry = this.createGeometry(geoPackageBinaryBlob); // correctly encoded per ISO 13249-3 clause 5.1.46
+ final Geometry geometry = this.createGeometry(binaryHeader, geoPackageBinaryBlob); // correctly encoded per ISO 13249-3 clause 5.1.46
return binaryHeader.getEnvelopeContentsIndicator() != EnvelopeContentsIndicator.NoEnvelope ||
binaryHeader.getEnvelope().equals(geometry.createEnvelope());
@@ -377,10 +377,9 @@ private boolean isValidGeometry(final byte[] geoPackageBinaryBlob)
}
}
- private Geometry createGeometry(final byte[] geoPackageBinaryBlob) throws WellKnownBinaryFormatException
+ private Geometry createGeometry(final BinaryHeader binaryHeader,
+ final byte[] geoPackageBinaryBlob) throws WellKnownBinaryFormatException
{
- final BinaryHeader binaryHeader = new BinaryHeader(geoPackageBinaryBlob); // This will throw if the array length is too short to contain a header (or if it's not long enough to contain the envelope type specified)
-
if(binaryHeader.getBinaryType() == BinaryType.Standard)
{
final int headerByteLength = binaryHeader.getByteSize();
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/features/GeoPackageFeatures.java b/GeoPackage/src/main/java/com/rgi/geopackage/features/GeoPackageFeatures.java
index 7e65aa18..75721931 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/features/GeoPackageFeatures.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/features/GeoPackageFeatures.java
@@ -854,17 +854,17 @@ protected void addGeometryColumnNoCommit(final String tableNam
{
this.createGeometryColumnTableNoCommit(); // Create the feature metadata table
- final String insertTileMatrix = String.format("INSERT INTO %s (%s, %s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?, ?)",
- GeoPackageFeatures.GeometryColumnsTableName,
- "table_name",
- "column_name",
- "geometry_type_name",
- "srs_id",
- "z",
- "m");
+ final String insertGeometryColumn = String.format("INSERT INTO %s (%s, %s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?, ?)",
+ GeoPackageFeatures.GeometryColumnsTableName,
+ "table_name",
+ "column_name",
+ "geometry_type_name",
+ "srs_id",
+ "z",
+ "m");
JdbcUtility.update(this.databaseConnection,
- insertTileMatrix,
+ insertGeometryColumn,
preparedStatement -> { preparedStatement.setString(1, tableName);
preparedStatement.setString(2, geometryColumn.getName());
preparedStatement.setString(3, geometryColumn.getType());
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/metadata/GeoPackageMetadata.java b/GeoPackage/src/main/java/com/rgi/geopackage/metadata/GeoPackageMetadata.java
index e8d705d2..a7203602 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/metadata/GeoPackageMetadata.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/metadata/GeoPackageMetadata.java
@@ -23,6 +23,13 @@
package com.rgi.geopackage.metadata;
+import com.rgi.common.util.jdbc.ResultSetStream;
+import com.rgi.geopackage.utility.DatabaseUtility;
+import com.rgi.geopackage.utility.SelectBuilder;
+import com.rgi.geopackage.verification.VerificationIssue;
+import com.rgi.geopackage.verification.VerificationLevel;
+
+import javax.activation.MimeType;
import java.net.URI;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -37,14 +44,6 @@
import java.util.Objects;
import java.util.stream.Collectors;
-import javax.activation.MimeType;
-
-import com.rgi.common.util.jdbc.ResultSetStream;
-import com.rgi.geopackage.utility.DatabaseUtility;
-import com.rgi.geopackage.utility.SelectBuilder;
-import com.rgi.geopackage.verification.VerificationIssue;
-import com.rgi.geopackage.verification.VerificationLevel;
-
/**
* @author Luke Lambert
*
@@ -493,12 +492,12 @@ protected String getMetadataTableCreationSql()
// http://www.geopackage.org/spec/#gpkg_metadata_cols
// http://www.geopackage.org/spec/#gpkg_metadata_sql
return "CREATE TABLE " + GeoPackageMetadata.MetadataTableName + "\n" +
- "(id INTEGER CONSTRAINT m_pk PRIMARY KEY ASC NOT NULL UNIQUE, -- Metadata primary key\n" +
- " md_scope TEXT NOT NULL DEFAULT 'dataset', -- Case sensitive name of the data scope to which this metadata applies; see Metadata Scopes\n" +
- " md_standard_uri TEXT NOT NULL, -- URI reference to the metadata structure definition authority\n" +
- " mime_type TEXT NOT NULL DEFAULT 'text/xml', -- MIME encoding of metadata\n" +
- " metadata TEXT NOT NULL -- metadata\n" +
- ");";
+ "(id INTEGER CONSTRAINT m_pk PRIMARY KEY ASC NOT NULL UNIQUE, -- Metadata primary key\n" +
+ " md_scope TEXT NOT NULL DEFAULT 'dataset', -- Case sensitive name of the data scope to which this metadata applies; see Metadata Scopes\n" +
+ " md_standard_uri TEXT NOT NULL, -- URI reference to the metadata structure definition authority\n" +
+ " mime_type TEXT NOT NULL DEFAULT 'text/xml', -- MIME encoding of metadata\n" +
+ " metadata TEXT NOT NULL -- metadata\n" +
+ ");";
}
@SuppressWarnings("static-method")
@@ -507,15 +506,15 @@ protected String getMetadataReferenceTableCreationSql()
// http://www.geopackage.org/spec/#gpkg_metadata_reference_cols
// http://www.geopackage.org/spec/#gpkg_metadata_reference_sql
return "CREATE TABLE " + GeoPackageMetadata.MetadataReferenceTableName + "\n" +
- "(reference_scope TEXT NOT NULL, -- Lowercase metadata reference scope; one of 'geopackage', 'table','column', 'row', 'row/col'\n" +
- " table_name TEXT, -- Name of the table to which this metadata reference applies, or NULL for reference_scope of 'geopackage'\n" +
- " column_name TEXT, -- Name of the column to which this metadata reference applies; NULL for reference_scope of 'geopackage','table' or 'row', or the name of a column in the table_name table for reference_scope of 'column' or 'row/col'\n" +
- " row_id_value INTEGER, -- NULL for reference_scope of 'geopackage', 'table' or 'column', or the rowed of a row record in the table_name table for reference_scope of 'row' or 'row/col'\n" +
- " timestamp DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), -- timestamp value in ISO 8601 format as defined by the strftime function '%Y-%m-%dT%H:%M:%fZ' format string applied to the current time\n" +
- " md_file_id INTEGER NOT NULL, -- gpkg_metadata table id column value for the metadata to which this gpkg_metadata_reference applies\n" +
- " md_parent_id INTEGER, -- gpkg_metadata table id column value for the hierarchical parent gpkg_metadata for the gpkg_metadata to which this gpkg_metadata_reference applies, or NULL if md_file_id forms the root of a metadata hierarchy\n" +
- " CONSTRAINT crmr_mfi_fk FOREIGN KEY (md_file_id) REFERENCES gpkg_metadata(id),\n" +
- " CONSTRAINT crmr_mpi_fk FOREIGN KEY (md_parent_id) REFERENCES gpkg_metadata(id));";
+ "(reference_scope TEXT NOT NULL, -- Lowercase metadata reference scope; one of 'geopackage', 'table','column', 'row', 'row/col'\n" +
+ " table_name TEXT, -- Name of the table to which this metadata reference applies, or NULL for reference_scope of 'geopackage'\n" +
+ " column_name TEXT, -- Name of the column to which this metadata reference applies; NULL for reference_scope of 'geopackage','table' or 'row', or the name of a column in the table_name table for reference_scope of 'column' or 'row/col'\n" +
+ " row_id_value INTEGER, -- NULL for reference_scope of 'geopackage', 'table' or 'column', or the rowed of a row record in the table_name table for reference_scope of 'row' or 'row/col'\n" +
+ " timestamp DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), -- timestamp value in ISO 8601 format as defined by the strftime function '%Y-%m-%dT%H:%M:%fZ' format string applied to the current time\n" +
+ " md_file_id INTEGER NOT NULL, -- gpkg_metadata table id column value for the metadata to which this gpkg_metadata_reference applies\n" +
+ " md_parent_id INTEGER, -- gpkg_metadata table id column value for the hierarchical parent gpkg_metadata for the gpkg_metadata to which this gpkg_metadata_reference applies, or NULL if md_file_id forms the root of a metadata hierarchy\n" +
+ " CONSTRAINT crmr_mfi_fk FOREIGN KEY (md_file_id) REFERENCES gpkg_metadata(id),\n" +
+ " CONSTRAINT crmr_mpi_fk FOREIGN KEY (md_parent_id) REFERENCES gpkg_metadata(id));";
}
/**
diff --git a/GeoPackage/src/main/java/com/rgi/geopackage/utility/DatabaseUtility.java b/GeoPackage/src/main/java/com/rgi/geopackage/utility/DatabaseUtility.java
index d8285db8..039a129f 100644
--- a/GeoPackage/src/main/java/com/rgi/geopackage/utility/DatabaseUtility.java
+++ b/GeoPackage/src/main/java/com/rgi/geopackage/utility/DatabaseUtility.java
@@ -279,7 +279,7 @@ public static void validateTableName(final String tableName)
throw new IllegalArgumentException("The table name must begin with a letter (A..Z, a..z) or an underscore (_) and may only be followed by letters, underscores, or numbers");
}
- if(tableName.startsWith("gpkg_"))
+ if(tableName.toLowerCase().startsWith("gpkg_"))
{
throw new IllegalArgumentException("The table name may not start with the reserved prefix 'gpkg_'");
}