forked from finos/vuu
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finos#1052 refactored to separated generic file reader vs basket spec…
…ific logic
- Loading branch information
1 parent
39c2e71
commit cddecb2
Showing
4 changed files
with
167 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/BasketLoader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package org.finos.vuu.core.module.basket.csv | ||
|
||
import com.typesafe.scalalogging.StrictLogging | ||
|
||
import scala.util.control.NonFatal | ||
|
||
class BasketLoader(resourcePath: Option[String] = None) extends StrictLogging { | ||
def loadBasketIds(): Array[String] = { | ||
FileLoader.getFileNames(getPath(resourcePath), ".csv") | ||
.map(fileName => "." + fileName.replace(".csv", "").toUpperCase) | ||
} | ||
|
||
def loadConstituents(basketId: String): Array[Map[String, Any]] = { | ||
try { | ||
val csvFiles = FileLoader.getFiles(getPath(resourcePath), getBasketFileName(basketId)) | ||
|
||
if (csvFiles.isEmpty) { | ||
logger.error(s"Failed to find constituents file for $basketId") | ||
Array.empty | ||
} | ||
else { | ||
val csvFile = csvFiles(0) | ||
logger.info("Loading basket static:" + basketId + "(" + csvFile + ")") | ||
val csvContent = FileLoader.readCsvContent(csvFile) | ||
|
||
logger.info(s"Found ${csvContent.dataRows.length} constituents for basket $basketId") | ||
|
||
csvContent.dataRows.map(row => toConstituent(csvContent, row)) | ||
} | ||
} | ||
catch { | ||
case NonFatal(t) => logger.error(s"Failed to parse constituents for $basketId", t) | ||
Array.empty | ||
} | ||
} | ||
|
||
private def toConstituent(csvContent: CsvContent, row: Array[String]) = { | ||
Map[String, Any]( | ||
"Symbol" -> csvContent.getValue("Symbol", row), | ||
"Last Trade" -> csvContent.getValue("Last Trade", row), | ||
"Name" -> csvContent.getValue("Name", row), | ||
"Weighting" -> csvContent.getValueAsDouble("Weighting", row, 0.0D), | ||
"Volume" -> csvContent.getValue("Volume", row), | ||
"Change" -> csvContent.getValue("Change", row) | ||
) | ||
} | ||
|
||
private def getBasketFileName(basketId: String) = { | ||
basketId.replace(".", "").toLowerCase + ".csv" | ||
} | ||
|
||
private def getPath(resourcePath: Option[String] = None): String = { | ||
if (resourcePath.isDefined) resourcePath.get | ||
else getClass.getResource("/static").getPath | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvContent.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.finos.vuu.core.module.basket.csv | ||
|
||
class CsvContent(data: Array[Array[String]]) { | ||
|
||
private val header = data(0) | ||
val dataRows: Array[Array[String]] = data.tail | ||
|
||
def getValue(headerName: String, row: Array[String]) = { | ||
val index = header.indexOf(headerName) | ||
if (row.length > index && index > -1) row(index) else null | ||
} | ||
|
||
def getValueAsDouble(headerName: String, row: Array[String], defaultValue: Double) = { | ||
val x = getValue(headerName, row) | ||
if (x == null) defaultValue else x.toDouble | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/FileLoader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.finos.vuu.core.module.basket.csv | ||
|
||
import java.io.File | ||
import scala.io.Source | ||
|
||
object FileLoader { | ||
def getFileNames(folderPath: String, extensionFilter: String): Array[String] = { | ||
getFiles(folderPath) | ||
.filter(_.getName.endsWith(extensionFilter)) | ||
.map(file => file.getName) | ||
} | ||
|
||
def getFiles(folderPath: String, fileName: String): Array[File] = { | ||
getFiles(folderPath) | ||
.filter(_.getName.equals(fileName)) | ||
} | ||
|
||
def readCsvContent(file: File): CsvContent = { | ||
val bufferedSource = Source.fromFile(file) | ||
val csv = for (line <- bufferedSource.getLines) yield line.split(",").map(_.trim) | ||
val array = csv.toArray | ||
bufferedSource.close | ||
new CsvContent(array) | ||
} | ||
|
||
private def getFiles(folderPath: String): Array[File] = { | ||
val dir = new File(folderPath) | ||
if (dir.listFiles == null) Array.empty | ||
else dir.listFiles.filter(_.isFile) | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
example/basket/src/test/scala/org/finos/vuu/csv/BasketLoaderTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.finos.vuu.csv | ||
|
||
import org.finos.vuu.core.module.basket.csv.BasketLoader | ||
import org.scalatest.featurespec.AnyFeatureSpec | ||
class BasketLoaderTests extends AnyFeatureSpec { | ||
|
||
Feature("Basket ids loading Test Case") { | ||
|
||
Scenario("Can successfully get basket ids from files") { | ||
val testResourcePath = this.getClass.getResource("/constituents").getPath | ||
val basketLoader = new BasketLoader(Some(testResourcePath)) | ||
val basketIds = basketLoader.loadBasketIds() | ||
|
||
assert(basketIds.length == 2) | ||
assert(basketIds.contains(".FTSE100")) | ||
assert(basketIds.contains(".FTSEWITHERROR")) | ||
} | ||
|
||
Scenario("when no file found return empty") { | ||
val testResourcePath = this.getClass.getResource("/constituents").getPath + "/doesNotExist" | ||
val basketLoader = new BasketLoader(Some(testResourcePath)) | ||
val basketIds = basketLoader.loadBasketIds() | ||
|
||
assert(basketIds.length == 0) | ||
} | ||
} | ||
|
||
Feature("Basket constituent loading Test Case") { | ||
|
||
val testResourcePath = this.getClass.getResource("/constituents").getPath | ||
val basketLoader = new BasketLoader(Some(testResourcePath)) | ||
|
||
Scenario("Can successfully load and parse basket constituents") { | ||
|
||
val constituents = basketLoader.loadConstituents(".FTSE100") | ||
|
||
assert(constituents.length == 3) | ||
val firstRow = constituents.head | ||
assert(firstRow("Symbol") == "AAL.L") | ||
assert(firstRow("Last Trade") == "436.35") | ||
assert(firstRow("Name") == "Anglo American PLC") | ||
assert(firstRow("Weighting") == 0.0278736825813547) | ||
assert(firstRow("Volume") == "5799089") | ||
assert(firstRow("Change") == "5.35") | ||
} | ||
|
||
Scenario("When parsing basket constituents fails return empty") { | ||
|
||
val constituents = basketLoader.loadConstituents(".FTSEWithError") | ||
|
||
assert(constituents.length == 0) | ||
} | ||
|
||
|
||
Scenario("When no matching basket constituents file return empty") { | ||
|
||
val constituents = basketLoader.loadConstituents(".NoSuchFile") | ||
|
||
assert(constituents.length == 0) | ||
} | ||
|
||
} | ||
} |