Skip to content

Commit

Permalink
Refactor transformers to factories
Browse files Browse the repository at this point in the history
  • Loading branch information
davesavic committed Aug 19, 2023
1 parent b9e40b3 commit 4ab4eb9
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 73 deletions.
4 changes: 4 additions & 0 deletions examples/destination.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
id,full_name,street,city,state,postcode,country
1,John Lmith,123 Something Street,Anytown,Queensland,4209,Australia
2,Jane Doe,456 Something Street,Anytown,Queensland,4209,Australia
3,John Doe,789 Something Street,Anytown,Queensland,4209,Australia
20 changes: 20 additions & 0 deletions examples/script.csvshift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Input Columns id, first_name, last_name, address

Column last_name
-> Trim
-> Replace "S" with "K"

Columns first_name, last_name
-> Replace "K" with "L"
-> Join with " " as full_name

Column address
-> Split on "," as street, city, state

Columns street, city, state
-> Trim

Column state
-> Split on " " as state, postcode, country

Output Columns id, full_name, street, city, state, postcode, country
4 changes: 4 additions & 0 deletions examples/source.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
id,first_name,last_name,address
1,John,Smith ,"123 Something Street, Anytown, Queensland 4209 Australia"
2,Jane,Doe,"456 Something Street, Anytown, Queensland 4209 Australia"
3,John,Doe,"789 Something Street, Anytown, Queensland 4209 Australia"
79 changes: 24 additions & 55 deletions listeners/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ type CsvShiftListener struct {
Data *ParsedData
}

var singleColumnTransformerFactories = []transformers.SingleColumnTransformerFactory{
&transformers.SingleColumnTrimTransformerFactory{},
&transformers.SingleColumnReplaceTransformerFactory{},
&transformers.SingleColumnLowerTransformerFactory{},
&transformers.SingleColumnUpperTransformerFactory{},
&transformers.SingleColumnSplitTransformerFactory{},
}

var multipleColumnTransformerFactories = []transformers.MultipleColumnTransformerFactory{
&transformers.MultipleColumnJoinTransformerFactory{},
&transformers.MultipleColumnTrimTransformerFactory{},
&transformers.MultipleColumnReplaceTransformerFactory{},
&transformers.MultipleColumnLowerTransformerFactory{},
&transformers.MultipleColumnUpperTransformerFactory{},
}

