Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type information to collection types #94

Merged
merged 2 commits into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions collections/dictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type IDictionary interface {
Get(...interface{}) interface{} // Returns the values associated with key.
GetHelpers() (IDictionaryHelper, IListHelper) // Returns the helpers implementation associated with the current type.
GetKeys() IGenericList // Returns the keys in the dictionary in alphabetical order.
GetKinds() IDictionary // Returns the kind associated to each key in the dictionary.
GetTypes() IDictionary // Returns the type associated to each key in the dictionary.
GetValues() IGenericList // Returns the values in the dictionary in alphabetical order of keys.
Has(...interface{}) bool // Returns true if the dictionary object contains all the key.
KeysAsString() StringArray // Returns the keys in the dictionary in alphabetical order.
Expand All @@ -30,8 +32,9 @@ type IDictionary interface {
PrettyPrint() string // Returns the pretty string representation of the dictionary.
Set(key, value interface{}) IDictionary // Sets key to value in the dictionary.
String() string // Returns the string representation of the dictionary.
Transpose() IDictionary // Transpose keys/values and return the resulting dictionary
TypeName() String // Returns the actual type name
Transpose() IDictionary // Transpose keys/values and return the resulting dictionary.
Type() String // Returns the type of object.
TypeName() String // Returns the actual type name.
}

// IDictionaryHelper represents objects that implement IDictionary compatible objects
Expand Down
16 changes: 16 additions & 0 deletions collections/implementation/dict_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package implementation

import (
"fmt"
"reflect"

"github.com/coveooss/gotemplate/v3/collections"
)
Expand Down Expand Up @@ -105,6 +106,16 @@ func (dh DictHelper) GetKeys(dict baseIDict) baseIList {
return result
}

// GetTypes returns a dictionary with key and type (or kind) for each element.
func (dh DictHelper) GetTypes(dict baseIDict, kind bool) baseIDict {
result := dh.CreateDictionary(dict.Len())

for key, value := range dict.AsMap() {
result.Set(key, iif(kind, reflect.TypeOf(value).Kind().String(), reflect.TypeOf(value).Name()))
}
return result
}

// KeysAsString returns the keys in the dictionary in alphabetical order.
func (dh DictHelper) KeysAsString(dict baseIDict) collections.StringArray {
keys := make(collections.StringArray, 0, dict.Len())
Expand Down Expand Up @@ -223,6 +234,11 @@ func (dh DictHelper) Transpose(dict baseIDict) baseIDict {
return result
}

// Type returns the actual type of object.
func (dh DictHelper) Type(dict baseIDict) str {
return str(reflect.TypeOf(dict).Name())
}

func (dh DictHelper) delete(dict baseIDict, keys []interface{}, mustExist bool) (baseIDict, error) {
for i := range keys {
if mustExist && !dict.Has(keys[i]) {
Expand Down
14 changes: 12 additions & 2 deletions collections/implementation/generic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package implementation

import (
"strings"

"github.com/coveooss/gotemplate/v3/collections"
"github.com/coveooss/multilogger/errors"
)
Expand All @@ -10,6 +12,8 @@ type ListTypeName = baseList
type baseIList = collections.IGenericList
type baseList []interface{}

var baseLower = strings.ToLower("base") // This is required because genny capitalize the type name in strings

func (l baseList) AsArray() []interface{} { return []interface{}(l) }
func (l baseList) Cap() int { return cap(l) }
func (l baseList) Capacity() int { return cap(l) }
Expand All @@ -20,6 +24,8 @@ func (l baseList) Create(args ...int) baseIList { return baseListHelper.C
func (l baseList) CreateDict(args ...int) baseIDict { return baseListHelper.CreateDictionary(args...) }
func (l baseList) First() interface{} { return baseListHelper.GetIndexes(l, 0) }
func (l baseList) Get(indexes ...int) interface{} { return baseListHelper.GetIndexes(l, indexes...) }
func (l baseList) GetKinds() baseIList { return baseListHelper.GetTypes(l, true) }
func (l baseList) GetTypes() baseIList { return baseListHelper.GetTypes(l, false) }
func (l baseList) Has(values ...interface{}) bool { return l.Contains(values...) }
func (l baseList) Join(sep interface{}) str { return l.StringArray().Join(sep) }
func (l baseList) Last() interface{} { return baseListHelper.GetIndexes(l, len(l)-1) }
Expand All @@ -28,7 +34,8 @@ func (l baseList) New(args ...interface{}) baseIList { return baseListHelper.N
func (l baseList) Reverse() baseIList { return baseListHelper.Reverse(l) }
func (l baseList) StringArray() strArray { return baseListHelper.GetStringArray(l) }
func (l baseList) Strings() []string { return baseListHelper.GetStrings(l) }
func (l baseList) TypeName() str { return "base" }
func (l baseList) Type() str { return baseListHelper.Type(l) }
func (l baseList) TypeName() str { return str(baseLower) }
func (l baseList) Unique() baseIList { return baseListHelper.Unique(l) }

func (l baseList) GetHelpers() (collections.IDictionaryHelper, collections.IListHelper) {
Expand Down Expand Up @@ -84,6 +91,8 @@ func (d baseDict) CreateList(args ...int) baseIList { return baseHelper.Creat
func (d baseDict) Flush(keys ...interface{}) baseIDict { return baseDictHelper.Flush(d, keys) }
func (d baseDict) Get(keys ...interface{}) interface{} { return baseDictHelper.Get(d, keys) }
func (d baseDict) GetKeys() baseIList { return baseDictHelper.GetKeys(d) }
func (d baseDict) GetKinds() baseIDict { return baseDictHelper.GetTypes(d, true) }
func (d baseDict) GetTypes() baseIDict { return baseDictHelper.GetTypes(d, false) }
func (d baseDict) GetValues() baseIList { return baseDictHelper.GetValues(d) }
func (d baseDict) Has(keys ...interface{}) bool { return baseDictHelper.Has(d, keys) }
func (d baseDict) KeysAsString() strArray { return baseDictHelper.KeysAsString(d) }
Expand All @@ -92,7 +101,8 @@ func (d baseDict) Native() interface{} { return must(collections
func (d baseDict) Pop(keys ...interface{}) interface{} { return baseDictHelper.Pop(d, keys) }
func (d baseDict) Set(key, v interface{}) baseIDict { return baseDictHelper.Set(d, key, v) }
func (d baseDict) Transpose() baseIDict { return baseDictHelper.Transpose(d) }
func (d baseDict) TypeName() str { return "base" }
func (d baseDict) Type() str { return baseDictHelper.Type(d) }
func (d baseDict) TypeName() str { return str(baseLower) }

func (d baseDict) GetHelpers() (collections.IDictionaryHelper, collections.IListHelper) {
return baseDictHelper, baseListHelper
Expand Down
100 changes: 68 additions & 32 deletions collections/implementation/generic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import (
"strings"
"testing"

"github.com/stretchr/testify/assert"

"github.com/coveooss/multilogger/errors"
"github.com/stretchr/testify/assert"
)

var strFixture = baseList(baseListHelper.NewStringList(strings.Split("Hello World, I'm Foo Bar!", " ")...).AsArray())
Expand Down Expand Up @@ -171,6 +170,33 @@ func Test_list_Get(t *testing.T) {
}
}

func Test_list_GetTypes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
kind bool
l baseList
want interface{}
}{
{"Empty", false, nil, baseList{}},
{"Fixture", false, strFixture, baseList{"string", "string", "string", "string", "string"}},
{"Mixed Types", false, baseList{1, 1.2, true, "Hello", baseList{}, baseDict{}}, baseList{"int", "float64", "bool", "string", baseLower + "List", baseLower + "Dict"}},
{"Mixed Kinds", true, baseList{1, 1.2, true, "Hello", baseList{}, baseDict{}}, baseList{"int", "float64", "bool", "string", "slice", "map"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testFunc := tt.l.GetTypes
name := "Types"
if tt.kind {
testFunc = tt.l.GetKinds
name = "Kinds"
}
if got := testFunc(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("baseList.Get%s() = %v, want %v", name, got, tt.want)
}
})
}
}
func Test_list_Len(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1007,58 +1033,68 @@ func Test_dict_Transpose(t *testing.T) {
}
}

func Test_baseList_Get(t *testing.T) {
type args struct {
indexes []int
}
func Test_dict_GetTypes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
l baseList
args args
kind bool
d baseDict
want interface{}
}{
// TODO: Add test cases.
{"Empty", false, nil, baseDict{}},
{"Fixture Types", false, dictFixture, baseDict{
"float": "float64",
"int": "int",
"list": baseLower + "List",
"listInt": baseLower + "List",
"map": baseLower + "Dict",
"mapInt": baseLower + "Dict",
"string": "string",
}},
{"Fixture Kinds", true, dictFixture, baseDict{
"float": "float64",
"int": "int",
"list": "slice",
"listInt": "slice",
"map": "map",
"mapInt": "map",
"string": "string",
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.l.Get(tt.args.indexes...); !reflect.DeepEqual(got, tt.want) {
t.Errorf("baseList.Get() = %v, want %v", got, tt.want)
testFunc := tt.d.GetTypes
name := "Types"
if tt.kind {
testFunc = tt.d.GetKinds
name = "Kinds"
}
if got := testFunc(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("baseDict.Get%s() = %v, want %v", name, got, tt.want)
}
})
}
}

func Test_baseList_TypeName(t *testing.T) {
tests := []struct {
name string
l baseList
want str
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.l.TypeName(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("baseList.TypeName() = %v, want %v", got, tt.want)
}
})
}
func Test_base_Type(t *testing.T) {
t.Run("list", func(t *testing.T) { assert.Equal(t, str(baseLower+"List"), baseList{}.Type()) })
t.Run("dict", func(t *testing.T) { assert.Equal(t, str(baseLower+"Dict"), baseDict{}.Type()) })
}

func Test_base_TypeName(t *testing.T) {
t.Run("list", func(t *testing.T) { assert.Equal(t, baseList{}.TypeName(), str("base")) })
t.Run("dict", func(t *testing.T) { assert.Equal(t, baseDict{}.TypeName(), str("base")) })
t.Run("list", func(t *testing.T) { assert.Equal(t, str(baseLower), baseList{}.TypeName()) })
t.Run("dict", func(t *testing.T) { assert.Equal(t, str(baseLower), baseDict{}.TypeName()) })
}

func Test_base_GetHelper(t *testing.T) {
t.Run("list", func(t *testing.T) {
gotD, gotL := baseList{}.GetHelpers()
assert.Equal(t, gotD.CreateDictionary().TypeName(), baseDictHelper.CreateDictionary().TypeName())
assert.Equal(t, gotL.CreateList().TypeName(), baseListHelper.CreateList().TypeName())
assert.Equal(t, baseDictHelper.CreateDictionary().TypeName(), gotD.CreateDictionary().TypeName())
assert.Equal(t, baseListHelper.CreateList().TypeName(), gotL.CreateList().TypeName())
})
t.Run("dict", func(t *testing.T) {
gotD, gotL := baseDict{}.GetHelpers()
assert.Equal(t, gotD.CreateDictionary().TypeName(), baseDictHelper.CreateDictionary().TypeName())
assert.Equal(t, gotL.CreateList().TypeName(), baseListHelper.CreateList().TypeName())
assert.Equal(t, baseDictHelper.CreateDictionary().TypeName(), gotD.CreateDictionary().TypeName())
assert.Equal(t, baseListHelper.CreateList().TypeName(), gotL.CreateList().TypeName())
})
}
15 changes: 15 additions & 0 deletions collections/implementation/list_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ func (lh ListHelper) GetStringArray(list baseIList) strArray {
return result
}

// GetTypes returns a list with all types (or kinds) for each element.
func (lh ListHelper) GetTypes(list baseIList, kind bool) baseIList {
result := lh.CreateList(list.Len())
for i := range list.AsArray() {
value := list.Get(i)
result.Set(i, iif(kind, reflect.TypeOf(value).Kind().String(), reflect.TypeOf(value).Name()))
}
return result
}

// NewList creates a new IGenericList from supplied arguments.
func (bh BaseHelper) NewList(items ...interface{}) baseIList {
if len(items) == 1 && items[0] != nil {
Expand Down Expand Up @@ -120,6 +130,11 @@ func (lh ListHelper) SetIndex(list baseIList, index int, value interface{}) (bas
return list, nil
}

// Type returns the actual type of object.
func (lh ListHelper) Type(list baseIList) str {
return str(reflect.TypeOf(list).Name())
}

// Register the implementation of list functions
var _ = func() int {
collections.SetListHelper(baseListHelper)
Expand Down
Loading