From 5d162d316e0500050a485c2d49ccee17dc638fa3 Mon Sep 17 00:00:00 2001 From: Todd Burnside Date: Mon, 11 Dec 2023 10:06:12 -0300 Subject: [PATCH] Add ProposalAttachmentType dynamic enum. --- .../scala/lucuma/schemas/ObservationDB.scala | 64 ++++++++++--------- .../schemas/enums/ObsAttachmentType.scala | 1 - .../enums/ProposalAttachmentType.scala | 46 +++++++++++++ 3 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 model/src/main/scala/lucuma/schemas/enums/ProposalAttachmentType.scala diff --git a/lucuma-schemas/src/clue/scala/lucuma/schemas/ObservationDB.scala b/lucuma-schemas/src/clue/scala/lucuma/schemas/ObservationDB.scala index ed5834c3..d4b38008 100644 --- a/lucuma-schemas/src/clue/scala/lucuma/schemas/ObservationDB.scala +++ b/lucuma-schemas/src/clue/scala/lucuma/schemas/ObservationDB.scala @@ -20,41 +20,44 @@ import lucuma.core.math.BrightnessUnits._ trait ObservationDB { object Scalars { // Ids - type AtomId = Atom.Id - type ExecutionEventId = ExecutionEvent.Id - type GroupId = Group.Id - type ObsAttachmentId = ObsAttachment.Id - type ObservationId = Observation.Id - type ProgramId = Program.Id - type StepId = Step.Id - type DatasetId = Dataset.Id - type TargetId = Target.Id - type UserId = User.Id - type VisitId = Visit.Id + type AtomId = Atom.Id + type ExecutionEventId = ExecutionEvent.Id + type GroupId = Group.Id + type ObsAttachmentId = ObsAttachment.Id + type ObservationId = Observation.Id + type ProgramId = Program.Id + type StepId = Step.Id + type DatasetId = Dataset.Id + type TargetId = Target.Id + type UserId = User.Id + type VisitId = Visit.Id // Basic types - type BigDecimal = scala.BigDecimal - type Long = scala.Long + type BigDecimal = scala.BigDecimal + type Long = scala.Long // Formatted strings - type DatasetFilename = String - type DmsString = String - type EpochString = String - type HmsString = String + type DatasetFilename = String + type DmsString = String + type EpochString = String + type HmsString = String // Refined - type Extinction = NonNegBigDecimal // """Non-negative floating-point value.""" - type NonEmptyString = eu.timepit.refined.types.string.NonEmptyString - type NonNegBigDecimal = eu.timepit.refined.types.numeric.NonNegBigDecimal - type NonNegInt = eu.timepit.refined.types.numeric.NonNegInt - type NonNegLong = eu.timepit.refined.types.numeric.NonNegLong - type NonNegShort = eu.timepit.refined.types.numeric.NonNegShort - type PosBigDecimal = eu.timepit.refined.types.numeric.PosBigDecimal - type PosInt = eu.timepit.refined.types.numeric.PosInt - type PosLong = eu.timepit.refined.types.numeric.PosLong - type PosShort = eu.timepit.refined.types.numeric.PosShort + type Extinction = NonNegBigDecimal // """Non-negative floating-point value.""" + type NonEmptyString = eu.timepit.refined.types.string.NonEmptyString + type NonNegBigDecimal = eu.timepit.refined.types.numeric.NonNegBigDecimal + type NonNegInt = eu.timepit.refined.types.numeric.NonNegInt + type NonNegLong = eu.timepit.refined.types.numeric.NonNegLong + type NonNegShort = eu.timepit.refined.types.numeric.NonNegShort + type PosBigDecimal = eu.timepit.refined.types.numeric.PosBigDecimal + type PosInt = eu.timepit.refined.types.numeric.PosInt + type PosLong = eu.timepit.refined.types.numeric.PosLong + type PosShort = eu.timepit.refined.types.numeric.PosShort // Core Types - type SignalToNoise = lucuma.core.math.SignalToNoise - type Timestamp = lucuma.core.util.Timestamp + type SignalToNoise = lucuma.core.math.SignalToNoise + type Timestamp = lucuma.core.util.Timestamp // Enum Meta - type ObsAttachmentTypeMeta = lucuma.schemas.enums.ObsAttachmentType + // These mappings cannot be used, because the decoder is for the + // Enumerated instances, but this prevents a spurious codec from being generated. + type ObsAttachmentTypeMeta = lucuma.schemas.enums.ObsAttachmentType + type ProposalAttachmentTypeMeta = lucuma.schemas.enums.ProposalAttachmentType } object Enums { @@ -113,6 +116,7 @@ trait ObservationDB { type Partner = model.Partner type PlanetSpectrum = enums.PlanetSpectrum type PlanetaryNebulaSpectrum = enums.PlanetaryNebulaSpectrum + type ProposalAttachmentType = lucuma.schemas.enums.ProposalAttachmentType type QuasarSpectrum = enums.QuasarSpectrum type ScienceMode = enums.ScienceMode type SequenceCommand = enums.SequenceCommand diff --git a/model/src/main/scala/lucuma/schemas/enums/ObsAttachmentType.scala b/model/src/main/scala/lucuma/schemas/enums/ObsAttachmentType.scala index a48d2c71..542c8a0a 100644 --- a/model/src/main/scala/lucuma/schemas/enums/ObsAttachmentType.scala +++ b/model/src/main/scala/lucuma/schemas/enums/ObsAttachmentType.scala @@ -7,7 +7,6 @@ import cats.Eq import cats.derived.* import io.circe.* import io.circe.generic.semiauto -import io.circe.generic.semiauto.* import lucuma.core.util.Display import lucuma.core.util.Enumerated import lucuma.core.util.NewType diff --git a/model/src/main/scala/lucuma/schemas/enums/ProposalAttachmentType.scala b/model/src/main/scala/lucuma/schemas/enums/ProposalAttachmentType.scala new file mode 100644 index 00000000..1e18a628 --- /dev/null +++ b/model/src/main/scala/lucuma/schemas/enums/ProposalAttachmentType.scala @@ -0,0 +1,46 @@ +// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA) +// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause + +package lucuma.schemas.enums + +import cats.Eq +import cats.derived.* +import io.circe.* +import io.circe.generic.semiauto +import lucuma.core.util.Display +import lucuma.core.util.Enumerated +import monocle.Focus +import monocle.Lens + +case class ProposalAttachmentType( + tag: String, + shortName: String, + longName: String +) derives Eq: + val accept: String = ".pdf" // only PDF files are currently allowed + +object ProposalAttachmentType: + given Display[ProposalAttachmentType] = Display.by(_.shortName, _.longName) + + val tag: Lens[ProposalAttachmentType, String] = Focus[ProposalAttachmentType](_.tag) + val shortName: Lens[ProposalAttachmentType, String] = Focus[ProposalAttachmentType](_.shortName) + val longName: Lens[ProposalAttachmentType, String] = Focus[ProposalAttachmentType](_.longName) + + val values: List[ProposalAttachmentType] = + // This is a meta decoder, not a decoder for enum instances (which comes from the `Enumerated` instance) + given Decoder[ProposalAttachmentType] = semiauto.deriveDecoder + + DynamicEnums.parsedEnums + .downField("proposalAttachmentTypeMeta") + .as[List[ProposalAttachmentType]] match + case Left(err) => err.printStackTrace; throw err + case Right(json) => json + + // The givens are apparently (probably) constructed lazily. + // See https://alexn.org/blog/2022/05/11/implicit-vs-scala-3-given/ + // We want to fail immediately if there is a problem, so we'll reference + // the enumerated givens here. + Enumerated[ProposalAttachmentType] + + given Enumerated[ProposalAttachmentType] = + Enumerated.from(values.head, values.tail: _*).withTag(_.tag)