Starting working at new navigableMap

This commit is contained in:
Trial97
2020-02-10 16:29:35 +02:00
committed by Dan Christian Bogos
parent 0bcb52a23f
commit 2ddfd8ae3c

272
utils/navigablemap.go Normal file
View File

@@ -0,0 +1,272 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
import (
"fmt"
"strings"
)
// DataStorage is the new DataProvider
type DataStorage interface {
String() string // printable version of data
Get(fldPath []string) (interface{}, error)
GetString(fldPath []string) (string, error)
Set(fldPath []string, val interface{}) error
Remove(fldPath []string) error
GetKeys(nesteed bool) []string
// RemoteHost() net.Addr
}
// MapStorage is the basic DataStorage
type MapStorage map[string]interface{}
// String returns the map as json string
func (ms *MapStorage) String() string { return ToJSON(ms) }
// Get returns the value from the path
func (ms *MapStorage) Get(fldPath []string) (val interface{}, err error) {
if len(fldPath) == 0 {
err = ErrNotFound
return
}
var has bool
if val, has = (*ms)[fldPath[0]]; !has {
err = ErrNotFound
return
}
if len(fldPath) == 1 {
return
}
ds, ok := val.(DataStorage)
if !ok {
err = fmt.Errorf("Wrong type")
return
}
return ds.Get(fldPath[1:])
}
// GetString returns thevalue from path as string
func (ms *MapStorage) GetString(fldPath []string) (str string, err error) {
var val interface{}
if val, err = ms.Get(fldPath); err != nil {
return
}
return IfaceAsString(val), nil
}
// Set sets the value at the given path
func (ms *MapStorage) Set(fldPath []string, val interface{}) (err error) {
if len(fldPath) == 0 {
return fmt.Errorf("Wrong path")
}
if len(fldPath) == 1 {
(*ms)[fldPath[0]] = val
return
}
nMap := &MapStorage{}
(*ms)[fldPath[0]] = nMap
return nMap.Set(fldPath[1:], val)
}
// GetKeys returns all the keys from map
func (ms *MapStorage) GetKeys(nesteed bool) (keys []string) {
for k, v := range *ms {
keys = append(keys, k)
if !nesteed {
continue
}
ds, ok := v.(DataStorage)
if !ok {
continue
}
for _, dsKey := range ds.GetKeys(nesteed) {
keys = append(keys, k+NestingSep+dsKey)
}
}
return
}
// Remove removes the item at path
func (ms *MapStorage) Remove(fldPath []string) (err error) {
if len(fldPath) == 0 {
return fmt.Errorf("Wrong path")
}
var val interface{}
var has bool
if val, has = (*ms)[fldPath[0]]; !has {
return // ignore (already removed)
}
if len(fldPath) == 1 {
delete(*ms, fldPath[0])
return
}
ds, ok := val.(DataStorage)
if !ok {
err = fmt.Errorf("Wrong type")
return
}
return ds.Remove(fldPath[1:])
}
// NavigableMap is a DataStorage
type NavigableMap map[string]DataStorage
// String returns the map as json string
func (nm *NavigableMap) String() string { return ToJSON(nm) }
// Get returns the value from the path
func (nm *NavigableMap) Get(fldPath []string) (val interface{}, err error) {
if len(fldPath) == 0 {
err = ErrNotFound
return
}
ds, has := (*nm)[fldPath[0]]
if !has {
err = ErrNotFound
return
}
if len(fldPath) == 1 {
val = ds
return
}
return ds.Get(fldPath[1:])
}
// GetString returns thevalue from path as string
func (nm *NavigableMap) GetString(fldPath []string) (str string, err error) {
var val interface{}
if val, err = nm.Get(fldPath); err != nil {
return
}
return IfaceAsString(val), nil
}
// Set sets the value at the given path
func (nm *NavigableMap) Set(fldPath []string, val interface{}) (err error) {
if len(fldPath) == 0 {
return fmt.Errorf("Wrong path")
}
if len(fldPath) == 1 {
ds, ok := val.(DataStorage)
if !ok {
return fmt.Errorf("Wrong type")
}
(*nm)[fldPath[0]] = ds
return
}
if _, has := (*nm)[fldPath[0]]; !has {
(*nm)[fldPath[0]] = &MapStorage{}
}
return (*nm)[fldPath[0]].Set(fldPath[1:], val)
}
// GetKeys returns all the keys from map
func (nm *NavigableMap) GetKeys(nesteed bool) (keys []string) {
for k, v := range *nm {
keys = append(keys, k)
if !nesteed {
continue
}
for _, dsKey := range v.GetKeys(nesteed) {
keys = append(keys, k+NestingSep+dsKey)
}
}
return
}
// Remove removes the item at path
func (nm *NavigableMap) Remove(fldPath []string) (err error) {
if len(fldPath) == 0 {
return fmt.Errorf("Wrong path")
}
var val DataStorage
var has bool
if val, has = (*nm)[fldPath[0]]; !has {
return // ignore (already removed)
}
if len(fldPath) == 1 {
delete(*nm, fldPath[0])
return
}
return val.Remove(fldPath[1:])
}
// NewOrderedNavigableMap initializates a structure of OrderedNavigableMap with a NavigableMap
func NewOrderedNavigableMap(nm *NavigableMap) *OrderedNavigableMap {
if nm == nil {
return &OrderedNavigableMap{
nm: &NavigableMap{},
order: [][]string{},
}
}
keys := nm.GetKeys(true)
order := make([][]string, len(keys))
for i, k := range keys {
order[i] = strings.Split(k, NestingSep)
}
return &OrderedNavigableMap{
nm: nm,
order: order,
}
}
// OrderedNavigableMap is the same as NavigableMap but keeps the order of fields
type OrderedNavigableMap struct {
nm *NavigableMap
order [][]string
}
// String returns the map as json string
func (onm *OrderedNavigableMap) String() string { return ToJSON(onm.nm) }
// Get returns the value from the path
func (onm *OrderedNavigableMap) Get(fldPath []string) (val interface{}, err error) {
return onm.nm.Get(fldPath)
}
// GetString returns thevalue from path as string
func (onm *OrderedNavigableMap) GetString(fldPath []string) (str string, err error) {
return onm.nm.GetString(fldPath)
}
// Set sets the value at the given path
func (onm *OrderedNavigableMap) Set(fldPath []string, val interface{}) (err error) {
if err = onm.nm.Set(fldPath, val); err == nil {
onm.order = append(onm.order, fldPath)
}
return
}
// GetKeys returns all the keys from map
func (onm *OrderedNavigableMap) GetKeys(nesteed bool) (keys []string) {
keys = make([]string, len(onm.order))
for i, k := range onm.order {
keys[i] = strings.Join(k, NestingSep)
}
return
}
// Remove removes the item at path
func (onm *OrderedNavigableMap) Remove(fldPath []string) (err error) {
if len(fldPath) == 0 {
return fmt.Errorf("Wrong path")
}
return onm.nm.Remove(fldPath)
}