Skip to content

Commit

Permalink
Merge branch 'main' into fix/ontology-cache
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone authored Jan 22, 2025
2 parents 09256f5 + b58e89b commit 728c5cc
Show file tree
Hide file tree
Showing 21 changed files with 526 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport {
private val testPass = SharedTestDataADM.testPass
private val projectIri = SharedTestDataADM.imagesProject.id
private val projectIriEnc = URLEncoder.encode(projectIri, "utf-8")
private val projectShortname = SharedTestDataADM.imagesProject.shortname
private val projectShortname = SharedTestDataADM.imagesProject.shortname.value
private val projectShortcode = SharedTestDataADM.imagesProject.shortcode

override lazy val rdfDataObjects: List[RdfDataObject] = List(
Expand Down Expand Up @@ -171,7 +171,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport {

// check the rest of project info
result.shortcode should be("3333")
result.shortname should be("newprojectWithIri")
result.shortname.value should be("newprojectWithIri")
result.longname should be(Some("new project with a custom IRI"))
result.keywords should be(Seq("projectIRI"))
result.description should be(Seq(StringLiteralV2.from("a project created with a custom IRI", Some("en"))))
Expand Down Expand Up @@ -229,7 +229,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport {
response.status should be(StatusCodes.OK)

val result = AkkaHttpUtils.httpResponseToJson(response).fields("project").convertTo[Project]
result.shortname should be("newproject")
result.shortname.value should be("newproject")
result.shortcode should be("1111")
result.longname should be(Some("project longname"))
result.description should be(Seq(StringLiteralV2.from(value = "project description", language = Some("en"))))
Expand Down Expand Up @@ -354,7 +354,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport {
response.status should be(StatusCodes.OK)

val result: Project = AkkaHttpUtils.httpResponseToJson(response).fields("project").convertTo[Project]
result.shortname should be("newproject")
result.shortname.value should be("newproject")
result.shortcode should be("1111")
result.longname should be(Some("updated project longname"))
result.description should be(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import org.knora.webapi.slice.admin.domain.model.Group
import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution
import org.knora.webapi.slice.admin.domain.model.KnoraProject.LicenseText
import org.knora.webapi.slice.admin.domain.model.KnoraProject.LicenseUri
import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname
import org.knora.webapi.slice.admin.domain.model.User
import org.knora.webapi.slice.common.Value.StringValue

Expand Down Expand Up @@ -216,6 +217,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol {
override val from: String => Either[String, LicenseUri] = LicenseUri.from
}

implicit object ShortnameFormat extends StringValueFormat[Shortname] {
override val from: String => Either[String, Shortname] = Shortname.from
}

implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply)

implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {

"return information about a project identified by shortname" in {
val actual = UnsafeZioRun.runOrThrow(
ProjectRestService(_.findByShortname(SharedTestDataADM.incunabulaProject.getShortname)),
ProjectRestService(_.findByShortname(SharedTestDataADM.incunabulaProject.shortname)),
)
assert(actual == ProjectGetResponse(toExternal(SharedTestDataADM.incunabulaProject)))
}
Expand Down Expand Up @@ -106,7 +106,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
"return restricted view settings using project SHORTNAME" in {
val actual = UnsafeZioRun.runOrThrow(
ProjectRestService(
_.getProjectRestrictedViewSettingsByShortname(SharedTestDataADM.imagesProject.getShortname),
_.getProjectRestrictedViewSettingsByShortname(SharedTestDataADM.imagesProject.shortname),
),
)
actual shouldEqual expectedResult
Expand Down Expand Up @@ -168,7 +168,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
),
)

received.project.shortname should be("newproject")
received.project.shortname.value should be("newproject")
received.project.shortcode should be(shortcode.toUpperCase) // upper case
received.project.longname should contain("project longname")
received.project.description should be(
Expand Down Expand Up @@ -262,7 +262,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
),
)

received.project.shortname should be("newproject2")
received.project.shortname.value should be("newproject2")
received.project.shortcode should be("1112")
received.project.longname should contain("project longname")
received.project.description should be(
Expand Down Expand Up @@ -382,7 +382,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
),
),
)
received.project.shortname should be("newproject")
received.project.shortname.value should be("newproject")
received.project.shortcode should be("111C")
received.project.longname should be(Some("updated project longname"))
received.project.description should be(
Expand Down Expand Up @@ -436,7 +436,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
"return all members of a project identified by shortname" in {
val actual = UnsafeZioRun.runOrThrow(
ProjectRestService(
_.getProjectMembersByShortname(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.getShortname),
_.getProjectMembersByShortname(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.shortname),
),
)

Expand Down Expand Up @@ -512,7 +512,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender {
ProjectRestService(
_.getProjectAdminMembersByShortname(
SharedTestDataADM.rootUser,
SharedTestDataADM.imagesProject.getShortname,
SharedTestDataADM.imagesProject.shortname,
),
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ case class ProjectInfo(
)

object ProjectInfo {
def from(projectADM: Project): ProjectInfo =
def from(project: Project): ProjectInfo =
ProjectInfo(
id = projectADM.id,
shortname = projectADM.shortname,
shortcode = projectADM.shortcode,
longname = projectADM.longname,
description = projectADM.description.headOption.map(_.value),
keywords = projectADM.keywords.headOption.map(_ => projectADM.keywords.mkString(", ")),
logo = projectADM.logo,
ontologies = projectADM.ontologies,
status = projectADM.status,
selfjoin = projectADM.selfjoin,
id = project.id,
shortname = project.shortname.value,
shortcode = project.shortcode,
longname = project.longname,
description = project.description.headOption.map(_.value),
keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")),
logo = project.logo,
ontologies = project.ontologies,
status = project.status,
selfjoin = project.selfjoin,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2
import org.knora.webapi.messages.util.KnoraSystemInstances
import org.knora.webapi.slice.admin.api.model.Project
import org.knora.webapi.slice.admin.domain.model.Group
import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname
import org.knora.webapi.slice.admin.domain.model.Permission
import org.knora.webapi.slice.admin.domain.model.User
import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo
Expand Down Expand Up @@ -155,7 +156,7 @@ object SharedTestDataADM {
/* represents the full ProjectADM of the Knora System project */
def systemProject: Project = Project(
id = KnoraProjectRepo.builtIn.SystemProject.id.value,
shortname = "SystemProject",
shortname = Shortname.unsafeFrom("SystemProject"),
shortcode = "FFFF",
longname = Some("Knora System Project"),
description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))),
Expand All @@ -174,7 +175,7 @@ object SharedTestDataADM {
/* represents the full ProjectADM of the default shared ontologies project */
def defaultSharedOntologiesProject: Project = Project(
id = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject,
shortname = "DefaultSharedOntologiesProject",
shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"),
shortcode = "0000",
longname = Some("Default Knora Shared Ontologies Project"),
description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))),
Expand Down Expand Up @@ -286,7 +287,7 @@ object SharedTestDataADM {
/* represents the full ProjectADM of the images project */
def imagesProject: Project = Project(
id = imagesProjectIri,
shortname = "images",
shortname = Shortname.unsafeFrom("images"),
shortcode = "00FF",
longname = Some("Image Collection Demo"),
description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))),
Expand All @@ -300,7 +301,7 @@ object SharedTestDataADM {
/* represents the full ProjectADM of the images project in the external format */
def imagesProjectExternal: Project = Project(
id = imagesProjectIri,
shortname = "images",
shortname = Shortname.unsafeFrom("images"),
shortcode = "00FF",
longname = Some("Image Collection Demo"),
description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))),
Expand Down Expand Up @@ -442,7 +443,7 @@ object SharedTestDataADM {
/* represents the ProjectADM of the incunabula project */
def incunabulaProject: Project = Project(
id = incunabulaProjectIri,
shortname = "incunabula",
shortname = Shortname.unsafeFrom("incunabula"),
shortcode = "0803",
longname = Some("Bilderfolgen Basler Frühdrucke"),
description = Seq(
Expand Down Expand Up @@ -477,7 +478,7 @@ object SharedTestDataADM {
/* represents the ProjectADM of the incunabula project in the external format*/
def incunabulaProjectExternal: Project = Project(
id = incunabulaProjectIri,
shortname = "incunabula",
shortname = Shortname.unsafeFrom("incunabula"),
shortcode = "0803",
longname = Some("Bilderfolgen Basler Frühdrucke"),
description = Seq(
Expand Down Expand Up @@ -610,7 +611,7 @@ object SharedTestDataADM {

def anythingProject: Project = Project(
id = anythingProjectIri,
shortname = "anything",
shortname = Shortname.unsafeFrom("anything"),
shortcode = "0001",
longname = Some("Anything Project"),
description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)),
Expand All @@ -623,7 +624,7 @@ object SharedTestDataADM {

def anythingProjectExternal: Project = Project(
id = anythingProjectIri,
shortname = "anything",
shortname = Shortname.unsafeFrom("anything"),
shortcode = "0001",
longname = Some("Anything Project"),
description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)),
Expand Down Expand Up @@ -658,7 +659,7 @@ object SharedTestDataADM {

def beolProject: Project = Project(
id = beolProjectIri,
shortname = "beol",
shortname = Shortname.unsafeFrom("beol"),
shortcode = "0801",
longname = Some("Bernoulli-Euler Online"),
description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)),
Expand Down Expand Up @@ -712,7 +713,7 @@ object SharedTestDataADM {

def dokubibProject: Project = Project(
id = dokubibProjectIri,
shortname = "dokubib",
shortname = Shortname.unsafeFrom("dokubib"),
shortcode = "0804",
longname = Some("Dokubib"),
description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,26 +443,6 @@ case class CreateClassRequestV2(
requestingUser: User,
) extends OntologiesResponderRequestV2

/**
* Constructs instances of [[CreateClassRequestV2]] based on JSON-LD requests.
*/
object CreateClassRequestV2 {

/**
* Converts a JSON-LD request to a [[CreateClassRequestV2]].
*
* @param document the JSON-LD input.
* @param apiRequestID the UUID of the API request.
* @param requestingUser the user making the request.
* @return a [[CreateClassRequestV2]] representing the input.
*/
def fromJsonLd(document: JsonLDDocument, apiRequestID: UUID, requestingUser: User): CreateClassRequestV2 = {
val inputOntologiesV2 = InputOntologyV2.fromJsonLD(document)
val updateInfo = OntologyUpdateHelper.getClassDef(inputOntologiesV2)
CreateClassRequestV2(updateInfo.classInfoContent, updateInfo.lastModificationDate, apiRequestID, requestingUser)
}
}

/**
* Requests the addition of cardinalities to a class. A successful response will be a [[ReadOntologyV2]].
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ final case class OntologiesRouteV2()(
entity(as[String]) { jsonRequest => requestContext =>
val requestMessageTask = for {
requestingUser <- ZIO.serviceWithZIO[Authenticator](_.getUserADM(requestContext))
requestDoc <- RouteUtilV2.parseJsonLd(jsonRequest)
apiRequestId <- RouteUtilZ.randomUuid()
requestMessage <- ZIO.attempt(CreateClassRequestV2.fromJsonLd(requestDoc, apiRequestId, requestingUser))
requestMessage <- requestParser(_.createClassRequestV2(jsonRequest, apiRequestId, requestingUser))
.mapError(BadRequestException.apply)
} yield requestMessage
RouteUtilV2.runRdfRouteZ(requestMessageTask, requestContext)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupName
import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin
import org.knora.webapi.slice.admin.domain.model.GroupStatus
import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri
import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname
import org.knora.webapi.slice.admin.domain.model.User
import org.knora.webapi.slice.admin.domain.model.UserIri
import org.knora.webapi.slice.admin.domain.model.UserStatus
Expand Down Expand Up @@ -84,7 +85,7 @@ object Examples {

private val project: Project = Project(
id = ProjectExample.projectIri.value,
shortname = "example",
shortname = Shortname.unsafeFrom("example"),
shortcode = "0001",
longname = Some("Example Project"),
description = Seq(StringLiteralV2.from("An example project", Some("en"))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import zio.json.JsonCodec
import org.knora.webapi.IRI
import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM
import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2
import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortname
import org.knora.webapi.slice.admin.domain.model.KnoraProject.*
import org.knora.webapi.slice.admin.domain.model.RestrictedView
import org.knora.webapi.slice.admin.domain.model.User
Expand All @@ -31,7 +32,7 @@ import org.knora.webapi.slice.admin.domain.model.User
*/
case class Project(
id: IRI,
shortname: String,
shortname: Shortname,
shortcode: String,
longname: Option[String],
description: Seq[StringLiteralV2],
Expand All @@ -44,7 +45,6 @@ case class Project(

def projectIri: ProjectIri = ProjectIri.unsafeFrom(id)

def getShortname: Shortname = Shortname.unsafeFrom(shortname)
def getShortcode: Shortcode = Shortcode.unsafeFrom(shortcode)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ final case class ProjectService(
.map(ontologies =>
Project(
knoraProject.id.value,
knoraProject.shortname.value,
knoraProject.shortname,
knoraProject.shortcode.value,
knoraProject.longname.map(_.value),
knoraProject.description.map(_.value),
Expand All @@ -62,7 +62,7 @@ final case class ProjectService(
private def toKnoraProject(project: Project, restrictedView: RestrictedView): KnoraProject =
KnoraProject(
id = ProjectIri.unsafeFrom(project.id),
shortname = Shortname.unsafeFrom(project.shortname),
shortname = project.shortname,
shortcode = Shortcode.unsafeFrom(project.shortcode),
longname = project.longname.map(Longname.unsafeFrom),
description = NonEmptyChunk
Expand Down Expand Up @@ -95,8 +95,7 @@ object ProjectService {
*/
def projectDataNamedGraphV2(project: Project): InternalIri = {
val shortcode = Shortcode.unsafeFrom(project.shortcode)
val shortname = Shortname.unsafeFrom(project.shortname)
projectDataNamedGraphV2(shortcode, shortname)
projectDataNamedGraphV2(shortcode, project.shortname)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import org.knora.webapi.slice.admin.domain.model.UserIri
import org.knora.webapi.slice.admin.domain.service.ProjectService
import org.knora.webapi.slice.admin.domain.service.UserService
import org.knora.webapi.slice.common.KnoraIris.*
import org.knora.webapi.slice.common.KnoraIris.ResourceClassIri as KResourceClassIri
import org.knora.webapi.slice.common.KnoraIris.ResourceIri as KResourceIri
import org.knora.webapi.slice.common.jena.JenaConversions.given
import org.knora.webapi.slice.common.jena.ModelOps
Expand Down Expand Up @@ -97,8 +96,7 @@ final case class ApiComplexV2JsonLdRequestParser(
private def resourceClassIri(r: Resource): IO[String, ResourceClassIri] = ZIO
.fromOption(r.rdfsType)
.orElseFail("No root resource class IRI found")
.flatMap(converter.asSmartIri(_).mapError(_.getMessage))
.flatMap(iri => ZIO.fromEither(KResourceClassIri.fromApiV2Complex(iri)))
.flatMap(str => converter.asResourceClassIri(str))
}

def updateResourceMetadataRequestV2(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,16 @@ object KnoraIris {
Right(ResourceIri(iri, shortcode, resourceId))
else Left(s"<$iri> is not a Knora resource IRI")
}

final case class OntologyIri private (smartIri: SmartIri) extends KnoraIri
object OntologyIri {
def unsafeFrom(iri: SmartIri): OntologyIri = from(iri).fold(e => throw IllegalArgumentException(e), identity)

def fromApiV2Complex(iri: SmartIri): Either[String, OntologyIri] =
from(iri).filterOrElse(_.smartIri.isApiV2ComplexSchema, s"Not an API v2 complex IRI ${iri.toString}")

def from(iri: SmartIri): Either[String, OntologyIri] =
if iri.isKnoraOntologyIri then Right(OntologyIri(iri))
else Left(s"<$iri> is not a Knora ontology IRI")
}
}
Loading

0 comments on commit 728c5cc

Please sign in to comment.