1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.core
21 
22 import java.time.{LocalDate, ZonedDateTime}
23 import java.util.UUID
24 
25 import cats.data.NonEmptyList
26 import com.sksamuel.elastic4s.requests.searches.sort.SortOrder
27 import enumeratum.values.{StringEnum, StringEnumEntry}
28 import spray.json._
29 
30 @SuppressWarnings(Array("org.wartremover.warts.Throw"))
31 trait SprayJsonFormatters {
32 
33   implicit val localDateFormatter: JsonFormat[LocalDate] = new JsonFormat[LocalDate] {
34     override def read(json: JsValue): LocalDate = json match {
35       case JsString(s) => LocalDate.parse(s)
36       case other       => throw new IllegalArgumentException(s"Unable to convert $other")
37     }
38 
39     override def write(obj: LocalDate): JsValue = {
40       JsString(obj.toString)
41     }
42   }
43 
44   implicit val zonedDateTimeFormatter: JsonFormat[ZonedDateTime] = new JsonFormat[ZonedDateTime] {
45     override def read(json: JsValue): ZonedDateTime = json match {
46       case JsString(s) => ZonedDateTime.parse(s)
47       case other       => throw new IllegalArgumentException(s"Unable to convert $other")
48     }
49 
50     override def write(obj: ZonedDateTime): JsValue = {
51       JsString(obj.toString)
52     }
53   }
54 
55   implicit val uuidFormatter: JsonFormat[UUID] = new JsonFormat[UUID] {
56     override def read(json: JsValue): UUID = json match {
57       case JsString(s) => UUID.fromString(s)
58       case other       => throw new IllegalArgumentException(s"Unable to convert $other")
59     }
60 
61     override def write(obj: UUID): JsValue = {
62       JsString(obj.toString)
63     }
64   }
65 
66   implicit val sortOrderFormatted: JsonFormat[SortOrder] = new JsonFormat[SortOrder] {
67     override def read(json: JsValue): SortOrder = json match {
68       case JsString(asc) if asc.toLowerCase == "asc"    => SortOrder.Asc
69       case JsString(desc) if desc.toLowerCase == "desc" => SortOrder.Desc
70       case other                                        => throw new IllegalArgumentException(s"Unable to convert $other")
71     }
72 
73     override def write(obj: SortOrder): JsValue = {
74       obj match {
75         case SortOrder.Asc  => JsString("asc")
76         case SortOrder.Desc => JsString("desc")
77       }
78     }
79   }
80 
81   implicit def stringEnumFormatter[A <: StringEnumEntry](implicit stringEnum: StringEnum[A]): JsonFormat[A] =
82     new JsonFormat[A] {
83       override def read(json: JsValue): A = json match {
84         case JsString(s) =>
85           stringEnum.withValueOpt(s).getOrElse(throw new IllegalArgumentException(s"Unable to convert $s"))
86         case other => throw new IllegalArgumentException(s"Unable to convert $other")
87       }
88 
89       override def write(a: A): JsValue = JsString(a.value)
90     }
91 
92 }
93 
94 object SprayJsonFormatters extends SprayJsonFormatters {
95 
96   def forStringValue[T <: StringValue](f: String => T): JsonFormat[T] = new JsonFormat[T] {
97     @SuppressWarnings(Array("org.wartremover.warts.Throw"))
98     override def read(json: JsValue): T = json match {
99       case JsString(s) => f(s)
100       case other       => throw new IllegalArgumentException(s"Unable to convert $other")
101     }
102 
103     override def write(obj: T): JsValue = {
104       JsString(obj.value)
105     }
106   }
107 
108   implicit def nonEmptyListFormat[T](implicit f: JsonFormat[T]): JsonFormat[NonEmptyList[T]] =
109     new JsonFormat[NonEmptyList[T]] {
110 
111       @SuppressWarnings(Array("org.wartremover.warts.Throw"))
112       override def read(json: JsValue): NonEmptyList[T] =
113         json match {
114           case JsArray(vec) =>
115             NonEmptyList.fromFoldable(vec) match {
116               case None      => throw new IllegalArgumentException(s"Array was empty")
117               case Some(nel) => nel.map(_.convertTo[T])
118             }
119           case other => throw new IllegalArgumentException(s"Unable to decode $other")
120         }
121 
122       override def write(obj: NonEmptyList[T]): JsValue =
123         JsArray(obj.map(f.write).toList.toVector)
124     }
125 
126   object syntax {
127 
128     implicit class JsFieldSyntax(val key: String) extends AnyVal {
129       def :=[A: JsonWriter](a: A): JsField = key -> a.toJson
130     }
131 
132     implicit class JsonReaderSyntax(val json: JsValue) extends AnyVal {
133       def as[A](implicit reader: JsonReader[A]): A = reader.read(json)
134     }
135 
136   }
137 
138 }
Line Stmt Id Pos Tree Symbol Tests Code
33 5440 1148 - 1151 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,akka.http.scaladsl.testkit.routetest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.user.persistentuserservicecomponenttest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
35 2009 1265 - 1283 Apply java.time.LocalDate.parse java.time.LocalDate.parse(s)
36 5037 1310 - 1373 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
40 2078 1439 - 1461 Apply spray.json.JsString.apply spray.json.JsString.apply(obj.toString())
40 3070 1448 - 1460 Apply java.time.LocalDate.toString obj.toString()
44 2017 1540 - 1543 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,akka.http.scaladsl.testkit.routetest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.user.persistentuserservicecomponenttest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
46 3656 1665 - 1687 Apply java.time.ZonedDateTime.parse org.scalatest.testsuite,org.make.api.technical.crm.crmservicecomponenttest java.time.ZonedDateTime.parse(s)
47 1418 1714 - 1777 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
51 3733 1847 - 1869 Apply spray.json.JsString.apply spray.json.JsString.apply(obj.toString())
51 431 1856 - 1868 Apply java.time.ZonedDateTime.toString obj.toString()
55 3664 1930 - 1933 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,akka.http.scaladsl.testkit.routetest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.user.persistentuserservicecomponenttest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
57 5286 2037 - 2055 Apply java.util.UUID.fromString java.util.UUID.fromString(s)
58 3245 2082 - 2145 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
62 2085 2215 - 2227 Apply java.util.UUID.toString obj.toString()
62 5580 2206 - 2228 Apply spray.json.JsString.apply spray.json.JsString.apply(obj.toString())
66 5588 2299 - 2302 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,akka.http.scaladsl.testkit.routetest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.user.persistentuserservicecomponenttest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
68 1528 2418 - 2442 Apply java.lang.Object.== asc.toLowerCase().==("asc")
68 534 2449 - 2462 Select com.sksamuel.elastic4s.requests.searches.sort.SortOrder.Asc com.sksamuel.elastic4s.requests.searches.sort.SortOrder.Asc
69 1970 2522 - 2536 Select com.sksamuel.elastic4s.requests.searches.sort.SortOrder.Desc com.sksamuel.elastic4s.requests.searches.sort.SortOrder.Desc
69 3740 2492 - 2518 Apply java.lang.Object.== desc.toLowerCase().==("desc")
70 5297 2596 - 2659 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
75 3256 2768 - 2783 Apply spray.json.JsString.apply spray.json.JsString.apply("asc")
76 2192 2815 - 2831 Apply spray.json.JsString.apply spray.json.JsString.apply("desc")
82 5170 2965 - 2968 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.proposal.defaultadminproposalapicomponenttest,org.make.api.tag.tagservicetest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
85 1536 3080 - 3177 Apply scala.Option.getOrElse org.make.api.proposal.proposalstatetest,org.make.api.technical.crm.crmservicecomponenttest stringEnum.withValueOpt(s).getOrElse[A](throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(s): String)))
85 3608 3117 - 3176 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(s): String))
86 4907 3200 - 3263 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
89 1979 3315 - 3332 Apply spray.json.JsString.apply spray.json.JsString.apply(a.value)
89 3721 3324 - 3331 Select enumeratum.values.ValueEnumEntry.value a.value
96 1544 3473 - 3476 Apply org.make.core.SprayJsonFormatters.$anon.<init> org.make.api.avro.avrocompatibilitytest,akka.http.scaladsl.testkit.routetest,org.make.api.technical.elasticsearch.proposalindexationstreamtest,org.make.api.makekafkatest,org.make.api.user.persistentuserservicecomponenttest,org.make.core.proposal.indexed.proposaltest,org.make.api.sessionhistory.sessionhistorycoordinatortest new $anon()
99 3180 3634 - 3638 Apply scala.Function1.apply org.scalatest.testsuite,org.make.api.technical.crm.crmservicecomponenttest f.apply(s)
100 2205 3665 - 3728 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to convert ".+(other): String))
104 3615 3786 - 3805 Apply spray.json.JsString.apply spray.json.JsString.apply(obj.value)
104 5359 3795 - 3804 Select org.make.core.StringValue.value obj.value
109 4845 3916 - 3919 Apply org.make.core.SprayJsonFormatters.$anon.<init> new $anon()
115 4835 4160 - 4160 Select cats.UnorderedFoldable.catsTraverseForVector cats.this.UnorderedFoldable.catsTraverseForVector
115 3730 4135 - 4165 ApplyToImplicitArgs cats.data.NonEmptyList.fromFoldable cats.data.NonEmptyList.fromFoldable[Vector, spray.json.JsValue](vec)(cats.this.UnorderedFoldable.catsTraverseForVector)
116 1763 4206 - 4260 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Array was empty": String))
117 5119 4301 - 4315 ApplyToImplicitArgs spray.json.JsValue.convertTo x$1.convertTo[T](f)
117 3192 4293 - 4316 Apply cats.data.NonEmptyList.map nel.map[T](((x$1: spray.json.JsValue) => x$1.convertTo[T](f)))
119 1081 4355 - 4417 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(("Unable to decode ".+(other): String))
123 1491 4495 - 4536 Apply spray.json.JsArray.apply spray.json.JsArray.apply(obj.map[spray.json.JsValue](((obj: T) => f.write(obj))).toList.toVector)
123 5372 4511 - 4518 Apply spray.json.JsonWriter.write f.write(obj)
123 3660 4503 - 4535 Select scala.collection.IterableOnceOps.toVector obj.map[spray.json.JsValue](((obj: T) => f.write(obj))).toList.toVector
129 5290 4675 - 4690 Apply scala.Predef.ArrowAssoc.-> org.scalatest.testsuite scala.Predef.ArrowAssoc[String](JsFieldSyntax.this.key).->[spray.json.JsValue](spray.json.`package`.enrichAny[A](a).toJson(evidence$1))
129 1773 4682 - 4690 ApplyToImplicitArgs spray.json.RichAny.toJson org.scalatest.testsuite spray.json.`package`.enrichAny[A](a).toJson(evidence$1)
129 4006 4675 - 4678 Select org.make.core.SprayJsonFormatters.syntax.JsFieldSyntax.key org.scalatest.testsuite JsFieldSyntax.this.key
133 1087 4823 - 4840 Apply spray.json.JsonReader.read org.scalatest.testsuite reader.read(JsonReaderSyntax.this.json)
133 3135 4835 - 4839 Select org.make.core.SprayJsonFormatters.syntax.JsonReaderSyntax.json org.scalatest.testsuite JsonReaderSyntax.this.json