diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
index 3893d9441..da0bb1bdf 100644
--- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
+++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
@@ -873,7 +873,7 @@ trait APIMethods400 {
case EntityName(entityName) :: Nil JsonGet req => { cc =>
val listName = StringHelpers.snakify(English.plural(entityName))
for {
- (Full(resultList: JObject), _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entityName, None, None, Some(cc))
+ (Full(resultList: JArray), _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entityName, None, None, Some(cc))
} yield {
import net.liftweb.json.JsonDSL._
val jValue: JObject = listName -> resultList
diff --git a/obp-api/src/main/scala/code/api/v4_0_0/DynamicEntityHelper.scala b/obp-api/src/main/scala/code/api/v4_0_0/DynamicEntityHelper.scala
index 48e06859a..cc3906968 100644
--- a/obp-api/src/main/scala/code/api/v4_0_0/DynamicEntityHelper.scala
+++ b/obp-api/src/main/scala/code/api/v4_0_0/DynamicEntityHelper.scala
@@ -53,7 +53,11 @@ object MockerConnector {
def getAll(entityName: String) = persistedEntities.filter(pair => pair._1._2 == entityName).values
- def delete(entityName: String, id: String): Box[Boolean] = persistedEntities.remove(id -> entityName).map(_ => true)
+ def delete(entityName: String, id: String): Box[Boolean] = {
+ val idName = StringUtils.uncapitalize(entityName) + "Id"
+ require(persistedEntities.contains(id -> entityName), s"$InvalidUrl not exists ${entityName} of ${idName} = $id")
+ persistedEntities.remove(id -> entityName).map(_ => true)
+ }
def doc = {
val docs: Seq[ResourceDoc] = definitionsMap.values.flatMap(createDocs).toSeq
diff --git a/obp-api/src/main/scala/code/bankconnectors/ConnectorEndpoints.scala b/obp-api/src/main/scala/code/bankconnectors/ConnectorEndpoints.scala
index c5130576b..2be0a303a 100644
--- a/obp-api/src/main/scala/code/bankconnectors/ConnectorEndpoints.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/ConnectorEndpoints.scala
@@ -144,8 +144,8 @@ object ConnectorEndpoints extends RestHelper{
// it is impossible to get the type of OBPQueryParam*, ru.typeOf[OBPQueryParam*] not work, it is Seq type indeed
private val paramsType = ru.typeOf[Seq[OBPQueryParam]]
- // (methodName, paramNames, method, allParamNames)
- lazy val allMethods: List[(String, List[String], ru.MethodSymbol, List[String])] = {
+ // (methodName, paramNames, method, allParamNames, fn: paramName => isOption)
+ lazy val allMethods: List[(String, List[String], ru.MethodSymbol, List[String], String => Boolean)] = {
val mirror: ru.Mirror = ru.runtimeMirror(this.getClass.getClassLoader)
val objMirror = mirror.reflect(LocalMappedConnector)
@@ -161,14 +161,17 @@ object ConnectorEndpoints extends RestHelper{
val names = allParams
.filterNot(symbol => isCallContextOrQueryParams(symbol.info))
.map(_.name.toString.trim)
- (it.name.toString, names, it.asMethod, allNames)
+ val paramNameToIsOption: Map[String, Boolean] = allParams.map(it => (it.name.toString.trim, it.info <:< ru.typeOf[Option[_]])).toMap
+ val isParamOption: String => Boolean = name => paramNameToIsOption.get(name).filter(true ==).isDefined
+ (it.name.toString, names, it.asMethod, allNames, isParamOption)
})
.toList
}
def getMethod(methodName: String, json: JValue): Option[ru.MethodSymbol] = {
- this.allMethods.filter { triple =>
- triple._1 == methodName && triple._2.forall(paramName => (json \ paramName) != JNothing)
+ this.allMethods.filter { quadruple =>
+ val (mName, paramNames, _, _, isParamOption) = quadruple
+ mName == methodName && paramNames.forall(paramName => isParamOption(paramName) || (json \ paramName) != JNothing)
}
.sortBy(_._2.size)
.lastOption
diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala
index c4b72553a..82ae24715 100644
--- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala
@@ -13,6 +13,7 @@ import code.api.util.ErrorMessages._
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA
import code.api.util._
import code.api.v4_0_0.MockerConnector
+import code.api.v4_0_0.MockerConnector.persistedEntities
import code.atms.Atms.Atm
import code.atms.MappedAtm
import code.branches.Branches.Branch
@@ -64,6 +65,7 @@ import net.liftweb.mapper.{By, _}
import net.liftweb.util.Helpers.{tryo, _}
import net.liftweb.util.Mailer
import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To}
+import org.apache.commons.lang3.StringUtils
import org.mindrot.jbcrypt.BCrypt
import scalacache.ScalaCache
import scalacache.guava.GuavaCache
@@ -2793,25 +2795,39 @@ object LocalMappedConnector extends Connector with MdcLoggable {
entityName: String,
requestBody: Option[JObject],
entityId: Option[String],
- callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = Future {
- val processResult: Box[JValue] = operation match {
- case GET_ALL => Full {
- JArray(MockerConnector.getAll(entityName).toList)
- }
- case GET_ONE => {
- val boxedEntity: Box[JValue] = MockerConnector.getSingle(entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required.")))
- boxedEntity
- }
- case CREATE | UPDATE => {
- val body = requestBody.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument please supply the requestBody."))
- val persistedEntity = MockerConnector.persist(entityName, body, entityId)
- Full(persistedEntity)
- }
- case DELETE => {
- val deleteResult = MockerConnector.delete(entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required. ")))
- deleteResult.map(JBool(_))
+ callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
+ operation match {
+ case GET_ONE | UPDATE | DELETE => {
+ val id = entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required."))
+ val idName = StringUtils.uncapitalize(entityName) + "Id"
+ val idExists = persistedEntities.contains(id -> entityName)
+ if(!idExists) {
+ throw new RuntimeException(s"$InvalidUrl not exists ${entityName} of ${idName} = $id")
+ }
}
+ case _ => Unit
+ }
+
+ Future {
+ val processResult: Box[JValue] = operation match {
+ case GET_ALL => Full {
+ JArray(MockerConnector.getAll(entityName).toList)
+ }
+ case GET_ONE => {
+ val boxedEntity: Box[JValue] = MockerConnector.getSingle(entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required.")))
+ boxedEntity
+ }
+ case CREATE | UPDATE => {
+ val body = requestBody.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument please supply the requestBody."))
+ val persistedEntity = MockerConnector.persist(entityName, body, entityId)
+ Full(persistedEntity)
+ }
+ case DELETE => {
+ val deleteResult = MockerConnector.delete(entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required. ")))
+ deleteResult.map(JBool(_))
+ }
+ }
+ (processResult, callContext)
}
- (processResult, callContext)
}
}
diff --git a/obp-api/src/main/scala/code/bankconnectors/package.scala b/obp-api/src/main/scala/code/bankconnectors/package.scala
index 426b98d5c..0775ad09d 100644
--- a/obp-api/src/main/scala/code/bankconnectors/package.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/package.scala
@@ -71,6 +71,12 @@ package object bankconnectors {
}
val connectorName: Box[String] = bankId match {
+ case None if methodName == "dynamicEntityProcess" => {
+ val entityName = args.tail.head
+ NewStyle.function.getMethodRoutings(Some(methodName))
+ .find(_.parameters.exists(it => it.key == "entityName" && it.value == entityName))
+ .map(_.connectorName)
+ }
case None => NewStyle.function.getMethodRoutings(Some(methodName), Some(false))
.find {routing =>
val bankIdPattern = routing.bankIdPattern
diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala
index ae9d2a910..bc9d5c8d6 100644
--- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala
+++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala
@@ -57,7 +57,7 @@ import code.api.util.APIUtil._
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA
import code.customer.internalMapping.MappedCustomerIdMappingProvider
import code.model.dataAccess.internalMapping.MappedAccountIdMappingProvider
-import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, ProductAttributeType}
+import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, DynamicEntityOperation, ProductAttributeType}
import com.openbankproject.commons.util.ReflectUtils
import net.liftweb.json._
@@ -9240,9 +9240,19 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
val result: OBPReturnType[Box[TransactionId]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext))
result
}
-
-//---------------- dynamic end ---------------------please don't modify this line
-
+
+ //---------------- dynamic end ---------------------please don't modify this line
+ override def dynamicEntityProcess(operation: DynamicEntityOperation,
+ entityName: String,
+ requestBody: Option[JObject],
+ entityId: Option[String],
+ callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
+ import com.openbankproject.commons.dto.{OutBoundDynamicEntityProcess => OutBound, InBoundDynamicEntityProcess => InBound}
+ val url = getUrl(callContext, "dynamicEntityProcess")
+ val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , operation, entityName, requestBody, entityId)
+ val result: OBPReturnType[Box[JValue]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext))
+ result
+ }
//In RestConnector, we use the headers to propagate the parameters to Adapter. The parameters come from the CallContext.outboundAdapterAuthInfo.userAuthContext
diff --git a/obp-commons/pom.xml b/obp-commons/pom.xml
index 91e4084ed..c8d52f56b 100644
--- a/obp-commons/pom.xml
+++ b/obp-commons/pom.xml
@@ -40,6 +40,11 @@
org.scalactic
scalactic_${scala.version}
+
+ net.liftweb
+ lift-json_${scala.version}
+ ${lift.version}
+
diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala
index a38c49748..10381839b 100644
--- a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala
+++ b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala
@@ -28,9 +28,10 @@ package com.openbankproject.commons.dto
import java.util.Date
-import com.openbankproject.commons.model.enums.CardAttributeType
+import com.openbankproject.commons.model.enums.{CardAttributeType, DynamicEntityOperation}
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA
import com.openbankproject.commons.model.{enums, _}
+import net.liftweb.json.{JObject, JValue}
import scala.collection.immutable.List
@@ -1157,4 +1158,11 @@ case class InBoundGetBankAccountByIban (inboundAdapterCallContext: InboundAdapte
case class OutBoundGetBankAccounts (outboundAdapterCallContext: OutboundAdapterCallContext,
bankIdAccountIds: List[BankIdAccountId]) extends TopicTrait
-case class InBoundGetBankAccounts (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[BankAccountCommons]) extends InBoundTrait[List[BankAccountCommons]]
\ No newline at end of file
+case class InBoundGetBankAccounts (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[BankAccountCommons]) extends InBoundTrait[List[BankAccountCommons]]
+
+case class OutBoundDynamicEntityProcess (outboundAdapterCallContext: OutboundAdapterCallContext,
+ operation: DynamicEntityOperation,
+ entityName: String,
+ requestBody: Option[JObject],
+ entityId: Option[String]) extends TopicTrait
+case class InBoundDynamicEntityProcess (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: JValue) extends InBoundTrait[JValue]
\ No newline at end of file