json.scala 6.09 KB
Newer Older
Jens Korinth's avatar
Jens Korinth committed
1
2
package de.tu_darmstadt.cs.esa.tapasco.tapasco_status
import  de.tu_darmstadt.cs.esa.tapasco.Implicits._
3
import  Slot._
Jens Korinth's avatar
Jens Korinth committed
4
import  play.api.libs.json._
5
import  play.api.libs.json.Reads._
Jens Korinth's avatar
Jens Korinth committed
6
7
8
9
10
11
12
13
import  play.api.libs.functional.syntax._

package object json {
  implicit object SlotIdFormats extends Format[SlotId] {
    def reads(json: JsValue): JsResult[SlotId] = json match {
      case JsNumber(n) => JsSuccess(SlotId(n.toInt))
      case _           => JsError(Seq(JsPath() -> Seq(JsonValidationError("validation.error.expected.jsnumber"))))
    }
14
    def writes(id: SlotId): JsValue = Json.toJson(id: Int)
Jens Korinth's avatar
Jens Korinth committed
15
16
17
18
19
20
21
  }

  implicit object KernelIdFormats extends Format[KernelId] {
    def reads(json: JsValue): JsResult[KernelId] = json match {
      case JsNumber(n) => JsSuccess(KernelId(n.toInt))
      case _           => JsError(Seq(JsPath() -> Seq(JsonValidationError("validation.error.expected.jsnumber"))))
    }
22
    def writes(id: KernelId): JsValue = Json.toJson(id: Int)
Jens Korinth's avatar
Jens Korinth committed
23
24
25
26
27
28
29
  }

  implicit object SizeFormats extends Format[Size] {
    def reads(json: JsValue): JsResult[Size] = json match {
      case JsNumber(n) => JsSuccess(Size(n.toInt))
      case _           => JsError(Seq(JsPath() -> Seq(JsonValidationError("validation.error.expected.jsnumber"))))
    }
30
    def writes(sz: Size): JsValue = Json.toJson(sz: Int)
Jens Korinth's avatar
Jens Korinth committed
31
32
  }

33
  implicit val kernelWrites: Writes[Kernel] = (
Jens Korinth's avatar
Jens Korinth committed
34
35
36
37
38
    (JsPath \ "Type").write[String] ~
    (JsPath \ "SlotId").write[SlotId] ~
    (JsPath \ "Kernel").write[KernelId]
  ) (unlift(Kernel.unapply _ andThen (_ map ("Kernel" +: _))))

39
40
41
42
43
44
45
  val kernelReads: Reads[Slot] = (
    (JsPath \ "Type").read[String] (verifying[String](_.toLowerCase equals "kernel")) ~>
    (JsPath \ "SlotId").read[SlotId] ~
    (JsPath \ "Kernel").read[KernelId]
  ) (Kernel.apply _)

  implicit val memoryWrites: Writes[Memory] = (
Jens Korinth's avatar
Jens Korinth committed
46
47
    (JsPath \ "Type").write[String] ~
    (JsPath \ "SlotId").write[SlotId] ~
48
    (JsPath \ "Bytes").write[Size]
Jens Korinth's avatar
Jens Korinth committed
49
  ) (unlift(Memory.unapply _ andThen (_ map ("Memory" +: _))))
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

  val memoryReads: Reads[Slot] = (
    (JsPath \ "Type").read[String] (verifying[String](_.toLowerCase equals "memory")) ~>
    (JsPath \ "SlotId").read[SlotId] ~
    (JsPath \ "Bytes").read[Size]
  ) (Memory.apply _)

  implicit val slotReads: Reads[Slot] = kernelReads | memoryReads

  implicit object SlotWrites extends Writes[Slot] {
    def writes(c: Slot): JsValue = c match {
      case k: Kernel => kernelWrites.writes(k)
      case m: Memory => memoryWrites.writes(m)
    }
  }

  implicit val versionWrites: Writes[Versions.Version] = (
    (JsPath \ "Software").write[String] ~
    (JsPath \ "Year").write[Int] ~
    (JsPath \ "Release").write[Int]
  ) (_.unapply)

  val tapascoVersionReads: Reads[Versions.Version] = (
    (JsPath \ "Software").read[String] (verifying[String](_.toLowerCase contains "tapasco")) ~>
    (JsPath \ "Year").read[Int] ~
    (JsPath \ "Release").read[Int]
  ) (Versions.Tapasco.apply _)

  val vivadoVersionReads: Reads[Versions.Version] = (
    (JsPath \ "Software").read[String] (verifying[String](_.toLowerCase contains "vivado")) ~>
    (JsPath \ "Year").read[Int] ~
    (JsPath \ "Release").read[Int]
  ) (Versions.Vivado.apply _)

  implicit val versionReads: Reads[Versions.Version] = tapascoVersionReads | vivadoVersionReads

  implicit object VersionsFormat extends Format[Versions] {
    private def tapascoVersion(vs: Seq[Versions.Version]): Versions.Tapasco = vs match {
      case t +: tt => t match {
        case v: Versions.Tapasco => v
        case _ => tapascoVersion(tt)
      }
      case _ => throw new IllegalArgumentException("TaPaSCo version not found in JSON")
    }

    private def vivadoVersion(vs: Seq[Versions.Version]): Versions.Vivado = vs match {
      case t +: tt => t match {
        case v: Versions.Vivado => v
        case _ => vivadoVersion(tt)
      }
      case _ => throw new IllegalArgumentException("Vivado version not found in JSON")
    }

    def reads(json: JsValue): JsResult[Versions] = json match {
      case vs: JsArray => Json.fromJson[Seq[Versions.Version]](vs) map (vs => Versions(tapascoVersion(vs), vivadoVersion(vs)))
      case _           => JsError(Seq(JsPath() -> Seq(JsonValidationError("validation.error.expected.jsarray"))))
    }
    def writes(v: Versions): JsValue = Json.toJson(Seq(v.vivado, v.tapasco))
  }

  implicit val freqWrites: Writes[Clocks.Frequency] = (
    (JsPath \ "Domain").write[String] ~
    (JsPath \ "Frequency").write[Double]
  ) (_.unapply)

  val hostFreqReads: Reads[Clocks.Frequency] = (
    (JsPath \ "Domain").read[String] (verifying[String](_.toLowerCase equals "host")) ~>
    (JsPath \ "Frequency").read[Double]
  ) fmap (Clocks.HostFreq.apply _)

  val designFreqReads: Reads[Clocks.Frequency] = (
    (JsPath \ "Domain").read[String] (verifying[String](_.toLowerCase equals "design")) ~>
    (JsPath \ "Frequency").read[Double]
  ) fmap (Clocks.DesignFreq.apply _)

  val memFreqReads: Reads[Clocks.Frequency] = (
    (JsPath \ "Domain").read[String] (verifying[String](_.toLowerCase equals "memory")) ~>
    (JsPath \ "Frequency").read[Double]
  ) fmap (Clocks.MemFreq.apply _)

  implicit val freqReads: Reads[Clocks.Frequency] = hostFreqReads | designFreqReads | memFreqReads

  implicit object ClocksFormat extends Format[Clocks] {
    def reads(json: JsValue): JsResult[Clocks] = json match {
      case cs: JsArray => Json.fromJson[Seq[Clocks.Frequency]](cs) map ((clocks: Seq[Clocks.Frequency]) => for {
        hf <- (clocks collectFirst { case h: Clocks.HostFreq => h })
        df <- (clocks collectFirst { case d: Clocks.DesignFreq => d })
        mf <- (clocks collectFirst { case m: Clocks.MemFreq => m })
      } yield Clocks(hf, df, mf)) map (_.get)
      case _           => JsError(Seq(JsPath() -> Seq(JsonValidationError("validation.error.expected.jsarray"))))
    }
    def writes(c: Clocks): JsValue = Json.toJson(Seq(c.host, c.design, c.memory))
  }

  implicit val statusFormat: Format[Status] = (
    (JsPath \ "Composition").format[Seq[Slot]] ~
    (JsPath \ "Timestamp").format[Int] ~
    (JsPath \ "Interrupt Controllers").format[Int] ~
    (JsPath \ "Versions").format[Versions] ~
    (JsPath \ "Clocks").format[Clocks]
  ) (Status.apply _, unlift(Status.unapply _))
Jens Korinth's avatar
Jens Korinth committed
151
}