Merge pull request #2175 from hongwei1/bugfix/Resource_Doc_Missing_Users

Bugfix/resource doc missing users
This commit is contained in:
Simon Redfern 2023-01-26 12:23:21 +01:00 committed by GitHub
commit 9a34c8763c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 193 additions and 18 deletions

View File

@ -1802,7 +1802,7 @@ object ExampleValue {
lazy val canSeeBankRoutingAddressExample = ConnectorField(booleanTrue,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("can_see_bank_routing_address", canSeeBankRoutingAddressExample)
lazy val usersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val usersExample = ConnectorField("user list", "Please refer to the user object.")
glossaryItems += makeGlossaryItem("users", usersExample)
lazy val staffNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)

View File

@ -26,6 +26,8 @@ import java.util.regex.Pattern
import com.openbankproject.commons.model.enums.LanguageParam
import java.lang.reflect.Field
object JSONFactory1_4_0 extends MdcLoggable{
implicit def formats: Formats = CustomJsonFormats.formats
case class PostCustomerJson(
@ -450,7 +452,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
def boldIfMandatory() = {
optionalTypeFields.exists(i => i._1 == parameter && i._2 == false) match {
case true =>
s"***$parameter**"
s"**$parameter**"
case false =>
s"$parameter"
}
@ -460,33 +462,55 @@ object JSONFactory1_4_0 extends MdcLoggable{
} else {
s"""
|
|* [${boldIfMandatory()}](/glossary#$glossaryItemTitle): $exampleFieldValue
|[${boldIfMandatory()}](/glossary#$glossaryItemTitle): $exampleFieldValue
|
|""".stripMargin
}
}
def prepareJsonFieldDescription(jsonBody: scala.Product, jsonType: String): String = {
jsonBody.productIterator
val (jsonBodyJValue: json.JValue, optionalTypeFields) = jsonBody match {
case JvalueCaseClass(jValue) =>
val types = Nil
(jValue, types)
case _ =>
val types = jsonBody.getClass()
.getDeclaredFields().toList
.map(f => (f.getName(), f.getType().getCanonicalName().contains("Option")))
(decompose(jsonBody), types)
def getAllFields(jsonBody: scala.Product): List[Field] = {
def loopAllFields(rootFields: List[Field]) = {
val fields = for {
field <- jsonBody.productIterator.toList if (field.isInstanceOf[scala.Product] && field != jsonBody)
fields = getAllFields(field.asInstanceOf[scala.Product])
} yield
fields
(rootFields ++ fields.flatten).toSet.toList
}
//The root level is a list: eg: List[Users]
if(jsonBody.isInstanceOf[List[Any]] && jsonBody.productIterator.toList.nonEmpty){
val rootFields: List[Field] = jsonBody.productIterator.toSet.head.getClass.getDeclaredFields.toList
loopAllFields(rootFields)
}else {
jsonBody match {
case JvalueCaseClass(jValue) =>
val types = Nil
types
case _ =>
val rootFields: List[Field] = jsonBody.getClass().getDeclaredFields().toSet.toList
loopAllFields(rootFields)
}
}
}
def checkFieldOption(jsonBody: scala.Product, rootFields: List[Field]) = {
val types = rootFields.map(f => (f.getName(), f.getType().getCanonicalName().contains("Option")))
(decompose(jsonBody), types)
}
def prepareJsonFieldDescription(jsonBody: scala.Product, jsonType: String): String = {
val allFields = getAllFields(jsonBody)
val (jsonBodyJValue: json.JValue, allFieldsAndOptionStatus) = checkFieldOption(jsonBody, allFields)
// Group by is mandatory criteria and sort those 2 groups by name of the field
val jsonBodyFieldsOptional = JsonUtils.collectFieldNames(jsonBodyJValue).keySet.toList
.filter(x => optionalTypeFields.exists(i => i._1 == x && i._2 == true)).sorted
.filter(x => allFieldsAndOptionStatus.exists(i => i._1 == x && i._2 == true)).sorted
val jsonBodyFieldsMandatory = JsonUtils.collectFieldNames(jsonBodyJValue).keySet.toList
.filter(x => optionalTypeFields.exists(i => i._1 == x && i._2 == false)).sorted
.filter(x => allFieldsAndOptionStatus.exists(i => i._1 == x && i._2 == false)).sorted
val jsonBodyFields = jsonBodyFieldsMandatory ::: jsonBodyFieldsOptional
val jsonFieldsDescription = jsonBodyFields.map(i => prepareDescription(i, optionalTypeFields))
val jsonFieldsDescription = jsonBodyFields.map(i => prepareDescription(i, allFieldsAndOptionStatus))
val jsonTitleType = if (jsonType.contains("request")) "\n\n\n**JSON request body fields:**\n\n" else "\n\n\n**JSON response body fields:**\n\n"
@ -527,6 +551,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
""
}
//3rd: get the fields description from the response body:
//response body can be a nest class, need to loop all the fields.
val responseFieldsDescription = prepareJsonFieldDescription(resourceDocUpdatedTags.successResponseBody,"response")
urlParametersDescription ++ exampleRequestBodyFieldsDescription ++ responseFieldsDescription
}

View File

@ -1,7 +1,8 @@
package code.api.v1_4_0
import java.util.Date
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.usersJsonV400
import java.util.Date
import code.api.util.APIUtil.ResourceDoc
import code.api.util.{APIUtil, ExampleValue}
import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocJson
@ -51,6 +52,40 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers {
description.contains("[BANK_ID](/glossary#Bank.bank_id): gh.29.uk") should be (true)
}
scenario("prepareJsonFieldDescription should work well - users object") {
val usersJson = usersJsonV400
val description = JSONFactory1_4_0.prepareJsonFieldDescription(usersJson, "response")
description.contains(
"""
|JSON response body fields:
|
|*user_id = 9ca9a7e4-6d02-40e3-a129-0b2bf89de9b1,
|
|*email = felixsmith@example.com,
|
|*provider_id = ,
|
|*provider = ,
|
|*username = felixsmith,
|
|*entitlements = ,
|
|*views = ,
|
|*agreements = ,
|
|*is_deleted = false,
|
|*last_marketing_agreement_signed_date = ,
|
|*is_locked = false
|
|""".stripMargin
) should be (false)
println(description)
}
scenario("PrepareUrlParameterDescription should work well, extract the parameters from URL") {
val requestUrl1 = "/obp/v4.0.0/banks/BANK_ID/accounts/account_ids/private"
val requestUrl1Description = JSONFactory1_4_0.prepareUrlParameterDescription(requestUrl1)

View File

@ -0,0 +1,115 @@
package code.api.v1_4_0
import code.api.util.CustomJsonFormats
import code.util.Helper.MdcLoggable
import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FeatureSpec, GivenWhenThen, Matchers}
import java.lang.reflect.Field
import java.util.Date
class JSONFactory1_4_0_LightTest extends FeatureSpec
with BeforeAndAfterEach
with GivenWhenThen
with BeforeAndAfterAll
with Matchers
with MdcLoggable
with CustomJsonFormats {
feature("Test JSONFactory1_4_0.getJValueAndAllFields method") {
case class ClassOne(
string1: String = "1"
)
case class ClassTwo(
string2: String = "2",
strings2: List[String] = List("List-2")
)
val oneObject = ClassOne()
case class NestedClass(
classes: List[ClassOne] = List(oneObject)
)
val twoObject = ClassTwo()
case class NestedListClass(
classes1: List[ClassOne] = List(oneObject)
)
val nestedClass = NestedClass()
val nestedListClass = NestedListClass()
case class ComplexNestedClass(
complexNestedClassString: String = "ComplexNestedClass1",
complexNestedClassInt: Int = 1,
complexNestedClassDate: Date = new Date(),
complexNestedClassOptionSomeInt: Option[Int] = Some(1),
complexNestedClassOptionNoneInt: Option[Int] = None,
classes1: List[ClassOne] = List(oneObject),
classes2: List[ClassTwo] = List(twoObject),
)
val complexNestedClass = ComplexNestedClass()
scenario("getJValueAndAllFields -input is the oneObject, basic no nested, no List inside") {
val listFields: List[Field] = JSONFactory1_4_0.getAllFields(oneObject)
val expectedListFieldsString = "List(private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.string1, " +
"private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.$outer)"
listFields.toString shouldBe (expectedListFieldsString)
// println(listFields)
}
scenario("getJValueAndAllFields -input it the nestedClass") {
val listFields: List[Field] = JSONFactory1_4_0.getAllFields(nestedClass)
val expectedListFieldsString = "List(" +
"public static final long scala.collection.immutable.Nil$.serialVersionUID, public static scala.collection.immutable.Nil$ scala.collection.immutable.Nil$.MODULE$, " +
"private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.$outer, " +
"private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$NestedClass$1.$outer, " +
"private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.string1, " +
"private final scala.collection.immutable.List code.api.v1_4_0.JSONFactory1_4_0_LightTest$NestedClass$1.classes)"
listFields.toString shouldBe (expectedListFieldsString)
// println(listFields)
}
scenario("getJValueAndAllFields - input is the List[nestedClass]") {
val listFields: List[Field] = JSONFactory1_4_0.getAllFields(List(oneObject))
// it should return all the fields in the List
val expectedListFieldsString = "List(private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.string1, " +
"private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.$outer, " +
"public static scala.collection.immutable.Nil$ scala.collection.immutable.Nil$.MODULE$, " +
"public static final long scala.collection.immutable.Nil$.serialVersionUID)"
listFields.toString shouldBe (expectedListFieldsString)
// println(listFields)
}
scenario("getJValueAndAllFields -input it the complexNestedClass") {
val listFields: List[Field] = JSONFactory1_4_0.getAllFields(complexNestedClass)
listFields.toString contains ("private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassString, ") shouldBe (true)
listFields.toString contains ("private final int code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassInt, ") shouldBe (true)
listFields.toString contains ("private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.$outer,") shouldBe (true)
listFields.toString contains ("public static final long scala.collection.immutable.Nil$.serialVersionUID, ") shouldBe (true)
listFields.toString contains ("private final scala.collection.immutable.List code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.classes2, ") shouldBe (true)
listFields.toString contains ("private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.string2, ") shouldBe (true)
listFields.toString contains ("public static scala.collection.immutable.Nil$ scala.collection.immutable.Nil$.MODULE$, public static final long scala.None$.serialVersionUID, ") shouldBe (true)
listFields.toString contains ("private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.$outer, ") shouldBe (true)
listFields.toString contains ("private final scala.Option code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassOptionSomeInt") shouldBe (true)
listFields.toString contains ("public static scala.None$ scala.None$.MODULE$, private final java.lang.Object scala.Some.value, private final scala.collection.immutable.List code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.classes1, ") shouldBe (true)
listFields.toString contains ("private final java.util.Date code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassDate, ") shouldBe (true)
listFields.toString contains ("private final scala.collection.immutable.List code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.strings2, ") shouldBe (true)
listFields.toString contains ("private int java.lang.String.hash, private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.string1, ") shouldBe (true)
listFields.toString contains ("private static final long java.lang.String.serialVersionUID, private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.$outer, ") shouldBe (true)
listFields.toString contains ("private final scala.Option code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassOptionNoneIn") shouldBe (true)
// println(listFields)
}
}
}