From 9258f4c6899db8b21f9a9ad9f8df22fcac922dd7 Mon Sep 17 00:00:00 2001 From: shuang Date: Sat, 3 Aug 2019 18:33:29 +0800 Subject: [PATCH] add unit test to check whether there are some modify in frozen types --- .gitignore | 3 +- .../swagger/APIBuilderSwagger.scala | 3 +- .../scala/code/api/util/ScannedApis.scala | 5 +- .../code/api/util/VersionedOBPApis.scala | 15 +++ .../scala/code/api/v1_2_1/OBPAPI1.2.1.scala | 4 +- .../scala/code/api/v1_3_0/OBPAPI1_3_0.scala | 4 +- .../scala/code/api/v1_4_0/OBPAPI1_4_0.scala | 4 +- .../scala/code/api/v2_0_0/OBPAPI2_0_0.scala | 4 +- .../scala/code/api/v2_1_0/OBPAPI2_1_0.scala | 4 +- .../scala/code/api/v2_2_0/OBPAPI2_2_0.scala | 4 +- .../scala/code/api/v3_0_0/OBPAPI3_0_0.scala | 4 +- .../scala/code/api/v3_1_0/OBPAPI3_1_0.scala | 4 +- .../scala/code/api/v4_0_0/OBPAPI4_0_0.scala | 6 +- .../main/scala/code/util/ClassScanUtils.scala | 5 +- .../src/test/resources/frozen_type_meta_data | Bin 0 -> 52392 bytes obp-api/src/test/scala/RunWebApp.scala | 1 - .../scala/code/util/FrozenClassTest.scala | 81 +++++++++++++++ .../scala/code/util/FrozenClassUtil.scala | 96 ++++++++++++++++++ .../commons/util/ReflectUtils.scala | 17 +++- 19 files changed, 235 insertions(+), 29 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/VersionedOBPApis.scala create mode 100644 obp-api/src/test/resources/frozen_type_meta_data create mode 100644 obp-api/src/test/scala/code/util/FrozenClassTest.scala create mode 100644 obp-api/src/test/scala/code/util/FrozenClassUtil.scala diff --git a/.gitignore b/.gitignore index e2db29849..bb86ade8d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ .cache target obp-api/src/main/resources/ -obp-api/src/test/resources/ +obp-api/src/test/resources/** +!obp-api/src/test/resources/frozen_type_meta_data *.iml obp-api/src/main/resources/log4j.properties obp-api/src/main/scripts/kafka/kafka_* diff --git a/obp-api/src/main/scala/code/api/APIBuilder/swagger/APIBuilderSwagger.scala b/obp-api/src/main/scala/code/api/APIBuilder/swagger/APIBuilderSwagger.scala index cab09d1d8..454a5c93a 100644 --- a/obp-api/src/main/scala/code/api/APIBuilder/swagger/APIBuilderSwagger.scala +++ b/obp-api/src/main/scala/code/api/APIBuilder/swagger/APIBuilderSwagger.scala @@ -33,8 +33,7 @@ import net.liftweb.json.{JArray, JValue} import scala.meta._ -object APIBuilderSwagger -{ +object APIBuilderSwagger { def main(args: Array[String]): Unit = overwriteApiCode(apiSource,jsonFactorySource) val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("src/main/scala/code/api/APIBuilder/swagger/swaggerResource.json") diff --git a/obp-api/src/main/scala/code/api/util/ScannedApis.scala b/obp-api/src/main/scala/code/api/util/ScannedApis.scala index 2dd96c9b7..d92bc633d 100644 --- a/obp-api/src/main/scala/code/api/util/ScannedApis.scala +++ b/obp-api/src/main/scala/code/api/util/ScannedApis.scala @@ -21,5 +21,8 @@ object ScannedApis { /** * this map value are all scanned objects those extends ScannedApiVersion, the key is it apiVersion field */ - lazy val versionMapScannedApis: Map[ScannedApiVersion, ScannedApis] = ClassScanUtils.getSubTypeObjects(classOf[ScannedApis]).map(it=> (it.apiVersion, it)).toMap + lazy val versionMapScannedApis: Map[ScannedApiVersion, ScannedApis] = + ClassScanUtils.getSubTypeObjects[ScannedApis] + .map(it=> (it.apiVersion, it)) + .toMap } diff --git a/obp-api/src/main/scala/code/api/util/VersionedOBPApis.scala b/obp-api/src/main/scala/code/api/util/VersionedOBPApis.scala new file mode 100644 index 000000000..49d1b5221 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/VersionedOBPApis.scala @@ -0,0 +1,15 @@ +package code.api.util + +import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc} + +import scala.collection.mutable.ArrayBuffer + +trait VersionedOBPApis { + def version : ApiVersion + + def versionStatus: String + + def allResourceDocs: ArrayBuffer[ResourceDoc] + + def routes: List[OBPEndpoint] +} diff --git a/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala b/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala index 55f48a034..5c7b8bc80 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala @@ -28,12 +28,12 @@ package code.api.v1_2_1 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.util.Helper.MdcLoggable // Added so we can add resource docs for this version of the API -object OBPAPI1_2_1 extends OBPRestHelper with APIMethods121 with MdcLoggable { +object OBPAPI1_2_1 extends OBPRestHelper with APIMethods121 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v1_2_1 // "1.2.1" diff --git a/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala b/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala index ab451b6b5..28dcf5f1a 100644 --- a/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala +++ b/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala @@ -2,7 +2,7 @@ package code.api.v1_3_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.api.v1_2_1.APIMethods121 import code.util.Helper.MdcLoggable @@ -11,7 +11,7 @@ import code.util.Helper.MdcLoggable //has APIMethods121 as all api calls that went unchanged from 1.2.1 to 1.3.0 will use the old //implementation -object OBPAPI1_3_0 extends OBPRestHelper with APIMethods130 with APIMethods121 with MdcLoggable { +object OBPAPI1_3_0 extends OBPRestHelper with APIMethods130 with APIMethods121 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v1_3_0 // "1.3.0" val versionStatus = "STABLE" diff --git a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala index 18fabf9b3..73e97db0a 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala @@ -2,11 +2,11 @@ package code.api.v1_4_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.util.Helper.MdcLoggable -object OBPAPI1_4_0 extends OBPRestHelper with APIMethods140 with MdcLoggable { +object OBPAPI1_4_0 extends OBPRestHelper with APIMethods140 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v1_4_0 //"1.4.0" val versionStatus = "STABLE" diff --git a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala index e13429c19..b34a23e74 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala @@ -28,12 +28,12 @@ package code.api.v2_0_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.api.v1_3_0.APIMethods130 import code.api.v1_4_0.APIMethods140 import code.util.Helper.MdcLoggable -object OBPAPI2_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with MdcLoggable { +object OBPAPI2_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v2_0_0 // "2.0.0" diff --git a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala index fe9aedae1..c70a76562 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala @@ -28,7 +28,7 @@ package code.api.v2_1_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.{APIUtil, ApiVersion} +import code.api.util.{APIUtil, ApiVersion, VersionedOBPApis} import code.api.v1_3_0.APIMethods130 import code.api.v1_4_0.APIMethods140 import code.api.v2_0_0.APIMethods200 @@ -36,7 +36,7 @@ import code.util.Helper.MdcLoggable import scala.collection.immutable.Nil -object OBPAPI2_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with MdcLoggable { +object OBPAPI2_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with MdcLoggable with VersionedOBPApis{ diff --git a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala index 4c933d04d..261f4fa1e 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala @@ -3,7 +3,7 @@ package code.api.v2_2_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.{APIUtil, ApiVersion} +import code.api.util.{APIUtil, ApiVersion, VersionedOBPApis} import code.api.v1_3_0.APIMethods130 import code.api.v1_4_0.APIMethods140 import code.api.v2_0_0.APIMethods200 @@ -12,7 +12,7 @@ import code.util.Helper.MdcLoggable import scala.collection.immutable.Nil -object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with MdcLoggable { +object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v2_2_0 // "2.2.0" val versionStatus = "STABLE" diff --git a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala index 7e6c2dd04..d5f487b6c 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala @@ -28,7 +28,7 @@ package code.api.v3_0_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.api.v1_3_0.APIMethods130 import code.api.v1_4_0.APIMethods140 import code.api.v2_0_0.APIMethods200 @@ -46,7 +46,7 @@ This file defines which endpoints from all the versions are available in v3.0.0 */ -object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with MdcLoggable { +object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with MdcLoggable with VersionedOBPApis{ diff --git a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala index e6be767d9..c8c2ea7ab 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala @@ -28,7 +28,7 @@ package code.api.v3_1_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion +import code.api.util.{ApiVersion, VersionedOBPApis} import code.api.v1_3_0.APIMethods130 import code.api.v1_4_0.APIMethods140 import code.api.v2_0_0.APIMethods200 @@ -47,7 +47,7 @@ This file defines which endpoints from all the versions are available in v3.0.0 */ -object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with APIMethods310 with MdcLoggable { +object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with APIMethods310 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v3_1_0 diff --git a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala index 430a17028..2c3278e3e 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala @@ -28,8 +28,8 @@ package code.api.v4_0_0 import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} -import code.api.util.ApiVersion -import code.api.v1_3_0.APIMethods130 +import code.api.util.{ApiVersion, VersionedOBPApis} +import code.api.v1_3_0.{APIMethods130} import code.api.v1_4_0.APIMethods140 import code.api.v2_0_0.APIMethods200 import code.api.v2_1_0.APIMethods210 @@ -48,7 +48,7 @@ This file defines which endpoints from all the versions are available in v4.0.0 */ -object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with APIMethods310 with APIMethods400 with MdcLoggable { +object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 with APIMethods200 with APIMethods210 with APIMethods220 with APIMethods300 with CustomAPIMethods300 with APIMethods310 with APIMethods400 with MdcLoggable with VersionedOBPApis{ val version : ApiVersion = ApiVersion.v4_0_0 diff --git a/obp-api/src/main/scala/code/util/ClassScanUtils.scala b/obp-api/src/main/scala/code/util/ClassScanUtils.scala index 57f0bcc39..c7cc44284 100644 --- a/obp-api/src/main/scala/code/util/ClassScanUtils.scala +++ b/obp-api/src/main/scala/code/util/ClassScanUtils.scala @@ -5,6 +5,7 @@ import java.io.File import com.openbankproject.commons.model.Bank import org.apache.commons.lang3.StringUtils import org.clapper.classutil.{ClassFinder, ClassInfo} +import com.openbankproject.commons.util.ReflectUtils import scala.reflect.runtime.universe.TypeTag @@ -29,11 +30,11 @@ object ClassScanUtils { /** * scan classpath to get all companion objects or singleton objects those implements given trait - * @param clazz a trait type for filter object * @tparam T the trait type parameter * @return all companion objects or singleton object those implements given clazz */ - def getSubTypeObjects[T:TypeTag](clazz: Class[T]) = { + def getSubTypeObjects[T:TypeTag]: List[T] = { + val clazz = ReflectUtils.typeTagToClass[T] finder.getClasses().filter(_.implements(clazz.getName)).map(_.name).map(companion[T](_)).toList } diff --git a/obp-api/src/test/resources/frozen_type_meta_data b/obp-api/src/test/resources/frozen_type_meta_data new file mode 100644 index 0000000000000000000000000000000000000000..ad3f22a56ed7f25c904057b0b778052dc77ff281 GIT binary patch literal 52392 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 Pk=lmgNKUh(K~Me(RjX=K literal 0 HcmV?d00001 diff --git a/obp-api/src/test/scala/RunWebApp.scala b/obp-api/src/test/scala/RunWebApp.scala index a02470c71..ef1248db3 100644 --- a/obp-api/src/test/scala/RunWebApp.scala +++ b/obp-api/src/test/scala/RunWebApp.scala @@ -26,7 +26,6 @@ TESOBE (http://www.tesobe.com/) */ import code.api.util.APIUtil -import net.liftweb.util.Props import org.eclipse.jetty.server.Server import org.eclipse.jetty.webapp.WebAppContext diff --git a/obp-api/src/test/scala/code/util/FrozenClassTest.scala b/obp-api/src/test/scala/code/util/FrozenClassTest.scala new file mode 100644 index 000000000..8161fa690 --- /dev/null +++ b/obp-api/src/test/scala/code/util/FrozenClassTest.scala @@ -0,0 +1,81 @@ +package code.util + +import code.api.util.ApiVersion +import code.setup.ServerSetup +import org.scalatest.Tag + +class FrozenClassTest extends ServerSetup { + + object FrozenClassTag extends Tag("Frozen_Classes") + + val (persistedVersionToEndpointNames, persistedTypeNameToTypeValFields) = FrozenClassUtil.readPersistedFrozenApiInfo + val (versionToEndpointNames, typeNameToTypeValFields) = FrozenClassUtil.getFrozenApiInfo + + feature("Frozen version apis not changed") { + + scenario(s"count of STABLE OBPAPIxxxx should not be reduce, if pretty sure need modify it, please run ${FrozenClassUtil.sourceName}", FrozenClassTag) { + + val persistedStableVersions = persistedVersionToEndpointNames.map(_._1).toSet + val currentStableVersions = versionToEndpointNames.map(_._1).toSet + + val increasedVersions = persistedStableVersions.diff(currentStableVersions) + increasedVersions should equal(Set.empty[ApiVersion]) + } + + scenario(s"count of STABLE OBPAPIxxxx should not be increased, if pretty sure need modify it, please run ${FrozenClassUtil.sourceName}", FrozenClassTag) { + val persistedStableVersions = persistedVersionToEndpointNames.map(_._1).toSet + val currentStableVersions = versionToEndpointNames.map(_._1).toSet + + val reducedVersions = currentStableVersions.diff(persistedStableVersions) + reducedVersions should equal(Set.empty[ApiVersion]) + } + + scenario(s"api count of STABLE value of OBPAPIxxxx#versionStatus should not be reduce, if pretty sure need modify it, please run ${FrozenClassUtil.sourceName}", FrozenClassTag) { + val reducedApis = for { + (pVersion, pEndpointNames) <- persistedVersionToEndpointNames + (version, endpointNames) <- versionToEndpointNames + if (pVersion == version) + reducedApisOfVersion = pEndpointNames.diff(endpointNames).mkString(",") + if (reducedApisOfVersion.size > 0) + } yield { + s"$version reduced apis: $reducedApisOfVersion" + } + reducedApis should equal(Nil) + } + + scenario(s"api count of STABLE value of OBPAPIxxxx#versionStatus should not be increased, if pretty sure need modify it, please run ${FrozenClassUtil.sourceName}", FrozenClassTag) { + val increasedApis = for { + (pVersion, pEndpointNames) <- persistedVersionToEndpointNames + (version, endpointNames) <- versionToEndpointNames + if (pVersion == version) + increasedApis = endpointNames.diff(pEndpointNames).mkString(",") + if (increasedApis.size > 0) + } yield { + s"$version increased apis: $increasedApis" + } + increasedApis should equal(Nil) + } + } + + feature("Frozen type structure not be modified") { + scenario(s"frozen class structure should not be modified, if pretty sure need modify it, please run ${FrozenClassUtil.sourceName}", FrozenClassTag) { + val changedTypes = for { + (pTypeName, pFields) <- persistedTypeNameToTypeValFields.toList + (typeName, fields) <- typeNameToTypeValFields.toList + if(pTypeName == typeName && pFields != fields) + } yield { + val expectStructure = pFields.map(pair => s"${pair._1}:${pair._2}").mkString("(", ", ", ")") + val actualStructure = fields.map(pair => s"${pair._1}:${pair._2}").mkString("(", ", ", ")") + + s""" + |{ + | typeName: $typeName + | expectStructure: $expectStructure + | actualStructure: $actualStructure + |} + |""".stripMargin + } + changedTypes should equal (Nil) + } + } +} diff --git a/obp-api/src/test/scala/code/util/FrozenClassUtil.scala b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala new file mode 100644 index 000000000..077df525b --- /dev/null +++ b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala @@ -0,0 +1,96 @@ +package code.util + +import java.io._ +import java.net.URI + +import code.TestServer +import code.api.util.{ApiVersion, VersionedOBPApis} +import com.openbankproject.commons.util.ReflectUtils +import org.apache.commons.io.IOUtils + +import scala.reflect.runtime.universe._ + +/** + * this util is for persist metadata of frozen type, those frozen type is versionStatus = "STABLE" related example classes, + * after persist the metadata, the FrozenClassTest can check whether there some modify change any frozen type, the test will fail when there are some changes in the frozen type + */ +object FrozenClassUtil { + + val sourceName = s"""${this.getClass.getName.replace("$", "")}.scala""" + // current project absolute path + val basePath = this.getClass.getResource("/").toString .replaceFirst("target[/\\\\].*$", "") + val persistFilePath = new URI(s"${basePath}/src/test/resources/frozen_type_meta_data").getPath + + def main(args: Array[String]): Unit = { + System.setProperty("run.mode", "test") // make sure this Props.mode is the same as unit test Props.mode + val server = TestServer + val out = new ObjectOutputStream(new FileOutputStream(persistFilePath)) + try { + out.writeObject(getFrozenApiInfo) + } finally { + IOUtils.closeQuietly(out) + // there is no graceful way to shutdown jetty server, so here use brutal way to shutdown it. + server.server.stop() + System.exit(0) + } + } + + /** + * get frozen api information by scan classes + * @return frozen api information, include api names of given api version and frozen class metadata + */ + def getFrozenApiInfo: (List[(ApiVersion, Set[String])], Map[String, Map[String, String]]) = { + val versionedOBPApisList: List[VersionedOBPApis] = ClassScanUtils.getSubTypeObjects[VersionedOBPApis] + .filter(_.versionStatus == "STABLE") + + val versionToEndpointNames: List[(ApiVersion, Set[String])] = versionedOBPApisList + .map(it => { + val version = it.version + val currentVersionApis = it.allResourceDocs.filter(version == _.implementedInApiVersion).toSet + (version, currentVersionApis.map(_.partialFunctionName)) + }) + + val allFreezingTypes: Set[Type] = versionedOBPApisList + .flatMap(_.allResourceDocs) + .flatMap(it => it.exampleRequestBody :: it.successResponseBody :: Nil) + .filter(ReflectUtils.isObpObject(_)) + .map(ReflectUtils.getType(_)) + .toSet + .flatMap(getNestedOBPType(_)) + + val typeNameToTypeValFields: Map[String, Map[String, String]] = allFreezingTypes + .map(it => { + val valNameToTypeName = ReflectUtils.getConstructorParamInfo(it).map(pair => (pair._1, pair._2.toString)) + (it.typeSymbol.asClass.fullName, valNameToTypeName) + }) + .toMap + (versionToEndpointNames, typeNameToTypeValFields) + } + + /** + * read persisted frozen api info from persist file + * @return persisted frozen api information, include api names of given api version and frozen class metadata + */ + def readPersistedFrozenApiInfo: (List[(ApiVersion, Set[String])], Map[String, Map[String, String]]) = { + assume(new File(persistFilePath).exists(), s"freeze type not persisted yet, please run ${this.sourceName}") + val input = new ObjectInputStream(new FileInputStream(persistFilePath)) + try { + input.readObject().asInstanceOf[(List[(ApiVersion, Set[String])], Map[String, Map[String, String]])] + } finally { + IOUtils.closeQuietly(input) + } + } + + private def getNestedOBPType(tp: Type): Set[Type] = { + ReflectUtils.getConstructorParamInfo(tp) + .values + .map(it => ReflectUtils.getDeepGenericType(it).head) + .toSet + .filter(ReflectUtils.isObpType) + .filterNot(tp ==) // avoid infinite recursive + match { + case set if(set.size > 0) => set.flatMap(getNestedOBPType) + tp + case _ => Set(tp) + } + } +} 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 023c6cb60..0b6454dc1 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 @@ -15,7 +15,7 @@ object ReflectUtils { def isObpObject(any: Any): Boolean = any != null && OBP_TYPE_REGEX.findFirstIn(any.getClass.getName).isDefined - def isObpType(tp: Type): Boolean = tp != null && OBP_TYPE_REGEX.findFirstIn(tp.typeSymbol.fullName).isDefined + def isObpType(tp: Type): Boolean = tp != null && tp.typeSymbol.isClass && OBP_TYPE_REGEX.findFirstIn(tp.typeSymbol.fullName).isDefined /** * get all val and var name to values of given object @@ -278,6 +278,11 @@ object ReflectUtils { }) } + def typeTagToClass[T: TypeTag]: Class[_] = { + val tt = implicitly[TypeTag[T]] + tt.mirror.runtimeClass(tt.tpe.typeSymbol.asClass) + } + def classToSymbol(clazz: Class[_]): ru.ClassSymbol = ru.runtimeMirror(clazz.getClassLoader).classSymbol(clazz) /** @@ -285,10 +290,16 @@ object ReflectUtils { * @param tp to do extract type * @return a map of constructor parameter name to type, if tp is abstract, return empty amp */ - def getConstructorParamInfo(tp: ru.Type): Map[String, ru.Type] = tp.typeSymbol.isClass match { + def getConstructorParamInfo(tp: ru.Type): Map[String, ru.Type] = + tp.typeSymbol.isClass && !tp.typeSymbol.asClass.isTrait match { case false => Map.empty[String, ru.Type] case true => { - ReflectUtils.getPrimaryConstructor(tp).paramLists.headOption.getOrElse(Nil).map(it => (it.name.toString, it.info)).toMap + ReflectUtils.getPrimaryConstructor(tp) + .paramLists + .headOption + .getOrElse(Nil) + .map(it => (it.name.toString, it.info)) + .toMap } } /**