feature/dynamicEntity_add_minLength_and_maxLength: if "type":"string", example: "minLength":3, "maxLength":20,

This commit is contained in:
shuang 2020-07-12 21:00:37 +08:00
parent fb44ed174b
commit e6d12cf500
4 changed files with 80 additions and 30 deletions

View File

@ -402,6 +402,8 @@ object ExampleValue {
| "properties": {
| "name": {
| "type": "string",
| "maxLength": 20,
| "minLength": 3,
| "example": "James Brown",
| "description":"description of **name** field, can be markdown text."
| },
@ -420,7 +422,7 @@ object ExampleValue {
"description of this entity, can be markdown text.",
List("name"),
DynamicEntityFullBarFields(
DynamicEntityStringTypeExample(DynamicEntityFieldType.string, "James Brown", "description of **name** field, can be markdown text."),
DynamicEntityStringTypeExample(DynamicEntityFieldType.string, 3, 20, "James Brown", "description of **name** field, can be markdown text."),
DynamicEntityIntTypeExample(DynamicEntityFieldType.integer, 698761728, "description of **number** field, can be markdown text.")
)
)

View File

@ -60,34 +60,44 @@ trait DynamicEntityT {
)
}
val invalidPropertyMsg = (definition \ entityName \ "properties").asInstanceOf[JObject].obj
.map(it => {
val JField(propertyName, propertyDef: JObject) = it
val propertyTypeName = (propertyDef \ "type").asInstanceOf[JString].s
(propertyName, propertyTypeName)
})
.map(it => {
val (propertyName, propertyType) = it
val propertyValue = entityJson \ propertyName
val typeEnumOption = DynamicEntityFieldType.withNameOption(propertyType)
val invalidPropertyMsg: List[Future[String]] = for {
JField(propertyName, propertyDef: JObject) <- (definition \ entityName \ "properties").asInstanceOf[JObject].obj
propertyTypeName = (propertyDef \ "type").asInstanceOf[JString].s
propertyValue = entityJson \ propertyName
typeEnumOption = DynamicEntityFieldType.withNameOption(propertyTypeName)
} yield {
val minLength: JValue = propertyDef \ "minLength"
val maxLength: JValue = propertyDef \ "maxLength"
(propertyTypeName, typeEnumOption, propertyValue) match {
case (_, _, JNothing | JNull) => Future.successful("") // required properties already checked.
(propertyType, typeEnumOption, propertyValue) match {
case (_, _, JNothing | JNull) => Future.successful("") // required properties already checked.
case (_, Some(typeEnum), v) if !typeEnum.isJValueValid(v) =>
Future.successful(s"The value of '$propertyName' is wrong, ${typeEnum.wrongTypeMsg}")
case (_, Some(typeEnum), v) if !typeEnum.isJValueValid(v) =>
Future.successful(s"The value of '$propertyName' is wrong, ${typeEnum.wrongTypeMsg}")
case (t, None, v) if t.startsWith("reference:") && !v.isInstanceOf[JString] =>
val errorMsg = s"The type of '$propertyName' is 'reference', value should be a string that represent reference entity's Id"
Future.successful(errorMsg)
case (t, None, v) if t.startsWith("reference:") && !v.isInstanceOf[JString] =>
val errorMsg = s"The type of '$propertyName' is 'reference', value should be a string that represent reference entity's Id"
Future.successful(errorMsg)
case (t, None, v) if t.startsWith("reference:") =>
val value = v.asInstanceOf[JString].s
ReferenceType.validateRefValue(t, propertyName, value, callContext)
case (t, None, v) if t.startsWith("reference:") =>
val value = v.asInstanceOf[JString].s
ReferenceType.validateRefValue(t, propertyName, value, callContext)
case (_, Some(DynamicEntityFieldType.string), v)
if ! DynamicEntityFieldType.string.isLengthValid(v, minLength, maxLength) =>
var errorMsg = s"The $propertyName's value length is not correct"
if(minLength != JNothing) {
errorMsg += s", minLength: ${minLength.asInstanceOf[JInt].num}"
}
if(maxLength != JNothing) {
errorMsg += s", maxLength: ${maxLength.asInstanceOf[JInt].num}"
}
errorMsg += "."
Future.successful(errorMsg)
case _ => Future.successful("")
}
}
case _ => Future.successful("")
}
})
Future.sequence(invalidPropertyMsg)
.map(_.filter(_.nonEmpty))
.collect {
@ -346,6 +356,8 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
* "properties": {
* "name": {
* "type": "string",
* "minLength": 3,
* "maxLength": 20,
* "example": "James Brown",
* "description":"description of **name** field, can be markdown text."
* },
@ -424,6 +436,24 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
checkFormat(fieldType.isInstanceOf[JString] && fieldTypeName.nonEmpty, s"$DynamicEntityInstanceValidateFail The property of $fieldName's 'type' field should be exists and type is json string")
checkFormat(allowedFieldType.contains(fieldTypeName), s"$DynamicEntityInstanceValidateFail The property of $fieldName's 'type' field should be one of these string value: ${allowedFieldType.mkString(", ")}")
if(DynamicEntityFieldType.withName(fieldTypeName) == DynamicEntityFieldType.string) {
val minLength = value \ "minLength"
val maxLength = value \ "maxLength"
def toInt(jValue: JValue) = jValue.asInstanceOf[JInt].num.intValue()
if(minLength != JNothing) {
checkFormat(minLength.isInstanceOf[JInt], s"$DynamicEntityInstanceValidateFail The property of minLength's 'type' should be integer")
checkFormat(toInt(minLength) >= 0, s"$DynamicEntityInstanceValidateFail The property of minLength value should be non-negative integer, current value: ${toInt(minLength)}")
}
if(maxLength != JNothing) {
checkFormat(maxLength.isInstanceOf[JInt], s"$DynamicEntityInstanceValidateFail The property of maxLength's 'type' should be integer")
checkFormat(toInt(maxLength) >= 0, s"$DynamicEntityInstanceValidateFail The property of minLength value should be non-negative integer, current value: ${toInt(maxLength)}")
}
if(minLength != JNothing && maxLength != JNothing) {
checkFormat(toInt(minLength) < toInt(maxLength), s"$DynamicEntityInstanceValidateFail The property of minLength value should be less than maxLength, minLength: ${toInt(minLength)}, maxLength: ${toInt(maxLength)}")
}
}
// example is exists
val fieldExample = value \ "example"
checkFormat(fieldExample != JNothing, s"$DynamicEntityInstanceValidateFail The property of $fieldName's 'example' field should be exists")
@ -463,7 +493,7 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
case class DynamicEntityFooBar(FooBar: DynamicEntityDefinition, dynamicEntityId: Option[String] = None)
case class DynamicEntityDefinition(description: String, required: List[String],properties: DynamicEntityFullBarFields)
case class DynamicEntityFullBarFields(name: DynamicEntityStringTypeExample, number: DynamicEntityIntTypeExample)
case class DynamicEntityStringTypeExample(`type`: DynamicEntityFieldType, example: String, description: String)
case class DynamicEntityStringTypeExample(`type`: DynamicEntityFieldType, minLength: Int, maxLength: Int, example: String, description: String)
case class DynamicEntityIntTypeExample(`type`: DynamicEntityFieldType, example: Int, description: String)
//-------------------example case class end

View File

@ -63,6 +63,8 @@ class DynamicEntityTest extends V400ServerSetup {
| "properties": {
| "name": {
| "type": "string",
| "maxLength": 20,
| "minLength": 3,
| "example": "James Brown",
| "description":"description of **name** field, can be markdown text."
| },

View File

@ -4,7 +4,7 @@ import java.time.format.DateTimeFormatter
import com.openbankproject.commons.util.{EnumValue, JsonAble, OBPEnumeration}
import net.liftweb.common.Box
import net.liftweb.json.JsonAST.JString
import net.liftweb.json.JsonAST.{JNothing, JString}
import net.liftweb.json.{Formats, JBool, JDouble, JInt, JValue}
sealed trait AccountAttributeType extends EnumValue
@ -73,10 +73,26 @@ sealed trait DynamicEntityFieldType extends EnumValue {
def wrongTypeMsg = s"the value's type should be $this."
}
object DynamicEntityFieldType extends OBPEnumeration[DynamicEntityFieldType]{
object string extends Value{val jValueType = classOf[JString]}
object number extends Value{val jValueType = classOf[JDouble]}
object integer extends Value{val jValueType = classOf[JInt]}
object boolean extends Value{val jValueType = classOf[JBool]}
object number extends Value{val jValueType = classOf[JDouble]}
object integer extends Value{val jValueType = classOf[JInt]}
object boolean extends Value{val jValueType = classOf[JBool]}
object string extends Value{
val jValueType = classOf[JString]
def isLengthValid(jValue: JValue, minLength: JValue, maxLength: JValue) = {
if(minLength == JNothing && maxLength == JNothing) {
true
} else if(jValue == JNothing) {
true
} else {
val value = jValue.asInstanceOf[JString].s
val minLengthValue = if(minLength != JNothing) minLength.asInstanceOf[JInt].num.intValue() else 0
val maxLengthValue = if(minLength != JNothing) maxLength.asInstanceOf[JInt].num.intValue() else Int.MaxValue
minLengthValue <= value.size && value.size <= maxLengthValue
}
}
}
object DATE_WITH_DAY extends Value {
val jValueType = classOf[JString]