Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ class UploadService(
}.toSeq.sortBy(sp => sp.id)

def completeUpload(hash: Sha256Sum, info: UploadCompletionInfo)(using Envri): Future[Report] =
uploadLock.wrapFuture(hash):
completer.completeUpload(hash, info)
Future.fromTry(validator.validatePreviousTemporalCoverage(hash, info)).flatMap: _ =>
uploadLock.wrapFuture(hash):
completer.completeUpload(hash, info)

end UploadService

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import java.net.URI
import java.time.Instant
import scala.language.strictEquality
import scala.util.{Success, Try}
import se.lu.nateko.cp.meta.core.data.UploadCompletionInfo
import se.lu.nateko.cp.meta.core.data.TimeSeriesExtract
import se.lu.nateko.cp.meta.core.data.SpatialTimeSeriesExtract
import se.lu.nateko.cp.meta.core.data.TabularIngestionExtract

private class ScopedValidator(vocab: CpVocab, val metaVocab: CpmetaVocab) extends CpmetaReader:

Expand Down Expand Up @@ -132,9 +136,9 @@ private class ScopedValidator(vocab: CpVocab, val metaVocab: CpmetaVocab) extend
.toIndexedSeq
.nonEmpty

def compareToPreviousTemporalCoverage(dto: DataObjectDto)(using Envri, DocConn | DobjConn): Try[NotUsed] =
def compareToPreviousTemporalCoverage(dto: DataObjectDto)(using Envri, DobjConn): Try[NotUsed] =

val newIntervalIncludesPrevious = for
val compareInterval = for
dataDto <- dto.asOptInstanceOf[DataObjectDto]
timeSeries <- dataDto.specificInfo.fold(_ => None, ts => Some(ts))
newTimeInterval <- timeSeries.acquisitionInterval
Expand All @@ -146,17 +150,47 @@ private class ScopedValidator(vocab: CpVocab, val metaVocab: CpmetaVocab) extend
.toIndexedSeq
allAquiredByIris = (autoDeprecateIris ++ selectedDeprecateIris).toSet
.flatMap(getSingleUri(_, metaVocab.wasAcquiredBy).result)
previousStarts = allAquiredByIris.flatMap(getSingleInstant(_, metaVocab.prov.startedAtTime).result)
previousStops = allAquiredByIris.flatMap(getSingleInstant(_, metaVocab.prov.endedAtTime).result)
.toIndexedSeq

yield
(previousStarts.isEmpty || !newTimeInterval.start.isAfter(previousStarts.min))
&& (previousStops.isEmpty || !newTimeInterval.stop.isBefore(previousStops.max))
compareToPreviousInterval(allAquiredByIris, newTimeInterval)

if newIntervalIncludesPrevious.getOrElse(true) then ok
else userFail("New temporal coverage must include temporal coverage of the objects being deprecated.")
compareInterval.getOrElse(ok)

end compareToPreviousTemporalCoverage

def compareToPreviousTemporalCoverageByIri(iri: IRI, info: UploadCompletionInfo)(using Envri, DobjConn): Try[NotUsed] =

val compareInterval = for
tabularExtract <- info.ingestionResult match
case Some(timeSeries: TimeSeriesExtract) => Some(timeSeries.tabular)
case Some(spatialTimeSeries: SpatialTimeSeriesExtract) => Some(spatialTimeSeries.tabular)
case Some(tabularIngestion: TabularIngestionExtract) => Some(tabularIngestion)
case _ => None
newTimeInterval = tabularExtract.interval
aquiredBy <- getSingleUri(iri, metaVocab.wasAcquiredBy).result
selectedDeprecateIris = getUriValues(iri, metaVocab.isNextVersionOf)
.toIndexedSeq
.flatMap(getSingleUri(_, metaVocab.wasAcquiredBy).result)
yield
compareToPreviousInterval(selectedDeprecateIris, newTimeInterval)

compareInterval.getOrElse(ok)

end compareToPreviousTemporalCoverageByIri

private def compareToPreviousInterval(allAquiredByIris: Seq[IRI], newTimeInterval: TimeInterval)(using Envri, DobjConn): Try[NotUsed] =
val previousStarts = allAquiredByIris.flatMap(getSingleInstant(_, metaVocab.prov.startedAtTime).result)
val previousStops = allAquiredByIris.flatMap(getSingleInstant(_, metaVocab.prov.endedAtTime).result)

val newIntervalIncludesPrevious = (previousStarts.isEmpty || !newTimeInterval.start.isAfter(previousStarts.min))
&& (previousStops.isEmpty || !newTimeInterval.stop.isBefore(previousStops.max))

if newIntervalIncludesPrevious then ok
else userFail("New temporal coverage must include temporal coverage of the objects being deprecated.")

end compareToPreviousInterval


def growingIsGrowing(
dto: ObjectUploadDto,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.time.Instant
import scala.collection.mutable.Buffer
import scala.language.strictEquality
import scala.util.{Failure, Success, Try}
import se.lu.nateko.cp.meta.core.data.UploadCompletionInfo

given CanEqual[URI, URI] = CanEqual.derived
given CanEqual[IRI, IRI] = CanEqual.derived
Expand All @@ -45,6 +46,17 @@ class UploadValidator(servers: DataObjectInstanceServers):
case doc: DocObjectDto => validateDoc(doc, uploader)
yield dto

def validatePreviousTemporalCoverage(hash: Sha256Sum, info: UploadCompletionInfo)(using envri: Envri): Try[NotUsed] =
val objIri = vocab.getStaticObject(hash)
val validation = servers.vanillaGlobal.access:
for
given DobjConn <- metaReader.getLensForDataObj(objIri)(using envri, RdfLens.global)
yield
scoped.compareToPreviousTemporalCoverageByIri(objIri, info)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we always want to do this or does it depend on the type of the object for example?

validation.toTry(new UploadUserErrorException(_)).flatten

end validatePreviousTemporalCoverage


private def validateDobj(meta: DataObjectDto, uploader: UserId)(using Envri, DocConn): Try[DataObjectDto] =
for
Expand Down