func NewCsvShiftListener() *CsvShiftListener {
return &CsvShiftListener{
Data: &ParsedData{},
Expand Down Expand Up @@ -44,37 +60,10 @@ func (s *CsvShiftListener) ExitSingleColumnModifierSection(ctx *parser.SingleCol
var trs []transformers.Transformer

for _, modifier := range modifiers {
switch true {
case modifier.REPLACE() != nil:
trs = append(trs, &transformers.ReplaceTransformer{
Columns: []string{column},
From: extractStringContent(modifier.STRING(0).GetText()),
To: extractStringContent(modifier.STRING(1).GetText()),
})
case modifier.TRIM() != nil:
trs = append(trs, &transformers.TrimTransformer{
Columns: []string{column},
})
case modifier.LOWER() != nil:
trs = append(trs, &transformers.LowerTransformer{
Columns: []string{column},
})
case modifier.UPPER() != nil:
trs = append(trs, &transformers.UpperTransformer{
Columns: []string{column},
})
case modifier.SPLIT() != nil:
intoCols := modifier.Columns().AllIDENTIFIER()
var intoColNames []string
for _, intoCol := range intoCols {
intoColNames = append(intoColNames, intoCol.GetText())
for _, factory := range singleColumnTransformerFactories {
if factory.IsMatch(modifier) {
trs = append(trs, factory.Create(column, modifier))
}

trs = append(trs, &transformers.SplitTransformer{
Column: column,
Separator: extractStringContent(modifier.STRING(0).GetText()),
IntoColumns: intoColNames,
})
}
}

Expand Down Expand Up @@ -102,31 +91,11 @@ func (s *CsvShiftListener) ExitMultipleColumnModifierSection(ctx *parser.Multipl
var trs []transformers.Transformer

for _, modifier := range modifiers {
switch true {
case modifier.TRIM() != nil:
trs = append(trs, &transformers.TrimTransformer{
Columns: columns,
})
case modifier.REPLACE() != nil:
trs = append(trs, &transformers.ReplaceTransformer{
Columns: columns,
From: extractStringContent(modifier.STRING(0).GetText()),
To: extractStringContent(modifier.STRING(1).GetText()),
})
case modifier.JOIN() != nil:
trs = append(trs, &transformers.JoinTransformer{
Columns: columns,
With: extractStringContent(modifier.STRING(0).GetText()),
To: modifier.IDENTIFIER().GetText(),
})
case modifier.LOWER() != nil:
trs = append(trs, &transformers.LowerTransformer{
Columns: columns,
})
case modifier.UPPER() != nil:
trs = append(trs, &transformers.UpperTransformer{
Columns: columns,
})
for _, transformer := range multipleColumnTransformerFactories {
if transformer.IsMatch(modifier) {
trs = append(trs, transformer.Create(columns, modifier))
break
}
}
}

Expand Down
85 changes: 79 additions & 6 deletions transformers/casing.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
package transformers

import "strings"
import (
parser "csvshift/gen"
"strings"
)

type LowerTransformer struct {
type singleColumnLowerTransformer struct {
Column string
}

type SingleColumnLowerTransformerFactory struct{}

type singleColumnUpperTransformer struct {
Column string
}

type SingleColumnUpperTransformerFactory struct{}

type multipleColumnLowerTransformer struct {
Columns []string
}

type MultipleColumnLowerTransformerFactory struct{}

type multipleColumnUpperTransformer struct {
Columns []string
}

func (t *LowerTransformer) Apply(row map[string]interface{}) {
type MultipleColumnUpperTransformerFactory struct{}

func (t *multipleColumnLowerTransformer) Apply(row map[string]interface{}) {
for _, column := range t.Columns {
val, ok := row[column].(string)
if ok {
Expand All @@ -15,15 +38,65 @@ func (t *LowerTransformer) Apply(row map[string]interface{}) {
}
}

type UpperTransformer struct {
Columns []string
func (t *MultipleColumnLowerTransformerFactory) IsMatch(modifier parser.IMultipleColumnTransformationContext) bool {
return modifier.LOWER() != nil
}

func (t *UpperTransformer) Apply(row map[string]interface{}) {
func (t *MultipleColumnLowerTransformerFactory) Create(columns []string, _ parser.IMultipleColumnTransformationContext) Transformer {
return &multipleColumnLowerTransformer{
Columns: columns,
}
}

func (t *multipleColumnUpperTransformer) Apply(row map[string]interface{}) {
for _, column := range t.Columns {
val, ok := row[column].(string)
if ok {
row[column] = strings.ToUpper(val)
}
}
}

func (t *MultipleColumnUpperTransformerFactory) IsMatch(modifier parser.IMultipleColumnTransformationContext) bool {
return modifier.UPPER() != nil
}

func (t *MultipleColumnUpperTransformerFactory) Create(columns []string, _ parser.IMultipleColumnTransformationContext) Transformer {
return &multipleColumnUpperTransformer{
Columns: columns,
}
}

func (t *singleColumnLowerTransformer) Apply(row map[string]interface{}) {
val, ok := row[t.Column].(string)
if ok {
row[t.Column] = strings.ToLower(val)
}
}

func (t *SingleColumnLowerTransformerFactory) IsMatch(modifier parser.ISingleColumnTransformationContext) bool {
return modifier.LOWER() != nil
}

func (t *SingleColumnLowerTransformerFactory) Create(column string, _ parser.ISingleColumnTransformationContext) Transformer {
return &singleColumnLowerTransformer{
Column: column,
}
}

func (t *singleColumnUpperTransformer) Apply(row map[string]interface{}) {
val, ok := row[t.Column].(string)
if ok {
row[t.Column] = strings.ToUpper(val)
}
}

func (t *SingleColumnUpperTransformerFactory) IsMatch(modifier parser.ISingleColumnTransformationContext) bool {
return modifier.UPPER() != nil
}

func (t *SingleColumnUpperTransformerFactory) Create(column string, _ parser.ISingleColumnTransformationContext) Transformer {
return &singleColumnUpperTransformer{
Column: column,
}
}
23 changes: 20 additions & 3 deletions transformers/join.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package transformers

import "strings"
import (
parser "csvshift/gen"
"strings"
)

type JoinTransformer struct {
type MultipleColumnJoinTransformerFactory struct{}

type multipleColumnJoinTransformer struct {
Columns []string
With string
To string
}

func (t *JoinTransformer) Apply(row map[string]interface{}) {
func (t *multipleColumnJoinTransformer) Apply(row map[string]interface{}) {
values := make([]string, 0, len(t.Columns))
for _, column := range t.Columns {
val, ok := row[column].(string)
Expand All @@ -21,3 +26,15 @@ func (t *JoinTransformer) Apply(row map[string]interface{}) {

row[t.To] = strings.Join(values, t.With)
}

func (t *MultipleColumnJoinTransformerFactory) IsMatch(modifier parser.IMultipleColumnTransformationContext) bool {
return modifier.JOIN() != nil
}

func (t *MultipleColumnJoinTransformerFactory) Create(columns []string, modifier parser.IMultipleColumnTransformationContext) Transformer {
return &multipleColumnJoinTransformer{
Columns: columns,
With: ExtractStringContent(modifier.STRING(0).GetText()),
To: modifier.IDENTIFIER().GetText(),
}
}
50 changes: 47 additions & 3 deletions transformers/replace.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
package transformers

import "strings"
import (
parser "csvshift/gen"
"strings"
)

type ReplaceTransformer struct {
type multipleColumnReplaceTransformer struct {
Columns []string
From string
To string
}

func (t *ReplaceTransformer) Apply(row map[string]interface{}) {
type MultipleColumnReplaceTransformerFactory struct{}

type singleColumnReplaceTransformer struct {
Column string
From string
To string
}

type SingleColumnReplaceTransformerFactory struct{}

func (t *multipleColumnReplaceTransformer) Apply(row map[string]interface{}) {
for _, column := range t.Columns {
val, ok := row[column].(string)
if ok {
row[column] = strings.ReplaceAll(val, t.From, t.To)
}
}
}

func (t *MultipleColumnReplaceTransformerFactory) IsMatch(modifier parser.IMultipleColumnTransformationContext) bool {
return modifier.REPLACE() != nil
}

func (t *MultipleColumnReplaceTransformerFactory) Create(columns []string, modifier parser.IMultipleColumnTransformationContext) Transformer {
return &multipleColumnReplaceTransformer{
Columns: columns,
From: ExtractStringContent(modifier.STRING(0).GetText()),
To: ExtractStringContent(modifier.STRING(1).GetText()),
}
}

func (t *singleColumnReplaceTransformer) Apply(row map[string]interface{}) {
val, ok := row[t.Column].(string)
if ok {
row[t.Column] = strings.ReplaceAll(val, t.From, t.To)
}
}

func (t *SingleColumnReplaceTransformerFactory) IsMatch(modifier parser.ISingleColumnTransformationContext) bool {
return modifier.REPLACE() != nil
}

func (t *SingleColumnReplaceTransformerFactory) Create(column string, modifier parser.ISingleColumnTransformationContext) Transformer {
return &singleColumnReplaceTransformer{
Column: column,
From: ExtractStringContent(modifier.STRING(0).GetText()),
To: ExtractStringContent(modifier.STRING(1).GetText()),
}
}
29 changes: 26 additions & 3 deletions transformers/split.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package transformers

import "strings"
import (
parser "csvshift/gen"
"strings"
)

type SplitTransformer struct {
type singleColumnSplitTransformer struct {
Column string
Separator string
IntoColumns []string
}

func (t *SplitTransformer) Apply(row map[string]interface{}) {
type SingleColumnSplitTransformerFactory struct{}

func (t *singleColumnSplitTransformer) Apply(row map[string]interface{}) {
val, ok := row[t.Column].(string)
if ok {
parts := strings.Split(val, t.Separator)
Expand All @@ -21,3 +26,21 @@ func (t *SplitTransformer) Apply(row map[string]interface{}) {
}
}
}

func (t *SingleColumnSplitTransformerFactory) IsMatch(modifier parser.ISingleColumnTransformationContext) bool {
return modifier.SPLIT() != nil
}

func (t *SingleColumnSplitTransformerFactory) Create(column string, modifier parser.ISingleColumnTransformationContext) Transformer {
intoCols := modifier.Columns().AllIDENTIFIER()
var intoColNames []string
for _, intoCol := range intoCols {
intoColNames = append(intoColNames, intoCol.GetText())
}

return &singleColumnSplitTransformer{
Column: column,
Separator: ExtractStringContent(modifier.STRING(0).GetText()),
IntoColumns: intoColNames,
}
}
Loading

0 comments on commit 4ab4eb9

Please sign in to comment.