diff --git a/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/provider/IgniteOrderDataProvider.scala b/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/provider/IgniteOrderDataProvider.scala index 0f8b31400..b4d712545 100644 --- a/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/provider/IgniteOrderDataProvider.scala +++ b/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/provider/IgniteOrderDataProvider.scala @@ -12,7 +12,7 @@ import org.finos.vuu.feature.ignite.IgniteSqlQuery import org.finos.vuu.plugin.virtualized.table.{VirtualizedRange, VirtualizedSessionTable, VirtualizedViewPortKeys} import org.finos.vuu.provider.VirtualizedProvider import org.finos.vuu.util.schema.SchemaMapperBuilder -import org.finos.vuu.viewport.ViewPort +import org.finos.vuu.viewport.{ViewPort, ViewPortColumns} import java.util.concurrent.atomic.AtomicInteger @@ -82,6 +82,9 @@ class IgniteOrderDataProvider(final val igniteStore: IgniteOrderStore) override def getUniqueValuesStartingWith(columnName: String, starts: String): Array[String] = igniteStore.getDistinct(columnName, starts, 10).toArray + override def getUniqueValuesVPColumn(columnName: String, viewPortColumns: ViewPortColumns): Array[String] = ??? + + override def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String, viewPortColumns: ViewPortColumns): Array[String] = ??? } object IgniteOrderDataProvider { diff --git a/example/virtualized-table/src/main/scala/org/finos/vuu/example/virtualtable/provider/ReallyBigVirtualizedDataProvider.scala b/example/virtualized-table/src/main/scala/org/finos/vuu/example/virtualtable/provider/ReallyBigVirtualizedDataProvider.scala index 3eee0bc2e..f23d951bd 100644 --- a/example/virtualized-table/src/main/scala/org/finos/vuu/example/virtualtable/provider/ReallyBigVirtualizedDataProvider.scala +++ b/example/virtualized-table/src/main/scala/org/finos/vuu/example/virtualtable/provider/ReallyBigVirtualizedDataProvider.scala @@ -8,7 +8,7 @@ import org.finos.vuu.core.table.{DataTable, RowWithData} import org.finos.vuu.example.virtualtable.bigdatacache.FakeBigDataCache import org.finos.vuu.plugin.virtualized.table.{VirtualizedRange, VirtualizedSessionTable, VirtualizedViewPortKeys} import org.finos.vuu.provider.VirtualizedProvider -import org.finos.vuu.viewport.ViewPort +import org.finos.vuu.viewport.{ViewPort, ViewPortColumns} class ReallyBigVirtualizedDataProvider(implicit clock: Clock) extends VirtualizedProvider with StrictLogging { @@ -82,4 +82,8 @@ class ReallyBigVirtualizedDataProvider(implicit clock: Clock) extends Virtualize override def getUniqueValues(columnName: String): Array[String] = ??? override def getUniqueValuesStartingWith(columnName: String, starts: String): Array[String] = ??? + + override def getUniqueValuesVPColumn(columnName: String, viewPortColumns: ViewPortColumns): Array[String] = ??? + + override def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String, viewPortColumns: ViewPortColumns): Array[String] = ??? } diff --git a/plugin/ignite-plugin/src/test/scala/org/finos/vuu/feature/ignite/SchemaMapperFunctionalTest.scala b/plugin/ignite-plugin/src/test/scala/org/finos/vuu/feature/ignite/SchemaMapperFunctionalTest.scala index 340344316..501662bc7 100644 --- a/plugin/ignite-plugin/src/test/scala/org/finos/vuu/feature/ignite/SchemaMapperFunctionalTest.scala +++ b/plugin/ignite-plugin/src/test/scala/org/finos/vuu/feature/ignite/SchemaMapperFunctionalTest.scala @@ -7,7 +7,7 @@ import org.finos.vuu.plugin.virtualized.api.VirtualizedSessionTableDef import org.finos.vuu.provider.VirtualizedProvider import org.finos.vuu.test.{FakeDataSource, FakeInMemoryTable} import org.finos.vuu.util.schema.{ExternalEntitySchema, SchemaMapperBuilder, SchemaMapperFunctionalTestBase, SchemaTestData} -import org.finos.vuu.viewport.ViewPort +import org.finos.vuu.viewport.{ViewPort, ViewPortColumns} class SchemaMapperFunctionalTest extends SchemaMapperFunctionalTestBase { @@ -80,4 +80,8 @@ class TestVirtualProvider(fakeDataSource:FakeDataSource[SchemaTestData]) extends fakeDataSource.getColumnValues(queryName, columnName) .getOrElse(throw new Exception("query does not exist in store. make sure it is setup")) } + + override def getUniqueValuesVPColumn(columnName: String, viewPortColumns: ViewPortColumns): Array[String] = ??? + + override def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String, viewPortColumns: ViewPortColumns): Array[String] = ??? } diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/typeahead/ViewPortTypeAheadRpcHandler.scala b/vuu/src/main/scala/org/finos/vuu/core/module/typeahead/ViewPortTypeAheadRpcHandler.scala index f8d545e5a..675aa4c62 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/typeahead/ViewPortTypeAheadRpcHandler.scala +++ b/vuu/src/main/scala/org/finos/vuu/core/module/typeahead/ViewPortTypeAheadRpcHandler.scala @@ -4,6 +4,7 @@ import com.typesafe.scalalogging.StrictLogging import org.finos.vuu.core.table.{DataTable, TableContainer} import org.finos.vuu.net.rpc.{DefaultRpcHandler, RpcMethodCallResult, RpcMethodSuccess, RpcParams} import org.finos.vuu.net.{RequestContext, RpcNames} +import org.finos.vuu.viewport.ViewPortColumns class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends DefaultRpcHandler with StrictLogging { @@ -15,6 +16,7 @@ class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends Defaul params.namedParams("table").toString, //how to report error when expected param missing or fail to cast to right type params.namedParams("module").toString, params.namedParams("column").toString, + params.viewPortColumns.get, null //todo what to do about request context ) new RpcMethodSuccess(values) @@ -26,26 +28,27 @@ class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends Defaul params.namedParams("module").toString, params.namedParams("column").toString, params.namedParams("starts").toString, + params.viewPortColumns.get, null //todo what to do about request context ) new RpcMethodSuccess(values) //how to control what viewport action to trigger? } - def getUniqueFieldValues(tableName: String, moduleName: String, column: String, ctx: RequestContext): Array[String] = { + def getUniqueFieldValues(tableName: String, moduleName: String, column: String, viewPortColumns: ViewPortColumns, ctx: RequestContext): Array[String] = { tableContainer.getTable(tableName) match { case dataTable: DataTable => val columValueProvider = dataTable.getColumnValueProvider - columValueProvider.getUniqueValuesVPColumn(column) + columValueProvider.getUniqueValuesVPColumn(column, viewPortColumns) case null => throw new Exception("Could not find table by name:" + tableName) } } - def getUniqueFieldValuesStartingWith(tableName: String, moduleName: String, column: String, starts: String, ctx: RequestContext): Array[String] = { + def getUniqueFieldValuesStartingWith(tableName: String, moduleName: String, column: String, starts: String, viewPortColumns: ViewPortColumns, ctx: RequestContext): Array[String] = { tableContainer.getTable(tableName) match { case dataTable: DataTable => val columValueProvider = dataTable.getColumnValueProvider - columValueProvider.getUniqueValuesStartingWithVPColumn(column, starts) + columValueProvider.getUniqueValuesStartingWithVPColumn(column, starts, viewPortColumns) case null => throw new Exception("Could not find table by name:" + tableName) } diff --git a/vuu/src/main/scala/org/finos/vuu/core/table/ColumnValueProvider.scala b/vuu/src/main/scala/org/finos/vuu/core/table/ColumnValueProvider.scala index 73c284f82..9e6ff18dc 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/table/ColumnValueProvider.scala +++ b/vuu/src/main/scala/org/finos/vuu/core/table/ColumnValueProvider.scala @@ -5,8 +5,8 @@ import org.finos.vuu.viewport.ViewPortColumns trait ColumnValueProvider { - def getUniqueValuesVPColumn(columnName: String): Array[String] - def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String): Array[String] + def getUniqueValuesVPColumn(columnName: String, viewPortColumns: ViewPortColumns): Array[String] + def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String, viewPortColumns: ViewPortColumns): Array[String] @deprecated("to be replaced by getUniqueValuesVPColumn") def getUniqueValues(columnName: String): Array[String] @@ -15,7 +15,6 @@ trait ColumnValueProvider { } - object InMemColumnValueProvider { def apply(dataTable: DataTable): InMemColumnValueProvider = { dataTable match { @@ -28,16 +27,14 @@ object InMemColumnValueProvider { class InMemColumnValueProvider(dataTable: InMemDataTable) extends ColumnValueProvider with StrictLogging { private val get10DistinctValues = DistinctValuesGetter(10) - def getUniqueValuesVPColumn(columnName: String): Array[String] = { - val viewPortColumns = ViewPortColumnCreator.create(dataTable, List(columnName)) + def getUniqueValuesVPColumn(columnName: String, viewPortColumns: ViewPortColumns): Array[String] = { viewPortColumns.getColumnForName(columnName) match { case Some(column) => get10DistinctValues.fromVP(viewPortColumns, column) case None => logger.error(s"Column $columnName not found in table ${dataTable.name}"); Array.empty; } } - def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String): Array[String] = { - val viewPortColumns = ViewPortColumnCreator.create(dataTable, List(columnName)) + def getUniqueValuesStartingWithVPColumn(columnName: String, starts: String, viewPortColumns: ViewPortColumns): Array[String] = { viewPortColumns.getColumnForName(columnName) match { case Some(column) => get10DistinctValues.fromVP(viewPortColumns, column, _.toLowerCase.startsWith(starts.toLowerCase)) case None => logger.error(s"Column $columnName not found in table ${dataTable.name}"); Array.empty; @@ -56,7 +53,6 @@ class InMemColumnValueProvider(dataTable: InMemDataTable) extends ColumnValuePro case null => logger.error(s"Column $columnName not found in table ${dataTable.name}"); Array.empty; } - private case class DistinctValuesGetter(n: Int) { private type Filter = String => Boolean @@ -74,8 +70,6 @@ class InMemColumnValueProvider(dataTable: InMemDataTable) extends ColumnValuePro .flatMap(valueToString) .filter(filter) - - //todo if vp column doesnt have table column, return emtpy or error private def getDistinctValues(viewPortColumns: ViewPortColumns, column: Column, filter: Filter): Iterator[String] = dataTable.primaryKeys .iterator diff --git a/vuu/src/main/scala/org/finos/vuu/net/rpc/DefaultRpcHandler.scala b/vuu/src/main/scala/org/finos/vuu/net/rpc/DefaultRpcHandler.scala index 5e8459b66..89c6c490a 100644 --- a/vuu/src/main/scala/org/finos/vuu/net/rpc/DefaultRpcHandler.scala +++ b/vuu/src/main/scala/org/finos/vuu/net/rpc/DefaultRpcHandler.scala @@ -25,8 +25,8 @@ class DefaultRpcHandler extends RpcHandler with StrictLogging { rpcHandlerMap.put(functionName, handlerFunc) } - override def processViewPortRpcCall(methodName: String, params: Array[Any], namedParams: Map[String, Any])(ctx: RequestContext): ViewPortAction = { - val result = processRpcMethodHandler(methodName, params, namedParams, ctx) + override def processViewPortRpcCall(methodName: String, rpcParams: RpcParams): ViewPortAction = { + val result = processRpcMethodHandler(methodName, rpcParams) result match { case RpcMethodSuccess(result) => result match { @@ -43,17 +43,17 @@ class DefaultRpcHandler extends RpcHandler with StrictLogging { val namedPars = rpc.namedParams val module = Option(msg).map(_.module).getOrElse("") - processRpcMethodHandler(method, params, namedPars, ctx) match { + processRpcMethodHandler(method, new RpcParams(params, namedPars, None, ctx)) match { case result: RpcMethodSuccess => Some(VsMsg(ctx.requestId, ctx.session.sessionId, ctx.token, ctx.session.user, RpcResponse(method, result.optionalResult.orNull, error = null), module)) case error: RpcMethodFailure => Some(VsMsg(ctx.requestId, ctx.session.sessionId, ctx.token, ctx.session.user, RpcResponse(rpc.method, null, Error(error.error, error.code)), module)) } } - private def processRpcMethodHandler(methodName: String, params: Array[Any], namedParams: Map[String, Any], ctx: RequestContext) = { + private def processRpcMethodHandler(methodName: String, rpcParams: RpcParams) = { if (rpcHandlerMap.containsKey(methodName)) { try { val handler = rpcHandlerMap.get(methodName) - handler(new RpcParams(params, namedParams, ctx)) + handler(rpcParams) } catch { case e: Exception => logger.error(s"Error processing rpc method $methodName", e) diff --git a/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcHandler.scala b/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcHandler.scala index deed1bd02..3b7303551 100644 --- a/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcHandler.scala +++ b/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcHandler.scala @@ -40,7 +40,9 @@ trait RpcHandler extends StrictLogging { val methodsAndParams: Map[String, Array[(String, Array[Type], Method)]] = this.getClass.getMethods.map(method => (method.getName, method.getGenericParameterTypes, method)).groupBy(_._1) - def processViewPortRpcCall(methodName: String, params: Array[Any], namedParams: Map[String, Any])(ctx: RequestContext):ViewPortAction = { + def processViewPortRpcCall(methodName: String, rcpParams: RpcParams):ViewPortAction = { + + val (params, ctx) = (rcpParams.params, rcpParams.ctx) if (!methodsAndParams.contains(methodName)) { ViewPortRpcFailure(s"Could not find method $methodName") diff --git a/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcMethodHandler.scala b/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcMethodHandler.scala index 6b1fbb54e..d2a1eaac4 100644 --- a/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcMethodHandler.scala +++ b/vuu/src/main/scala/org/finos/vuu/net/rpc/RpcMethodHandler.scala @@ -1,12 +1,17 @@ package org.finos.vuu.net.rpc import org.finos.vuu.net.RequestContext +import org.finos.vuu.viewport.ViewPortColumns -class RpcParams(val params: Array[Any], val namedParams: Map[String, Any], ctx: RequestContext) +class RpcParams( + val params: Array[Any], + val namedParams: Map[String, Any], + val viewPortColumns: Option[ViewPortColumns], + val ctx: RequestContext) trait RpcMethodCallResult {} -case class RpcMethodSuccess(optionalResult: Option[Any]) extends RpcMethodCallResult{ +case class RpcMethodSuccess(optionalResult: Option[Any]) extends RpcMethodCallResult { def this(result:Any) = this(Some(result)) def this() = this(None) } diff --git a/vuu/src/main/scala/org/finos/vuu/viewport/ViewPortContainer.scala b/vuu/src/main/scala/org/finos/vuu/viewport/ViewPortContainer.scala index 45424b03b..dcbcb2fd7 100644 --- a/vuu/src/main/scala/org/finos/vuu/viewport/ViewPortContainer.scala +++ b/vuu/src/main/scala/org/finos/vuu/viewport/ViewPortContainer.scala @@ -16,7 +16,7 @@ import org.finos.vuu.core.table.{DataTable, SessionTable, TableContainer} import org.finos.vuu.core.tree.TreeSessionTableImpl import org.finos.vuu.feature.EmptyViewPortKeys import org.finos.vuu.feature.inmem.InMemTablePrimaryKeys -import org.finos.vuu.net.rpc.EditRpcHandler +import org.finos.vuu.net.rpc.{EditRpcHandler, RpcParams} import org.finos.vuu.net.{ClientSessionId, FilterSpec, RequestContext, SortSpec} import org.finos.vuu.plugin.PluginRegistry import org.finos.vuu.provider.{Provider, ProviderContainer} @@ -84,7 +84,7 @@ class ViewPortContainer(val tableContainer: TableContainer, val providerContaine throw new Exception(s"No viewport $vpId found for RPC Call for $method") val viewPortDef = viewPort.getStructure.viewPortDef - viewPortDef.service.processViewPortRpcCall(method, params, namedParams)(ctx) + viewPortDef.service.processViewPortRpcCall(method, new RpcParams(params, namedParams, Some(viewPort.getColumns), ctx)) } def callRpcCell(vpId: String, rpcName: String, session: ClientSessionId, rowKey: String, field: String, singleValue: Object): ViewPortAction = { diff --git a/vuu/src/test/scala/org/finos/vuu/net/rpc/DefaultRpcHandlerTest.scala b/vuu/src/test/scala/org/finos/vuu/net/rpc/DefaultRpcHandlerTest.scala index 6a94443db..b14d20136 100644 --- a/vuu/src/test/scala/org/finos/vuu/net/rpc/DefaultRpcHandlerTest.scala +++ b/vuu/src/test/scala/org/finos/vuu/net/rpc/DefaultRpcHandlerTest.scala @@ -19,13 +19,17 @@ class DefaultRpcHandlerTest extends AnyFeatureSpec with Matchers with BeforeAndA Scenario("Can register and handle Rpc request that perform action") { handler.registerRpc("myMethod", _ => new RpcMethodSuccess()) - handler.processViewPortRpcCall("myMethod", Array("param1"), Map("namedParam1" -> "value1"))(null) should be(ViewPortRpcSuccess()) + val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), None, ctx)) + + result should be(ViewPortRpcSuccess()) } Scenario("Can register and handle Rpc request that returns result") { handler.registerRpc("myMethod", _ => new RpcMethodSuccess("result")) - handler.processViewPortRpcCall("myMethod", Array("param1"), Map("namedParam1" -> "value1"))(null) should be(DisplayResultAction("result")) + val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), None, ctx)) + + result should be(DisplayResultAction("result")) } Scenario("Throw exception when registering a function under already registered name") { @@ -40,7 +44,7 @@ class DefaultRpcHandlerTest extends AnyFeatureSpec with Matchers with BeforeAndA Scenario("Rpc request with null params should return ViewPortRpcSuccess when the rpc method is successful") { handler.registerRpc("myMethod", _ => new RpcMethodSuccess()) - val result = handler.processViewPortRpcCall("myMethod", null, null)(null) + val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, None, ctx)) result should be(ViewPortRpcSuccess()) } @@ -48,7 +52,7 @@ class DefaultRpcHandlerTest extends AnyFeatureSpec with Matchers with BeforeAndA Scenario("Rpc request should return ViewPortRpcFailure when the rpc method fails") { handler.registerRpc("myMethod", _ => RpcMethodFailure(1, "error", new Exception("exception"))) - val result = handler.processViewPortRpcCall("myMethod", null, null)(null) + val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, None, ctx)) result should be(ViewPortRpcFailure("Exception occurred calling rpc myMethod")) }