Skip to content

Commit

Permalink
Merge pull request #61 from webability-go/late-night
Browse files Browse the repository at this point in the history
patch v2.0.5
  • Loading branch information
metalwolf committed Mar 23, 2021
2 parents 829ee50 + 10f8867 commit 1f61a7f
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 28 deletions.
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
@UTF-8

[![Go Report Card](https://goreportcard.com/badge/github.com/webability-go/xcore)](https://goreportcard.com/report/github.com/webability-go/xcore)
[![GoDoc](https://godoc.org/github.com/webability-go/xcore?status.png)](https://godoc.org/github.com/webability-go/xcore)
[![GoDoc](https://godoc.org/github.com/webability-go/xcore/v2?status.png)](https://godoc.org/github.com/webability-go/xcore/v2)
[![GolangCI](https://golangci.com/badges/github.com/webability-go/xcore.svg)](https://golangci.com)

XCore for GO v1
XCore for GO v2
=============================

# Please use xcore/v2

import "github.com/webability-go/xcore/v2"

The XCore package is used to build basic object for programmation. for the WebAbility compatility code
For GO, the actual existing code includes:
- XCache: Application Memory Caches
- XDataset: Basic nested data structures for any purpose (template injection, configuration files, database records, etc)
- XLanguage: language dependent text tables
- XTemplate: template system with meta language
- XCache: Application Memory Caches, thread safe.
- XDataset: Basic nested data structures for any purpose (template injection, configuration files, database records, etc) Support thread safe operations on thread safe structures (XDatasetTS and XDatasetCollectionTS)
- XLanguage: language dependent text tables, thread safe
- XTemplate: template system with meta language, thread safe cloning

Manuals are available on godoc.org [![GoDoc](https://godoc.org/github.com/webability-go/xcore?status.png)](https://godoc.org/github.com/webability-go/xcore)
Manuals are available on godoc.org [![GoDoc](https://godoc.org/github.com/webability-go/xcore/v2?status.png)](https://godoc.org/github.com/webability-go/xcore/v2)


TO DO:
======
- XTemplate must concatenate strings after compilation
- Implements functions as data entry for template Execute (simple data or loop functions, can get backs anything, creates an interface)
- Some improvements to check, later:
Adds mutex on XLanguage, XDataset, XTemplate ?? (they should be used locally on every thread, or not ??), maybe adds a flag "thread safe" ?
XCache: activate persistant cache too (shared memory) ????? maybe not for go itself, but for instance to talk with other memory data used by other languages and apps, or to not loose the caches if the app is restarted.
The version 1 is obsolete.


Version Changes Control
=======================

# Please use xcore/v2

v1.1.0 - 2020-03-01
-----------------------
- Modularization of XCore
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/webability-go/xcore

go 1.14
go 1.15

require golang.org/x/text v0.3.2
require golang.org/x/text v0.3.5
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
12 changes: 10 additions & 2 deletions v2/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@UTF-8

[![Go Report Card](https://goreportcard.com/badge/github.com/webability-go/xcore)](https://goreportcard.com/report/github.com/webability-go/xcore)
[![GoDoc](https://godoc.org/github.com/webability-go/xcore?status.png)](https://godoc.org/github.com/webability-go/xcore)
[![GoDoc](https://godoc.org/github.com/webability-go/xcore/v2?status.png)](https://godoc.org/github.com/webability-go/xcore/v2)
[![GolangCI](https://golangci.com/badges/github.com/webability-go/xcore.svg)](https://golangci.com)

XCore for GO v2
Expand All @@ -24,13 +24,21 @@ TO DO:
- XTemplate must concatenate strings after compilation
- Implements functions as data entry for template Execute (simple data or loop functions, can get backs anything, creates an interface)
Some improvements to check, later:
- Adds mutex on XLanguage, XDataset, XTemplate ?? (they should be used locally on every thread, or not ??), maybe adds a flag "thread safe" ?
- Adds mutex on XTemplate ?? (they should be used locally on every thread, or not ??), maybe adds a flag "thread safe" ?
- XCache: activate persistant cache too (shared memory) ????? maybe not for go itself, but for instance to talk with other memory data used by other languages and apps, or to not loose the caches if the app is restarted.


Version Changes Control
=======================

v2.0.5 - 2021-03-23
-----------------------
- function NewXDataset(data) and NewXDatasetCollection(data) added, to build XDatasets based on a classic map[string]interface{}
- XDatasetTS added to the manual
- XLanguage is now thread safe
- XTemplate: Error corrected in string() function (was saying XLanguage)
- Each cache entry is now able to manage its own TLL if set. New function SetTTL(id, duration)

v2.0.4 - 2020-04-13
-----------------------
- XLanguage: Added GetEntries() func (not thread safe yet)
Expand Down
4 changes: 2 additions & 2 deletions v2/go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/webability-go/xcore/v2

go 1.14
go 1.15

require golang.org/x/text v0.3.2
require golang.org/x/text v0.3.5
2 changes: 2 additions & 0 deletions v2/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
25 changes: 25 additions & 0 deletions v2/xcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type XCacheEntry struct {
ctime time.Time
// - rtime is the last read time (used to clean the cache: the less accessed objects are removed).
rtime time.Time
// - ttl is the max duration of object in cache (ctime + ttl > now = invalid)
ttl time.Duration
// The data as itself is an interface to whatever the user need to cache.
data interface{}
}
Expand Down Expand Up @@ -75,6 +77,19 @@ func (c *XCache) Set(key string, indata interface{}) {
}
}

// Set will set a TTL on the entry in the cache.
// If the entry exists, just ads the TTL to the entry
// If the entry does not exist, it does nothing
// Returns nothing.
func (c *XCache) SetTTL(key string, duration time.Duration) {
c.mutex.Lock()
_, ok := c.items[key]
if ok {
c.items[key].ttl = duration
}
c.mutex.Unlock()
}

// removeFromPile will remove an entry key from the ordered pile.
// No lock into this func since it has been set by entry func already
func (c *XCache) removeFromPile(key string) {
Expand All @@ -99,6 +114,16 @@ func (c *XCache) Get(key string) (interface{}, bool) {
c.mutex.RLock()
if x, ok := c.items[key]; ok {
c.mutex.RUnlock()
// expired by TTL ?
if x.ttl != 0 {
if x.ctime.Add(x.ttl).Before(time.Now()) {
c.mutex.Lock()
delete(c.items, key)
c.removeFromPile(key)
c.mutex.Unlock()
return nil, true
}
}
if c.Validator != nil {
if b := c.Validator(key, x.ctime); !b {
if LOG {
Expand Down
29 changes: 28 additions & 1 deletion v2/xcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
// The XLanguage table of text entries can be loaded from XML file, XML string or normal text file or string.
// It is used to keep a table of id=value set of entries in any languages you need, so it is easy to switch between XLanguage instance based on the required language needed.
// Obviously, any XLanguage you load in any language should have the same id entries translated, for the same use.
// The XLanguage object is thread safe
//
// 1. loading:
//
Expand Down Expand Up @@ -282,6 +283,32 @@
//
// The XDatasetCollection type is a simple []DatasetDef with all the implemented methods and should be enough to use for almost all required cases.
//
// XDataSetTS
//
// 1. Overview:
//
// The XDataSetTS is a DatasetDef structure, thread safe.
// It is build on the XDataset with the same properties, but is thread safe to protect Read/Write accesses from different thread.
//
// Example:
//
// import "github.com/webability-go/xcore/v2"
//
// data := &xcore.XDatasetTS{} // data is a XDatasetDef
// data.Set("data1", "DATA1")
// data.Set("newkey", 123.45)
//
// You may also build a XDatasetTS to encapsulate a XDatasetDef that is not thread safe, to use it safely
//
// import "github.com/webability-go/xcore/v2"
//
// datanots := xcore.NewXDataset()
// datats := xcore.NewXDatasetTS(datanots)
//
// Note that all references to XDatasetTS are pointers, always (to be able to modify the values of them).
//
// The DatasetTS meet the XDatasetDef interface
//
//
// XTemplate
//
Expand Down Expand Up @@ -836,7 +863,7 @@
package xcore

// VERSION is the used version nombre of the XCore library.
const VERSION = "2.0.4"
const VERSION = "2.0.5"

// LOG is the flag to activate logging on the library.
// if LOG is set to TRUE, LOG indicates to the XCore libraries to log a trace of functions called, with most important parameters.
Expand Down
17 changes: 17 additions & 0 deletions v2/xdataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ import (
// XDataset IS NOT thread safe
type XDataset map[string]interface{}

// NewXDataset is used to build an XDataset from a standard map
func NewXDataset(data map[string]interface{}) XDatasetDef {
// Scan data and encapsulate it into the XDataset
ds := &XDataset{}
for i, v := range data {
switch v.(type) {
case []map[string]interface{}:
ds.Set(i, NewXDatasetCollection(v.([]map[string]interface{})))
case map[string]interface{}:
ds.Set(i, NewXDataset(v.(map[string]interface{})))
default:
ds.Set(i, v)
}
}
return ds
}

// String will transform the XDataset into a readable string for humans
func (d *XDataset) String() string {
sdata := []string{}
Expand Down
31 changes: 31 additions & 0 deletions v2/xdataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ func ExampleXDataset() {
// xcore.XDataset{clientname:Fred clientpicture:face.jpg hobbies:XDatasetCollection[0:xcore.XDataset{name:Football sport:yes} 1:xcore.XDataset{name:Ping-pong sport:yes} 2:xcore.XDataset{name:Swimming sport:yes} 3:xcore.XDataset{name:Videogames sport:no} ] metadata:xcore.XDataset{Salary:3568.65 hiredate:2020-01-01 12:00:00 +0000 UTC preferred-color:blue} preferredhobby:xcore.XDataset{name:Baseball sport:yes}}
}

func TestXDataset_new(t *testing.T) {

tmp, _ := time.Parse(time.RFC3339, "2020-01-01T12:00:00.0Z")
data := map[string]interface{}{
"clientname": "Fred",
"clientpicture": "face.jpg",
"hobbies": []map[string]interface{}{
{"name": "Football", "sport": "yes"},
{"name": "Ping-pong", "sport": "yes"},
{"name": "Swimming", "sport": "yes"},
{"name": "Videogames", "sport": "no"},
},
"preferredhobby": map[string]interface{}{
"name": "Baseball",
"sport": "yes",
},
"metadata": map[string]interface{}{
"preferred-color": "blue",
"Salary": 3568.65,
"hiredate": tmp,
},
}

ds := NewXDataset(data)
str := fmt.Sprintf("%#v", ds)
if str != "#xcore.XDataset{clientname:\"Fred\" clientpicture:\"face.jpg\" hobbies:XDatasetCollection[0:xcore.XDataset{name:Football sport:yes} 1:xcore.XDataset{name:Ping-pong sport:yes} 2:xcore.XDataset{name:Swimming sport:yes} 3:xcore.XDataset{name:Videogames sport:no} ] metadata:#xcore.XDataset{Salary:3568.65 hiredate:time.Time{wall:0x0, ext:63713476800, loc:(*time.Location)(nil)} preferred-color:\"blue\"} preferredhobby:#xcore.XDataset{name:\"Baseball\" sport:\"yes\"}}" {
t.Error("Error creating and #printing new complex XDataset " + str)
return
}
}

func TestXDataset_simple_print(t *testing.T) {

// 1. Create a simple XDataset
Expand Down
10 changes: 10 additions & 0 deletions v2/xdatasetcollection.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ import (
// XDatasetCollection is the basic collection of XDatasetDefs
type XDatasetCollection []XDatasetDef

// NewXDatasetCollection is used to build an XDatasetCollection from a standard []map
func NewXDatasetCollection(data []map[string]interface{}) XDatasetCollectionDef {
// Scan data and encapsulate it into the XDataset
dsc := &XDatasetCollection{}
for _, v := range data {
dsc.Push(NewXDataset(v))
}
return dsc
}

// String will transform the XDataset into a readable string
func (d *XDatasetCollection) String() string {
str := "XDatasetCollection["
Expand Down
27 changes: 22 additions & 5 deletions v2/xlanguage.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ func (l *XLanguage) LoadXMLString(data string) error {
// Scan to our XLanguage Object
l.Name = temp.Name
l.Language, _ = language.Parse(temp.Language)
l.mutex.Lock()
for _, e := range temp.Entries {
l.entries[e.ID] = e.Entry
}
l.mutex.Unlock()
return nil
}

Expand Down Expand Up @@ -154,7 +156,9 @@ func (l *XLanguage) LoadString(data string) error {
if len(line) > posequal {
value = strings.TrimSpace(line[posequal+1:])
}
l.mutex.Lock()
l.entries[key] = value
l.mutex.Unlock()
}
if err := scanner.Err(); err != nil {
return err
Expand Down Expand Up @@ -184,12 +188,16 @@ func (l *XLanguage) GetLanguage() language.Tag {

// Set will add an entry id-value into the language table
func (l *XLanguage) Set(entry string, value string) {
l.mutex.Lock()
l.entries[entry] = value
l.mutex.Unlock()
}

// Get will read an entry id-value from the language table
func (l *XLanguage) Get(entry string) string {
l.mutex.RLock()
v, ok := l.entries[entry]
l.mutex.RUnlock()
if ok {
return v
}
Expand All @@ -198,33 +206,42 @@ func (l *XLanguage) Get(entry string) string {

// Del will remove an entry id-value from the language table
func (l *XLanguage) Del(entry string) {
l.mutex.Lock()
delete(l.entries, entry)
l.mutex.Unlock()
}

// GetEntries will return a COPY of the key-values pairs of the language.
func (l *XLanguage) GetEntries() map[string]string {
// mutext lock
// if no mutex:
return l.entries
// else makes a clone copy of entries
// mutex realese
clone := map[string]string{}
l.mutex.RLock()
for k, v := range l.entries {
clone[k] = v
}
l.mutex.RUnlock()
return clone
}

// String will transform the XDataset into a readable string for humans
func (l *XLanguage) String() string {
sdata := []string{}
l.mutex.RLock()
for key, val := range l.entries {
sdata = append(sdata, key+":"+fmt.Sprintf("%v", val))
}
l.mutex.RUnlock()
sort.Strings(sdata) // Lets be sure the print is always the same presentation
return "xcore.XLanguage{" + strings.Join(sdata, " ") + "}"
}

// GoString will transform the XDataset into a readable string for humans
func (l *XLanguage) GoString() string {
sdata := []string{}
l.mutex.RLock()
for key, val := range l.entries {
sdata = append(sdata, key+":"+fmt.Sprintf("%#v", val))
}
l.mutex.RUnlock()
sort.Strings(sdata) // Lets be sure the print is always the same presentation
return "#xcore.XLanguage{" + strings.Join(sdata, " ") + "}"
}
4 changes: 3 additions & 1 deletion v2/xtemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sort"
"strconv"
"strings"
// "sync"
)

/*
Expand Down Expand Up @@ -72,6 +73,7 @@ type XTemplate struct {
Name string
Root *XTemplateData
SubTemplates map[string]*XTemplate
// mutex sync.Mutex
}

// NewXTemplate will create a new empty template
Expand Down Expand Up @@ -466,7 +468,7 @@ func (t *XTemplate) String() string {
sdata = append(sdata, fmt.Sprintf("%v", val))
}
sort.Strings(sdata) // Lets be sure the print is always the same presentation
return "xcore.XLanguage{" + strings.Join(sdata, " ") + "}"
return "xcore.XTemplate{" + strings.Join(sdata, " ") + "}"
}

// GoString will transform the XDataset into a readable string for humans
Expand Down

0 comments on commit 1f61a7f

Please sign in to comment.