Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0d0d3d6
Merge remote-tracking branch 'origin/master' into crypto
rchillyard Dec 21, 2021
1807503
V1.1.0 crypto
rchillyard Dec 21, 2021
5e3b641
Added capabilities to render table via Csv
rchillyard Dec 22, 2021
94e0ac9
Added some CsvRenderers
rchillyard Dec 22, 2021
9c77798
Beginning of implementation of header generation for CSV output
rchillyard Dec 23, 2021
b59f0db
First version of CsvGenerator
rchillyard Dec 24, 2021
37e2aee
Tentative improvement on CsvGenerator
rchillyard Dec 25, 2021
290d84e
Minor improvement to CsvGenerator classes
rchillyard Dec 25, 2021
d614388
rchillyard Dec 25, 2021
50cbe8f
Enabled multi-nested case class header generation
rchillyard Dec 25, 2021
824406c
Removed ignored parameters in CsvGenerator and its sub-type
rchillyard Dec 25, 2021
9449e5d
Add select methods to Table
rchillyard Dec 26, 2021
0e5e9b3
Added shuffle, various cleanups
rchillyard Dec 26, 2021
3995ab0
WARNING: does not pass unit tests (31 failures)
rchillyard Dec 28, 2021
98a6425
Completed enabling of more than one header row.
rchillyard Dec 28, 2021
ddd1696
Correctly ingest TeamProject.cvs
rchillyard Dec 31, 2021
71ffa89
Finished implementing Csv rendering.
rchillyard Dec 31, 2021
fb508ba
Implemented (and tested) skipRenderer and skipGenerator
rchillyard Dec 31, 2021
23b81b0
Added FileWriter
rchillyard Jan 1, 2022
07fa57b
New class Writable.StringBuilderWritable
rchillyard Jan 1, 2022
1868501
Minor change
rchillyard Jan 1, 2022
f53df54
rchillyard Jan 1, 2022
8ad6d54
Updates to README and other cosmetics.
rchillyard Jan 1, 2022
5ac27bc
Cosmetic changes to 51 files.
rchillyard Jan 1, 2022
60b87b3
Minor cosmetics based on Analysis.
rchillyard Jan 1, 2022
8bcd075
Removed minor analysis complaint.
rchillyard Jan 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ target/
/.scannerwork/
/.bsp/sbt.json
/src/it/resources/AIRBNB.Listing.csv
/src/it/resources/com/phasmidsoftware/examples/CSYE7200-FALL2021-Project.csv
/output.csv

src/it/resources/2020VAERSData/

TeamProjectOutput.csv
103 changes: 82 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,29 @@ See section on _CellParsers_ below.

## Table

The _Table_ class has several methods for manipulation:
* def iterator: Iterator\[Row]
* def rows: Seq\[Row]
* def maybeHeader: Option\[Header]
* def map\[S](f: Row => S): Table\[S]
* def flatMap\[U](f: Row => Table\[U]): Table\[U]
* def unit\[S](rows: Seq\[S], maybeHeader: Option\[Header]): Table\[S]
* def ++\[U >: Row](table: Table\[U]): Table\[U]

It is to be expected that _join_ methods will be added later.

The following object methods are available for parsing text:
The _Table_ class, which implements _Iterable\[Row]_, also has several methods for manipulation:
### query methods
* def rows: Seq\[Row]
* def maybeHeader: Option\[Header]
* def toCSV(implicit renderer: CsvRenderer\[Row], generator: CsvProductGenerator\[Row], csvAttributes: CsvAttributes): Iterable\[String]
* def maybeColumnNames: Option\[Seq\[String]]
* def column(name: String): Iterator\[Option\[String]]

### transformation methods
* def flatMap\[U](f: Row => Iterable\[U]): Table\[U]
* def unit\[S](rows: Iterable\[S], maybeHeader: Option\[Header]): Table\[S]
* def ++\[U >: Row](table: Table\[U]): Table\[U]
* def processRows\[S](f: Iterable\[Row] => Iterable\[S]): Table\[S]
* def processRows\[R, S](f: (Iterable\[Row], Iterable\[R]) => Iterable\[S])(other: Table\[R]): Table\[S]
* def sort\[S >: Row : Ordering]: Table\[S]
* def select(range: Range): Table\[Row]
* def select(n: Int): Table\[Row]
* lazy val shuffle: Table\[Row]


