Updated AgentRequest

This commit is contained in:
Trial97
2020-05-05 17:02:37 +03:00
committed by Dan Christian Bogos
parent 3b9b2895e0
commit 763710fb80
22 changed files with 411 additions and 331 deletions

View File

@@ -32,27 +32,31 @@ import (
)
// NewAgentRequest returns a new AgentRequest
func NewAgentRequest(req config.DataProvider,
vars map[string]interface{},
cgrRply, rply, opts *config.NavigableMap,
func NewAgentRequest(req utils.DataProvider,
vars utils.NavigableMap2,
cgrRply *utils.NavigableMap2,
rply, opts *utils.OrderedNavigableMap,
tntTpl config.RSRParsers,
dfltTenant, timezone string,
filterS *engine.FilterS,
header, trailer config.DataProvider) (ar *AgentRequest) {
header, trailer utils.DataProvider) (ar *AgentRequest) {
if cgrRply == nil {
cgrRply = config.NewNavigableMap(nil)
cgrRply = &utils.NavigableMap2{}
}
if vars == nil {
vars = make(utils.NavigableMap2)
}
if rply == nil {
rply = config.NewNavigableMap(nil)
rply = utils.NewOrderedNavigableMap()
}
if opts == nil {
opts = config.NewNavigableMap(nil)
opts = utils.NewOrderedNavigableMap()
}
ar = &AgentRequest{
Request: req,
Vars: config.NewNavigableMap(vars),
CGRRequest: config.NewNavigableMap(nil),
diamreq: config.NewNavigableMap(nil), // special case when CGRateS is building the request
Vars: vars,
CGRRequest: utils.NewOrderedNavigableMap(),
diamreq: utils.NewOrderedNavigableMap(), // special case when CGRateS is building the request
CGRReply: cgrRply,
Reply: rply,
Timezone: timezone,
@@ -69,39 +73,39 @@ func NewAgentRequest(req config.DataProvider,
} else {
ar.Tenant = dfltTenant
}
ar.Vars.Set([]string{utils.NodeID}, config.CgrConfig().GeneralCfg().NodeID, false, true)
ar.Vars.Set(utils.PathItems{{Field: utils.NodeID}}, utils.NewNMData(config.CgrConfig().GeneralCfg().NodeID))
return
}
// AgentRequest represents data related to one request towards agent
// implements engine.DataProvider so we can pass it to filters
// implements utils.DataProvider so we can pass it to filters
type AgentRequest struct {
Request config.DataProvider // request
Vars *config.NavigableMap // shared data
CGRRequest *config.NavigableMap // Used in reply to access the request that was send
CGRReply *config.NavigableMap
Reply *config.NavigableMap
Tenant,
Timezone string
filterS *engine.FilterS
Header config.DataProvider
Trailer config.DataProvider
diamreq *config.NavigableMap // used in case of building requests (ie. DisconnectSession)
tmp *config.NavigableMap // used in case you want to store temporary items and access them later
Opts *config.NavigableMap
Request utils.DataProvider // request
Vars utils.NavigableMap2 // shared data
CGRRequest *utils.OrderedNavigableMap // Used in reply to access the request that was send
CGRReply *utils.NavigableMap2
Reply *utils.OrderedNavigableMap
Tenant string
Timezone string
filterS *engine.FilterS
Header utils.DataProvider
Trailer utils.DataProvider
diamreq *utils.OrderedNavigableMap // used in case of building requests (ie. DisconnectSession)
tmp utils.NavigableMap2 // used in case you want to store temporary items and access them later
Opts *utils.OrderedNavigableMap
}
// String implements engine.DataProvider
// String implements utils.DataProvider
func (ar *AgentRequest) String() string {
return utils.ToIJSON(ar)
}
// RemoteHost implements engine.DataProvider
// RemoteHost implements utils.DataProvider
func (ar *AgentRequest) RemoteHost() net.Addr {
return ar.Request.RemoteHost()
}
// FieldAsInterface implements engine.DataProvider
// FieldAsInterface implements utils.DataProvider
func (ar *AgentRequest) FieldAsInterface(fldPath []string) (val interface{}, err error) {
switch fldPath[0] {
default:
@@ -109,15 +113,15 @@ func (ar *AgentRequest) FieldAsInterface(fldPath []string) (val interface{}, err
case utils.MetaReq:
val, err = ar.Request.FieldAsInterface(fldPath[1:])
case utils.MetaVars:
val, err = ar.Vars.GetField(fldPath[1:])
val, err = ar.Vars.FieldAsInterface(fldPath[1:])
case utils.MetaCgreq:
val, err = ar.CGRRequest.GetField(fldPath[1:])
val, err = ar.CGRRequest.FieldAsInterface(fldPath[1:])
case utils.MetaCgrep:
val, err = ar.CGRReply.GetField(fldPath[1:])
val, err = ar.CGRReply.FieldAsInterface(fldPath[1:])
case utils.MetaDiamreq:
val, err = ar.diamreq.FieldAsInterface(fldPath[1:])
case utils.MetaRep:
val, err = ar.Reply.GetField(fldPath[1:])
val, err = ar.Reply.FieldAsInterface(fldPath[1:])
case utils.MetaHdr:
val, err = ar.Header.FieldAsInterface(fldPath[1:])
case utils.MetaTrl:
@@ -136,27 +140,44 @@ func (ar *AgentRequest) FieldAsInterface(fldPath []string) (val interface{}, err
return
}
// FieldAsString implements engine.DataProvider
// Field implements utils.NMInterface
func (ar *AgentRequest) Field(fldPath utils.PathItems) (val utils.NMInterface, err error) {
switch fldPath[0].Field {
default:
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
case utils.MetaVars:
val, err = ar.Vars.Field(fldPath[1:])
case utils.MetaCgreq:
val, err = ar.CGRRequest.Field(fldPath[1:])
case utils.MetaCgrep:
val, err = ar.CGRReply.Field(fldPath[1:])
case utils.MetaDiamreq:
val, err = ar.diamreq.Field(fldPath[1:])
case utils.MetaRep:
val, err = ar.Reply.Field(fldPath[1:])
case utils.MetaTmp:
val, err = ar.tmp.Field(fldPath[1:])
case utils.MetaOpts:
val, err = ar.tmp.Field(fldPath[1:])
}
return
}
// FieldAsString implements utils.DataProvider
func (ar *AgentRequest) FieldAsString(fldPath []string) (val string, err error) {
var iface interface{}
if iface, err = ar.FieldAsInterface(fldPath); err != nil {
return
}
if nmItems, isNMItems := iface.([]*config.NMItem); isNMItems { // special handling of NMItems, take the last value out of it
iface = nmItems[len(nmItems)-1].Data // could be we need nil protection here
if nmItems, isNMItems := iface.(*utils.NMSlice); isNMItems { // special handling of NMItems, take the last value out of it
iface = (*nmItems)[len(*nmItems)-1].Interface()
}
return utils.IfaceAsString(iface), nil
}
// AsNavigableMap implements engine.DataProvider
func (ar *AgentRequest) AsNavigableMap(tplFlds []*config.FCTemplate) (
nM *config.NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}
//SetFields will populate fields of AgentRequest out of templates
func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) {
ar.tmp = config.NewNavigableMap(nil)
ar.tmp = utils.NavigableMap2{}
for _, tplFld := range tplFlds {
if pass, err := ar.filterS.Pass(ar.Tenant,
tplFld.Filters, ar); err != nil {
@@ -167,51 +188,19 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) {
switch tplFld.Type {
case utils.META_NONE:
case utils.MetaRemove:
fldPath := strings.Split(tplFld.Path, utils.NestingSep)
switch fldPath[0] {
default:
return fmt.Errorf("unsupported field prefix: <%s> when set fields", fldPath[0])
case utils.MetaVars:
ar.Vars.Remove(fldPath[1:])
case utils.MetaCgreq:
ar.CGRRequest.Remove(fldPath[1:])
case utils.MetaCgrep:
ar.CGRReply.Remove(fldPath[1:])
case utils.MetaRep:
ar.Reply.Remove(fldPath[1:])
case utils.MetaDiamreq:
ar.diamreq.Remove(fldPath[1:])
case utils.MetaTmp:
ar.tmp.Remove(fldPath[1:])
case utils.MetaCache:
engine.Cache.Remove(utils.CacheUCH, strings.Join(fldPath[1:], utils.NestingSep), true, utils.NonTransactional)
case utils.MetaOpts:
ar.Opts.Remove(fldPath[1:])
if err = ar.Remove(&utils.FullPath{
PathItems: tplFld.GetPathItems(),
Path: tplFld.Path,
}); err != nil {
return
}
case utils.MetaRemoveAll:
fldPath := strings.Split(tplFld.Path, utils.NestingSep)
switch fldPath[0] {
default:
return fmt.Errorf("unsupported field prefix: <%s> when set fields", fldPath[0])
case utils.MetaVars:
ar.Vars.RemoveAll()
case utils.MetaCgreq:
ar.CGRRequest.RemoveAll()
case utils.MetaCgrep:
ar.CGRReply.RemoveAll()
case utils.MetaRep:
ar.Reply.RemoveAll()
case utils.MetaDiamreq:
ar.diamreq.RemoveAll()
case utils.MetaTmp:
ar.tmp.RemoveAll()
case utils.MetaCache:
engine.Cache.Clear([]string{utils.CacheUCH})
case utils.MetaOpts:
ar.Opts.RemoveAll()
if err = ar.RemoveAll(tplFld.GetPathSlice()[0]); err != nil {
return
}
default:
out, err := ar.ParseField(tplFld)
var out interface{}
out, err = ar.ParseField(tplFld)
if err != nil {
if err == utils.ErrNotFound {
if !tplFld.Mandatory {
@@ -220,49 +209,24 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) {
}
err = utils.ErrPrefixNotFound(tplFld.Tag)
}
return err
return
}
fullPath := &utils.FullPath{
PathItems: tplFld.GetPathItems().Clone(), // need to clone so me do not modify the template
Path: tplFld.Path,
}
var valSet []*config.NMItem
fldPath := strings.Split(tplFld.Path, utils.NestingSep)
nMItm := &config.NMItem{Data: out, Path: fldPath[1:], Config: tplFld}
if nMFields, err := ar.FieldAsInterface(fldPath); err != nil {
if err != utils.ErrNotFound {
return err
}
} else {
valSet = nMFields.([]*config.NMItem) // start from previous stored fields
switch tplFld.Type {
case utils.META_COMPOSED:
prevNMItem := valSet[len(valSet)-1] // could be we need nil protection here
*nMItm = *prevNMItem // inherit the particularities, ie AttributeName
nMItm.Data = utils.IfaceAsString(prevNMItem.Data) + utils.IfaceAsString(out)
valSet = valSet[:len(valSet)-1] // discard the last item since we have captured it in nmItem
case utils.MetaGroup: // in case of *group type simply append to valSet
default:
valSet = nil
}
}
valSet = append(valSet, nMItm)
switch fldPath[0] {
nMItm := &config.NMItem{Data: out, Path: tplFld.GetPathSlice()[1:], Config: tplFld}
switch tplFld.Type {
case utils.META_COMPOSED:
err = utils.ComposeNavMapVal(ar, fullPath, nMItm)
case utils.MetaGroup: // in case of *group type simply append to valSet
err = utils.AppendNavMapVal(ar, fullPath, nMItm)
default:
return fmt.Errorf("unsupported field prefix: <%s> when set fields", fldPath[0])
case utils.MetaVars:
ar.Vars.Set(fldPath[1:], valSet, false, true)
case utils.MetaCgreq:
ar.CGRRequest.Set(fldPath[1:], valSet, false, true)
case utils.MetaCgrep:
ar.CGRReply.Set(fldPath[1:], valSet, false, true)
case utils.MetaRep:
ar.Reply.Set(fldPath[1:], valSet, false, true)
case utils.MetaDiamreq:
ar.diamreq.Set(fldPath[1:], valSet, false, true)
case utils.MetaTmp:
ar.tmp.Set(fldPath[1:], valSet, false, true)
case utils.MetaCache:
engine.Cache.Set(utils.CacheUCH, strings.Join(fldPath[1:], utils.NestingSep), valSet, nil, true, utils.NonTransactional)
case utils.MetaOpts:
ar.Opts.Set(fldPath[1:], valSet, false, true)
_, err = ar.Set(fullPath, &utils.NMSlice{nMItm})
}
if err != nil {
return
}
}
if tplFld.Blocker { // useful in case of processing errors first
@@ -272,6 +236,104 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) {
return
}
// Set implements utils.NMInterface
func (ar *AgentRequest) Set(fullPath *utils.FullPath, nm utils.NMInterface) (added bool, err error) {
switch fullPath.PathItems[0].Field {
default:
return false, fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0].Field)
case utils.MetaVars:
return ar.Vars.Set(fullPath.PathItems[1:], nm)
case utils.MetaCgreq:
return ar.CGRRequest.Set(&utils.FullPath{
PathItems: fullPath.PathItems[1:],
Path: fullPath.Path[7:],
}, nm)
case utils.MetaCgrep:
return ar.CGRReply.Set(fullPath.PathItems[1:], nm)
case utils.MetaRep:
return ar.Reply.Set(&utils.FullPath{
PathItems: fullPath.PathItems[1:],
Path: fullPath.Path[5:],
}, nm)
case utils.MetaDiamreq:
return ar.diamreq.Set(&utils.FullPath{
PathItems: fullPath.PathItems[1:],
Path: fullPath.Path[9:],
}, nm)
case utils.MetaTmp:
return ar.tmp.Set(fullPath.PathItems[1:], nm)
case utils.MetaOpts:
return ar.diamreq.Set(&utils.FullPath{
PathItems: fullPath.PathItems[1:],
Path: fullPath.Path[6:],
}, nm)
case utils.MetaCache:
err = engine.Cache.Set(utils.CacheUCH, fullPath.Path[7:], nm, nil, true, utils.NonTransactional)
}
return false, err
}
// RemoveAll deletes all fields at given prefix
func (ar *AgentRequest) RemoveAll(prefix string) error {
switch prefix {
default:
return fmt.Errorf("unsupported field prefix: <%s> when set fields", prefix)
case utils.MetaVars:
ar.Vars = utils.NavigableMap2{}
case utils.MetaCgreq:
ar.CGRRequest.RemoveAll()
case utils.MetaCgrep:
ar.CGRReply = &utils.NavigableMap2{}
case utils.MetaRep:
ar.Reply.RemoveAll()
case utils.MetaDiamreq:
ar.diamreq.RemoveAll()
case utils.MetaTmp:
ar.tmp = utils.NavigableMap2{}
case utils.MetaCache:
engine.Cache.Clear([]string{utils.CacheUCH})
case utils.MetaOpts:
ar.Opts.RemoveAll()
}
return nil
}
// Remove deletes the fields found at path with the given prefix
func (ar *AgentRequest) Remove(fullPath *utils.FullPath) error {
switch fullPath.PathItems[0].Field {
default:
return fmt.Errorf("unsupported field prefix: <%s> when set fields", fullPath.PathItems[0].Field)
case utils.MetaVars:
return ar.Vars.Remove(fullPath.PathItems[1:])
case utils.MetaCgreq:
return ar.CGRRequest.Remove(&utils.FullPath{
PathItems: fullPath.PathItems[1:].Clone(),
Path: fullPath.Path[7:],
})
case utils.MetaCgrep:
return ar.CGRReply.Remove(fullPath.PathItems[1:])
case utils.MetaRep:
return ar.Reply.Remove(&utils.FullPath{
PathItems: fullPath.PathItems[1:].Clone(),
Path: fullPath.Path[5:],
})
case utils.MetaDiamreq:
return ar.diamreq.Remove(&utils.FullPath{
PathItems: fullPath.PathItems[1:].Clone(),
Path: fullPath.Path[9:],
})
case utils.MetaTmp:
return ar.tmp.Remove(fullPath.PathItems[1:])
case utils.MetaOpts:
return ar.Opts.Remove(&utils.FullPath{
PathItems: fullPath.PathItems[1:].Clone(),
Path: fullPath.Path[6:],
})
case utils.MetaCache:
return engine.Cache.Remove(utils.CacheUCH, fullPath.Path[7:], true, utils.NonTransactional)
}
}
// ParseField outputs the value based on the template item
func (ar *AgentRequest) ParseField(
cfgFld *config.FCTemplate) (out interface{}, err error) {
@@ -443,20 +505,17 @@ func (ar *AgentRequest) ParseField(
// setCGRReply will set the aReq.cgrReply based on reply coming from upstream or error
// returns error in case of reply not converting to NavigableMap
func (ar *AgentRequest) setCGRReply(rply config.NavigableMapper, errRply error) (err error) {
var nm *config.NavigableMap
func (ar *AgentRequest) setCGRReply(rply utils.NavigableMapper, errRply error) (err error) {
var nm utils.NavigableMap2
if errRply != nil {
nm = config.NewNavigableMap(map[string]interface{}{
utils.Error: errRply.Error()})
nm = utils.NavigableMap2{utils.Error: utils.NewNMData(errRply.Error())}
} else {
nm = config.NewNavigableMap(nil)
nm = utils.NavigableMap2{}
if rply != nil {
if nm, err = rply.AsNavigableMap(nil); err != nil {
return
}
nm = rply.AsNavigableMap()
}
nm.Set([]string{utils.Error}, "", false, false) // enforce empty error
nm.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData("")) // enforce empty error
}
*ar.CGRReply = *nm // update value so we can share CGRReply
*ar.CGRReply = nm // update value so we can share CGRReply
return
}

View File

@@ -288,7 +288,7 @@ func writeOnConn(c diam.Conn, m *diam.Message) (err error) {
}
// newDADataProvider constructs a DataProvider for a diameter message
func newDADataProvider(c diam.Conn, m *diam.Message) config.DataProvider {
func newDADataProvider(c diam.Conn, m *diam.Message) utils.DataProvider {
return &diameterDP{c: c, m: m, cache: config.NewNavigableMap(nil)}
}

View File

@@ -60,7 +60,7 @@ func domainNameFromNAPTR(name string) (dName string) {
// newDADataProvider constructs a DataProvider for a diameter message
func newDNSDataProvider(req *dns.Msg,
w dns.ResponseWriter) config.DataProvider {
w dns.ResponseWriter) utils.DataProvider {
return &dnsDP{req: req, w: w,
cache: config.NewNavigableMap(nil)}
}

View File

@@ -35,7 +35,7 @@ import (
// newHADataProvider constructs a DataProvider
func newHADataProvider(reqPayload string,
req *http.Request) (dP config.DataProvider, err error) {
req *http.Request) (dP utils.DataProvider, err error) {
switch reqPayload {
default:
return nil, fmt.Errorf("unsupported decoder type <%s>", reqPayload)
@@ -47,7 +47,7 @@ func newHADataProvider(reqPayload string,
}
}
func newHTTPUrlDP(req *http.Request) (dP config.DataProvider, err error) {
func newHTTPUrlDP(req *http.Request) (dP utils.DataProvider, err error) {
dP = &httpUrlDP{req: req, cache: config.NewNavigableMap(nil)}
return
}
@@ -105,7 +105,7 @@ func (hU *httpUrlDP) RemoteHost() net.Addr {
return utils.NewNetAddr("TCP", hU.req.RemoteAddr)
}
func newHTTPXmlDP(req *http.Request) (dP config.DataProvider, err error) {
func newHTTPXmlDP(req *http.Request) (dP utils.DataProvider, err error) {
byteData, err := ioutil.ReadAll(req.Body)
if err != nil {
return nil, err

View File

@@ -60,7 +60,7 @@ func radReplyAppendAttributes(reply *radigo.Packet, rplNM *config.NavigableMap)
}
// newRADataProvider constructs a DataProvider
func newRADataProvider(req *radigo.Packet) (dP config.DataProvider) {
func newRADataProvider(req *radigo.Packet) (dP utils.DataProvider) {
dP = &radiusDP{req: req, cache: config.NewNavigableMap(nil)}
return
}

View File

@@ -1,51 +0,0 @@
/*
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 config
import (
"net"
"strings"
"github.com/cgrates/cgrates/utils"
)
// DataProvider is a data source from multiple formats
type DataProvider interface {
String() string // printable version of data
FieldAsInterface(fldPath []string) (interface{}, error)
FieldAsString(fldPath []string) (string, error)
AsNavigableMap([]*FCTemplate) (*NavigableMap, error)
RemoteHost() net.Addr
}
func DPDynamicInterface(dnVal string, dP DataProvider) (interface{}, error) {
if strings.HasPrefix(dnVal, utils.DynamicDataPrefix) {
dnVal = strings.TrimPrefix(dnVal, utils.DynamicDataPrefix)
return dP.FieldAsInterface(strings.Split(dnVal, utils.NestingSep))
}
return utils.StringToInterface(dnVal), nil
}
func DPDynamicString(dnVal string, dP DataProvider) (string, error) {
if strings.HasPrefix(dnVal, utils.DynamicDataPrefix) {
dnVal = strings.TrimPrefix(dnVal, utils.DynamicDataPrefix)
return dP.FieldAsString(strings.Split(dnVal, utils.NestingSep))
}
return dnVal, nil
}

View File

@@ -20,6 +20,7 @@ package config
import (
"fmt"
"strings"
"time"
"github.com/cgrates/cgrates/utils"
@@ -33,6 +34,9 @@ func NewFCTemplateFromFCTemplateJsonCfg(jsnCfg *FcTemplateJsonCfg, separator str
}
if jsnCfg.Path != nil {
fcTmp.Path = *jsnCfg.Path
fcTmp.pathSlice = strings.Split(*jsnCfg.Path, utils.NestingSep)
fcTmp.pathItems = utils.NewPathToItem(fcTmp.pathSlice)
fcTmp.Tag = fcTmp.Path
}
fcTmp.Tag = fcTmp.Path
if jsnCfg.Tag != nil {
@@ -116,6 +120,8 @@ type FCTemplate struct {
RoundingDecimals *int
MaskDestID string
MaskLen int
pathItems utils.PathItems // Field identifier
pathSlice []string // Used when we set a NMItem to not recreate this slice for every itemsc
}
func FCTemplatesFromFCTemplatesJsonCfg(jsnCfgFlds []*FcTemplateJsonCfg, separator string) ([]*FCTemplate, error) {
@@ -161,36 +167,41 @@ func InflateTemplates(fcts []*FCTemplate, msgTpls map[string][]*FCTemplate) ([]*
return fcts, nil
}
func (self *FCTemplate) Clone() *FCTemplate {
func (fc *FCTemplate) Clone() *FCTemplate {
cln := new(FCTemplate)
cln.Tag = self.Tag
cln.Type = self.Type
cln.Path = self.Path
if len(self.Filters) != 0 {
cln.Filters = make([]string, len(self.Filters))
for idx, val := range self.Filters {
cln.Tag = fc.Tag
cln.Type = fc.Type
cln.Path = fc.Path
cln.pathItems = fc.pathItems.Clone()
cln.pathSlice = make([]string, len(fc.pathSlice))
for i, v := range fc.pathSlice {
cln.pathSlice[i] = v
}
if len(fc.Filters) != 0 {
cln.Filters = make([]string, len(fc.Filters))
for idx, val := range fc.Filters {
cln.Filters[idx] = val
}
}
cln.Value = make(RSRParsers, len(self.Value))
for idx, val := range self.Value {
cln.Value = make(RSRParsers, len(fc.Value))
for idx, val := range fc.Value {
clnVal := *val
cln.Value[idx] = &clnVal
}
cln.Width = self.Width
cln.Strip = self.Strip
cln.Padding = self.Padding
cln.Mandatory = self.Mandatory
cln.AttributeID = self.AttributeID
cln.NewBranch = self.NewBranch
cln.Timezone = self.Timezone
cln.Blocker = self.Blocker
cln.BreakOnSuccess = self.BreakOnSuccess
cln.Layout = self.Layout
cln.CostShiftDigits = self.CostShiftDigits
cln.RoundingDecimals = self.RoundingDecimals
cln.MaskDestID = self.MaskDestID
cln.MaskLen = self.MaskLen
cln.Width = fc.Width
cln.Strip = fc.Strip
cln.Padding = fc.Padding
cln.Mandatory = fc.Mandatory
cln.AttributeID = fc.AttributeID
cln.NewBranch = fc.NewBranch
cln.Timezone = fc.Timezone
cln.Blocker = fc.Blocker
cln.BreakOnSuccess = fc.BreakOnSuccess
cln.Layout = fc.Layout
cln.CostShiftDigits = fc.CostShiftDigits
cln.RoundingDecimals = fc.RoundingDecimals
cln.MaskDestID = fc.MaskDestID
cln.MaskLen = fc.MaskLen
return cln
}
@@ -265,3 +276,19 @@ func (fc *FCTemplate) AsMapInterface(separator string) (mp map[string]interface{
return
}
// GetPathSlice returns the cached split of the path
func (fc *FCTemplate) GetPathSlice() []string {
return fc.pathSlice
}
// GetPathItems returns the cached path as PathItems
func (fc *FCTemplate) GetPathItems() utils.PathItems {
return fc.pathItems
}
// ComputePath used in test to populate private fields used to store the path
func (fc *FCTemplate) ComputePath() {
fc.pathSlice = strings.Split(fc.Path, utils.NestingSep)
fc.pathItems = utils.NewPathToItem(fc.pathSlice)
}

View File

@@ -27,25 +27,25 @@ import (
"github.com/cgrates/cgrates/utils"
)
// NewfwvProvider constructs a DataProvider
func NewFWVProvider(record string) (dP DataProvider) {
// NewfwvProvider constructs a utils.DataProvider
func NewFWVProvider(record string) (dP utils.DataProvider) {
dP = &FWVProvider{req: record, cache: NewNavigableMap(nil)}
return
}
// fwvProvider implements engine.DataProvider so we can pass it to filters
// fwvProvider implements engine.utils.DataProvider so we can pass it to filters
type FWVProvider struct {
req string
cache *NavigableMap
}
// String is part of engine.DataProvider interface
// String is part of engine.utils.DataProvider interface
// when called, it will display the already parsed values out of cache
func (fP *FWVProvider) String() string {
return utils.ToJSON(fP)
}
// FieldAsInterface is part of engine.DataProvider interface
// FieldAsInterface is part of engine.utils.DataProvider interface
func (fP *FWVProvider) FieldAsInterface(fldPath []string) (data interface{}, err error) {
if len(fldPath) == 0 {
return
@@ -79,7 +79,7 @@ func (fP *FWVProvider) FieldAsInterface(fldPath []string) (data interface{}, err
return
}
// FieldAsString is part of engine.DataProvider interface
// FieldAsString is part of engine.utils.DataProvider interface
func (fP *FWVProvider) FieldAsString(fldPath []string) (data string, err error) {
var valIface interface{}
valIface, err = fP.FieldAsInterface(fldPath)
@@ -89,13 +89,13 @@ func (fP *FWVProvider) FieldAsString(fldPath []string) (data string, err error)
return utils.IfaceAsString(valIface), nil
}
// AsNavigableMap is part of engine.DataProvider interface
// AsNavigableMap is part of engine.utils.DataProvider interface
func (fP *FWVProvider) AsNavigableMap([]*FCTemplate) (
nm *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}
// RemoteHost is part of engine.DataProvider interface
// RemoteHost is part of engine.utils.DataProvider interface
func (fP *FWVProvider) RemoteHost() net.Addr {
return utils.LocalAddr()
}

View File

@@ -31,9 +31,56 @@ import (
"github.com/cgrates/cgrates/utils"
)
// CGRReplier is the interface supported by replies convertible to CGRReply
type NavigableMapper interface {
AsNavigableMap([]*FCTemplate) (*NavigableMap, error)
// NMItem is an item in the NavigableMap
type NMItem struct {
Path []string // path in map
Data interface{} // value of the element
Config *FCTemplate // so we can store additional configuration
}
func (nmi *NMItem) String() string {
return utils.ToJSON(nmi)
}
// Interface returns the wraped interface
func (nmi *NMItem) Interface() interface{} {
return nmi.Data
}
// Field not implemented only used in order to implement the NM interface
func (nmi *NMItem) Field(path utils.PathItems) (val utils.NMInterface, err error) {
return nil, utils.ErrNotImplemented
}
// Set not implemented only used in order to implement the NM interface
// special case when the path is empty the interface should be seted
// this is in order to modify the wraped interface
func (nmi *NMItem) Set(path utils.PathItems, val utils.NMInterface) (added bool, err error) {
if len(path) != 0 {
return false, utils.ErrWrongPath
}
nmi.Data = val.Interface()
return
}
// Remove not implemented only used in order to implement the NM interface
func (nmi *NMItem) Remove(path utils.PathItems) (err error) {
return utils.ErrNotImplemented
}
// Type returns the type of the NM interface
func (nmi *NMItem) Type() utils.NMType {
return utils.NMDataType
}
// Empty returns true if the NM is empty(no data)
func (nmi *NMItem) Empty() bool {
return nmi == nil || nmi.Data == nil
}
// Len not implemented only used in order to implement the NM interface
func (nmi *NMItem) Len() int {
return 0
}
// NewNavigableMap constructs a NavigableMap
@@ -44,13 +91,6 @@ func NewNavigableMap(data map[string]interface{}) *NavigableMap {
return &NavigableMap{data: data}
}
// NMItem is an item in the NavigableMap
type NMItem struct {
Path []string // path in map
Data interface{} // value of the element
Config *FCTemplate // so we can store additional configuration
}
// NavigableMap is a map who's values can be navigated via path
// data can be retrieved as ordered
// NavigableMap is not thread safe due to performance demands, could come back if needed
@@ -111,7 +151,7 @@ func (nM *NavigableMap) GetField(path []string) (fldVal interface{}, err error)
switch mv := dp.(type) { // used for cdr when populating eventCost whitin
case map[string]interface{}:
lastMp = mv
case DataProvider:
case utils.DataProvider:
return mv.FieldAsInterface(path[i+1:])
default:
return nil, fmt.Errorf("cannot cast field: <%+v> type: %T with path: <%s> to map[string]interface{}",
@@ -157,7 +197,7 @@ func (nM *NavigableMap) getLastRealItem(mp map[string]interface{}, spath string)
}
// FieldAsInterface returns the field value as interface{} for the path specified
// implements DataProvider
// implements utils.DataProvider
// supports spath with selective elements in case of []*NMItem
func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) {
lenPath := len(fldPath)
@@ -176,7 +216,7 @@ func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{},
switch mv := dp.(type) { // used for cdr when populating eventCost whitin
case map[string]interface{}:
lastMp = mv
case DataProvider:
case utils.DataProvider:
return mv.FieldAsInterface(fldPath[i+1:])
default:
return nil, fmt.Errorf("cannot cast field: <%+v> type: %T with path: <%s> to map[string]interface{}",
@@ -250,7 +290,7 @@ func (nM *NavigableMap) getNextMap(mp map[string]interface{}, spath string) (int
return mv.data, nil
case *NavigableMap:
return mv.data, nil
case DataProvider: // used for cdr when populating eventCost whitin
case utils.DataProvider: // used for cdr when populating eventCost whitin
return mv, nil
default:
}
@@ -286,7 +326,7 @@ func (nM *NavigableMap) getNextMap(mp map[string]interface{}, spath string) (int
if *idx < len(mv) {
return mv[*idx].data, nil
}
case []DataProvider: // used for cdr when populating eventCost whitin
case []utils.DataProvider: // used for cdr when populating eventCost whitin
if *idx < len(mv) {
return mv[*idx], nil
}
@@ -319,7 +359,7 @@ func (nM *NavigableMap) getIndex(spath string) (opath string, idx *int) {
}
// FieldAsString returns the field value as string for the path specified
// implements DataProvider
// implements utils.DataProvider
func (nM *NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error) {
var valIface interface{}
valIface, err = nM.FieldAsInterface(fldPath)
@@ -329,12 +369,12 @@ func (nM *NavigableMap) FieldAsString(fldPath []string) (fldVal string, err erro
return utils.IfaceAsString(valIface), nil
}
// String is part of engine.DataProvider interface
// String is part of engine.utils.DataProvider interface
func (nM *NavigableMap) String() string {
return utils.ToJSON(nM.data)
}
// RemoteHost is part of engine.DataProvider interface
// RemoteHost is part of engine.utils.DataProvider interface
func (nM *NavigableMap) RemoteHost() net.Addr {
return utils.LocalAddr()
}
@@ -369,7 +409,7 @@ func (nM *NavigableMap) Values() (vals []interface{}) {
return
}
// AsNavigableMap implements both NavigableMapper as well as DataProvider interfaces
// AsNavigableMap implements both NavigableMapper as well as utils.DataProvider interfaces
func (nM *NavigableMap) AsNavigableMap(
tpl []*FCTemplate) (oNM *NavigableMap, err error) {
return nil, utils.ErrNotImplemented

View File

@@ -26,8 +26,8 @@ import (
"github.com/cgrates/cgrates/utils"
)
//NewObjectDP constructs a DataProvider
func NewObjectDP(obj interface{}) (dP DataProvider) {
//NewObjectDP constructs a utils.DataProvider
func NewObjectDP(obj interface{}) (dP utils.DataProvider) {
dP = &ObjectDP{obj: obj, cache: make(map[string]interface{})}
return
}
@@ -46,13 +46,13 @@ func (objDP *ObjectDP) getCache(path string) (val interface{}, has bool) {
return
}
// String is part of engine.DataProvider interface
// String is part of engine.utils.DataProvider interface
// when called, it will display the already parsed values out of cache
func (objDP *ObjectDP) String() string {
return utils.ToJSON(objDP.obj)
}
// FieldAsInterface is part of engine.DataProvider interface
// FieldAsInterface is part of engine.utils.DataProvider interface
func (objDP *ObjectDP) FieldAsInterface(fldPath []string) (data interface{}, err error) {
obj := objDP.obj
// []string{ BalanceMap *monetary[0] Value }
@@ -109,7 +109,7 @@ func (objDP *ObjectDP) FieldAsInterface(fldPath []string) (data interface{}, err
return
}
// FieldAsString is part of engine.DataProvider interface
// FieldAsString is part of engine.utils.DataProvider interface
func (objDP *ObjectDP) FieldAsString(fldPath []string) (data string, err error) {
var valIface interface{}
valIface, err = objDP.FieldAsInterface(fldPath)
@@ -119,13 +119,13 @@ func (objDP *ObjectDP) FieldAsString(fldPath []string) (data string, err error)
return utils.IfaceAsString(valIface), nil
}
// AsNavigableMap is part of engine.DataProvider interface
// AsNavigableMap is part of engine.utils.DataProvider interface
func (objDP *ObjectDP) AsNavigableMap([]*FCTemplate) (
nm *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}
// RemoteHost is part of engine.DataProvider interface
// RemoteHost is part of engine.utils.DataProvider interface
func (objDP *ObjectDP) RemoteHost() net.Addr {
return utils.LocalAddr()
}

View File

@@ -107,7 +107,7 @@ func (prsrs RSRParsers) ParseEvent(ev map[string]interface{}) (out string, err e
return
}
func (prsrs RSRParsers) ParseDataProvider(dP DataProvider, separator string) (out string, err error) {
func (prsrs RSRParsers) ParseDataProvider(dP utils.DataProvider, separator string) (out string, err error) {
for _, prsr := range prsrs {
if outPrsr, err := prsr.ParseDataProvider(dP, separator); err != nil {
return "", err
@@ -118,7 +118,7 @@ func (prsrs RSRParsers) ParseDataProvider(dP DataProvider, separator string) (ou
return
}
func (prsrs RSRParsers) ParseDataProviderWithInterfaces(dP DataProvider, separator string) (out string, err error) {
func (prsrs RSRParsers) ParseDataProviderWithInterfaces(dP utils.DataProvider, separator string) (out string, err error) {
for _, prsr := range prsrs {
if outPrsr, err := prsr.ParseDataProviderWithInterfaces(dP, separator); err != nil {
return "", err
@@ -280,7 +280,7 @@ func (prsr *RSRParser) ParseEvent(ev map[string]interface{}) (out string, err er
return prsr.ParseValue(val)
}
func (prsr *RSRParser) ParseDataProvider(dP DataProvider, separator string) (out string, err error) {
func (prsr *RSRParser) ParseDataProvider(dP utils.DataProvider, separator string) (out string, err error) {
var outStr string
if prsr.attrValue == "" {
if outStr, err = dP.FieldAsString(
@@ -292,7 +292,7 @@ func (prsr *RSRParser) ParseDataProvider(dP DataProvider, separator string) (out
return prsr.ParseValue(outStr)
}
func (prsr *RSRParser) ParseDataProviderWithInterfaces(dP DataProvider, separator string) (out string, err error) {
func (prsr *RSRParser) ParseDataProviderWithInterfaces(dP utils.DataProvider, separator string) (out string, err error) {
var outIface interface{}
if prsr.attrValue == "" {
if outIface, err = dP.FieldAsInterface(

View File

@@ -26,25 +26,25 @@ import (
"github.com/cgrates/cgrates/utils"
)
// NewSliceDP constructs a DataProvider
func NewSliceDP(record []string) (dP DataProvider) {
// NewSliceDP constructs a utils.DataProvider
func NewSliceDP(record []string) (dP utils.DataProvider) {
dP = &SliceDP{req: record, cache: NewNavigableMap(nil)}
return
}
// SliceDP implements engine.DataProvider so we can pass it to filters
// SliceDP implements engine.utils.DataProvider so we can pass it to filters
type SliceDP struct {
req []string
cache *NavigableMap
}
// String is part of engine.DataProvider interface
// String is part of engine.utils.DataProvider interface
// when called, it will display the already parsed values out of cache
func (cP *SliceDP) String() string {
return utils.ToJSON(cP)
}
// FieldAsInterface is part of engine.DataProvider interface
// FieldAsInterface is part of engine.utils.DataProvider interface
func (cP *SliceDP) FieldAsInterface(fldPath []string) (data interface{}, err error) {
if len(fldPath) == 0 {
return
@@ -69,7 +69,7 @@ func (cP *SliceDP) FieldAsInterface(fldPath []string) (data interface{}, err err
return
}
// FieldAsString is part of engine.DataProvider interface
// FieldAsString is part of engine.utils.DataProvider interface
func (cP *SliceDP) FieldAsString(fldPath []string) (data string, err error) {
var valIface interface{}
valIface, err = cP.FieldAsInterface(fldPath)
@@ -79,13 +79,13 @@ func (cP *SliceDP) FieldAsString(fldPath []string) (data string, err error) {
return utils.IfaceAsString(valIface), nil
}
// AsNavigableMap is part of engine.DataProvider interface
// AsNavigableMap is part of engine.utils.DataProvider interface
func (cP *SliceDP) AsNavigableMap([]*FCTemplate) (
nm *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}
// RemoteHost is part of engine.DataProvider interface
// RemoteHost is part of engine.utils.DataProvider interface
func (cP *SliceDP) RemoteHost() net.Addr {
return utils.LocalAddr()
}

View File

@@ -28,26 +28,26 @@ import (
"github.com/cgrates/cgrates/utils"
)
// NewXmlProvider constructs a DataProvider
func NewXmlProvider(req *xmlquery.Node, cdrPath utils.HierarchyPath) (dP DataProvider) {
// NewXmlProvider constructs a utils.DataProvider
func NewXmlProvider(req *xmlquery.Node, cdrPath utils.HierarchyPath) (dP utils.DataProvider) {
dP = &XmlProvider{req: req, cdrPath: cdrPath, cache: NewNavigableMap(nil)}
return
}
// XmlProvider implements engine.DataProvider so we can pass it to filters
// XmlProvider implements engine.utils.DataProvider so we can pass it to filters
type XmlProvider struct {
req *xmlquery.Node
cdrPath utils.HierarchyPath //used to compute relative path
cache *NavigableMap
}
// String is part of engine.DataProvider interface
// String is part of engine.utils.DataProvider interface
// when called, it will display the already parsed values out of cache
func (xP *XmlProvider) String() string {
return utils.ToJSON(xP)
}
// FieldAsInterface is part of engine.DataProvider interface
// FieldAsInterface is part of engine.utils.DataProvider interface
func (xP *XmlProvider) FieldAsInterface(fldPath []string) (data interface{}, err error) {
if len(fldPath) == 0 {
return nil, utils.ErrNotFound
@@ -81,7 +81,7 @@ func (xP *XmlProvider) FieldAsInterface(fldPath []string) (data interface{}, err
return
}
// FieldAsString is part of engine.DataProvider interface
// FieldAsString is part of engine.utils.DataProvider interface
func (xP *XmlProvider) FieldAsString(fldPath []string) (data string, err error) {
var valIface interface{}
valIface, err = xP.FieldAsInterface(fldPath)
@@ -91,13 +91,13 @@ func (xP *XmlProvider) FieldAsString(fldPath []string) (data string, err error)
return utils.IfaceAsString(valIface), nil
}
// AsNavigableMap is part of engine.DataProvider interface
// AsNavigableMap is part of engine.utils.DataProvider interface
func (xP *XmlProvider) AsNavigableMap([]*FCTemplate) (
nm *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}
// RemoteHost is part of engine.DataProvider interface
// RemoteHost is part of engine.utils.DataProvider interface
func (xP *XmlProvider) RemoteHost() net.Addr {
return utils.LocalAddr()
}

View File

@@ -893,7 +893,7 @@ func (apl Actions) Clone() (interface{}, error) {
}
// newCdrLogProvider constructs a DataProvider
func newCdrLogProvider(acnt *Account, action *Action) (dP config.DataProvider) {
func newCdrLogProvider(acnt *Account, action *Action) (dP utils.DataProvider) {
dP = &cdrLogProvider{acnt: acnt, action: action, cache: config.NewNavigableMap(nil)}
return
}

View File

@@ -49,7 +49,7 @@ type FilterS struct {
// there should be at least one filter passing, ie: if filters are not active event will fail to pass
// receives the event as DataProvider so we can accept undecoded data (ie: HttpRequest)
func (fS *FilterS) Pass(tenant string, filterIDs []string,
ev config.DataProvider) (pass bool, err error) {
ev utils.DataProvider) (pass bool, err error) {
if len(filterIDs) == 0 {
return true, nil
}
@@ -112,7 +112,7 @@ func verifyPrefixes(rule *FilterRule, prefixes []string) (hasPrefix bool) {
//LazyPass is almost the same as Pass except that it verify if the
//Element of the Values from FilterRules has as prefix one of the pathPrfxs
func (fS *FilterS) LazyPass(tenant string, filterIDs []string,
ev config.DataProvider, pathPrfxs []string) (pass bool, lazyCheckRules []*FilterRule, err error) {
ev utils.DataProvider, pathPrfxs []string) (pass bool, lazyCheckRules []*FilterRule, err error) {
if len(filterIDs) == 0 {
return true, nil, nil
}
@@ -270,7 +270,7 @@ func (fltr *FilterRule) CompileValues() (err error) {
}
// Pass is the method which should be used from outside.
func (fltr *FilterRule) Pass(dDP config.DataProvider) (result bool, err error) {
func (fltr *FilterRule) Pass(dDP utils.DataProvider) (result bool, err error) {
if fltr.negative == nil {
fltr.negative = utils.BoolPointer(strings.HasPrefix(fltr.Type, utils.MetaNot))
}
@@ -305,8 +305,8 @@ func (fltr *FilterRule) Pass(dDP config.DataProvider) (result bool, err error) {
return result != *(fltr.negative), nil
}
func (fltr *FilterRule) passString(dDP config.DataProvider) (bool, error) {
strVal, err := config.DPDynamicString(fltr.Element, dDP)
func (fltr *FilterRule) passString(dDP utils.DataProvider) (bool, error) {
strVal, err := utils.DPDynamicString(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -314,7 +314,7 @@ func (fltr *FilterRule) passString(dDP config.DataProvider) (bool, error) {
return false, err
}
for _, val := range fltr.Values {
sval, err := config.DPDynamicString(val, dDP)
sval, err := utils.DPDynamicString(val, dDP)
if err != nil {
continue
}
@@ -325,7 +325,7 @@ func (fltr *FilterRule) passString(dDP config.DataProvider) (bool, error) {
return false, nil
}
func (fltr *FilterRule) passExists(dDP config.DataProvider) (bool, error) {
func (fltr *FilterRule) passExists(dDP utils.DataProvider) (bool, error) {
var err error
path := fltr.Element
if fltr.rsrFields != nil {
@@ -333,7 +333,7 @@ func (fltr *FilterRule) passExists(dDP config.DataProvider) (bool, error) {
return false, err
}
}
if _, err = config.DPDynamicInterface(path, dDP); err != nil {
if _, err = utils.DPDynamicInterface(path, dDP); err != nil {
if err == utils.ErrNotFound {
return false, nil
}
@@ -342,8 +342,8 @@ func (fltr *FilterRule) passExists(dDP config.DataProvider) (bool, error) {
return true, nil
}
func (fltr *FilterRule) passEmpty(fielNameDP config.DataProvider) (bool, error) {
val, err := config.DPDynamicInterface(fltr.Element, fielNameDP)
func (fltr *FilterRule) passEmpty(fielNameDP utils.DataProvider) (bool, error) {
val, err := utils.DPDynamicInterface(fltr.Element, fielNameDP)
if err != nil {
if err == utils.ErrNotFound {
return true, nil
@@ -372,8 +372,8 @@ func (fltr *FilterRule) passEmpty(fielNameDP config.DataProvider) (bool, error)
}
}
func (fltr *FilterRule) passStringPrefix(dDP config.DataProvider) (bool, error) {
strVal, err := config.DPDynamicString(fltr.Element, dDP)
func (fltr *FilterRule) passStringPrefix(dDP utils.DataProvider) (bool, error) {
strVal, err := utils.DPDynamicString(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -381,7 +381,7 @@ func (fltr *FilterRule) passStringPrefix(dDP config.DataProvider) (bool, error)
return false, err
}
for _, prfx := range fltr.Values {
prfx, err := config.DPDynamicString(prfx, dDP)
prfx, err := utils.DPDynamicString(prfx, dDP)
if err != nil {
continue
}
@@ -392,8 +392,8 @@ func (fltr *FilterRule) passStringPrefix(dDP config.DataProvider) (bool, error)
return false, nil
}
func (fltr *FilterRule) passStringSuffix(dDP config.DataProvider) (bool, error) {
strVal, err := config.DPDynamicString(fltr.Element, dDP)
func (fltr *FilterRule) passStringSuffix(dDP utils.DataProvider) (bool, error) {
strVal, err := utils.DPDynamicString(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -401,7 +401,7 @@ func (fltr *FilterRule) passStringSuffix(dDP config.DataProvider) (bool, error)
return false, err
}
for _, prfx := range fltr.Values {
prfx, err := config.DPDynamicString(prfx, dDP)
prfx, err := utils.DPDynamicString(prfx, dDP)
if err != nil {
continue
}
@@ -413,12 +413,12 @@ func (fltr *FilterRule) passStringSuffix(dDP config.DataProvider) (bool, error)
}
// ToDo when Timings will be available in DataDb
func (fltr *FilterRule) passTimings(dDP config.DataProvider) (bool, error) {
func (fltr *FilterRule) passTimings(dDP utils.DataProvider) (bool, error) {
return false, utils.ErrNotImplemented
}
func (fltr *FilterRule) passDestinations(dDP config.DataProvider) (bool, error) {
dst, err := config.DPDynamicString(fltr.Element, dDP)
func (fltr *FilterRule) passDestinations(dDP utils.DataProvider) (bool, error) {
dst, err := utils.DPDynamicString(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -433,7 +433,7 @@ func (fltr *FilterRule) passDestinations(dDP config.DataProvider) (bool, error)
}
for _, dID := range destIDs {
for _, valDstID := range fltr.Values {
valDstID, err := config.DPDynamicString(valDstID, dDP)
valDstID, err := utils.DPDynamicString(valDstID, dDP)
if err != nil {
continue
}
@@ -446,7 +446,7 @@ func (fltr *FilterRule) passDestinations(dDP config.DataProvider) (bool, error)
return false, nil
}
func (fltr *FilterRule) passRSR(dDP config.DataProvider) (bool, error) {
func (fltr *FilterRule) passRSR(dDP utils.DataProvider) (bool, error) {
_, err := fltr.rsrFields.ParseDataProviderWithInterfaces(dDP, utils.NestingSep)
if err != nil {
if err == utils.ErrNotFound || err == utils.ErrFilterNotPassingNoCaps {
@@ -457,8 +457,8 @@ func (fltr *FilterRule) passRSR(dDP config.DataProvider) (bool, error) {
return true, nil
}
func (fltr *FilterRule) passGreaterThan(dDP config.DataProvider) (bool, error) {
fldIf, err := config.DPDynamicInterface(fltr.Element, dDP)
func (fltr *FilterRule) passGreaterThan(dDP utils.DataProvider) (bool, error) {
fldIf, err := utils.DPDynamicInterface(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -474,7 +474,7 @@ func (fltr *FilterRule) passGreaterThan(dDP config.DataProvider) (bool, error) {
orEqual = true
}
for _, val := range fltr.Values {
sval, err := config.DPDynamicInterface(val, dDP)
sval, err := utils.DPDynamicInterface(val, dDP)
if err != nil {
continue
}
@@ -489,8 +489,8 @@ func (fltr *FilterRule) passGreaterThan(dDP config.DataProvider) (bool, error) {
return false, nil
}
func (fltr *FilterRule) passEqualTo(dDP config.DataProvider) (bool, error) {
fldIf, err := config.DPDynamicInterface(fltr.Element, dDP)
func (fltr *FilterRule) passEqualTo(dDP utils.DataProvider) (bool, error) {
fldIf, err := utils.DPDynamicInterface(fltr.Element, dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
@@ -501,7 +501,7 @@ func (fltr *FilterRule) passEqualTo(dDP config.DataProvider) (bool, error) {
fldIf = utils.StringToInterface(fldStr)
}
for _, val := range fltr.Values {
sval, err := config.DPDynamicInterface(val, dDP)
sval, err := utils.DPDynamicInterface(val, dDP)
if err != nil {
continue
}
@@ -515,7 +515,7 @@ func (fltr *FilterRule) passEqualTo(dDP config.DataProvider) (bool, error) {
}
func newDynamicDP(cfg *config.CGRConfig, connMgr *ConnManager,
tenant string, initialDP config.DataProvider) *dynamicDP {
tenant string, initialDP utils.DataProvider) *dynamicDP {
return &dynamicDP{
cfg: cfg,
connMgr: connMgr,
@@ -529,7 +529,7 @@ type dynamicDP struct {
cfg *config.CGRConfig
connMgr *ConnManager
tenant string
initialDP config.DataProvider
initialDP utils.DataProvider
cache *config.NavigableMap
}

View File

@@ -56,7 +56,7 @@ func TestMapEventNewMapEvent(t *testing.T) {
}
func TestMapEventFieldAsInterface(t *testing.T) {
data := config.DataProvider(mapEv)
data := utils.DataProvider(mapEv)
if _, err := data.FieldAsInterface([]string{"first", "second"}); err != utils.ErrNotFound {
t.Error(err)
}
@@ -76,7 +76,7 @@ func TestMapEventFieldAsInterface(t *testing.T) {
}
func TestMapEventFieldAsString(t *testing.T) {
data := config.DataProvider(mapEv)
data := utils.DataProvider(mapEv)
if _, err := data.FieldAsString([]string{"first", "second"}); err != utils.ErrNotFound {
t.Error(err)
}
@@ -96,8 +96,7 @@ func TestMapEventFieldAsString(t *testing.T) {
}
func TestMapEventAsNavigableMap(t *testing.T) {
data := config.DataProvider(mapEv)
if rply, err := data.AsNavigableMap(nil); err != nil {
if rply, err := mapEv.AsNavigableMap(nil); err != nil {
t.Error(err)
} else if expected := config.NewNavigableMap(mapEv); !reflect.DeepEqual(expected, rply) {
t.Errorf("Expecting %+v, received: %+v", expected, rply)
@@ -105,7 +104,7 @@ func TestMapEventAsNavigableMap(t *testing.T) {
}
func TestMapEventRemoteHost(t *testing.T) {
data := config.DataProvider(mapEv)
data := utils.DataProvider(mapEv)
if rply, expected := data.RemoteHost(), utils.LocalAddr(); !reflect.DeepEqual(expected, rply) {
t.Errorf("Expecting %+v, received: %+v", expected, rply)
}

View File

@@ -53,7 +53,7 @@ func TestSafEventMapEvent(t *testing.T) {
}
func TestSafEventFieldAsInterface(t *testing.T) {
data := config.DataProvider(safEv)
data := utils.DataProvider(safEv)
if _, err := data.FieldAsInterface([]string{"first", "second"}); err != utils.ErrNotFound {
t.Error(err)
}
@@ -73,7 +73,7 @@ func TestSafEventFieldAsInterface(t *testing.T) {
}
func TestSafEventFieldAsString(t *testing.T) {
data := config.DataProvider(safEv)
data := utils.DataProvider(safEv)
if _, err := data.FieldAsString([]string{"first", "second"}); err != utils.ErrNotFound {
t.Error(err)
}
@@ -93,8 +93,7 @@ func TestSafEventFieldAsString(t *testing.T) {
}
func TestSafEventAsNavigableMap(t *testing.T) {
data := config.DataProvider(safEv)
if rply, err := data.AsNavigableMap(nil); err != nil {
if rply, err := safEv.AsNavigableMap(nil); err != nil {
t.Error(err)
} else if expected := config.NewNavigableMap(sMap); !reflect.DeepEqual(expected, rply) {
t.Errorf("Expecting %+v, received: %+v", expected, rply)
@@ -102,7 +101,7 @@ func TestSafEventAsNavigableMap(t *testing.T) {
}
func TestSafEventRemoteHost(t *testing.T) {
data := config.DataProvider(safEv)
data := utils.DataProvider(safEv)
if rply, expected := data.RemoteHost(), utils.LocalAddr(); !reflect.DeepEqual(expected, rply) {
t.Errorf("Expecting %+v, received: %+v", expected, rply)
}

View File

@@ -41,12 +41,12 @@ func (t *Task) Execute() error {
}).Execute(nil, nil)
}
// String implements config.DataProvider
// String implements utils.DataProvider
func (t *Task) String() string {
return utils.ToJSON(t)
}
// AsNavigableMap implements config.DataProvider
// AsNavigableMap implements utils.DataProvider
func (t *Task) AsNavigableMap(_ []*config.FCTemplate) (nm *config.NavigableMap, err error) {
nm = config.NewNavigableMap(nil)
nm.Set([]string{utils.UUID}, t.Uuid, false, false)
@@ -55,13 +55,13 @@ func (t *Task) AsNavigableMap(_ []*config.FCTemplate) (nm *config.NavigableMap,
return
}
// FieldAsInterface implements config.DataProvider
// FieldAsInterface implements utils.DataProvider
// ToDo: support Action fields
func (t *Task) FieldAsInterface(fldPath []string) (iface interface{}, err error) {
return t.FieldAsString(fldPath)
}
// FieldAsInterface implements config.DataProvider
// FieldAsInterface implements utils.DataProvider
// ToDo: support Action fields
func (t *Task) FieldAsString(fldPath []string) (s string, err error) {
if len(fldPath) == 0 {
@@ -82,7 +82,7 @@ func (t *Task) FieldAsString(fldPath []string) (s string, err error) {
}
}
// RemoteHost implements config.DataProvider
// RemoteHost implements utils.DataProvider
func (t *Task) RemoteHost() (rh net.Addr) {
return
}

View File

@@ -74,8 +74,8 @@ type FWVFileER struct {
headerOffset int64
trailerOffset int64 // Index where trailer starts, to be used as boundary when reading cdrs
trailerLenght int64
headerDP config.DataProvider
trailerDP config.DataProvider
headerDP utils.DataProvider
trailerDP utils.DataProvider
}
func (rdr *FWVFileER) Config() *config.EventReaderCfg {

View File

@@ -84,7 +84,7 @@ func (ld LoaderData) UpdateFromCSV(fileName string, record []string,
}
// newCsvProvider constructs a DataProvider
func newCsvProvider(record []string, fileName string) (dP config.DataProvider) {
func newCsvProvider(record []string, fileName string) (dP utils.DataProvider) {
dP = &csvProvider{req: record, fileName: fileName, cache: config.NewNavigableMap(nil)}
return
}

View File

@@ -79,30 +79,30 @@ type NMInterface interface {
// navMap subset of function for NM interface
type navMap interface {
Field(path PathItems) (val NMInterface, err error)
Set(path PathItems, val NMInterface) (addedNew bool, err error)
Set(fullpath *FullPath, val NMInterface) (addedNew bool, err error)
}
// AppendNavMapVal appends value to the map
func AppendNavMapVal(nm navMap, fldPath PathItems, val NMInterface) (err error) {
func AppendNavMapVal(nm navMap, fldPath *FullPath, val NMInterface) (err error) {
var prevItm NMInterface
var indx int
if prevItm, err = nm.Field(fldPath); err != nil {
if prevItm, err = nm.Field(fldPath.PathItems); err != nil {
if err != ErrNotFound {
return
}
} else {
indx = prevItm.Len()
}
fldPath[len(fldPath)-1].Index = &indx
fldPath.PathItems[len(fldPath.PathItems)-1].Index = &indx
_, err = nm.Set(fldPath, val)
return
}
// ComposeNavMapVal compose adds value to prevision item
func ComposeNavMapVal(nm navMap, fldPath PathItems, val NMInterface) (err error) {
func ComposeNavMapVal(nm navMap, fldPath *FullPath, val NMInterface) (err error) {
var prevItmSlice NMInterface
var indx int
if prevItmSlice, err = nm.Field(fldPath); err != nil {
if prevItmSlice, err = nm.Field(fldPath.PathItems); err != nil {
if err != ErrNotFound {
return
}
@@ -117,7 +117,7 @@ func ComposeNavMapVal(nm navMap, fldPath PathItems, val NMInterface) (err error)
return
}
}
fldPath[len(fldPath)-1].Index = &indx
fldPath.PathItems[len(fldPath.PathItems)-1].Index = &indx
_, err = nm.Set(fldPath, val)
return
}

View File

@@ -70,7 +70,7 @@ func (onm *OrderedNavigableMap) Empty() bool {
}
// Remove removes the item for the given path and updates the order
func (onm *OrderedNavigableMap) Remove(fullPath FullPath) (err error) {
func (onm *OrderedNavigableMap) Remove(fullPath *FullPath) (err error) {
path := stripIdxFromLastPathElm(fullPath.Path)
if path == EmptyString || fullPath.PathItems[len(fullPath.PathItems)-1].Index != nil {
return ErrWrongPath
@@ -91,16 +91,16 @@ func (onm *OrderedNavigableMap) Remove(fullPath FullPath) (err error) {
return
}
// Set sets the value at the given path
// this is the old to be capable of building the code without updating all the code
// will be replaced with Set2 after we decide that is the optimal solution
func (onm *OrderedNavigableMap) Set(fldPath PathItems, val NMInterface) (addedNew bool, err error) {
return onm.Set2(&FullPath{PathItems: fldPath, Path: fldPath.String()}, val)
}
// // Set sets the value at the given path
// // this is the old to be capable of building the code without updating all the code
// // will be replaced with Set2 after we decide that is the optimal solution
// func (onm *OrderedNavigableMap) Set(fldPath PathItems, val NMInterface) (addedNew bool, err error) {
// return onm.Set2(&FullPath{PathItems: fldPath, Path: fldPath.String()}, val)
// }
// Set2 sets the value at the given path
// Set sets the value at the given path
// this used with full path and the processed path to not calculate them for every set
func (onm *OrderedNavigableMap) Set2(fullPath *FullPath, val NMInterface) (addedNew bool, err error) {
func (onm *OrderedNavigableMap) Set(fullPath *FullPath, val NMInterface) (addedNew bool, err error) {
if len(fullPath.PathItems) == 0 {
return false, ErrWrongPath
}
@@ -182,3 +182,10 @@ func (onm *OrderedNavigableMap) GetOrder() (order []PathItems) {
}
return
}
// RemoveAll will clean the data and the odrder from OrderedNavigableMap
func (onm *OrderedNavigableMap) RemoveAll() {
onm.nm = NavigableMap2{}
onm.orderIdx = NewPathItemList()
onm.orderRef = make(map[string][]*PathItemElement)
}