Skip to content

Commit

Permalink
add images only flag clarify short code model, add schema and zio-jso…
Browse files Browse the repository at this point in the history
…n codec
  • Loading branch information
seakayone committed Aug 4, 2023
1 parent 184805c commit 07233ef
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 25 deletions.
8 changes: 2 additions & 6 deletions src/main/scala/swiss/dasch/api/ApiProblem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import zio.schema.{ DeriveSchema, Schema }

sealed trait ApiProblem

case class ProjectNotFound(shortcode: String) extends ApiProblem

object ProjectNotFound {
def make(shortcode: ProjectShortcode): ProjectNotFound = ProjectNotFound(shortcode.toString)
}
case class ProjectNotFound(shortcode: ProjectShortcode) extends ApiProblem

case class IllegalArguments(errors: List[IllegalArgument]) extends ApiProblem

Expand Down Expand Up @@ -65,5 +61,5 @@ object ApiProblem {
invalidHeader("Content-Type", actual.toString, s"expected '$expected'")

// other
def projectNotFound(shortcode: ProjectShortcode): ProjectNotFound = ProjectNotFound.make(shortcode)
def projectNotFound(shortcode: ProjectShortcode): ProjectNotFound = ProjectNotFound(shortcode)
}
6 changes: 2 additions & 4 deletions src/main/scala/swiss/dasch/api/ListProjectsEndpoint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ import zio.http.{ App, Status }
import zio.json.{ DeriveJsonEncoder, JsonEncoder }
import zio.schema.{ DeriveSchema, Schema }
object ListProjectsEndpoint {
final case class ProjectResponse(id: String)
final case class ProjectResponse(id: ProjectShortcode)
object ProjectResponse {
def make(shortcode: ProjectShortcode): ProjectResponse = ProjectResponse(shortcode.toString)

implicit val schema: Schema[ProjectResponse] = DeriveSchema.gen[ProjectResponse]
implicit val jsonEncoder: JsonEncoder[ProjectResponse] = DeriveJsonEncoder.gen[ProjectResponse]
}
Expand All @@ -34,7 +32,7 @@ object ListProjectsEndpoint {
.listAllProjects()
.mapBoth(
ApiProblem.internalError,
shortcodes => (EndTotal("items", 0, shortcodes.size, shortcodes.size), shortcodes.map(ProjectResponse.make)),
shortcodes => (EndTotal("items", 0, shortcodes.size, shortcodes.size), shortcodes.map(ProjectResponse.apply)),
)
)
.toApp
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/swiss/dasch/api/MaintenanceEndpoint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ object MaintenanceEndpoint {

val needsOriginalsEndpoint = Endpoint
.get(maintenance / "needs-originals")
.query(queryBool("imagesOnly"))
.query(queryBool("imagesOnly").optional)
.out[String](Status.Accepted)
.outErrors(
HttpCodec.error[ProjectNotFound](Status.NotFound),
Expand Down
19 changes: 10 additions & 9 deletions src/main/scala/swiss/dasch/api/MaintenanceEndpointRoutes.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package swiss.dasch.api

import swiss.dasch.api.ListProjectsEndpoint.ProjectResponse
import swiss.dasch.api.MaintenanceEndpoint.*
import swiss.dasch.domain.*
import zio.json.JsonEncoder
import zio.nio.file
import zio.nio.file.Files
import zio.{ Chunk, IO, ZIO }

import java.io.IOException
import zio.json.JsonEncoder

object MaintenanceEndpointRoutes {

Expand All @@ -33,8 +32,10 @@ object MaintenanceEndpointRoutes {
Files.createFile(tmpDir / "reports" / s"$name.json") *>
StorageService.saveJsonFile(tmpDir / "reports" / s"$name.json", report)

private val needsOriginalsRoute = needsOriginalsEndpoint.implement(imagesOnly =>
(
private val needsOriginalsRoute = needsOriginalsEndpoint.implement(imagesOnlyMaybe =>
{
val imagesOnly = imagesOnlyMaybe.getOrElse(true)
val reportName = if (imagesOnly) "needsOriginals_images_only" else "needsOriginals"
for {
_ <- ZIO.logInfo(s"Checking for originals")
assetDir <- StorageService.getAssetDirectory()
Expand All @@ -46,16 +47,16 @@ object MaintenanceEndpointRoutes {
.walk(assetDir / shortcode.toString)
.mapZIOPar(8)(originalNotPresent(imagesOnly))
.filter(identity)
.as(ProjectResponse.make(shortcode))
.as(shortcode)
.runHead
)
.map(_.flatten)
.flatMap(saveReport(tmpDir, "needsOriginals", _))
.zipLeft(ZIO.logInfo(s"Created needsOriginals.json"))
.flatMap(saveReport(tmpDir, reportName, _))
.zipLeft(ZIO.logInfo(s"Created $reportName.json"))
.logError
.forkDaemon
} yield "work in progress"
).logError.mapError(ApiProblem.internalError)
}.logError.mapError(ApiProblem.internalError)
)

private def originalNotPresent(imagesOnly: Boolean)(path: file.Path): IO[IOException, Boolean] = {
Expand Down Expand Up @@ -100,7 +101,7 @@ object MaintenanceEndpointRoutes {
.mapZIOPar(8)(imageService.needsTopLeftCorrection)
.filter(identity)
.runHead
.map(_.map(_ => ProjectResponse.make(shortcode)))
.map(_.map(_ => shortcode))
)
.map(_.flatten)
.flatMap(saveReport(tmpDir, "needsTopLeftCorrection", _))
Expand Down
12 changes: 10 additions & 2 deletions src/main/scala/swiss/dasch/domain/ProjectService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@ import eu.timepit.refined.refineV
import eu.timepit.refined.string.MatchesRegex
import org.apache.commons.io.FileUtils
import zio.*
import zio.json.JsonCodec
import zio.nio.file.Files.{ isDirectory, newDirectoryStream }
import zio.nio.file.{ Files, Path }
import zio.schema.Schema
import zio.stream.ZStream

import java.io.IOException

opaque type ProjectShortcode = String Refined MatchesRegex["""^\p{XDigit}{4,4}$"""]
type IiifPrefix = ProjectShortcode

object ProjectShortcode {
def make(shortcode: String): Either[String, ProjectShortcode] = refineV(shortcode.toUpperCase)

def make(shortcodeStr: String): Either[String, ProjectShortcode] = refineV(shortcodeStr.toUpperCase)

extension (c: ProjectShortcode) { def value: String = c.toString }

given schema: Schema[ProjectShortcode] = Schema[String].transformOrFail(ProjectShortcode.make, id => Right(id.value))

given codec: JsonCodec[ProjectShortcode] = JsonCodec[String].transformOrFail(ProjectShortcode.make, _.value)
}

trait ProjectService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package swiss.dasch.api
import swiss.dasch.api.ListProjectsEndpoint.ProjectResponse
import swiss.dasch.domain.*
import swiss.dasch.test.SpecConfigurations
import swiss.dasch.test.SpecConstants.toProjectShortcode
import zio.http.{ Request, Root, Status, URL }
import zio.json.*
import zio.test.{ ZIOSpecDefault, assertTrue }
Expand All @@ -20,7 +21,7 @@ object ListProjectsEndpointSpec extends ZIOSpecDefault {
for {
response <- ListProjectsEndpoint.app.runZIO(Request.get(URL(Root / "projects")))
body <- response.body.asString
} yield assertTrue(response.status == Status.Ok, body == Chunk(ProjectResponse("0001")).toJson)
} yield assertTrue(response.status == Status.Ok, body == Chunk(ProjectResponse("0001".toProjectShortcode)).toJson)
}
).provide(
AssetInfoServiceLive.layer,
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/swiss/dasch/domain/ProjectShortcodeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ object ProjectShortcodeSpec extends ZIOSpecDefault {
val spec: Spec[TestEnvironment with Scope, Nothing] = suite("ProjectShortcodeSpec")(
test("ProjectShortcode should accept any four digit hex strings") {
check(Gen.fromZIO(randomFourDigitHexString)) { shortcode =>
assertTrue(ProjectShortcode.make(shortcode).map(_.toString) == Right(shortcode.toUpperCase()))
assertTrue(ProjectShortcode.make(shortcode).map(_.value) == Right(shortcode.toUpperCase()))
}
},
test("ProjectShortcode should not accept invalid strings") {
Expand All @@ -32,5 +32,5 @@ object ProjectShortcodeSpec extends ZIOSpecDefault {
assertTrue(ProjectShortcode.make(shortcode.toUpperCase) == ProjectShortcode.make(shortcode.toLowerCase()))
}
},
)
) @@ TestAspect.withLiveRandom
}

0 comments on commit 07233ef

Please sign in to comment.