diff --git a/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/module/IgniteOrderDataModule.scala b/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/module/IgniteOrderDataModule.scala index 826512b08..1066f6727 100644 --- a/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/module/IgniteOrderDataModule.scala +++ b/example/apache-ignite/src/main/scala/org/finos/vuu/example/ignite/module/IgniteOrderDataModule.scala @@ -5,7 +5,7 @@ import org.finos.toolbox.time.Clock import org.finos.vuu.api.ViewPortDef import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} import org.finos.vuu.core.table.{Column, Columns} -import org.finos.vuu.example.ignite.IgniteOrderStore +import org.finos.vuu.example.ignite.{IgniteColumnValueProvider, IgniteOrderStore} import org.finos.vuu.example.ignite.provider.IgniteOrderDataProvider import org.finos.vuu.net.rpc.RpcHandler import org.finos.vuu.plugin.virtualized.api.VirtualizedSessionTableDef @@ -24,6 +24,7 @@ object IgniteOrderDataModule extends DefaultModule { columns ), (_, _) => new IgniteOrderDataProvider(igniteOrderStore), + table => new IgniteColumnValueProvider(igniteOrderStore), (table, _, _, _) => ViewPortDef( columns = table.getTableDef.columns, service = new NoOpIgniteService() diff --git a/vuu/src/main/scala/org/finos/vuu/core/VuuServer.scala b/vuu/src/main/scala/org/finos/vuu/core/VuuServer.scala index c916efdcc..3b0773e0c 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/VuuServer.scala +++ b/vuu/src/main/scala/org/finos/vuu/core/VuuServer.scala @@ -7,7 +7,7 @@ import org.finos.toolbox.thread.{LifeCycleRunOncePerThreadExecutorRunner, LifeCy import org.finos.toolbox.time.Clock import org.finos.vuu.api.{JoinTableDef, TableDef, ViewPortDef} import org.finos.vuu.core.module.{ModuleContainer, RealizedViewServerModule, StaticServedResource, TableDefContainer, ViewServerModule} -import org.finos.vuu.core.table.{DataTable, TableContainer} +import org.finos.vuu.core.table.{ColumnValueProvider, DataTable, InMemColumnValueProvider, TableContainer} import org.finos.vuu.feature.inmem.{VuuInMemPlugin, VuuInMemPluginType} import org.finos.vuu.net._ import org.finos.vuu.net.http.{Http2Server, VuuHttp2Server} @@ -23,6 +23,9 @@ import java.util.concurrent.{Callable, FutureTask} /** * Vuu Server + * + * + * demo - who is doing it, what env we are using, send headlines / notes we want to hit to key trader guys */ class VuuServer(config: VuuServerConfig)(implicit lifecycle: LifecycleContainer, timeProvider: Clock, metricsProvider: MetricsProvider) extends LifecycleEnabled with StrictLogging with IVuuServer { @@ -141,6 +144,10 @@ class VuuServer(config: VuuServerConfig)(implicit lifecycle: LifecycleContainer, table.setProvider(provider) } + def registerColumnValueProvider(table: DataTable, columnValueProvider: ColumnValueProvider): Unit = { + table.setColumnValueProvider(columnValueProvider) + } + private def registerModule(module: ViewServerModule): VuuServer = { val vs = this @@ -157,6 +164,9 @@ class VuuServer(config: VuuServerConfig)(implicit lifecycle: LifecycleContainer, override def getProviderForTable(table: DataTable, viewserver: IVuuServer)(implicit time: Clock, life: LifecycleContainer): Provider = { module.getProviderForTable(table, viewserver)(time, life) } + override def getColumnValueProviderForTable(table: DataTable, viewserver: IVuuServer): ColumnValueProvider = { + module.getColumnValueProviderForTable(table, viewserver) + } override def staticFileResources(): List[StaticServedResource] = module.staticFileResources() override def viewPortDefs: Map[String, (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef] = module.viewPortDefs } @@ -169,13 +179,17 @@ class VuuServer(config: VuuServerConfig)(implicit lifecycle: LifecycleContainer, case tableDef: JoinTableDef => tableDef.setModule(module) - createJoinTable(tableDef) + val table = createJoinTable(tableDef) + val columnValueProvider = module.getColumnValueProviderForTable(table, this) + registerColumnValueProvider(table, columnValueProvider) case tableDef: TableDef if tableDef.autosubscribe => tableDef.setModule(module) val table = createAutoSubscribeTable(tableDef) val provider = module.getProviderForTable(table, this) registerProvider(table, provider) + val columnValueProvider = module.getColumnValueProviderForTable(table, this) + registerColumnValueProvider(table, columnValueProvider) case tableDef: TableDef if !tableDef.autosubscribe => tableDef.setModule(module) @@ -183,6 +197,8 @@ class VuuServer(config: VuuServerConfig)(implicit lifecycle: LifecycleContainer, logger.info(s"Loading provider for table ${table.name}...") val provider = module.getProviderForTable(table, this) registerProvider(table, provider) + val columnValueProvider = module.getColumnValueProviderForTable(table, this) + registerColumnValueProvider(table, columnValueProvider) } module.viewPortDefs.foreach({ case (table, vpFunc) => diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/ModuleFactory.scala b/vuu/src/main/scala/org/finos/vuu/core/module/ModuleFactory.scala index 047b1ad5b..2cb1df76d 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/ModuleFactory.scala +++ b/vuu/src/main/scala/org/finos/vuu/core/module/ModuleFactory.scala @@ -2,7 +2,7 @@ package org.finos.vuu.core.module import org.finos.vuu.api.{JoinTableDef, NoViewPortDef, TableDef, ViewPortDef} import org.finos.vuu.core.{IVuuServer, VuuServer} -import org.finos.vuu.core.table.{DataTable, TableContainer} +import org.finos.vuu.core.table.{ColumnValueProvider, DataTable, EmptyColumnValueProvider, InMemColumnValueProvider, InMemDataTableData, TableContainer} import org.finos.vuu.net.rest.RestService import org.finos.vuu.net.rpc.RpcHandler import org.finos.vuu.provider.{NullProvider, Provider, ProviderContainer} @@ -12,10 +12,10 @@ import org.finos.toolbox.time.Clock import java.nio.file.Path -case class TableDefs protected(realizedTableDefs: List[TableDef], tableDefs: List[(TableDef, (DataTable, IVuuServer) => Provider)], joinDefs: List[TableDefContainer => JoinTableDef]) { +case class TableDefs protected(realizedTableDefs: List[TableDef], tableDefs: List[(TableDef, (DataTable, IVuuServer) => Provider, DataTable => ColumnValueProvider)], joinDefs: List[TableDefContainer => JoinTableDef]) { - def add(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider): TableDefs = { - TableDefs(realizedTableDefs, tableDefs ++ List((tableDef, func)), joinDefs) + def add(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider, createCVP: DataTable => ColumnValueProvider): TableDefs = { + TableDefs(realizedTableDefs, tableDefs ++ List((tableDef, func, createCVP)), joinDefs) } def addRealized(tableDef: TableDef): TableDefs = { @@ -28,7 +28,7 @@ case class TableDefs protected(realizedTableDefs: List[TableDef], tableDefs: Lis protected def getJoinDefFuncs(): List[TableDefContainer => JoinTableDef] = joinDefs - protected def getTableDefsAndProviders(): List[(TableDef, (DataTable, VuuServer) => Provider)] = tableDefs + protected def getTableDefsAndProviders(): List[(TableDef, (DataTable, VuuServer) => Provider,DataTable => ColumnValueProvider)] = tableDefs protected def getRealizedTableDefs(): List[TableDef] = realizedTableDefs @@ -53,23 +53,28 @@ case class ModuleFactoryNode protected(tableDefs: TableDefs, def addTable(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider): ModuleFactoryNode = { val noViewPortDefFunc = (dt: DataTable, prov: Provider, providerContainer: ProviderContainer, tableContainer: TableContainer) => NoViewPortDef - ModuleFactoryNode(tableDefs.add(tableDef, func), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> noViewPortDefFunc), tableDefContainer, unrealizedViewPortDefs) + ModuleFactoryNode(tableDefs.add(tableDef, func, (dt:DataTable) => InMemColumnValueProvider(dt)), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> noViewPortDefFunc), tableDefContainer, unrealizedViewPortDefs) } def addTable(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider, func2: (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef): ModuleFactoryNode = { - ModuleFactoryNode(tableDefs.add(tableDef, func), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) + ModuleFactoryNode(tableDefs.add(tableDef, func, (dt:DataTable) => InMemColumnValueProvider(dt)), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) } def addSessionTable(tableDef: TableDef, func2: (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef): ModuleFactoryNode = { - ModuleFactoryNode(tableDefs.add(tableDef, (dt, vs) => NullProvider), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) + ModuleFactoryNode(tableDefs.add(tableDef, (dt, vs) => NullProvider, dt => new EmptyColumnValueProvider()), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) } + //todo check usage to see what column value provider to support & the datatable types to support def addSessionTable(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider, func2: (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef): ModuleFactoryNode = { - ModuleFactoryNode(tableDefs.add(tableDef, func), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) + ModuleFactoryNode(tableDefs.add(tableDef, func, (dt:DataTable) => InMemColumnValueProvider(dt)), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) + } + + def addSessionTable(tableDef: TableDef, func: (DataTable, IVuuServer) => Provider, createCVP: DataTable => ColumnValueProvider, func2: (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef): ModuleFactoryNode = { + ModuleFactoryNode(tableDefs.add(tableDef, func, createCVP), rpc, vsName, staticServedResources, rest, viewPortDefs ++ Map(tableDef.name -> func2), tableDefContainer, unrealizedViewPortDefs) } def addSessionTable(tableDef: TableDef): ModuleFactoryNode = { - ModuleFactoryNode(tableDefs.add(tableDef, (dt, vs) => NullProvider), rpc, vsName, staticServedResources, rest, viewPortDefs, tableDefContainer, unrealizedViewPortDefs) + ModuleFactoryNode(tableDefs.add(tableDef, (dt, vs) => NullProvider, dt => new EmptyColumnValueProvider()), rpc, vsName, staticServedResources, rest, viewPortDefs, tableDefContainer, unrealizedViewPortDefs) } def addJoinTable(func: TableDefContainer => JoinTableDef): ModuleFactoryNode = { @@ -103,7 +108,8 @@ case class ModuleFactoryNode protected(tableDefs: TableDefs, def asModule(): ViewServerModule = { val baseTables = tableDefs.tableDefs - val justBaseTables = baseTables.map({ case (tbl, provFunc) => tbl }) + + val justBaseTables = baseTables.map({ case (tbl, provFunc, columnValueProvFunc) => tbl }) var mutableTableDefs = TableDefs(justBaseTables, List(), List()) @@ -141,14 +147,19 @@ case class ModuleFactoryNode protected(tableDefs: TableDefs, } override def getProviderForTable(table: DataTable, viewserver: IVuuServer)(implicit time: Clock, lifecycleContainer: LifecycleContainer): Provider = { - baseTables.find({ case (td, func) => td.name == table.name }).get._2(table, viewserver) + baseTables.find({ case (td, provFunc, columnValueProvFunc) => td.name == table.name }).get._2(table, viewserver) } + override def getColumnValueProviderForTable(table: DataTable, viewserver: IVuuServer): ColumnValueProvider = + baseTables.find({ case (td, provFunc, columnValueProvFunc) => td.name == table.name }).get._3(table) + + override def staticFileResources(): List[StaticServedResource] = staticServedResources override def restServicesUnrealized: List[IVuuServer => RestService] = rest override def viewPortDefs: Map[String, (DataTable, Provider, ProviderContainer, TableContainer) => ViewPortDef] = parentRef.viewPortDefs ++ joinViewPortDefs + } } diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/VsModule.scala b/vuu/src/main/scala/org/finos/vuu/core/module/VsModule.scala index d82b17819..8988e7200 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/VsModule.scala +++ b/vuu/src/main/scala/org/finos/vuu/core/module/VsModule.scala @@ -2,7 +2,7 @@ package org.finos.vuu.core.module import org.finos.vuu.api.{TableDef, ViewPortDef} import org.finos.vuu.core.{IVuuServer, VuuServer} -import org.finos.vuu.core.table.{DataTable, TableContainer} +import org.finos.vuu.core.table.{ColumnValueProvider, DataTable, TableContainer} import org.finos.vuu.net.rest.RestService import org.finos.vuu.net.rpc.RpcHandler import org.finos.vuu.provider.{Provider, ProviderContainer} @@ -37,6 +37,8 @@ trait ViewServerModule { def getProviderForTable(table: DataTable, viewserver: IVuuServer)(implicit time: Clock, lifecycleContainer: LifecycleContainer): Provider + def getColumnValueProviderForTable(table: DataTable, viewserver: IVuuServer): ColumnValueProvider + def staticFileResources(): List[StaticServedResource] def restServicesUnrealized: List[IVuuServer => RestService] 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 188c446eb..e57db5b6a 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 @@ -14,7 +14,22 @@ trait ColumnValueProvider { } +class EmptyColumnValueProvider extends ColumnValueProvider { + override def getUniqueValues(columnName: String): Array[String] = Array.empty + + override def getUniqueValuesStartingWith(columnName: String, starts: String): Array[String] = Array.empty +} + +object InMemColumnValueProvider { + def apply(dataTable: DataTable): InMemColumnValueProvider = { + dataTable match { + case inMemDataTable: InMemDataTable => new InMemColumnValueProvider(inMemDataTable) + case d => throw new UnsupportedOperationException(s"Cannot create InMemColumnValueProvider for data table ${d.name} as this is not InMemDataTable.") + } + } +} class InMemColumnValueProvider(dataTable: InMemDataTable) extends ColumnValueProvider with StrictLogging { + override def getUniqueValues(columnName: String): Array[String] = dataTable.columnForName(columnName) match { case c: Column =>