@@ -19,7 +19,7 @@ package uk.gov.hmrc.cataloguefrontend.connector.model
19
19
import java .time .LocalDate
20
20
21
21
import org .joda .time .DateTime
22
- import play .api .libs .json .{Format , JsError , JsObject , JsString , JsSuccess , JsValue , Json , OFormat , Reads , __ }
22
+ import play .api .libs .json .{Format , JsError , JsObject , JsPath , JsString , JsSuccess , JsValue , Json , OFormat , Reads , __ }
23
23
import play .api .libs .functional .syntax ._
24
24
import uk .gov .hmrc .http .controllers .RestFormats
25
25
@@ -33,11 +33,6 @@ object VersionState {
33
33
case object BobbyRulePending extends VersionState
34
34
}
35
35
36
- // TODO avoid caching LocalDate, and provide to isActive function
37
- case class BobbyRuleViolation (reason : String , range : String , from : LocalDate )(implicit now : LocalDate = LocalDate .now()) {
38
- def isActive : Boolean = now.isAfter(from)
39
- }
40
-
41
36
case class Dependency (
42
37
name : String ,
43
38
currentVersion : Version ,
@@ -74,12 +69,89 @@ case class Dependencies(
74
69
toSeq.exists(_.isOutOfDate)
75
70
}
76
71
72
+ case class BobbyVersion (version : Version , inclusive : Boolean )
73
+
74
+ object BobbyVersion {
75
+ val reads : Reads [BobbyVersion ] = {
76
+ implicit val bvf = Version .format
77
+ ( (__ \ " version" ).read[Version ]
78
+ ~ (__ \ " inclusive" ).read[Boolean ]
79
+ )(BobbyVersion .apply _)
80
+ }
81
+ }
82
+
83
+ case class BobbyVersionRange (
84
+ lowerBound : Option [BobbyVersion ]
85
+ , upperBound : Option [BobbyVersion ]
86
+ , qualifier : Option [String ]
87
+ , range : String
88
+ ) {
89
+ def description : String = {
90
+ def comp (v : BobbyVersion ) = if (v.inclusive) " <= " else " < "
91
+ lowerBound.map(v => s " ${v.version} ${comp(v)}" ).getOrElse(" " ) +
92
+ " x" +
93
+ upperBound.map(v => s " ${comp(v)} ${v.version}" ).getOrElse(" " )
94
+ }
95
+ }
96
+
97
+ object BobbyVersionRange {
98
+
99
+ private val fixed = """ ^\[(\d+\.\d+.\d+)\]""" .r
100
+ private val fixedUpper = """ ^\(,?(\d+\.\d+.\d+)[\]\)]""" .r
101
+ private val fixedLower = """ ^[\[\(](\d+\.\d+.\d+),[\]\)]""" .r
102
+ private val rangeRegex = """ ^[\[\(](\d+\.\d+.\d+),(\d+\.\d+.\d+)[\]\)]""" .r
103
+ private val qualifier = """ ^\[[-\*]+(.*)\]""" .r
104
+
105
+ def apply (range : String ): BobbyVersionRange = {
106
+ val trimmedRange = range.replaceAll(" " , " " )
107
+
108
+ trimmedRange match {
109
+ case fixed(v) =>
110
+ val fixed = Version .parse(v).map(BobbyVersion (_, inclusive = true ))
111
+ BobbyVersionRange (lowerBound = fixed, upperBound = fixed, qualifier = None , range = trimmedRange)
112
+ case fixedUpper(v) =>
113
+ BobbyVersionRange (
114
+ lowerBound = None ,
115
+ upperBound = Version .parse(v).map(BobbyVersion (_, inclusive = trimmedRange.endsWith(" ]" ))),
116
+ qualifier = None ,
117
+ range = trimmedRange)
118
+ case fixedLower(v) =>
119
+ BobbyVersionRange (
120
+ lowerBound = Version .parse(v).map(BobbyVersion (_, inclusive = trimmedRange.startsWith(" [" ))),
121
+ upperBound = None ,
122
+ qualifier = None ,
123
+ range = trimmedRange)
124
+ case rangeRegex(v1, v2) =>
125
+ BobbyVersionRange (
126
+ lowerBound = Version .parse(v1).map(BobbyVersion (_, inclusive = trimmedRange.startsWith(" [" ))),
127
+ upperBound = Version .parse(v2).map(BobbyVersion (_, inclusive = trimmedRange.endsWith(" ]" ))),
128
+ qualifier = None ,
129
+ range = trimmedRange
130
+ )
131
+ case qualifier(q) if q.length() > 1 =>
132
+ BobbyVersionRange (lowerBound = None , upperBound = None , qualifier = Some (q), range = trimmedRange)
133
+ case _ => BobbyVersionRange (lowerBound = None , upperBound = None , qualifier = None , range = trimmedRange)
134
+ }
135
+ }
136
+
137
+ val reads : Reads [BobbyVersionRange ] =
138
+ JsPath .read[String ].map(BobbyVersionRange .apply)
139
+
140
+ }
141
+
142
+ // TODO avoid caching LocalDate, and provide to isActive function
143
+ case class BobbyRuleViolation (reason : String , range : BobbyVersionRange , from : LocalDate )(implicit now : LocalDate = LocalDate .now()) {
144
+ def isActive : Boolean = now.isAfter(from)
145
+ }
146
+
147
+
77
148
object Dependencies {
78
149
val reads : Reads [Dependencies ] = {
79
150
implicit val dtr = RestFormats .dateTimeFormats
151
+ implicit val bvr = BobbyVersionRange .reads
80
152
implicit val brvf =
81
153
( (__ \ " reason" ).read[String ]
82
- ~ (__ \ " range" ).read[JsValue ].map(j => (j \ " range " ).as[ String ])
154
+ ~ (__ \ " range" ).read[BobbyVersionRange ]
83
155
~ (__ \ " from" ).read[LocalDate ]
84
156
)(BobbyRuleViolation .apply _)
85
157
0 commit comments