diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index 6c9cef4fb..2dbaf3b91 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -94,7 +94,7 @@ func TestAgReqAsNavigableMap(t *testing.T) { "~*cgrep.MaxUsage{*duration_seconds}", true)}, &config.FCTemplate{Tag: "Error", FieldId: "Error", Type: utils.META_COMPOSED, - Filters: []string{"*rsr::*cgrep.Error(!^$)"}, + Filters: []string{"*rsr::~*cgrep.Error(!^$)"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.Error", true)}, } diff --git a/config/rsrparser.go b/config/rsrparser.go index 196932285..4892224cf 100644 --- a/config/rsrparser.go +++ b/config/rsrparser.go @@ -102,9 +102,9 @@ func (prsrs RSRParsers) ParseDataProvider(dP DataProvider, separator string) (ou return } -func (prsrs RSRParsers) ParseCDR(dP DataProvider) (out string, err error) { +func (prsrs RSRParsers) ParseDataProviderWithInterfaces(dP DataProvider, separator string) (out string, err error) { for _, prsr := range prsrs { - if outPrsr, err := prsr.ParseCDR(dP); err != nil { + if outPrsr, err := prsr.ParseDataProviderWithInterfaces(dP, separator); err != nil { return "", err } else { out += outPrsr @@ -275,11 +275,11 @@ func (prsr *RSRParser) ParseDataProvider(dP DataProvider, separator string) (out return prsr.ParseValue(outStr) } -func (prsr *RSRParser) ParseCDR(dP DataProvider) (out string, err error) { +func (prsr *RSRParser) ParseDataProviderWithInterfaces(dP DataProvider, separator string) (out string, err error) { var outStr interface{} if prsr.attrValue == "" { if outStr, err = dP.FieldAsInterface( - strings.Split(prsr.attrName, utils.NestingSep)); err != nil { + strings.Split(prsr.attrName, separator)); err != nil { return } } diff --git a/data/tariffplans/cluelrn/Attributes.csv b/data/tariffplans/cluelrn/Attributes.csv index 121638ce6..fae2d53b8 100644 --- a/data/tariffplans/cluelrn/Attributes.csv +++ b/data/tariffplans/cluelrn/Attributes.csv @@ -1,8 +1,8 @@ #Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight cgrates.org,LRN_Dst3125650565,lrn,*string:Destination:3125650565,,Destination,*any,13128543000,true,false,10 cgrates.org,LRN_Dst3125650565,,,,OriginalDestination,*any,3125650565,true,false,10 -cgrates.org,LRN_LATA_Dst13128543000,lrn,*string:Destination:13128543000;*rsr::OriginalDestination(!^$),,DestinationLATA,*any,358,true,false,20 -cgrates.org,LRN_LATA_Cli9174269000,lrn,*string:Account:9174269000;*rsr::DestinationLATA(!^$),,CallerLATA,*any,132,true,false,30 +cgrates.org,LRN_LATA_Dst13128543000,lrn,*string:Destination:13128543000;*rsr::~OriginalDestination(!^$),,DestinationLATA,*any,358,true,false,20 +cgrates.org,LRN_LATA_Cli9174269000,lrn,*string:Account:9174269000;*rsr::~DestinationLATA(!^$),,CallerLATA,*any,132,true,false,30 cgrates.org,LRN_JURISDICTION_NY,lrn,FLTR_INTRALATA_NEWYORK,,LRNJurisdiction,*any,INTRA,true,false,50 cgrates.org,LRN_JURISDICTION_IL,lrn,FLTR_INTRALATA_ILLINOIS,,LRNJurisdiction,*any,INTRA,true,false,50 -cgrates.org,LRN_JURISDICTION_INTER,lrn,*string:Destination:13128543000;*rsr::CallerLATA(!^$),,LRNJurisdiction,*any,INTER,true,false,40 +cgrates.org,LRN_JURISDICTION_INTER,lrn,*string:Destination:13128543000;*rsr::~CallerLATA(!^$),,LRNJurisdiction,*any,INTER,true,false,40 diff --git a/data/tariffplans/oldtutorial/Filters.csv b/data/tariffplans/oldtutorial/Filters.csv index cbf0e34dd..d20147272 100644 --- a/data/tariffplans/oldtutorial/Filters.csv +++ b/data/tariffplans/oldtutorial/Filters.csv @@ -1,7 +1,7 @@ #Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5] cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z cgrates.org,FLTR_1,*prefix,Destination,10;20, -cgrates.org,FLTR_1,*rsr,,Subject(~^1.*1$);Destination(1002), +cgrates.org,FLTR_1,*rsr,,~Subject(~^1.*1$);~Destination(1002), cgrates.org,FLTR_ACNT_1007,*string,Account,1007,2014-07-29T15:00:00Z cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE_MOBILE,2014-07-29T15:00:00Z diff --git a/data/tariffplans/testit/Filters.csv b/data/tariffplans/testit/Filters.csv index f15d68604..b3dd50481 100644 --- a/data/tariffplans/testit/Filters.csv +++ b/data/tariffplans/testit/Filters.csv @@ -3,7 +3,7 @@ cgrates.org,FLTR_ACCOUNT_1001,*string,Account,1001,2014-07-29T15:00:00Z cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE_MOBILE,2014-07-29T15:00:00Z cgrates.org,FLTR_1,*string,Account,1003;1002,2014-07-29T15:00:00Z cgrates.org,FLTR_1,*prefix,Destination,10;20, -cgrates.org,FLTR_1,*rsr,,Subject(~^1.*1$);Destination(1002), +cgrates.org,FLTR_1,*rsr,,~Subject(~^1.*1$);~Destination(1002), cgrates.org,FLTR_ACNT_1007,*string,Account,1007,2014-07-29T15:00:00Z cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z cgrates.org,FLTR_SPP_ACNT_dan,*string,*req.Account,dan,2014-07-29T15:00:00Z diff --git a/data/tariffplans/testtp/Filters.csv b/data/tariffplans/testtp/Filters.csv index dd7be3a73..294aa501a 100644 --- a/data/tariffplans/testtp/Filters.csv +++ b/data/tariffplans/testtp/Filters.csv @@ -1,7 +1,7 @@ #Tenant[0],ID[1],FilterType[2],FilterFieldName[3],FilterFieldValues[4],ActivationInterval[5] cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z cgrates.org,FLTR_1,*prefix,Destination,10;20, -cgrates.org,FLTR_1,*rsr,,Subject(~^1.*1$);Destination(1002), +cgrates.org,FLTR_1,*rsr,,~Subject(~^1.*1$);~Destination(1002), cgrates.org,FLTR_ACNT_1007,*string,Account,1007,2014-07-29T15:00:00Z cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z diff --git a/engine/cdr.go b/engine/cdr.go index 675780b8e..c719613f8 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -155,7 +155,7 @@ func (cdr *CDR) FormatCost(shiftDecimals, roundDecimals int) string { // Used to retrieve fields as string, primary fields are const labeled func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err error) { - parsed, err = rsrPrs.ParseCDR(config.NewNavigableMap(cdr.AsMapStringIface())) + parsed, err = rsrPrs.ParseDataProviderWithInterfaces(config.NewNavigableMap(cdr.AsMapStringIface()), utils.NestingSep) if err != nil { return } @@ -164,7 +164,7 @@ func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err erro // concatenates values of multiple fields defined in template, used eg in CDR templates func (cdr *CDR) FieldsAsString(rsrFlds config.RSRParsers) string { - outVal, err := rsrFlds.ParseCDR(config.NewNavigableMap(cdr.AsMapStringIface())) + outVal, err := rsrFlds.ParseDataProviderWithInterfaces(config.NewNavigableMap(cdr.AsMapStringIface()), utils.NestingSep) if err != nil { return "" } diff --git a/engine/filters.go b/engine/filters.go index 65dcf2058..d7999409c 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -180,14 +180,14 @@ type FilterRule struct { Type string // Filter type (*string, *timing, *rsr_filters, *stats, *lt, *lte, *gt, *gte) FieldName string // Name of the field providing us the Values to check (used in case of some ) Values []string // Filter definition - rsrFields utils.RSRFields // Cache here the RSRFilter Values + rsrFields config.RSRParsers // Cache here the RSRFilter Values statSThresholds []*RFStatSThreshold // Cached compiled RFStatsThreshold out of Values } // Separate method to compile RSR fields func (rf *FilterRule) CompileValues() (err error) { if rf.Type == MetaRSR { - if rf.rsrFields, err = utils.ParseRSRFieldsFromSlice(rf.Values); err != nil { + if rf.rsrFields, err = config.NewRSRParsersFromSlice(rf.Values, true); err != nil { return } } else if rf.Type == MetaStatS { @@ -297,19 +297,14 @@ func (fltr *FilterRule) passDestinations(dP config.DataProvider) (bool, error) { } func (fltr *FilterRule) passRSR(dP config.DataProvider) (bool, error) { - for _, rsrFld := range fltr.rsrFields { - fldIface, err := dP.FieldAsInterface(strings.Split(rsrFld.Id, utils.NestingSep)) - if err != nil { - if err == utils.ErrNotFound { - return false, nil - } - return false, err - } - if _, err := rsrFld.Parse(fldIface); err == nil { - return true, nil + _, err := fltr.rsrFields.ParseDataProviderWithInterfaces(dP, utils.NestingSep) + if err != nil { + if err == utils.ErrNotFound || err == utils.ErrFilterNotPassingNoCaps { + return false, nil } + return false, err } - return false, nil + return true, nil } func (fltr *FilterRule) passStatS(dP config.DataProvider, diff --git a/engine/filters_test.go b/engine/filters_test.go index b0f4f11e9..89a04e2e0 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -90,7 +90,7 @@ func TestFilterPassRSRFields(t *testing.T) { TimeEnd: time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC), DurationIndex: 132 * time.Second, ExtraFields: map[string]string{"navigation": "off"}} - rf, err := NewFilterRule(MetaRSR, "", []string{"Tenant(~^cgr.*\\.org$)"}) + rf, err := NewFilterRule(MetaRSR, "", []string{"~Tenant(~^cgr.*\\.org$)"}) if err != nil { t.Error(err) } @@ -99,7 +99,7 @@ func TestFilterPassRSRFields(t *testing.T) { } else if !passes { t.Error("Not passing") } - rf, err = NewFilterRule(MetaRSR, "", []string{"navigation(on)"}) + rf, err = NewFilterRule(MetaRSR, "", []string{"~navigation(on)"}) if err != nil { t.Error(err) } @@ -108,7 +108,7 @@ func TestFilterPassRSRFields(t *testing.T) { } else if passes { t.Error("Passing") } - rf, err = NewFilterRule(MetaRSR, "", []string{"navigation(off)"}) + rf, err = NewFilterRule(MetaRSR, "", []string{"~navigation(off)"}) if err != nil { t.Error(err) } @@ -328,13 +328,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { "Tenant": "cgrates.org", } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, config.NewNavigableMap(failEvent)); err != nil { + []string{"*rsr::~Tenant(~^cgr.*\\.org$)"}, config.NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, config.NewNavigableMap(passEvent)); err != nil { + []string{"*rsr::~Tenant(~^cgr.*\\.org$)"}, config.NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -415,7 +415,7 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) { "Test": "MultipleCharacter", } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Test(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { + []string{"*rsr::~Test(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) @@ -424,7 +424,7 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) { "Test": "MultipleCharacter123456789MoreThan30Character", } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Test(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { + []string{"*rsr::~Test(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) @@ -436,7 +436,7 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) { }, } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Test.Test2(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { + []string{"*rsr::~Test.Test2(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) @@ -447,7 +447,7 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) { }, } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Test.Test2(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { + []string{"*rsr::~Test.Test2(~^\\w{30,})"}, config.NewNavigableMap(ev)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", false, pass)