Skip to content

Commit

Permalink
Throw exceptions outside cache configuration to have more control.
Browse files Browse the repository at this point in the history
  • Loading branch information
ComBatVision committed Jan 13, 2023
1 parent 52bb1d2 commit 9bc4e88
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import earth.worldwind.render.RenderResourceCache
import earth.worldwind.util.Logger.WARN
import earth.worldwind.util.Logger.logMessage
import kotlinx.coroutines.*
import kotlin.jvm.Throws

actual abstract class TiledImageLayer actual constructor(name: String): AbstractTiledImageLayer(name) {
/**
Expand All @@ -21,12 +22,15 @@ actual abstract class TiledImageLayer actual constructor(name: String): Abstract
* @param quality Tile image compression quality
*
* @return Cache configured successfully
* @throws IllegalArgumentException In case of incompatible level set configured in cache content.
* @throws IllegalStateException In case of new content creation required on read-only database.
*/
@Suppress("DEPRECATION")
@JvmOverloads
@Throws(IllegalArgumentException::class, IllegalStateException::class)
suspend fun configureCache(
pathName: String, tableName: String, readOnly: Boolean = false, format: CompressFormat = CompressFormat.PNG, quality: Int = 100
) = try {
) {
val isWebp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
format == CompressFormat.WEBP_LOSSLESS || format == CompressFormat.WEBP_LOSSY
} else {
Expand All @@ -37,13 +41,6 @@ actual abstract class TiledImageLayer actual constructor(name: String): Abstract
it.format = format
it.quality = quality
}
true
} catch (e: IllegalArgumentException) {
logMessage(WARN, "TiledImageLayer", "configureCache", e.message!!)
false
} catch (e: IllegalStateException) {
logMessage(WARN, "TiledImageLayer", "configureCache", e.message!!)
false
}