It is to be expected that _join_ methods will be added later (based upon the second signature of processRows).

The following **object** methods are available for parsing text:
* def parse\[T: TableParser](ws: Seq\[String]): Try\[T]
* def parse\[T: TableParser](ws: Iterator\[String]): Try\[T]
* def parse\[T: TableParser](x: => Source): Try\[T]
Expand Down Expand Up @@ -331,19 +342,19 @@ The other case classes look like this:
The _MovieParser_ object looks like this:

object MovieParser extends CellParsers {
def camelCaseColumnNameMapper(w: String): String = w.replaceAll("([A-Z0-9])", "_$1")
implicit val movieColumnHelper: ColumnHelper[Movie] = columnHelper(camelCaseColumnNameMapper _,
def camelToSnakeCaseColumnNameMapper(w: String): String = w.replaceAll("([A-Z0-9])", "_$1")
implicit val movieColumnHelper: ColumnHelper[Movie] = columnHelper(camelToSnakeCaseColumnNameMapper _,
"title" -> "movie_title",
"imdb" -> "movie_imdb_link")
implicit val reviewsColumnHelper: ColumnHelper[Reviews] = columnHelper(camelCaseColumnNameMapper _,
implicit val reviewsColumnHelper: ColumnHelper[Reviews] = columnHelper(camelToSnakeCaseColumnNameMapper _,
"facebookLikes" -> "movie_facebook_likes",
"numUsersReview" -> "num_user_for_reviews",
"numUsersVoted" -> "num_voted_users",
"numCriticReviews" -> "num_critic_for_reviews",
"totalFacebookLikes" -> "cast_total_facebook_likes")
implicit val formatColumnHelper: ColumnHelper[Format] = columnHelper(camelCaseColumnNameMapper _)
implicit val productionColumnHelper: ColumnHelper[Production] = columnHelper(camelCaseColumnNameMapper _)
implicit val principalColumnHelper: ColumnHelper[Principal] = columnHelper(camelCaseColumnNameMapper _, Some("$x_$c"))
implicit val formatColumnHelper: ColumnHelper[Format] = columnHelper(camelToSnakeCaseColumnNameMapper _)
implicit val productionColumnHelper: ColumnHelper[Production] = columnHelper(camelToSnakeCaseColumnNameMapper _)
implicit val principalColumnHelper: ColumnHelper[Principal] = columnHelper(camelToSnakeCaseColumnNameMapper _, Some("$x_$c"))
implicit val ratingParser: CellParser[Rating] = cellParser(Rating.apply: String => Rating)
implicit val formatParser: CellParser[Format] = cellParser4(Format)
implicit val productionParser: CellParser[Production] = cellParser4(Production)
Expand Down Expand Up @@ -402,6 +413,8 @@ A parameter can be optional, for example, in the _Movie_ example, the _Productio
In this example, some movies do not have a budget provided.
All you have to do is declare it optional in the case class and _TableParser_ will specify it as _Some(x)_ if valid, else _None_.

Note that there is a default, implicit _RowConfig_ object defined in the object _RowConfig_.

## Example: Submissions

This example has two variations on the earlier theme of the _Movies_ example:
Expand Down Expand Up @@ -530,16 +543,55 @@ As with the parsing methods, the conversion between instances of types (especial

If you need to set HTML attributes for a specific type, for example a row in the above example, then an attribute map can be defined for the _renderer2_ method.

## String Rendering
## CSV Rendering

If you simply need to write a table to CSV (comma-separated value) format as a _String_, then use the _toCsv_ method of _Table\[T]_.
Note that there is also an object method of _Table_ called _toCsvRow_ which can be used for instances of _Table\[Row]_.
More control can be gained by using _CsvTableStringRenderer\[T]_ or _CsvTableFileRenderer\[T]_ for a particular type _T_.

These require customizable (implicit) evidence parameters and are defined as follows:

case class CsvTableStringRenderer[T: CsvRenderer : CsvGenerator]()(implicit csvAttributes: CsvAttributes)
extends CsvTableRenderer[T, StringBuilder]()(implicitly[CsvRenderer[T]], implicitly[CsvGenerator[T]], Writable.stringBuilderWritable(csvAttributes.delimiter, csvAttributes.quote), csvAttributes)
case class CsvTableFileRenderer[T: CsvRenderer : CsvGenerator](file: File)(implicit csvAttributes: CsvAttributes)
extends CsvTableRenderer[T, FileWriter]()(implicitly[CsvRenderer[T]], implicitly[CsvGenerator[T]], Writable.fileWritable(file), csvAttributes)
abstract class CsvTableRenderer[T: CsvRenderer : CsvGenerator, O: Writable]()(implicit csvAttributes: CsvAttributes) extends Renderer[Table[T], O] {...}

_CsvRenderer\[T]_ determines the layout of the rows, while _CsvGenerator\[T]_ determines the header.
_CsvAttributes_ specify the delimiter and quote characters for the output.
Instances of each can be created using methods in _CsvRenderers_ and _CsvGenerators_ respectively.
Appropriate methods are:
* sequenceRenderer, optionRenderer, renderer1, renderer2, renderer3, etc. up to renderer12.
* sequenceGenerator, optionGenerator, generator1, generator2, generator3, etc. up to generator12.

In some situations, you will want to omit values (and corresponding header columns) when outputting a CSV file.
You may use the following methods (from the same types as above):

def skipRenderer[T](alignment: Int = 1)(implicit ca: CsvAttributes): CsvRenderer[T]
def skipGenerator[T](implicit ca: CsvAttributes): CsvGenerator[T]

Note that, when rendering a CSV row, you may want to simply render some number of delimiters
(this would be in the case where you have a fixed header).
You can use the _alignment_ parameter of _skipRenderer_ to ensure alignment is correct.

There is currently only one implementation of String rendering, and that is Json rendering.
As usual, the standard types are pre-defined for both _CsvRenderer\[T]_ and _CsvGenerator\[T]_ (for Int, Double, etc.).

The methods mentioned above render tables in the form of CSV Strings.
However, there are also methods available to render tables as a _File_: _writeCSVFile_ and _writeCSVFileRow_.
These utilize the type _CsvTableFileRenderer\[T]_ mentioned above.

If you wish to output only a subset of rows, then you should use one of the methods defined in _Table_ such as _take_.

## Other String Rendering

Apart from CSV, there is currently only one implementation of _String_ rendering, and that is _Json_ rendering.
Although Json is indeed a hierarchical serialization format, the manner of creating a Json string masks the hierarchical aspects.
The implemented Json reader/writer is Spray Json but that could easily be changed in the future.

Although this section is concerned with rendering, it is also true of course to say that tables can be read from Json strings.

The following example from _JsonRendererSpec.scala_ shows how we can take the following steps
(for the definitions of Player, Partnership, please see the spec file itself):
(for the definitions of _Player_, _Partnership_, please see the spec file itself):
* read a table of players from a list of Strings (there are, as shown above, other signatures of parse for files, URLs, etc.);
* convert to a table of partnerships;
* write the resulting table to a Json string;
Expand All @@ -556,6 +608,15 @@ The following example from _JsonRendererSpec.scala_ shows how we can take the fo
Release Notes
=============

V1.1.0 -> V1.1.1
* Enable cryptographic capabilities

V1.0.15 -> V1.1.0
* Enable CSV-rendering and selection of table rows.

V1.0.14 -> V1.0.15
* Minor changes

V1.0.13 -> V1.0.14
* Enabled multi-line quoted strings: if a quoted string spans more than one line, this is acceptable.
* Implemented analysis of raw-row tables.
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ organization := "com.phasmidsoftware"

name := "TableParser"

version := "1.0.15"
version := "1.1.0"

scalaVersion := "2.13.7"

Expand Down
Loading