diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index bff968de7..1cb7a578d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1,6 +1,7 @@ package code.api.ResourceDocs1_4_0 import java.util.Date + import code.api.Constant._ import code.api.Constant import code.api.UKOpenBanking.v2_0_0.JSONFactory_UKOpenBanking_200 @@ -25,7 +26,7 @@ import com.openbankproject.commons.model import com.openbankproject.commons.model.PinResetReason.{FORGOT, GOOD_SECURITY_PRACTICE} import com.openbankproject.commons.model.enums.CardAttributeType import com.openbankproject.commons.model.{UserAuthContextUpdateStatus, ViewBasic, _} -import com.openbankproject.commons.util.ReflectUtils +import com.openbankproject.commons.util.{ApiVersion, FieldNameApiVersions, ReflectUtils, RequiredArgs, RequiredInfo} import scala.collection.immutable.List @@ -432,7 +433,12 @@ object SwaggerDefinitionsJSON { example_inbound_message = defaultJValue, outboundAvroSchema = Some(defaultJValue), inboundAvroSchema = Some(defaultJValue), - adapter_implementation = adapterImplementationJson + adapter_implementation = adapterImplementationJson, + requiredFieldInfo = { + val fieldNameApiVersions = FieldNameApiVersions("data.bankId", List(ApiVersion.v3_1_0.toString)) + val requiredInfo = RequiredInfo(List(fieldNameApiVersions)) + Some(requiredInfo) + } ) val messageDocsJson = MessageDocsJson(message_docs = List(messageDocJson)) diff --git a/obp-api/src/main/scala/code/api/util/CustomJsonFormats.scala b/obp-api/src/main/scala/code/api/util/CustomJsonFormats.scala index 55b3f9cd9..f05903d3d 100644 --- a/obp-api/src/main/scala/code/api/util/CustomJsonFormats.scala +++ b/obp-api/src/main/scala/code/api/util/CustomJsonFormats.scala @@ -27,9 +27,9 @@ object CustomJsonFormats { val formats: Formats = net.liftweb.json.DefaultFormats + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + JsonAbleSerializer - val losslessFormats: Formats = net.liftweb.json.DefaultFormats.lossless + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + val losslessFormats: Formats = net.liftweb.json.DefaultFormats.lossless + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + JsonAbleSerializer - val emptyHintFormats = DefaultFormats.withHints(ShortTypeHints(List())) + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + val emptyHintFormats = DefaultFormats.withHints(ShortTypeHints(List())) + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + JsonAbleSerializer implicit val nullTolerateFormats = formats + JNothingSerializer @@ -37,7 +37,7 @@ object CustomJsonFormats { val dateFormat = net.liftweb.json.DefaultFormats.dateFormat override val typeHints = ShortTypeHints(rolesMappedToClasses) - } + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + } + BigDecimalSerializer + FiledRenameSerializer + ListResultSerializer + EnumValueSerializer + JsonAbleSerializer } object BigDecimalSerializer extends Serializer[BigDecimal] { diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 7c0ff5bc0..44aa6c192 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -8,16 +8,13 @@ import code.api.v3_1_0.ListResult import code.crm.CrmEvent.CrmEvent import code.transactionrequests.TransactionRequestTypeCharge import com.openbankproject.commons.model.{Product, _} -import com.openbankproject.commons.util.{EnumValue, OBPEnumeration} +import com.openbankproject.commons.util.{EnumValue, OBPEnumeration, ReflectUtils} import net.liftweb.common.Full import net.liftweb.json import net.liftweb.json.{JDouble, JInt, JString} import net.liftweb.json.JsonAST.{JArray, JBool, JObject, JValue} import net.liftweb.util.StringHelpers -import scala.reflect.runtime.currentMirror -import scala.reflect.runtime.universe._ - object JSONFactory1_4_0 { @@ -403,19 +400,13 @@ object JSONFactory1_4_0 { case v => v } - val r = currentMirror.reflect(extractedEntity) val mapOfFields: Map[String, Any] = extractedEntity match { case ListResult(name, results) => Map((name, results)) case JObject(jFields) => jFields.map(it => (it.name, it.value)).toMap - case _ => r.symbol.typeSignature.members.toStream - .collect { case s: TermSymbol if !s.isMethod => r.reflectField(s)} - .map(r => r.symbol.name.toString.trim -> r.get) - .toMap + case _ => ReflectUtils.getFieldValues(extractedEntity.asInstanceOf[AnyRef])() } - - val convertParamName = (name: String) => extractedEntity match { case _ : JsonFieldReName => StringHelpers.snakify(name) case _ => name @@ -457,7 +448,9 @@ object JSONFactory1_4_0 { case Some(i: String) => "\"" + key + """": {"type":"string"}""" case List(i: String, _*) => "\"" + key + """": {"type": "array","items": {"type": "string"}}""" case Some(List(i: String, _*)) => "\"" + key + """": {"type": "array","items": {"type": "string"}}""" - //Int + case Array(i: String, _*) => "\"" + key + """": {"type": "array","items": {"type": "string"}}""" + case Some(Array(i: String, _*)) => "\"" + key + """": {"type": "array","items": {"type": "string"}}""" + //Int case _: Int | _:JInt => "\"" + key + """": {"type":"integer"}""" case Some(i: Int) => "\"" + key + """": {"type":"integer"}""" case List(i: Int, _*) => "\"" + key + """": {"type": "array","items": {"type": "integer"}}""" diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index fff9f68a0..43a7abdca 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -410,7 +410,7 @@ trait APIMethods220 { messageDocs <- Full{connectorObject.messageDocs.toList} } yield { val json = JSONFactory220.createMessageDocsJson(messageDocs) - successJsonResponse(Extraction.decompose(json)) + successJsonResponse(Extraction.decompose(json)(CustomJsonFormats.formats)) } } } diff --git a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala index 936e9f348..573399c32 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala @@ -46,7 +46,7 @@ import code.model._ import com.openbankproject.commons.model.Product import code.users.Users import com.openbankproject.commons.model._ -import com.openbankproject.commons.util.{ReflectUtils, RequiredArgs, RequiredFieldValidation} +import com.openbankproject.commons.util.{ReflectUtils, RequiredFieldValidation, RequiredInfo} import net.liftweb.common.{Box, Full} import net.liftweb.json.Extraction.decompose import net.liftweb.json.JsonAST.JValue @@ -830,7 +830,7 @@ object JSONFactory220 extends CustomJsonFormats { outboundAvroSchema: Option[JValue] = None, inboundAvroSchema: Option[JValue] = None, adapter_implementation : AdapterImplementationJson, - requiredFieldInfo: Map[String, RequiredArgs] = Map.empty + requiredFieldInfo: Option[RequiredInfo] = None ) case class AdapterImplementationJson( @@ -849,8 +849,6 @@ object JSONFactory220 extends CustomJsonFormats { def createMessageDocJson(md: MessageDoc): MessageDocJson = { val inBoundType = ReflectUtils.getType(md.exampleInboundMessage) - val regex = Pattern.compile("""(code|com\.openbankproject\.commons)\..+""") - def findRequiredInfoFor(tp: Type): Boolean = regex.matcher(tp.toString).matches() MessageDocJson( process = md.process, @@ -868,7 +866,11 @@ object JSONFactory220 extends CustomJsonFormats { md.adapterImplementation.map(_.group).getOrElse(""), md.adapterImplementation.map(_.suggestedOrder).getOrElse(100) ), - requiredFieldInfo = RequiredFieldValidation.getAllNestedRequiredInfo(inBoundType, findRequiredInfoFor) + requiredFieldInfo = { + val requiredArgses = RequiredFieldValidation.getAllNestedRequiredInfo(inBoundType) + val requiredInfo = RequiredInfo(requiredArgses) + Some(requiredInfo) + } ) } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/Functions.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/Functions.scala index 991b46075..67b6dcafb 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/Functions.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/Functions.scala @@ -1,5 +1,9 @@ package com.openbankproject.commons.util +import java.util.regex.Pattern +import scala.collection.{IterableLike, immutable} +import scala.collection.generic.CanBuildFrom +import scala.reflect.runtime.universe.Type /** * function utils */ @@ -14,4 +18,48 @@ object Functions { def doNothing[T, D]: PartialFunction[T,D] = { case _ if false => ??? } + + def truePredicate[T]: T => Boolean = _ => true + def falsePredicate[T]: T => Boolean = _ => false + + private val obpTypeNamePattern = Pattern.compile("""(code|com\.openbankproject\.commons)\..+""") + + def isOBPType(tp: Type) = obpTypeNamePattern.matcher(tp.typeSymbol.fullName).matches() + def isOBPClass(clazz: Class[_]) = obpTypeNamePattern.matcher(clazz.getName).matches() + + implicit class RichCollection[A, Repr](iterable: IterableLike[A, Repr]){ + def distinctBy[B, That](f: A => B)(implicit canBuildFrom: CanBuildFrom[Repr, A, That]) = { + val builder = canBuildFrom(iterable.repr) + val set = scala.collection.mutable.Set[B]() + iterable.foreach(it => { + val calculatedElement = f(it) + if(set.add(calculatedElement)) { + builder += it + } + }) + builder.result + } + def toMapByKey[K](f: A => K): immutable.Map[K, A] = { + val b = immutable.Map.newBuilder[K, A] + for (x <- iterable) + b += f(x) -> x + + b.result() + } + def toMapByValue[V](f: A => V): immutable.Map[A, V] = { + val b = immutable.Map.newBuilder[A, V] + for (x <- iterable) + b += x -> f(x) + + b.result() + } + + def toMap[K, V](keyFn: A => K, valueFn: A => V): immutable.Map[K, V] = { + val b = immutable.Map.newBuilder[K, V] + for (x <- iterable) + b += keyFn(x) -> valueFn(x) + + b.result() + } + } } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala index aac595315..57e68de43 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala @@ -58,9 +58,9 @@ object ReflectUtils { val TermName(fieldName) = it.name if(it.isLazy) { // get lazy value - fieldName -> instanceMirror.reflectMethod(it.asMethod)() + fieldName.trim -> instanceMirror.reflectMethod(it.asMethod)() } else { - fieldName -> instanceMirror.reflectField(it).get + fieldName.trim -> instanceMirror.reflectField(it).get } }) .toMap diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala index 0b26ae784..a78a56ed5 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala @@ -1,12 +1,13 @@ package com.openbankproject.commons.util +import java.util.Objects + import com.openbankproject.commons.util.ApiVersion.allVersion -import net.liftweb.json.JValue -import net.liftweb.json.JsonAST.{JArray, JString} +import net.liftweb.json.JsonAST.{JArray, JField, JObject, JString} import scala.annotation.StaticAnnotation -import scala.collection.immutable.ListMap import scala.reflect.runtime.universe._ +import Functions.RichCollection /** @@ -37,8 +38,36 @@ class OBPRequired(value: Array[ApiVersion] = Array(ApiVersion.allVersion), exclude: Array[ApiVersion] = Array.empty ) extends StaticAnnotation +/** + * cooperate with RequiredInfo to deal with generate swagger doc and json serialization problem (show wrong structure of json) + * @param filedName + * @param apiVersions + */ +case class FieldNameApiVersions(filedName: String, apiVersions: List[String]) -case class RequiredArgs(include: Array[ApiVersion], +/** + * cooperate with RequiredInfo to deal with generate swagger doc and json serialization problem (show wrong structure of json) + * @param infos + */ +case class RequiredInfo(infos: List[FieldNameApiVersions]) extends JsonAble { + + override def toJValue: JObject = { + val jFields = infos.map(info => JField( + info.filedName, + JArray(info.apiVersions.map(JString(_)))) + ) + JObject(jFields) + } +} + +object RequiredInfo { + def apply(requiredArgs: Seq[RequiredArgs]): RequiredInfo = { + val fieldNameApiVersionses = requiredArgs.toList.map(arg => FieldNameApiVersions(arg.fieldPath, arg.apiVersions)) + RequiredInfo(fieldNameApiVersionses) + } +} + +case class RequiredArgs(fieldPath:String, include: Array[ApiVersion], exclude: Array[ApiVersion] = Array.empty) extends JsonAble { { val includeAll = include.contains(allVersion) @@ -69,10 +98,10 @@ case class RequiredArgs(include: Array[ApiVersion], } override def equals(obj: Any): Boolean = obj match { - case RequiredArgs(inc, exc) => include.sameElements(inc) && exclude.sameElements(exc) + case RequiredArgs(path, inc, exc) => Objects.equals(fieldPath, path) && include.sameElements(inc) && exclude.sameElements(exc) case _ => false } - override def toJValue: JValue = (include, exclude) match { + override val toJValue: JArray = (include, exclude) match { case (_, Array()) => val includeList = include.toList.map(_.toString).map(JString(_)) JArray(includeList) @@ -80,6 +109,10 @@ case class RequiredArgs(include: Array[ApiVersion], val excludeList = include.toList.map("-" + _.toString).map(JString(_)) JArray(excludeList) } + val apiVersions: List[String] = (include, exclude) match { + case (_, Array()) => include.toList.map(_.toString) + case _ => include.toList.map("-" + _.toString) + } } object RequiredFieldValidation { @@ -123,35 +156,43 @@ object RequiredFieldValidation { * @param tp to process type * @return map of field name to RequiredArgs */ - def getAnnotations(tp: Type): Map[String, RequiredArgs] = { + def getAnnotations(tp: Type): Iterable[RequiredArgs] = { val members = tp.members val constructors = members.filter(_.isConstructor).map(_.asMethod) - def getFieldNameAndAnnotation(symbol: Symbol): List[(String, RequiredArgs)] = { - (symbol.name.decodedName, getAnnotation(symbol)) match{ - case (TermName(name), Some(requiredArgs)) => List(name.trim -> requiredArgs) - case _ => Nil + def getFieldNameAndAnnotation(symbol: Symbol): Option[RequiredArgs] = { + val fieldName = symbol.name.decodedName.toString.trim + getAnnotation(fieldName, symbol) match{ + case some: Some[RequiredArgs] => some + case _ => None } } // constructor param name to RequiredArgs - val constructorParamToRequiredArgs: Map[String, RequiredArgs] = constructors + val constructorParamToRequiredArgs: Iterable[RequiredArgs] = constructors .flatMap(_.paramLists.head) // all the constructor's parameters - .flatMap(getFieldNameAndAnnotation) - .toMap + .map(getFieldNameAndAnnotation) + .collect { + case Some(requiredArgs) => requiredArgs + } + val constructorParamNames = constructorParamToRequiredArgs.map(_.fieldPath).toSet // those annotated field name to RequiredArgs - val annotatedFieldNameToRequiredArgs: Map[String, RequiredArgs] = - members.filter(it => { - !it.isConstructor && !constructorParamToRequiredArgs.contains(it.name.decodedName.toString.trim) - }) - .flatMap(getFieldNameAndAnnotation) - .toMap - val requiredFields: Map[String, RequiredArgs] = constructorParamToRequiredArgs ++ annotatedFieldNameToRequiredArgs - requiredFields + val annotatedFieldNameToRequiredArgs: Iterable[RequiredArgs] = + members + .filter(it => { + !it.isConstructor && !constructorParamNames.contains(it.name.decodedName.toString.trim) + }) + .map(getFieldNameAndAnnotation) + .collect { + case Some(requiredArgs) => requiredArgs + } + .distinctBy(_.fieldPath) + + constructorParamToRequiredArgs ++ annotatedFieldNameToRequiredArgs } - def getAnnotation(symbol: Symbol): Option[RequiredArgs] = { + def getAnnotation(fieldName: String, symbol: Symbol): Option[RequiredArgs] = { val annotation: Option[Annotation] = (symbol :: symbol.overrides) .flatMap(_.annotations) @@ -159,47 +200,45 @@ object RequiredFieldValidation { annotation.map { it: Annotation => it.tree.children.tail match { - case (include: Tree)::(exclude: Tree)::Nil => RequiredArgs(getVersions(include), getVersions(exclude)) + case (include: Tree)::(exclude: Tree)::Nil => RequiredArgs(fieldName, getVersions(include), getVersions(exclude)) } } } - private def getAllNestedRequiredInfo(tp: Type, - fieldName: String, - predicate: Type => Boolean - ): Map[String, RequiredArgs] = { + def getAllNestedRequiredInfo(tp: Type, + predicate: Type => Boolean = Functions.isOBPType, + fieldName: String = null + ): Seq[RequiredArgs] = { if(!predicate(tp)) { - return Map.empty + return Nil } - val fieldToRequiredInfo: Map[String, RequiredArgs] = getAnnotations(tp) + val fieldToRequiredInfo: Iterable[RequiredArgs] = getAnnotations(tp) // current type's fields full path to RequiredInfo val currentPathToRequiredInfo = fieldName match { case null => fieldToRequiredInfo - case _ => fieldToRequiredInfo.map(it=> (s"$fieldName.${it._1}", it._2)) + case _ => fieldToRequiredInfo.map(it=> it.copy(fieldPath = s"$fieldName.${it.fieldPath}")) } // find all sub fields RequiredInfo - val subPathToRequiredInfo: Map[String, RequiredArgs] = tp.members.collect { - case m: MethodSymbolApi if m.isGetter => (m.name.decodedName.toString.trim, ReflectUtils.getNestFirstTypeArg(m.returnType)) - case m: TermSymbolApi if m.isCaseAccessor || m.isVal => (m.name.decodedName.toString.trim, m.info) - }.filter(tuple => predicate(tuple._2)) + val subPathToRequiredInfo: Iterable[RequiredArgs] = tp.members.collect { + case m: MethodSymbolApi if m.isGetter => { + (m.name.decodedName.toString.trim, ReflectUtils.getNestFirstTypeArg(m.returnType)) + } + case m: TermSymbolApi if m.isCaseAccessor || m.isVal => { + (m.name.decodedName.toString.trim, ReflectUtils.getNestFirstTypeArg(m.info)) + } + } .filter(tuple => predicate(tuple._2)) + .distinctBy(_._1) .flatMap(pair => { val (memberName, membersType) = pair val subFieldName = if(fieldName == null) memberName else s"$fieldName.$memberName" - getAllNestedRequiredInfo(membersType, subFieldName, predicate) - }).toMap + getAllNestedRequiredInfo(membersType, predicate, subFieldName) + }) - currentPathToRequiredInfo ++ subPathToRequiredInfo - } - - def getAllNestedRequiredInfo(tp: Type, - predicate: Type => Boolean = _ => true - ): Map[String, RequiredArgs] = { - val unSortedResult = getAllNestedRequiredInfo(tp, null, predicate) - ListMap(unSortedResult.toSeq.sortBy(_._1): _*) + (currentPathToRequiredInfo ++ subPathToRequiredInfo).toSeq.sortBy(_.fieldPath) } } diff --git a/obp-commons/src/test/scala/com/openbankproject/commons/util/RequiredFieldValidationTest.scala b/obp-commons/src/test/scala/com/openbankproject/commons/util/RequiredFieldValidationTest.scala index 16da54be4..8fd4f94fa 100644 --- a/obp-commons/src/test/scala/com/openbankproject/commons/util/RequiredFieldValidationTest.scala +++ b/obp-commons/src/test/scala/com/openbankproject/commons/util/RequiredFieldValidationTest.scala @@ -1,65 +1,66 @@ package com.openbankproject.commons.util -import com.openbankproject.commons.util.ApiVersion import com.openbankproject.commons.util.ApiVersion._ import org.scalatest.{FlatSpec, Matchers, Tag} import org.scalatest.PartialFunctionValues._ import scala.reflect.runtime.universe._ +import Functions.RichCollection class RequiredFieldValidationTest extends FlatSpec with Matchers { object tag extends Tag("RequiredFieldValidation") "when annotated at constructor param and overriding val" should "all the annotations be extract by call RequiredFieldValidation.getAnnotations" taggedAs tag in { - val symbols = RequiredFieldValidation.getAnnotations(typeOf[Bar]) + val symbols = RequiredFieldValidation.getAnnotations(typeOf[Bar]).toMapByKey(_.fieldPath) symbols should have size 3 - symbols("name") should equal(RequiredArgs(Array(ApiVersion.allVersion), Array(v3_0_0))) + symbols("name") should equal(RequiredArgs("name", Array(ApiVersion.allVersion), Array(v3_0_0))) symbols("age") should equal ( - RequiredArgs(Array(v2_0_0, v1_2_1, v1_4_0), Array.empty) + RequiredArgs("age", Array(v2_0_0, v1_2_1, v1_4_0), Array.empty) ) - symbols("email") should equal(RequiredArgs(Array(ApiVersion.allVersion), Array())) + symbols("email") should equal(RequiredArgs("email", Array(ApiVersion.allVersion), Array())) } "method RequiredFieldValidation.getAllNestedRequiredInfo" should "extract all nested required info" taggedAs tag in { - val stringToArgs: Map[String, RequiredArgs] = RequiredFieldValidation.getAllNestedRequiredInfo(typeOf[Outer]) + val requiredArgses = RequiredFieldValidation.getAllNestedRequiredInfo(typeOf[Outer]) + val stringToArgs: Map[String, RequiredArgs] = requiredArgses.toMapByKey(_.fieldPath) - val expectedRequireFooAnnoInfo = RequiredArgs(Array( v1_4_0)) - stringToArgs.valueAt("requireFoo") should equal (expectedRequireFooAnnoInfo) + val expectedRequireFooAnnoInfo = RequiredArgs("", Array( v1_4_0)) + stringToArgs.valueAt("requireFoo") should equal (expectedRequireFooAnnoInfo.copy(fieldPath = "requireFoo")) - val expectedNameAnnoInfo = RequiredArgs(Array(ApiVersion.allVersion)) - val expectedAgeAnnoInfo = RequiredArgs(Array(v2_0_0, v1_2_1, v1_4_0)) - val expectedEmailAnnoInfo = RequiredArgs(Array(ApiVersion.allVersion), Array(v2_0_0)) + val expectedNameAnnoInfo = RequiredArgs("", Array(ApiVersion.allVersion)) + val expectedAgeAnnoInfo = RequiredArgs("", Array(v2_0_0, v1_2_1, v1_4_0)) + val expectedEmailAnnoInfo = RequiredArgs("", Array(ApiVersion.allVersion), Array(v2_0_0)) - stringToArgs.valueAt("foo.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("foo.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("foo.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("foo.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "foo.name")) + stringToArgs.valueAt("foo.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "foo.age")) + stringToArgs.valueAt("foo.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "foo.email")) - stringToArgs.valueAt("requireFoo.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("requireFoo.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("requireFoo.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("requireFoo.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "requireFoo.name")) + stringToArgs.valueAt("requireFoo.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "requireFoo.age")) + stringToArgs.valueAt("requireFoo.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "requireFoo.email")) - stringToArgs.valueAt("list.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("list.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("list.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("list.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "list.name")) + stringToArgs.valueAt("list.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "list.age")) + stringToArgs.valueAt("list.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "list.email")) - stringToArgs.valueAt("array.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("array.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("array.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("array.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "array.name")) + stringToArgs.valueAt("array.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "array.age")) + stringToArgs.valueAt("array.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "array.email")) - val expectedMiddleRequiredAnnoInfo = RequiredArgs(Array(ApiVersion.allVersion)) - stringToArgs.valueAt("middle.middleRequired") should equal (expectedMiddleRequiredAnnoInfo) + val expectedMiddleRequiredAnnoInfo = RequiredArgs("", Array(ApiVersion.allVersion)) + stringToArgs.valueAt("middle.middleRequired") should equal (expectedMiddleRequiredAnnoInfo.copy(fieldPath = "middle.middleRequired")) - stringToArgs.valueAt("middle.middleRequired.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("middle.middleRequired.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("middle.middleRequired.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("middle.middleRequired.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "middle.middleRequired.name")) + stringToArgs.valueAt("middle.middleRequired.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "middle.middleRequired.age")) + stringToArgs.valueAt("middle.middleRequired.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "middle.middleRequired.email")) - stringToArgs.valueAt("middle.middleNoRequire.name") should equal (expectedNameAnnoInfo) - stringToArgs.valueAt("middle.middleNoRequire.age") should equal (expectedAgeAnnoInfo) - stringToArgs.valueAt("middle.middleNoRequire.email") should equal (expectedEmailAnnoInfo) + stringToArgs.valueAt("middle.middleNoRequire.name") should equal (expectedNameAnnoInfo.copy(fieldPath = "middle.middleNoRequire.name")) + stringToArgs.valueAt("middle.middleNoRequire.age") should equal (expectedAgeAnnoInfo.copy(fieldPath = "middle.middleNoRequire.age")) + stringToArgs.valueAt("middle.middleNoRequire.email") should equal (expectedEmailAnnoInfo.copy(fieldPath = "middle.middleNoRequire.email")) stringToArgs should have size (20) } diff --git a/pom.xml b/pom.xml index 2f0653469..eb822f733 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 2011 2.12 - 2.12.10 + 2.12.6 2.5.19 0.22 1.1.0