/**
Expand All @@ -62,9 +59,10 @@ actual abstract class TiledImageLayer actual constructor(name: String): Abstract
* @return the coroutine Job executing the retrieval or `null` if the specified sector does
* not intersect the layer bounding sector.
*
* @throws IllegalStateException if tiled surface image is not initialized or cache not configured.
* @throws IllegalStateException if tiled surface image is not initialized or cache is not configured.
*/
@OptIn(DelicateCoroutinesApi::class)
@Throws(IllegalStateException::class)
fun makeLocal(
sector: Sector, resolution: Angle, cache: RenderResourceCache, scope: CoroutineScope = GlobalScope,
onProgress: ((Int, Int) -> Unit)? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import io.ktor.client.network.sockets.*
import kotlinx.coroutines.*
import java.io.FileNotFoundException
import java.net.SocketTimeoutException
import kotlin.jvm.Throws

actual open class TiledElevationCoverage actual constructor(
tileMatrixSet: TileMatrixSet, tileFactory: ElevationTileFactory,
Expand Down Expand Up @@ -53,30 +54,25 @@ actual open class TiledElevationCoverage actual constructor(
* @param isFloat If true, then cache will be stored in Float32 format, else Int16.
*
* @return Cache configured successfully
* @throws IllegalArgumentException In case of incompatible matrix set configured in cache content.
* @throws IllegalStateException In case of new content creation required on read-only database.
*/
suspend fun configureCache(pathName: String, tableName: String, readOnly: Boolean = false, isFloat: Boolean = false): Boolean {
return try {
val geoPackage = GeoPackage(pathName, readOnly)
val content = geoPackage.content.firstOrNull { it.tableName == tableName }?.also {
// Check if current layer fits cache content
val matrixSet = geoPackage.buildTileMatrixSet(it)
require(matrixSet.sector == tileMatrixSet.sector) { "Invalid sector" }
require(matrixSet.entries.size == tileMatrixSet.entries.size) { "Invalid number of matrices" }
requireNotNull(geoPackage.griddedCoverages.firstOrNull { gc ->
gc.tileMatrixSetName == tableName && gc.datatype == if (isFloat) "float" else "integer"
}) { "Invalid data type" }
} ?: geoPackage.setupGriddedCoverageContent(tableName, displayName ?: tableName, tileMatrixSet, isFloat)
@JvmOverloads
@Throws(IllegalArgumentException::class, IllegalStateException::class)
suspend fun configureCache(pathName: String, tableName: String, readOnly: Boolean = false, isFloat: Boolean = false) {
val geoPackage = GeoPackage(pathName, readOnly)
val content = geoPackage.content.firstOrNull { it.tableName == tableName }?.also {
// Check if current layer fits cache content
val matrixSet = geoPackage.buildTileMatrixSet(it)
require(matrixSet.sector == tileMatrixSet.sector) { "Invalid sector" }
require(matrixSet.entries.size == tileMatrixSet.entries.size) { "Invalid number of matrices" }
requireNotNull(geoPackage.griddedCoverages.firstOrNull { gc ->
gc.tileMatrixSetName == tableName && gc.datatype == if (isFloat) "float" else "integer"
}) { "Invalid data type" }
} ?: geoPackage.setupGriddedCoverageContent(tableName, displayName ?: tableName, tileMatrixSet, isFloat)

cacheContent = content
cacheTileFactory = GpkgElevationTileFactory(content, isFloat)
true
} catch (e: IllegalArgumentException) {
logMessage(WARN, "TiledImageLayer", "configureCache", e.message!!)
false
} catch (e: IllegalStateException) {
logMessage(WARN, "TiledImageLayer", "configureCache", e.message!!)
false
}
cacheContent = content
cacheTileFactory = GpkgElevationTileFactory(content, isFloat)
}

/**
Expand All @@ -89,7 +85,10 @@ actual open class TiledElevationCoverage actual constructor(

/**
* Delete all tiles from current cache storage
*
* @throws IllegalStateException In case of read-only database.
*/
@Throws(IllegalStateException::class)
suspend fun clearCache() = cacheContent?.run { container.deleteContent(tableName) }.also { disableCache() }

/**
Expand All @@ -107,9 +106,10 @@ actual open class TiledElevationCoverage actual constructor(
* @return the coroutine Job executing the retrieval or `null` if the specified sector does
* not intersect the elevation model bounding sector.
*
* @throws IllegalStateException if cache not configured.
* @throws IllegalStateException if cache is not configured.
*/
@OptIn(DelicateCoroutinesApi::class)
@Throws(IllegalStateException::class)
fun makeLocal(
sector: Sector, resolution: Angle, scope: CoroutineScope = GlobalScope, onProgress: ((Int, Int) -> Unit)? = null
): Job? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import earth.worldwind.render.image.ImageSource
import earth.worldwind.render.image.ImageTile
import earth.worldwind.shape.TiledSurfaceImage
import kotlinx.coroutines.*
import kotlin.jvm.Throws

actual abstract class AbstractTiledImageLayer actual constructor(name: String): RenderableLayer(name) {
actual var tiledSurfaceImage: TiledSurfaceImage? = null
Expand Down Expand Up @@ -43,9 +44,13 @@ actual abstract class AbstractTiledImageLayer actual constructor(name: String):

/**
* Delete all tiles from current cache storage
*
* @throws IllegalStateException In case of read-only database.
*/
@Throws(IllegalStateException::class)
suspend fun clearCache() = cacheContent?.run { container.deleteContent(tableName) }.also { disableCache() }

@Throws(IllegalArgumentException::class, IllegalStateException::class)
protected open suspend fun getOrSetupTilesContent(pathName: String, tableName: String, readOnly: Boolean, isWebp: Boolean): GpkgContent {
val tiledSurfaceImage = tiledSurfaceImage ?: error("Surface image not defined")
val levelSet = tiledSurfaceImage.levelSet
Expand All @@ -66,6 +71,7 @@ actual abstract class AbstractTiledImageLayer actual constructor(name: String):
} ?: geoPackage.setupTilesContent(tableName, displayName ?: tableName, levelSet, isWebp)
}

@Throws(IllegalStateException::class)
protected open fun launchBulkRetrieval(
scope: CoroutineScope, sector: Sector, resolution: Angle, onProgress: ((Int, Int) -> Unit)?,
retrieveTile: suspend (imageSource: ImageSource, cacheSource: ImageSource, options: ImageOptions?) -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import earth.worldwind.layer.mercator.MercatorSector
import earth.worldwind.util.LevelSet
import earth.worldwind.util.LevelSetConfig
import kotlinx.coroutines.runBlocking
import kotlin.jvm.Throws

// TODO verify its a GeoPackage container
abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
Expand Down Expand Up @@ -47,13 +48,15 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
suspend fun readTileUserData(tiles: GpkgContent, zoomLevel: Int, tileColumn: Int, tileRow: Int) =
readTileUserData(tiles.tableName, zoomLevel, tileColumn, tileRow)

@Throws(IllegalStateException::class)
suspend fun writeTileUserData(tiles: GpkgContent, zoomLevel: Int, tileColumn: Int, tileRow: Int, tileData: ByteArray) {
if (isReadOnly) error("Tile cannot be saved. GeoPackage is read-only!")
val tileUserData = readTileUserData(tiles.tableName, zoomLevel, tileColumn, tileRow)?.also { it.tileData = tileData }
?: GpkgTileUserData(this, -1, zoomLevel, tileColumn, tileRow, tileData)
writeTileUserData(tiles.tableName, tileUserData)
}

@Throws(IllegalStateException::class)
suspend fun writeGriddedTile(
tiles: GpkgContent, zoomLevel: Int, tileColumn: Int, tileRow: Int, scale: Double = 1.0, offset: Double = 0.0,
min: Double? = null, max: Double? = null, mean: Double? = null, stdDev: Double? = null
Expand All @@ -72,6 +75,7 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
}
}

@Throws(IllegalArgumentException::class)
fun buildLevelSetConfig(content: GpkgContent): LevelSetConfig {
require(content.dataType.equals("tiles", true)) {
"Unsupported GeoPackage content data_type: " + content.dataType
Expand Down Expand Up @@ -106,6 +110,7 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
}

// TODO What if data already exists?
@Throws(IllegalStateException::class)
suspend fun setupTilesContent(
tableName: String, identifier: String, levelSet: LevelSet, isWebp: Boolean = false
): GpkgContent {
Expand Down Expand Up @@ -138,6 +143,7 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
return content
}

@Throws(IllegalStateException::class)
suspend fun setupTileMatrices(tableName: String, levelSet: LevelSet) {
if (isReadOnly) error("Content $tableName cannot be updated. GeoPackage is read-only!")
for (i in 0 until levelSet.numLevels) levelSet.level(i)?.run {
Expand All @@ -156,6 +162,7 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
}
}

@Throws(IllegalArgumentException::class)
fun buildTileMatrixSet(content: GpkgContent): TileMatrixSet {
require(content.dataType.equals("2d-gridded-coverage", true)) {
"Unsupported GeoPackage content data_type: " + content.dataType
Expand All @@ -180,6 +187,7 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {
}

// TODO What if data already exists?
@Throws(IllegalStateException::class)
suspend fun setupGriddedCoverageContent(tableName: String, identifier: String, tileMatrixSet: TileMatrixSet, isFloat: Boolean = false): GpkgContent {
if (isReadOnly) error("Content $tableName cannot be created. GeoPackage is read-only!")
createRequiredTables()
Expand Down Expand Up @@ -232,7 +240,10 @@ abstract class AbstractGeoPackage(pathName: String, val isReadOnly: Boolean) {

/**
* Delete specified content table and its related metadata
*
* @throws IllegalStateException In case of new content creation required on read-only database.
*/
@Throws(IllegalStateException::class)
suspend fun deleteContent(tableName: String) {
if (isReadOnly) error("Content $tableName cannot be deleted. GeoPackage is read-only!")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import earth.worldwind.geom.Angle
import earth.worldwind.geom.Sector
import earth.worldwind.render.RenderResourceCache
import kotlinx.coroutines.*
import kotlin.jvm.Throws

actual abstract class TiledImageLayer actual constructor(name: String): AbstractTiledImageLayer(name) {
/**
Expand All @@ -22,9 +23,10 @@ actual abstract class TiledImageLayer actual constructor(name: String): Abstract
* @return the coroutine Job executing the retrieval or `null` if the specified sector does
* not intersect the layer bounding sector.
*
* @throws IllegalStateException if tiled surface image is not initialized or cache not configured.
* @throws IllegalStateException if tiled surface image is not initialized or cache is not configured.
*/
@OptIn(DelicateCoroutinesApi::class)
@Throws(IllegalStateException::class)
fun makeLocal(
sector: Sector, resolution: Angle, cache: RenderResourceCache, scope: CoroutineScope = GlobalScope,
onProgress: ((Int, Int) -> Unit)? = null
Expand Down

0 comments on commit 9bc4e88

Please sign in to comment.