-
Notifications
You must be signed in to change notification settings - Fork 2
Suggestion: Use Seq[T] instead of Option[Seq[T]] in UploadDtos #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: jonathanthiry/l3-variables
Are you sure you want to change the base?
Changes from all commits
b95dda0
a55f960
05e8152
2e52fb4
6e4271f
8de9db9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,9 +177,11 @@ class CitationMaker( | |
| val height = acq.samplingHeight.fold("")(sh => s" ($sh m)") | ||
| val vars = | ||
| if dobj.specification.self.uri === vocab.atmGhgProdSpec then | ||
| stationTs.columns.fold("")(_.collect{ | ||
| case v if v.valueType.unit.isDefined => v.label | ||
| }.mkString(" (", ", ", ")")) | ||
| if (stationTs.columns.nonEmpty) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original code wants to produce an empty string if there is no content, and the |
||
| stationTs.columns.collect{ | ||
| case v if v.valueType.unit.isDefined => v.label | ||
| }.mkString(" (", ", ", ")") | ||
| else "" | ||
| else "" | ||
|
|
||
| s"$spec$vars from $station$height" | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -183,7 +183,7 @@ class SchemaOrg(handleProxies: HandleProxiesConfig)(using envri: Envri, envriCon | |||||
| ) | ||||||
| } | ||||||
|
|
||||||
| val variableMeasured = asOptArray(dobj.specificInfo.fold(_.variables, _.columns))( | ||||||
| val variableMeasured = asOptArray(dobj.specificInfo.fold((_.variables), _.columns))( | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JSON serialization is one case there So, even though we are changing from an
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| variable => JsObject( | ||||||
| "@type" -> JsString("PropertyValue"), | ||||||
| "name" -> JsString(variable.label), | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -272,7 +272,7 @@ trait DobjMetaReader(val vocab: CpVocab) extends CpmetaReader: | |
| case Some(interval) => | ||
| addInstrDeplInfo(stationUri, interval, columns) | ||
| columnsOptV.sinkOption.map: columnsOpt => | ||
| StationTimeSeriesMeta(acq, prod, nRows, lblCoverage, columnsOpt) | ||
| StationTimeSeriesMeta(acq, prod, nRows, lblCoverage, columnsOpt.getOrElse(Nil)) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The option value |
||
| resV.flatMap(identity) | ||
| end getStationTimeSerMeta | ||
|
|
||
|
|
@@ -325,7 +325,7 @@ trait DobjMetaReader(val vocab: CpVocab) extends CpmetaReader: | |
| station = station, | ||
| samplingHeight = samplingHeightOpt.flatten, | ||
| productionInfo = prod, | ||
| variables = Some(variables.flatten).filterNot(_.isEmpty) | ||
| variables = variables.flatten() | ||
| ) | ||
|
|
||
| def getContributors(objIri: IRI, contribPredicate: IRI)(using conn: DobjConn | DocConn): Validated[IndexedSeq[Agent]] = | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -338,14 +338,16 @@ class UploadValidator(servers: DataObjectInstanceServers): | |
| if spec.specificDatasetType != DatasetType.SpatioTemporal | ||
| then errors += "Wrong type of dataset for this object spec (must be spatiotemporal)" | ||
| else | ||
| for vars <- spTempMeta.variables do spec.datasetSpec.fold( | ||
| errors += s"Data object specification ${spec.self.uri} lacks a dataset specification; cannot accept variable info." | ||
| ): dsSpec => | ||
| val valTypeLookupV = metaReader.getValTypeLookup(dsSpec.self.uri.toRdf) | ||
| errors ++= valTypeLookupV.errors | ||
| for valTypeLookup <- valTypeLookupV; varName <- vars do | ||
| if valTypeLookup.lookup(varName).isEmpty then errors += | ||
| s"Variable name '$varName' is not compatible with dataset specification ${dsSpec.self.uri}" | ||
| if (spTempMeta.variables.nonEmpty) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not entirely sure if this empty check is necessary, but including it assures we are keeping existing behaviour. |
||
| spec.datasetSpec.fold( | ||
| errors += s"Data object specification ${spec.self.uri} lacks a dataset specification; cannot accept variable info." | ||
| ): dsSpec => | ||
| val valTypeLookupV = metaReader.getValTypeLookup(dsSpec.self.uri.toRdf) | ||
| errors ++= valTypeLookupV.errors | ||
| for valTypeLookup <- valTypeLookupV; varName <- spTempMeta.variables do | ||
| if valTypeLookup.lookup(varName).isEmpty then errors += | ||
| s"Variable name '$varName' is not compatible with dataset specification ${dsSpec.self.uri}" | ||
| } | ||
|
|
||
| case Right(stationMeta) => | ||
| if spec.specificDatasetType != DatasetType.StationTimeSeries | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -133,7 +133,7 @@ <h2 class="fs-3 mt-5">Production</h2> | |
|
|
||
| <br> | ||
|
|
||
| @for(variables <- varMetas){ | ||
| @if(varMetas.nonEmpty){ | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserving original behaviour, so we do not show any preview if there are no items. There is a slight difference here from previous behaviour, which I argue is actually a bug-fix. |
||
| <h2 class="fs-3 mt-5">Previewable variables</h2> | ||
| <div class="col-md-12 overflow-auto"> | ||
| <table class="table"> | ||
|
|
@@ -155,7 +155,7 @@ <h2 class="fs-3 mt-5">Previewable variables</h2> | |
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| @for(varInfo <- variables){ | ||
| @for(varInfo <- varMetas){ | ||
| <tr> | ||
| <td>@(varInfo.label)</td> | ||
| <td>@(varInfo.valueType.self.label.getOrElse(""))</td> | ||
|
|
@@ -402,7 +402,7 @@ <h2 class="fs-3 mt-5">Technical information</h2> | |
| } | ||
|
|
||
| @instrumentDeploymentsPresent = @{ | ||
| varMetas.exists(_.exists(_.instrumentDeployments.isDefined)) | ||
| varMetas.exists(_.instrumentDeployments.isDefined) | ||
| } | ||
|
|
||
| @moratoriumText = @{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,18 +96,18 @@ object Backend { | |
| sparqlSelect(datasetVariableQuery(dataset)).map(_.map(toDatasetVar)) | ||
|
|
||
| def tryIngestion( | ||
| file: File, spec: ObjSpec, nRows: Option[Int], varnames: Option[Seq[String]] | ||
| file: File, spec: ObjSpec, nRows: Option[Int], varnames: Seq[String] | ||
| )(implicit envriConfig: EnvriConfig): Future[Unit] = { | ||
|
|
||
| val hasVars: Boolean = varnames.flatMap(_.headOption).isDefined | ||
| val hasVars = varnames.nonEmpty | ||
|
|
||
| if (spec.dataset.isDefined && (spec.isStationTimeSer || hasVars)) || spec.isZip || spec.isNetCDF then | ||
|
|
||
| val nRowsQ = nRows.fold("")(nr => s"&nRows=$nr") | ||
| val varsQ = varnames.fold(""){vns => | ||
| val varsJson = encodeURIComponent(Json.toJson(vns).toString) | ||
| val varsQ = if (varnames.nonEmpty) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Emptiness check to make sure we produce empty string instead of |
||
| val varsJson = encodeURIComponent(Json.toJson(varnames).toString) | ||
| s"&varnames=$varsJson" | ||
| } | ||
| } else { "" } | ||
|
|
||
| val url = s"https://${envriConfig.dataHost}/tryingest?specUri=${spec.uri}$nRowsQ$varsQ" | ||
| fetchOk("validate data object", url, new RequestInit{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,19 +10,17 @@ class L3VarInfoForm(elemId: String, notifyUpdate: () => Unit) { | |
|
|
||
| var list: IndexedSeq[DatasetVar] = IndexedSeq.empty | ||
|
|
||
| def values: Try[Option[Seq[DatasetVar]]] = if(elems.isEmpty) Success(None) else Try{ | ||
| Some(elems.map(_.varInfo.get).toIndexedSeq) | ||
| def values: Try[Seq[DatasetVar]] = if(elems.isEmpty) Success(Nil) else Try{ | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we clearly see that there is no semantic change from our perspective between Option and Seq, since we are explicitly turning the empty case into a |
||
| elems.map(_.varInfo.get).toIndexedSeq | ||
| } | ||
|
|
||
| def setValues(vars: Option[Seq[DatasetVar]]): Unit = { | ||
| def setValues(vars: Seq[DatasetVar]): Unit = { | ||
| elems.foreach(_.remove()) | ||
| elems.clear() | ||
| vars.foreach{vdtos => | ||
| vdtos.foreach{vdto => | ||
| val input = new L3VarInfoInput | ||
| input.setValue(vdto) | ||
| elems.append(input) | ||
| } | ||
| vars.foreach{vdto => | ||
| val input = new L3VarInfoInput | ||
| input.setValue(vdto) | ||
| elems.append(input) | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,10 +38,10 @@ class SpatioTemporalPanel(covs: IndexedSeq[SpatialCoverage])(implicit bus: PubSu | |
| samplingHeight = height, | ||
| production = prod, | ||
| customLandingPage = customLanding, | ||
| variables = varInfo.map(_.map(_.uri.toString.split('/').last)) | ||
| variables = varInfo.map(_.uri.toString.split('/').last) | ||
| ) | ||
|
|
||
| def varnames: Try[Option[Seq[String]]] = varInfoForm.values.map(_.map(_.map(_.title))) | ||
| def varnames: Try[Seq[String]] = varInfoForm.values.map(_.map(_.title)) | ||
|
|
||
| private val titleInput = new TextInput("l3title", notifyUpdate, "elaborated product title") | ||
| private val descriptionInput = new DescriptionInput("l3descr", notifyUpdate) | ||
|
|
@@ -55,14 +55,14 @@ class SpatioTemporalPanel(covs: IndexedSeq[SpatialCoverage])(implicit bus: PubSu | |
| private val varInfoForm = new L3VarInfoForm("l3varinfo-form", notifyUpdate) | ||
| private val externalPageInput = new UriOptInput("l3landingpage", notifyUpdate) | ||
| private var datasetSpec: Option[URI] = None | ||
| private var selsectedVars: Option[Seq[String]] = None | ||
| private var selsectedVars: Seq[String] = Nil | ||
|
|
||
| def resetForm(): Unit = { | ||
| Iterable( | ||
| titleInput, descriptionInput, timeStartInput, timeStopInput, | ||
| temporalResInput, externalPageInput | ||
| ).foreach(_.reset()) | ||
| varInfoForm.setValues(None) | ||
| varInfoForm.setValues(Nil) | ||
| spatialCovSelect.resetForm() | ||
| } | ||
|
|
||
|
|
@@ -76,9 +76,8 @@ class SpatioTemporalPanel(covs: IndexedSeq[SpatialCoverage])(implicit bus: PubSu | |
| case GotStationsList(stations) => stationSelect.setOptions(stations) | ||
| case GotVariableList(variables) => | ||
| varInfoForm.list = variables | ||
| selsectedVars.map { variables => | ||
| varInfoForm.setValues(Some(variables.flatMap(uri => varInfoForm.list.find(_.uri.toString.split('/').last == uri)))) | ||
| } | ||
| varInfoForm.setValues(selsectedVars.flatMap(uri => | ||
| varInfoForm.list.find(_.uri.toString.split('/').last == uri))) | ||
|
|
||
| } | ||
|
|
||
|
|
@@ -98,14 +97,19 @@ class SpatioTemporalPanel(covs: IndexedSeq[SpatialCoverage])(implicit bus: PubSu | |
| samplingHeightInput.value = spatTemp.samplingHeight | ||
| externalPageInput.value = spatTemp.customLandingPage | ||
| selsectedVars = spatTemp.variables | ||
| spatTemp.variables.map { varUris => | ||
| datasetSpec.map { dataset => | ||
| whenDone(getVariables(dataset)) { variables => | ||
| varInfoForm.list = variables | ||
| varInfoForm.setValues(Some(varUris.flatMap(uri => varInfoForm.list.find(_.uri.toString.split('/').last == uri)))) | ||
| if (selsectedVars.nonEmpty) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This block can be unindented. The |
||
| datasetSpec match { | ||
| case None => () | ||
| case Some(dataset) => { | ||
| whenDone(getVariables(dataset)) { variables => | ||
| varInfoForm.list = variables | ||
| varInfoForm.setValues(selsectedVars.flatMap(uri => | ||
| varInfoForm.list.find(_.uri.toString.split('/').last == uri) | ||
| )) | ||
| } | ||
| } | ||
|
Comment on lines
+100
to
+110
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another |
||
| } | ||
| } | ||
| } | ||
| spatialCovSelect.handleReceivedSpatialCoverage(Some(spatTemp.spatial)) | ||
| show() | ||
| case _ => | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note, but this usage of
Either.toOptionis why I don't really like theEithertype in general. It signifies that one value (theLeftone) is more important or correct than the other one. So, in that sense it is essentially an "Option with an error message".But, our usage of it here does not actually carry that meaning.
So, I would prefer a compound type like
SpatioTemporalMeta | StationTimeSeriesMetainstead, and that the uses ofEither.foldbe replaced by just pattern matches.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like it could be a nice improvement. I cannot think of a reason why we are using Either other than union types didn't exist when this code was written.