scala-cask.modelDataClass.mustache Maven / Gradle / Ivy
/** {{classname}}Data a data transfer object, primarily for simple json serialisation.
* It has no validation - there may be nulls, values out of range, etc
*/
case class {{classname}}Data(
{{#vars}}
{{#description}}
/* {{{description}}} */
{{/description}}
{{name}}: {{#isEnum}}{{classname}}.{{datatypeWithEnum}}{{/isEnum}}{{^isEnum}}{{{vendorExtensions.x-datatype-data}}}{{/isEnum}}{{^required}} = {{{vendorExtensions.x-defaultValue-data}}} {{/required}}{{^-last}},{{/-last}}
{{/vars}}
{{#isAdditionalPropertiesTrue}}, additionalProperties : ujson.Value = ujson.Null{{/isAdditionalPropertiesTrue}}
) derives RW {
def asJsonString: String = asJson.toString()
def asJson : ujson.Value = {
val jason = writeJs(this)
{{#isAdditionalPropertiesTrue}}
jason.obj.remove("additionalProperties")
jason.mergeWith(additionalProperties)
{{/isAdditionalPropertiesTrue}}
{{^isAdditionalPropertiesTrue}}
jason
{{/isAdditionalPropertiesTrue}}
}
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
val _allValidationErrors = scala.collection.mutable.ListBuffer[ValidationError]()
{{#vars}}
// ================== {{name}} validation ==================
{{#pattern}}
// validate against pattern '{{{pattern}}}'
if (_allValidationErrors.isEmpty || !failFast) {
val regex = """{{{pattern}}}"""
if {{name}} == null || !regex.r.matches({{name}}) then
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' doesn't match pattern $regex")
}
{{/pattern}}
{{#minimum}}
// validate against {{#exclusiveMinimum}}exclusive {{/exclusiveMinimum}}minimum {{minimum}}
if (_allValidationErrors.isEmpty || !failFast) {
if !({{name}} >{{^exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}) then
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMinimum}}exclusive {{/exclusiveMinimum}}minimum value {{minimum}}")
}
{{/minimum}}
{{#maximum}}
// validate against {{#exclusiveMaximum}}exclusive {{/exclusiveMaximum}}maximum {{maximum}}
if (_allValidationErrors.isEmpty || !failFast) {
if !({{name}} <{{^exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}) then
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"value '${{name}}' is not greater than the {{#exclusiveMaximum}}exclusive {{/exclusiveMaximum}}maximum value {{maximum}}")
}
{{/maximum}}
{{#minLength}}
// validate min length {{minLength}}
if (_allValidationErrors.isEmpty || !failFast) {
val len = if {{name}} == null then 0 else {{name}}.length
if (len < {{minLength}}) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is shorter than the min length {{minLength}}")
}
}
{{/minLength}}
{{#maxLength}}
// validate max length {{maxLength}}
if (_allValidationErrors.isEmpty || !failFast) {
val len = if {{name}} == null then 0 else {{name}}.length
if (len < {{maxLength}}) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"length $len is longer than the max length {{maxLength}}")
}
}
{{/maxLength}}
{{#isEmail}}
// validate {{name}} is a valid email address
if (_allValidationErrors.isEmpty || !failFast) {
val emailRegex = """^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"""
// validate {{name}} is email
if ({{name}} == null || !emailRegex.r.matches({{name}})) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"${{name}} is not a valid email address according to the pattern $emailRegex")
}
}
{{/isEmail}}
{{#required}}{{^isPrimitiveType}}
if (_allValidationErrors.isEmpty || !failFast) {
if ({{name}} == null) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, "{{name}} is a required field and cannot be null")
}
}
{{/isPrimitiveType}}{{/required}}
{{#uniqueItems}}
// validate {{name}} has unique items
if (_allValidationErrors.isEmpty || !failFast) {
if ({{name}} != null) {
{{name}}.foldLeft(Set[{{{vendorExtensions.x-containertype-data}}}]()) {
case (set, next) if set.contains(next) =>
_allValidationErrors += ValidationError(
path :+ {{classname}}.Fields.{{name}},
s"duplicate value: $next"
)
set + next
case (set, next) => set + next
}
}
}
{{/uniqueItems}}
{{#multipleOf}}
if (_allValidationErrors.isEmpty || !failFast) {
// validate {{name}} multiple of {{multipleOf}}
if ({{name}} % {{multipleOf}} != 0) {
_allValidationErrors += ValidationError(
path :+ {{classname}}.Fields.{{name}},
s"${{name}} is not a multiple of {{multipleOf}}"
)
}
}
{{/multipleOf}}
{{#minItems}}
// validate min items {{minItems}}
if (_allValidationErrors.isEmpty || !failFast) {
val len = if {{name}} == null then 0 else {{name}}.size
if (len < {{minItems}}) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is less than the min items {{minItems}}")
}
}
{{/minItems}}
{{#maxItems}}
// validate min items {{maxItems}}
if (_allValidationErrors.isEmpty || !failFast) {
val len = if {{name}} == null then 0 else {{name}}.size
if (len > {{maxItems}}) {
_allValidationErrors += ValidationError(path :+ {{classname}}.Fields.{{name}}, s"{{name}} has $len, which is greater than the max items {{maxItems}}")
}
}
{{/maxItems}}
{{#minProperties}} TODO - minProperties {{/minProperties}}
{{#maxProperties}} TODO - maxProperties {{/maxProperties}}
{{#items}}{{#isModel}}
if (_allValidationErrors.isEmpty || !failFast) {
if ({{name}} != null) {
{{name}}.zipWithIndex.foreach {
case (value, i) if _allValidationErrors.isEmpty || !failFast =>
_allValidationErrors ++= value.validationErrors(
path :+ {{classname}}.Fields.{{name}} :+ Field(i.toString),
failFast)
case (value, i) =>
}
}
}
{{/isModel}}{{/items}}
{{#isModel}}
// validating {{name}}
if (_allValidationErrors.isEmpty || !failFast) {
if {{name}} != null then _allValidationErrors ++= {{name}}.validationErrors(path :+ {{classname}}.Fields.{{name}}, failFast)
}
{{/isModel}}
{{/vars}}
_allValidationErrors.toSeq
}
/**
* @return the validated model within a Try (if successful)
*/
def validated(failFast : Boolean = false) : scala.util.Try[{{classname}}] = {
validationErrors(Vector(), failFast) match {
case Seq() => Success(asModel)
case first +: theRest => Failure(ValidationErrors(first, theRest))
}
}
/** use 'validated' to check validation */
def asModel : {{classname}} = {
{{classname}}(
{{#vars}}
{{name}} = {{{vendorExtensions.x-asModel}}}{{^-last}},{{/-last}}
{{/vars}}
{{#isAdditionalPropertiesTrue}}, additionalProperties{{/isAdditionalPropertiesTrue}}
)
}
}
object {{classname}}Data {
def validated(d8a : {{classname}}Data, failFast : Boolean) : scala.util.Try[{{classname}}] = d8a.validated(failFast)
def fromJson(jason : ujson.Value) : {{classname}}Data = try {
val data = read[{{classname}}Data](jason)
{{^isAdditionalPropertiesTrue}}
data
{{/isAdditionalPropertiesTrue}}
{{#isAdditionalPropertiesTrue}}
val obj = jason.obj
{{classname}}.Fields.values.foreach(v => obj.value.subtractOne(v.fieldName))
data.copy(additionalProperties = obj)
{{/isAdditionalPropertiesTrue}}
} catch {
case NonFatal(e) => sys.error(s"Error creating {{classname}}Data from json '$jason': $e")
}
def fromJsonString(jason : String) : {{classname}}Data = {
val parsed = try {
read[ujson.Value](jason)
} catch {
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
}
fromJson(parsed)
}
def manyFromJsonString(jason : String) : Seq[{{classname}}Data] = try {
read[List[{{classname}}Data]](jason)
} catch {
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
}
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[{{classname}}]] = {
Try(manyFromJsonString(jason)).flatMap { list =>
list.zipWithIndex.foldLeft(Try(Vector[{{classname}}]())) {
case (Success(list), (next, i)) =>
next.validated(failFast) match {
case Success(ok) => Success(list :+ ok)
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
}
case (fail, _) => fail
}
}
}
def mapFromJsonString(jason : String) : Map[String, {{classname}}Data] = try {
read[Map[String, {{classname}}Data]](jason)
} catch {
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
}
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, {{classname}}]] = {
Try(mapFromJsonString(jason)).flatMap { map =>
map.foldLeft(Try(Map[String, {{classname}}]())) {
case (Success(map), (key, next)) =>
next.validated(failFast) match {
case Success(ok) => Success(map.updated(key, ok))
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
}
case (fail, _) => fail
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy