/
ValueObjectsADM.scala
264 lines (235 loc) · 7.37 KB
/
ValueObjectsADM.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
package org.knora.webapi.messages.admin.responder.valueObjects
import org.knora.webapi.LanguageCodes
import org.knora.webapi.exceptions.{AssertionException, BadRequestException}
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2
import zio.prelude.Validation
import scala.util.matching.Regex
// TODO: this is so far shared value object file, consider to slice it
/** User value objects */
/**
* User Username value object.
*/
sealed abstract case class Username private (value: String)
object Username {
/**
* A regex that matches a valid username
* - 4 - 50 characters long
* - Only contains alphanumeric characters, underscore and dot.
* - Underscore and dot can't be at the end or start of a username
* - Underscore or dot can't be used multiple times in a row
*/
private val UsernameRegex: Regex =
"""^(?=.{4,50}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$""".r
def create(value: String): Either[Throwable, Username] =
if (value.isEmpty) {
Left(BadRequestException("Missing username"))
} else {
UsernameRegex.findFirstIn(value) match {
case Some(value) =>
Right(new Username(value) {})
case None => Left(BadRequestException("Invalid username"))
}
}
}
/**
* User Email value object.
*/
sealed abstract case class Email private (value: String)
object Email {
private val EmailRegex: Regex = """^.+@.+$""".r // TODO use proper validation
def create(value: String): Either[Throwable, Email] =
if (value.isEmpty) {
Left(BadRequestException("Missing email"))
} else {
EmailRegex.findFirstIn(value) match {
case Some(value) => Right(new Email(value) {})
case None => Left(BadRequestException("Invalid email"))
}
}
}
/**
* User Password value object.
*/
sealed abstract case class Password private (value: String)
object Password {
private val PasswordRegex: Regex = """^[\s\S]*$""".r //TODO: add password validation
def create(value: String): Either[Throwable, Password] =
if (value.isEmpty) {
Left(BadRequestException("Missing password"))
} else {
PasswordRegex.findFirstIn(value) match {
case Some(value) => Right(new Password(value) {})
case None => Left(BadRequestException("Invalid password"))
}
}
}
/**
* User GivenName value object.
*/
sealed abstract case class GivenName private (value: String)
object GivenName {
// TODO use proper validation for value
def create(value: String): Either[Throwable, GivenName] =
if (value.isEmpty) {
Left(BadRequestException("Missing given name"))
} else {
Right(new GivenName(value) {})
}
}
/**
* User FamilyName value object.
*/
sealed abstract case class FamilyName private (value: String)
object FamilyName {
// TODO use proper validation for value
def create(value: String): Either[Throwable, FamilyName] =
if (value.isEmpty) {
Left(BadRequestException("Missing family name"))
} else {
Right(new FamilyName(value) {})
}
}
/**
* User LanguageCode value object.
*/
sealed abstract case class LanguageCode private (value: String)
object LanguageCode {
def create(value: String): Either[Throwable, LanguageCode] =
if (value.isEmpty) {
Left(BadRequestException("Missing language code"))
} else if (!LanguageCodes.SupportedLanguageCodes.contains(value)) {
Left(BadRequestException("Invalid language code"))
} else {
Right(new LanguageCode(value) {})
}
}
/**
* User SystemAdmin value object.
*/
sealed abstract case class SystemAdmin private (value: Boolean)
object SystemAdmin {
def create(value: Boolean): Either[Throwable, SystemAdmin] =
Right(new SystemAdmin(value) {})
}
/** Project value objects */
/**
* Project Shortcode value object.
*/
sealed abstract case class Shortcode private (value: String)
object Shortcode {
val stringFormatter = StringFormatter.getGeneralInstance
def make(value: String): Validation[Throwable, Shortcode] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing shortcode"))
} else {
val validatedValue: Validation[Throwable, String] = Validation(
stringFormatter.validateProjectShortcode(value, throw AssertionException("not valid"))
)
validatedValue.map(new Shortcode(_) {})
}
}
/**
* Project Shortname value object.
*/
sealed abstract case class Shortname private (value: String)
object Shortname {
val stringFormatter = StringFormatter.getGeneralInstance
def make(value: String): Validation[Throwable, Shortname] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing shortname"))
} else {
val validatedValue = Validation(
stringFormatter.validateAndEscapeProjectShortname(value, throw AssertionException("not valid"))
)
validatedValue.map(new Shortname(_) {})
}
}
/**
* Project Longname value object.
*/
sealed abstract case class Longname private (value: String)
object Longname { self =>
def make(value: String): Validation[Throwable, Longname] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing long name"))
} else {
Validation.succeed(new Longname(value) {})
}
def make(value: Option[String]): Validation[Throwable, Option[Longname]] =
value match {
case None => Validation.succeed(None)
case Some(v) => self.make(v).map(Some(_))
}
}
/**
* Project Keywords value object.
*/
sealed abstract case class Keywords private (value: Seq[String])
object Keywords {
def make(value: Seq[String]): Validation[Throwable, Keywords] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing keywords"))
} else {
Validation.succeed(new Keywords(value) {})
}
}
/**
* Project Logo value object.
*/
sealed abstract case class Logo private (value: String)
object Logo { self =>
def make(value: String): Validation[Throwable, Logo] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing logo"))
} else {
Validation.succeed(new Logo(value) {})
}
def make(value: Option[String]): Validation[Throwable, Option[Logo]] =
value match {
case None => Validation.succeed(None)
case Some(v) => self.make(v).map(Some(_))
}
}
/** Groups value objects */
/**
* Group Name value object.
*/
sealed abstract case class Name private (value: String)
object Name {
def create(value: String): Either[Throwable, Name] =
if (value.isEmpty) {
Left(BadRequestException("Missing Name"))
} else {
Right(new Name(value) {})
}
}
/** Shared value objects */
/**
* Selfjoin value object.
*/
sealed abstract case class Selfjoin private (value: Boolean)
object Selfjoin {
def make(value: Boolean): Validation[Throwable, Selfjoin] =
Validation.succeed(new Selfjoin(value) {})
}
/**
* Status value object.
*/
sealed abstract case class Status private (value: Boolean)
object Status {
def make(value: Boolean): Validation[Throwable, Status] =
Validation.succeed(new Status(value) {})
}
/**
* Description value object.
*/
sealed abstract case class Description private (value: Seq[StringLiteralV2])
object Description {
def make(value: Seq[StringLiteralV2]): Validation[Throwable, Description] =
if (value.isEmpty) {
Validation.fail(BadRequestException("Missing description"))
} else {
Validation.succeed(new Description(value) {})
}
}