diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index fea95e429..67a24f21f 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -44,88 +44,91 @@ func TestAgReqSetFields(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.CGRID}, - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), - false, false) - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) - agReq.CGRRequest.Set([]string{utils.AnswerTime}, - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false, false) - agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false, false) - agReq.CGRRequest.Set([]string{utils.Usage}, time.Duration(3*time.Minute), false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.META_PREPAID)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, utils.NewNMData(time.Duration(3*time.Minute))) - cgrRply := map[string]interface{}{ - utils.CapAttributes: map[string]interface{}{ - "PaypalAccount": "cgrates@paypal.com", + cgrRply := utils.NavigableMap2{ + utils.CapAttributes: utils.NavigableMap2{ + "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), }, - utils.CapMaxUsage: time.Duration(120 * time.Second), - utils.Error: "", + utils.CapMaxUsage: utils.NewNMData(time.Duration(120 * time.Second)), + utils.Error: utils.NewNMData(""), } - agReq.CGRReply = config.NewNavigableMap(cgrRply) + agReq.CGRReply = &cgrRply tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaRep + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaRep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Destination", + {Tag: "Destination", Path: utils.MetaRep + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageVoice", + {Tag: "RequestedUsageVoice", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*voice"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_seconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageData", + {Tag: "RequestedUsageData", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*data"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageSMS", + {Tag: "RequestedUsageSMS", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*sms"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "AttrPaypalAccount", + {Tag: "AttrPaypalAccount", Path: utils.MetaRep + utils.NestingSep + "PaypalAccount", Type: utils.MetaVariable, Filters: []string{"*empty:~*cgrep.Error:"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.Attributes.PaypalAccount", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "MaxUsage", + {Tag: "MaxUsage", Path: utils.MetaRep + utils.NestingSep + "MaxUsage", Type: utils.MetaVariable, Filters: []string{"*empty:~*cgrep.Error:"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Error", + {Tag: "Error", Path: utils.MetaRep + utils.NestingSep + "Error", Type: utils.MetaVariable, Filters: []string{"*rsr::~*cgrep.Error(!^$)"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.Error", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + + eMp := utils.NewOrderedNavigableMap() + eMp.Set(&utils.FullPath{Path: utils.Tenant, PathItems: utils.PathItems{{Field: utils.Tenant}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) - eMp.Set([]string{utils.Destination}, []*config.NMItem{ + Config: tplFlds[1]}}) + eMp.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}, false, true) - eMp.Set([]string{"RequestedUsage"}, []*config.NMItem{ + Config: tplFlds[2]}}) + eMp.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}, false, true) - eMp.Set([]string{"PaypalAccount"}, []*config.NMItem{ + Config: tplFlds[3]}}) + eMp.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}, false, true) - eMp.Set([]string{"MaxUsage"}, []*config.NMItem{ + Config: tplFlds[6]}}) + eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}, false, true) + Config: tplFlds[7]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -142,8 +145,7 @@ func TestAgentRequestSetFields(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() dm := engine.NewDataManager(engine.NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items), config.CgrConfig().CacheCfg(), nil) - vars := map[string]interface{}{} - ar := NewAgentRequest(config.NewNavigableMap(req), vars, + ar := NewAgentRequest(config.NewNavigableMap(req), nil, nil, nil, nil, config.NewRSRParsersMustCompile("", false, utils.NestingSep), "cgrates.org", "", engine.NewFilterS(cfg, nil, dm), config.NewNavigableMap(req), config.NewNavigableMap(req)) @@ -152,177 +154,188 @@ func TestAgentRequestSetFields(t *testing.T) { t.Error(err) } // tplFld.Type == utils.META_NONE - input = []*config.FCTemplate{&config.FCTemplate{Type: utils.META_NONE}} + input = []*config.FCTemplate{{Type: utils.META_NONE}} if err := ar.SetFields(input); err != nil { t.Error(err) } // unsupported type: <> - input = []*config.FCTemplate{&config.FCTemplate{Blocker: true}} + input = []*config.FCTemplate{{Blocker: true}} if err := ar.SetFields(input); err == nil || err.Error() != "unsupported type: <>" { t.Error(err) } // case utils.MetaVars input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaVars), Tag: fmt.Sprintf("%s.Account", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + input[0].ComputePath() + if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // case utils.MetaCgreq input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaCgreq), Tag: fmt.Sprintf("%s.Account", utils.MetaCgreq), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.CGRRequest.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.CGRRequest.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // case utils.MetaCgrep input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaCgrep), Tag: fmt.Sprintf("%s.Account", utils.MetaCgrep), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.CGRReply.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.CGRReply.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // case utils.MetaRep input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaRep), Tag: fmt.Sprintf("%s.Account", utils.MetaRep), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Reply.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.Reply.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // case utils.MetaDiamreq input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaDiamreq), Tag: fmt.Sprintf("%s.Account", utils.MetaDiamreq), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.diamreq.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.diamreq.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } //META_COMPOSED input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.AccountID", utils.MetaVars), Tag: fmt.Sprintf("%s.AccountID", utils.MetaVars), Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Tenant", false, ";"), }, - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.AccountID", utils.MetaVars), Tag: fmt.Sprintf("%s.AccountID", utils.MetaVars), Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile(":", false, ";"), }, - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.AccountID", utils.MetaVars), Tag: fmt.Sprintf("%s.AccountID", utils.MetaVars), Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), }, } + for _, v := range input { + v.ComputePath() + } + if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"AccountID"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "AccountID"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "cgrates.org:1009" { - t.Error("Expecting 'cgrates.org:1009', received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "cgrates.org:1009" { + t.Error("Expecting 'cgrates.org:1009', received: ", (*nm)[0].Interface()) } // META_CONSTANT input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaVars), Tag: fmt.Sprintf("%s.Account", utils.MetaVars), Type: utils.META_CONSTANT, Value: config.NewRSRParsersMustCompile("2020", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"Account"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "2020" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "2020" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // Filters input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.AccountID", utils.MetaVars), Tag: fmt.Sprintf("%s.AccountID", utils.MetaVars), Filters: []string{utils.MetaString + ":~" + utils.MetaVars + ".Account:1003"}, @@ -330,20 +343,21 @@ func TestAgentRequestSetFields(t *testing.T) { Value: config.NewRSRParsersMustCompile("2021", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"AccountID"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "AccountID"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item ", utils.ToJSON(nm)) - } else if nm[0].Data != "cgrates.org:1009" { - t.Error("Expecting 'cgrates.org:1009', received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "cgrates.org:1009" { + t.Error("Expecting 'cgrates.org:1009', received: ", (*nm)[0].Interface()) } input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account", utils.MetaVars), Tag: fmt.Sprintf("%s.Account", utils.MetaVars), Filters: []string{"Not really a filter"}, @@ -351,54 +365,59 @@ func TestAgentRequestSetFields(t *testing.T) { Value: config.NewRSRParsersMustCompile("2021", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err == nil || err.Error() != "NOT_FOUND:Not really a filter" { t.Errorf("Expecting: 'NOT_FOUND:Not really a filter', received: %+v", err) } // Blocker: true input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Name", utils.MetaVars), Tag: fmt.Sprintf("%s.Name", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Account", false, ";"), Blocker: true, }, - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Name", utils.MetaVars), Tag: fmt.Sprintf("%s.Name", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1005", false, ";"), }, } + for _, v := range input { + v.ComputePath() + } if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"Name"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Name"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } // ErrNotFound input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Test", utils.MetaVars), Tag: fmt.Sprintf("%s.Test", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaReq+".Test", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if _, err := ar.Vars.GetField([]string{"Test"}); err == nil || err != utils.ErrNotFound { + } else if _, err := ar.Vars.Field(utils.PathItems{{Field: "Test"}}); err == nil || err != utils.ErrNotFound { t.Errorf("Expecting: %+v, received: %+v", utils.ErrNotFound, err) } input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Test", utils.MetaVars), Tag: fmt.Sprintf("%s.Test", utils.MetaVars), Type: utils.MetaVariable, @@ -406,13 +425,14 @@ func TestAgentRequestSetFields(t *testing.T) { Mandatory: true, }, } + input[0].ComputePath() if err := ar.SetFields(input); err == nil || err.Error() != "NOT_FOUND:"+utils.MetaVars+".Test" { t.Errorf("Expecting: %+v, received: %+v", "NOT_FOUND:"+utils.MetaVars+".Test", err) } //Not found input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: "wrong", Tag: "wrong", Type: utils.MetaVariable, @@ -420,49 +440,52 @@ func TestAgentRequestSetFields(t *testing.T) { Mandatory: true, }, } - if err := ar.SetFields(input); err == nil || err.Error() != "unsupported field prefix: " { - t.Errorf("Expecting: %+v, received: %+v", "unsupported field prefix: ", err) + input[0].ComputePath() + if err := ar.SetFields(input); err == nil || err.Error() != "unsupported field prefix: when set field" { + t.Errorf("Expecting: %+v, received: %+v", "unsupported field prefix: when set field", err) } // MetaHdr/MetaTrl input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account4", utils.MetaVars), Tag: fmt.Sprintf("%s.Account4", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaHdr+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"Account4"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account4"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } input = []*config.FCTemplate{ - &config.FCTemplate{ + { Path: fmt.Sprintf("%s.Account5", utils.MetaVars), Tag: fmt.Sprintf("%s.Account5", utils.MetaVars), Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~"+utils.MetaTrl+".Account", false, ";"), }, } + input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.GetField([]string{"Account5"}); err != nil { + } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account5"}}); err != nil { t.Error(err) - } else if nm, ok := val.([]*config.NMItem); !ok { + } else if nm, ok := val.(*utils.NMSlice); !ok { t.Error("Expecting NM items") - } else if len(nm) != 1 { + } else if len(*nm) != 1 { t.Error("Expecting one item") - } else if nm[0].Data != "1009" { - t.Error("Expecting 1009, received: ", nm[0].Data) + } else if (*nm)[0].Interface() != "1009" { + t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) } } @@ -473,25 +496,26 @@ func TestAgReqMaxCost(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.CapMaxUsage}, "120s", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CapMaxUsage, PathItems: utils.PathItems{{Field: utils.CapMaxUsage}}}, utils.NewNMData("120s")) - cgrRply := map[string]interface{}{ - utils.CapMaxUsage: time.Duration(120 * time.Second), + cgrRply := utils.NavigableMap2{ + utils.CapMaxUsage: utils.NewNMData(time.Duration(120 * time.Second)), } - agReq.CGRReply = config.NewNavigableMap(cgrRply) + agReq.CGRReply = &cgrRply tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "MaxUsage", + {Tag: "MaxUsage", Path: utils.MetaRep + utils.NestingSep + "MaxUsage", Type: utils.MetaVariable, Filters: []string{"*rsr::~*cgrep.MaxUsage(>0s)"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) + tplFlds[0].ComputePath() + eMp := utils.NewOrderedNavigableMap() - eMp.Set([]string{"MaxUsage"}, []*config.NMItem{ + eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[0]}}, false, true) + Config: tplFlds[0]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -520,19 +544,22 @@ func TestAgReqParseFieldDiameter(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "MandatoryFalse", + {Tag: "MandatoryFalse", Path: "MandatoryFalse", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true, utils.INFIELD_SEP), Mandatory: false}, - &config.FCTemplate{Tag: "MandatoryTrue", + {Tag: "MandatoryTrue", Path: "MandatoryTrue", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true, utils.INFIELD_SEP), Mandatory: true}, - &config.FCTemplate{Tag: "Session-Id", Filters: []string{}, + {Tag: "Session-Id", Filters: []string{}, Path: "Session-Id", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, } + for _, v := range tplFlds { + v.ComputePath() + } expected := "" if out, err := agReq.ParseField(tplFlds[0]); err != nil { t.Error(err) @@ -569,15 +596,18 @@ func TestAgReqParseFieldRadius(t *testing.T) { //pass the data provider to agent request agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "MandatoryFalse", + {Tag: "MandatoryFalse", Path: "MandatoryFalse", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true, utils.INFIELD_SEP), Mandatory: false}, - &config.FCTemplate{Tag: "MandatoryTrue", + {Tag: "MandatoryTrue", Path: "MandatoryTrue", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true, utils.INFIELD_SEP), Mandatory: true}, } + for _, v := range tplFlds { + v.ComputePath() + } expected := "" if out, err := agReq.ParseField(tplFlds[0]); err != nil { t.Error(err) @@ -609,11 +639,11 @@ Host: api.cgrates.org //pass the data provider to agent request agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "MandatoryFalse", + {Tag: "MandatoryFalse", Path: "MandatoryFalse", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true, utils.INFIELD_SEP), Mandatory: false}, - &config.FCTemplate{Tag: "MandatoryTrue", + {Tag: "MandatoryTrue", Path: "MandatoryTrue", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true, utils.INFIELD_SEP), Mandatory: true}, @@ -681,11 +711,11 @@ func TestAgReqParseFieldHttpXml(t *testing.T) { //pass the data provider to agent request agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "MandatoryFalse", + {Tag: "MandatoryFalse", Path: "MandatoryFalse", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true, utils.INFIELD_SEP), Mandatory: false}, - &config.FCTemplate{Tag: "MandatoryTrue", + {Tag: "MandatoryTrue", Path: "MandatoryTrue", Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true, utils.INFIELD_SEP), Mandatory: true}, @@ -709,34 +739,36 @@ func TestAgReqEmptyFilter(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.CGRID}, - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), - false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", Filters: []string{}, + {Tag: "Tenant", Filters: []string{}, Path: utils.MetaCgrep + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", Filters: []string{}, + {Tag: "Account", Filters: []string{}, Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Destination", Filters: []string{}, + {Tag: "Destination", Filters: []string{}, Path: utils.MetaCgrep + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := &utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(utils.PathItems{{Field: utils.Account}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) - eMp.Set([]string{utils.Destination}, []*config.NMItem{ + Config: tplFlds[1]}}) + eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}, false, true) + Config: tplFlds[2]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -751,18 +783,19 @@ func TestAgReqMetaExponent(t *testing.T) { config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set([]string{"Value"}, "2", false, false) - agReq.CGRRequest.Set([]string{"Exponent"}, "2", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Value", PathItems: utils.PathItems{{Field: "Value"}}}, utils.NewNMData("2")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Exponent", PathItems: utils.PathItems{{Field: "Exponent"}}}, utils.NewNMData("2")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "TestExpo", Filters: []string{}, + {Tag: "TestExpo", Filters: []string{}, Path: utils.MetaCgrep + utils.NestingSep + "TestExpo", Type: utils.MetaValueExponent, Value: config.NewRSRParsersMustCompile("~*cgreq.Value;~*cgreq.Exponent", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{"TestExpo"}, []*config.NMItem{ + tplFlds[0].ComputePath() + eMp := &utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: "TestExpo"}}, &utils.NMSlice{ &config.NMItem{Data: "200", Path: []string{"TestExpo"}, - Config: tplFlds[0]}}, false, true) + Config: tplFlds[0]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -778,29 +811,32 @@ func TestAgReqFieldAsNone(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaCgrep + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Type: utils.META_NONE, Blocker: true}, - &config.FCTemplate{Tag: "Destination", + {Type: utils.META_NONE, Blocker: true}, + {Tag: "Destination", Path: utils.MetaCgrep + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := &utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(utils.PathItems{{Field: utils.Account}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) + Config: tplFlds[1]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -815,32 +851,35 @@ func TestAgReqFieldAsNone2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaCgrep + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Type: utils.META_NONE}, - &config.FCTemplate{Tag: "Destination", + {Type: utils.META_NONE}, + {Tag: "Destination", Path: utils.MetaCgrep + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := &utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(utils.PathItems{{Field: utils.Account}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) - eMp.Set([]string{utils.Destination}, []*config.NMItem{ + Config: tplFlds[1]}}) + eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[3]}}, false, true) + Config: tplFlds[3]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -855,49 +894,52 @@ func TestAgReqSetField2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) - agReq.CGRRequest.Set([]string{utils.AnswerTime}, - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false, false) - agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.META_PREPAID)) - agReq.CGRReply = config.NewNavigableMap(nil) + agReq.CGRReply = &utils.NavigableMap2{} tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaCgrep + utils.NestingSep + utils.Tenant, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Destination", + {Tag: "Destination", Path: utils.MetaCgrep + utils.NestingSep + utils.Destination, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Usage", + {Tag: "Usage", Path: utils.MetaCgrep + utils.NestingSep + utils.Usage, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("30s", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "CalculatedUsage", + {Tag: "CalculatedUsage", Path: utils.MetaCgrep + utils.NestingSep + "CalculatedUsage", Type: "*difference", Value: config.NewRSRParsersMustCompile("~*cgreq.AnswerTime;~*cgrep.Usage", true, utils.INFIELD_SEP), }, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := &utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(utils.PathItems{{Field: utils.Account}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) - eMp.Set([]string{utils.Destination}, []*config.NMItem{ + Config: tplFlds[1]}}) + eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}, false, true) - eMp.Set([]string{"Usage"}, []*config.NMItem{ + Config: tplFlds[2]}}) + eMp.Set(utils.PathItems{{Field: "Usage"}}, &utils.NMSlice{ &config.NMItem{Data: "30s", Path: []string{"Usage"}, - Config: tplFlds[3]}}, false, true) - eMp.Set([]string{"CalculatedUsage"}, []*config.NMItem{ + Config: tplFlds[3]}}) + eMp.Set(utils.PathItems{{Field: "CalculatedUsage"}}, &utils.NMSlice{ &config.NMItem{Data: time.Date(2013, 12, 30, 14, 59, 31, 0, time.UTC), Path: []string{"CalculatedUsage"}, - Config: tplFlds[4]}}, false, true) + Config: tplFlds[4]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -913,15 +955,15 @@ func TestAgReqFieldAsInterface(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest = config.NewNavigableMap(nil) - agReq.CGRRequest.Set([]string{utils.Usage}, []*config.NMItem{{Data: 3 * time.Minute}}, false, false) - agReq.CGRRequest.Set([]string{utils.ToR}, []*config.NMItem{{Data: utils.VOICE}}, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) + agReq.CGRRequest = utils.NewOrderedNavigableMap() + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, &utils.NMSlice{&config.NMItem{Data: 3 * time.Minute}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, &utils.NMSlice{&config.NMItem{Data: utils.VOICE}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) path := []string{utils.MetaCgreq, utils.Usage} var expVal interface{} - expVal = []*config.NMItem{{Data: 3 * time.Minute}} + expVal = &utils.NMSlice{&config.NMItem{Data: 3 * time.Minute}} if rply, err := agReq.FieldAsInterface(path); err != nil { t.Error(err) } else if !reflect.DeepEqual(rply, expVal) { @@ -929,7 +971,7 @@ func TestAgReqFieldAsInterface(t *testing.T) { } path = []string{utils.MetaCgreq, utils.ToR} - expVal = []*config.NMItem{{Data: utils.VOICE}} + expVal = &utils.NMSlice{&config.NMItem{Data: utils.VOICE}} if rply, err := agReq.FieldAsInterface(path); err != nil { t.Error(err) } else if !reflect.DeepEqual(rply, expVal) { @@ -959,42 +1001,43 @@ func TestAgReqNewARWithCGRRplyAndRply(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) - ev := map[string]interface{}{ - "FirstLevel": map[string]interface{}{ - "SecondLevel": map[string]interface{}{ - "Fld1": "Val1", - }, + rply := utils.NewOrderedNavigableMap() + rply.Set(&utils.FullPath{ + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: utils.PathItems{ + {Field: "FirstLevel"}, + {Field: "SecondLevel"}, + {Field: "Fld1"}, + }}, utils.NewNMData("Val1")) + cgrRply := &utils.NavigableMap2{ + utils.CapAttributes: utils.NavigableMap2{ + "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), }, + utils.CapMaxUsage: utils.NewNMData(time.Duration(120 * time.Second)), + utils.Error: utils.NewNMData(""), } - rply := config.NewNavigableMap(ev) - - ev2 := map[string]interface{}{ - utils.CapAttributes: map[string]interface{}{ - "PaypalAccount": "cgrates@paypal.com", - }, - utils.CapMaxUsage: time.Duration(120 * time.Second), - utils.Error: "", - } - cgrRply := config.NewNavigableMap(ev2) agReq := NewAgentRequest(nil, nil, cgrRply, rply, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Fld1", + {Tag: "Fld1", Path: utils.MetaCgreq + utils.NestingSep + "Fld1", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*rep.FirstLevel.SecondLevel.Fld1", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Fld2", + {Tag: "Fld2", Path: utils.MetaCgreq + utils.NestingSep + "Fld2", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgrep.Attributes.PaypalAccount", true, utils.INFIELD_SEP)}, } + for _, v := range tplFlds { + v.ComputePath() + } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{"Fld1"}, []*config.NMItem{ + eMp := utils.NewOrderedNavigableMap() + eMp.Set(&utils.FullPath{Path: "Fld1", PathItems: utils.PathItems{{Field: "Fld1"}}}, &utils.NMSlice{ &config.NMItem{Data: "Val1", Path: []string{"Fld1"}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{"Fld2"}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(&utils.FullPath{Path: "Fld2", PathItems: utils.PathItems{{Field: "Fld2"}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"Fld2"}, - Config: tplFlds[1]}}, false, true) + Config: tplFlds[1]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1009,39 +1052,40 @@ func TestAgReqSetCGRReplyWithError(t *testing.T) { config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) - ev := map[string]interface{}{ - "FirstLevel": map[string]interface{}{ - "SecondLevel": map[string]interface{}{ - "Fld1": "Val1", - }, - }, - } - rply := config.NewNavigableMap(ev) - + rply := utils.NewOrderedNavigableMap() + rply.Set(&utils.FullPath{ + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: utils.PathItems{ + {Field: "FirstLevel"}, + {Field: "SecondLevel"}, + {Field: "Fld1"}, + }}, utils.NewNMData("Val1")) agReq := NewAgentRequest(nil, nil, nil, rply, nil, nil, "cgrates.org", "", filterS, nil, nil) agReq.setCGRReply(nil, utils.ErrNotFound) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Fld1", + {Tag: "Fld1", Path: utils.MetaCgreq + utils.NestingSep + "Fld1", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*rep.FirstLevel.SecondLevel.Fld1", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Fld2", + {Tag: "Fld2", Path: utils.MetaCgreq + utils.NestingSep + "Fld2", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgrep.Attributes.PaypalAccount", true, utils.INFIELD_SEP), Mandatory: true}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err == nil || err.Error() != "NOT_FOUND:Fld2" { t.Error(err) } } -type myEv map[string]interface{} +type myEv map[string]utils.NMInterface -func (ev myEv) AsNavigableMap(tpl []*config.FCTemplate) (*config.NavigableMap, error) { - return config.NewNavigableMap(ev), nil +func (ev myEv) AsNavigableMap() utils.NavigableMap2 { + return utils.NavigableMap2(ev) } func TestAgReqSetCGRReplyWithoutError(t *testing.T) { @@ -1050,21 +1094,21 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) - ev := map[string]interface{}{ - "FirstLevel": map[string]interface{}{ - "SecondLevel": map[string]interface{}{ - "Fld1": "Val1", - }, - }, - } - rply := config.NewNavigableMap(ev) + rply := utils.NewOrderedNavigableMap() + rply.Set(&utils.FullPath{ + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: utils.PathItems{ + {Field: "FirstLevel"}, + {Field: "SecondLevel"}, + {Field: "Fld1"}, + }}, utils.NewNMData("Val1")) myEv := myEv{ - utils.CapAttributes: map[string]interface{}{ - "PaypalAccount": "cgrates@paypal.com", + utils.CapAttributes: utils.NavigableMap2{ + "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), }, - utils.CapMaxUsage: time.Duration(120 * time.Second), - utils.Error: "", + utils.CapMaxUsage: utils.NewNMData(time.Duration(120 * time.Second)), + utils.Error: utils.NewNMData(""), } agReq := NewAgentRequest(nil, nil, nil, rply, nil, @@ -1073,21 +1117,23 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { agReq.setCGRReply(myEv, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Fld1", + {Tag: "Fld1", Path: utils.MetaCgreq + utils.NestingSep + "Fld1", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*rep.FirstLevel.SecondLevel.Fld1", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Fld2", + {Tag: "Fld2", Path: utils.MetaCgreq + utils.NestingSep + "Fld2", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgrep.Attributes.PaypalAccount", true, utils.INFIELD_SEP)}, } - - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{"Fld1"}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := utils.NewOrderedNavigableMap() + eMp.Set(&utils.FullPath{Path: "Fld1", PathItems: utils.PathItems{{Field: "Fld1"}}}, &utils.NMSlice{ &config.NMItem{Data: "Val1", Path: []string{"Fld1"}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{"Fld2"}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(&utils.FullPath{Path: "Fld2", PathItems: utils.PathItems{{Field: "Fld2"}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"Fld2"}, - Config: tplFlds[1]}}, false, true) + Config: tplFlds[1]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1116,55 +1162,61 @@ func TestAgReqParseFieldMetaCCUsage(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "CCUsage", Filters: []string{}, + {Tag: "CCUsage", Filters: []string{}, Path: "CCUsage", Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, } + tplFlds[0].ComputePath() + if _, err := agReq.ParseField(tplFlds[0]); err == nil || err.Error() != `invalid arguments <[{"Rules":"~*req.Session-Id","AllFiltersMatch":true}]> to *cc_usage` { t.Error(err) } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "CCUsage", Filters: []string{}, + {Tag: "CCUsage", Filters: []string{}, Path: "CCUsage", Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("~*req.Session-Id;12s;12s", true, utils.INFIELD_SEP), Mandatory: true}, } + tplFlds[0].ComputePath() if _, err := agReq.ParseField(tplFlds[0]); err == nil || err.Error() != `invalid requestNumber to *cc_usage` { t.Error(err) } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "CCUsage", Filters: []string{}, + {Tag: "CCUsage", Filters: []string{}, Path: "CCUsage", Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("10;~*req.Session-Id;12s", true, utils.INFIELD_SEP), Mandatory: true}, } + tplFlds[0].ComputePath() if _, err := agReq.ParseField(tplFlds[0]); err == nil || err.Error() != `invalid usedCCTime to *cc_usage` { t.Error(err) } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "CCUsage", Filters: []string{}, + {Tag: "CCUsage", Filters: []string{}, Path: "CCUsage", Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("10;12s;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, } + tplFlds[0].ComputePath() if _, err := agReq.ParseField(tplFlds[0]); err == nil || err.Error() != `invalid debitInterval to *cc_usage` { t.Error(err) } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "CCUsage", Filters: []string{}, + {Tag: "CCUsage", Filters: []string{}, Path: "CCUsage", Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("3;10s;5s", true, utils.INFIELD_SEP), Mandatory: true}, } + tplFlds[0].ComputePath() //5s*2 + 10s expected := time.Duration(20 * time.Second) if out, err := agReq.ParseField(tplFlds[0]); err != nil { @@ -1194,7 +1246,7 @@ func TestAgReqParseFieldMetaUsageDifference(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Usage", Filters: []string{}, + {Tag: "Usage", Filters: []string{}, Path: "Usage", Type: utils.META_USAGE_DIFFERENCE, Value: config.NewRSRParsersMustCompile("~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1205,7 +1257,7 @@ func TestAgReqParseFieldMetaUsageDifference(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Usage", Filters: []string{}, + {Tag: "Usage", Filters: []string{}, Path: "Usage", Type: utils.META_USAGE_DIFFERENCE, Value: config.NewRSRParsersMustCompile("1560325161;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1216,7 +1268,7 @@ func TestAgReqParseFieldMetaUsageDifference(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Usage", Filters: []string{}, + {Tag: "Usage", Filters: []string{}, Path: "Usage", Type: utils.META_USAGE_DIFFERENCE, Value: config.NewRSRParsersMustCompile("~*req.Session-Id;1560325161", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1227,7 +1279,7 @@ func TestAgReqParseFieldMetaUsageDifference(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Usage", Filters: []string{}, + {Tag: "Usage", Filters: []string{}, Path: "Usage", Type: utils.META_USAGE_DIFFERENCE, Value: config.NewRSRParsersMustCompile("1560325161;1560325151", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1260,7 +1312,7 @@ func TestAgReqParseFieldMetaSum(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Sum", Filters: []string{}, + {Tag: "Sum", Filters: []string{}, Path: "Sum", Type: utils.MetaSum, Value: config.NewRSRParsersMustCompile("15;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1271,7 +1323,7 @@ func TestAgReqParseFieldMetaSum(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Sum", Filters: []string{}, + {Tag: "Sum", Filters: []string{}, Path: "Sum", Type: utils.MetaSum, Value: config.NewRSRParsersMustCompile("15;15", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1304,7 +1356,7 @@ func TestAgReqParseFieldMetaDifference(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Diff", Filters: []string{}, + {Tag: "Diff", Filters: []string{}, Path: "Diff", Type: utils.MetaDifference, Value: config.NewRSRParsersMustCompile("15;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1315,7 +1367,7 @@ func TestAgReqParseFieldMetaDifference(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Diff", Filters: []string{}, + {Tag: "Diff", Filters: []string{}, Path: "Diff", Type: utils.MetaDifference, Value: config.NewRSRParsersMustCompile("15;12;2", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1348,7 +1400,7 @@ func TestAgReqParseFieldMetaMultiply(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Multiply", Filters: []string{}, + {Tag: "Multiply", Filters: []string{}, Path: "Multiply", Type: utils.MetaMultiply, Value: config.NewRSRParsersMustCompile("15;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1359,7 +1411,7 @@ func TestAgReqParseFieldMetaMultiply(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Multiply", Filters: []string{}, + {Tag: "Multiply", Filters: []string{}, Path: "Multiply", Type: utils.MetaMultiply, Value: config.NewRSRParsersMustCompile("15;15", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1392,7 +1444,7 @@ func TestAgReqParseFieldMetaDivide(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Divide", Filters: []string{}, + {Tag: "Divide", Filters: []string{}, Path: "Divide", Type: utils.MetaDivide, Value: config.NewRSRParsersMustCompile("15;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1403,7 +1455,7 @@ func TestAgReqParseFieldMetaDivide(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "Divide", Filters: []string{}, + {Tag: "Divide", Filters: []string{}, Path: "Divide", Type: utils.MetaDivide, Value: config.NewRSRParsersMustCompile("15;3", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1436,7 +1488,7 @@ func TestAgReqParseFieldMetaValueExponent(t *testing.T) { agReq := NewAgentRequest(dP, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "ValExp", Filters: []string{}, + {Tag: "ValExp", Filters: []string{}, Path: "ValExp", Type: utils.MetaValueExponent, Value: config.NewRSRParsersMustCompile("~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1447,7 +1499,7 @@ func TestAgReqParseFieldMetaValueExponent(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "ValExp", Filters: []string{}, + {Tag: "ValExp", Filters: []string{}, Path: "ValExp", Type: utils.MetaValueExponent, Value: config.NewRSRParsersMustCompile("15;~*req.Session-Id", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1458,7 +1510,7 @@ func TestAgReqParseFieldMetaValueExponent(t *testing.T) { } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "ValExp", Filters: []string{}, + {Tag: "ValExp", Filters: []string{}, Path: "ValExp", Type: utils.MetaValueExponent, Value: config.NewRSRParsersMustCompile("~*req.Session-Id;15", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1468,7 +1520,7 @@ func TestAgReqParseFieldMetaValueExponent(t *testing.T) { t.Error(err) } tplFlds = []*config.FCTemplate{ - &config.FCTemplate{Tag: "ValExp", Filters: []string{}, + {Tag: "ValExp", Filters: []string{}, Path: "ValExp", Type: utils.MetaValueExponent, Value: config.NewRSRParsersMustCompile("2;3", true, utils.INFIELD_SEP), Mandatory: true}, @@ -1488,46 +1540,48 @@ func TestAgReqOverwrite(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) - agReq.CGRRequest.Set([]string{utils.AnswerTime}, - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false, false) - agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.META_PREPAID)) - agReq.CGRReply = config.NewNavigableMap(nil) + agReq.CGRReply = &utils.NavigableMap2{} tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile(":", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("OverwrittenAccount", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.META_COMPOSED, Value: config.NewRSRParsersMustCompile("WithComposed", true, utils.INFIELD_SEP)}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } - if rcv, err := agReq.CGRReply.GetField([]string{utils.Account}); err != nil { + if rcv, err := agReq.CGRReply.Field(utils.PathItems{{Field: utils.Account}}); err != nil { t.Error(err) - } else if sls, canCast := rcv.([]*config.NMItem); !canCast { - t.Errorf("Cannot cast to []*config.NMItem %+v", rcv) - } else if len(sls) != 1 { - t.Errorf("expecting: %+v, \n received: %+v ", 1, len(sls)) - } else if sls[0].Data != "OverwrittenAccountWithComposed" { + } else if sls, canCast := rcv.(*utils.NMSlice); !canCast { + t.Errorf("Cannot cast to &utils.NMSlice %+v", rcv) + } else if len(*sls) != 1 { + t.Errorf("expecting: %+v, \n received: %+v ", 1, len(*sls)) + } else if (*sls)[0].Interface() != "OverwrittenAccountWithComposed" { t.Errorf("expecting: %+v, \n received: %+v ", - "OverwrittenAccountWithComposed", (rcv.([]*config.NMItem))[0].Data) + "OverwrittenAccountWithComposed", (*sls)[0].Interface()) } } @@ -1538,38 +1592,40 @@ func TestAgReqGroupType(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) - agReq.CGRRequest.Set([]string{utils.AnswerTime}, - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false, false) - agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.META_PREPAID)) - agReq.CGRReply = config.NewNavigableMap(nil) + agReq.CGRReply = &utils.NavigableMap2{} tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaGroup, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCgrep + utils.NestingSep + utils.Account, Type: utils.MetaGroup, Value: config.NewRSRParsersMustCompile("test", true, utils.INFIELD_SEP)}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } - if rcv, err := agReq.CGRReply.GetField([]string{utils.Account}); err != nil { + if rcv, err := agReq.CGRReply.Field(utils.PathItems{{Field: utils.Account}}); err != nil { t.Error(err) - } else if sls, canCast := rcv.([]*config.NMItem); !canCast { - t.Errorf("Cannot cast to []*config.NMItem %+v", rcv) - } else if len(sls) != 2 { - t.Errorf("expecting: %+v, \n received: %+v ", 1, len(sls)) - } else if sls[0].Data != "cgrates.org" { - t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", sls[0].Data) - } else if sls[1].Data != "test" { - t.Errorf("expecting: %+v, \n received: %+v ", "test", sls[0].Data) + } else if sls, canCast := rcv.(*utils.NMSlice); !canCast { + t.Errorf("Cannot cast to &utils.NMSlice %+v", rcv) + } else if len(*sls) != 2 { + t.Errorf("expecting: %+v, \n received: %+v ", 1, len(*sls)) + } else if (*sls)[0].Interface() != "cgrates.org" { + t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", (*sls)[0].Interface()) + } else if (*sls)[1].Interface() != "test" { + t.Errorf("expecting: %+v, \n received: %+v ", "test", (*sls)[1].Interface()) } } @@ -1579,23 +1635,26 @@ func TestAgReqSetFieldsInTmp(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaTmp + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaTmp + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := utils.NavigableMap2{} + eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(utils.PathItems{{Field: utils.Account}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) + Config: tplFlds[1]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1611,88 +1670,89 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set([]string{utils.CGRID}, - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), - false, false) - agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) - agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false, false) - agReq.CGRRequest.Set([]string{utils.AnswerTime}, - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false, false) - agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false, false) - agReq.CGRRequest.Set([]string{utils.Usage}, time.Duration(3*time.Minute), false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.VOICE)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.META_PREPAID)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, utils.NewNMData(time.Duration(3*time.Minute))) - cgrRply := map[string]interface{}{ - utils.CapAttributes: map[string]interface{}{ - "PaypalAccount": "cgrates@paypal.com", + agReq.CGRReply = &utils.NavigableMap2{ + utils.CapAttributes: utils.NavigableMap2{ + "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), }, - utils.CapMaxUsage: time.Duration(120 * time.Second), - utils.Error: "", + utils.CapMaxUsage: utils.NewNMData(time.Duration(120 * time.Second)), + utils.Error: utils.NewNMData(""), } - agReq.CGRReply = config.NewNavigableMap(cgrRply) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaRep + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaRep + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Destination", + {Tag: "Destination", Path: utils.MetaRep + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Destination", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageVoice", + {Tag: "RequestedUsageVoice", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*voice"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_seconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageData", + {Tag: "RequestedUsageData", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*data"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "RequestedUsageSMS", + {Tag: "RequestedUsageSMS", Path: utils.MetaRep + utils.NestingSep + "RequestedUsage", Type: utils.MetaVariable, Filters: []string{"*string:~*cgreq.ToR:*sms"}, Value: config.NewRSRParsersMustCompile( "~*cgreq.Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "AttrPaypalAccount", + {Tag: "AttrPaypalAccount", Path: utils.MetaRep + utils.NestingSep + "PaypalAccount", Type: utils.MetaVariable, Filters: []string{"*empty:~*cgrep.Error:"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.Attributes.PaypalAccount", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "MaxUsage", + {Tag: "MaxUsage", Path: utils.MetaRep + utils.NestingSep + "MaxUsage", Type: utils.MetaVariable, Filters: []string{"*empty:~*cgrep.Error:"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Error", + {Tag: "Error", Path: utils.MetaRep + utils.NestingSep + "Error", Type: utils.MetaVariable, Filters: []string{"*rsr::~*cgrep.Error(!^$)"}, Value: config.NewRSRParsersMustCompile( "~*cgrep.Error", true, utils.INFIELD_SEP)}, } - eMp := config.NewNavigableMap(nil) - eMp.Set([]string{utils.Tenant}, []*config.NMItem{ + for _, v := range tplFlds { + v.ComputePath() + } + eMp := utils.NewOrderedNavigableMap() + eMp.Set(&utils.FullPath{Path: utils.Tenant, PathItems: utils.PathItems{{Field: utils.Tenant}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}, false, true) - eMp.Set([]string{utils.Account}, []*config.NMItem{ + Config: tplFlds[0]}}) + eMp.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, &utils.NMSlice{ &config.NMItem{Data: "1001", Path: []string{utils.Account}, - Config: tplFlds[1]}}, false, true) - eMp.Set([]string{utils.Destination}, []*config.NMItem{ + Config: tplFlds[1]}}) + eMp.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}, false, true) - eMp.Set([]string{"RequestedUsage"}, []*config.NMItem{ + Config: tplFlds[2]}}) + eMp.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}, false, true) - eMp.Set([]string{"PaypalAccount"}, []*config.NMItem{ + Config: tplFlds[3]}}) + eMp.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}, false, true) - eMp.Set([]string{"MaxUsage"}, []*config.NMItem{ + Config: tplFlds[6]}}) + eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}, false, true) + Config: tplFlds[7]}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1701,40 +1761,42 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { } tplFldsRemove := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaRep + utils.NestingSep + utils.Tenant, Type: utils.MetaRemove}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaRep + utils.NestingSep + utils.Account, Type: utils.MetaRemove}, } - - eMpRemove := config.NewNavigableMap(nil) - eMpRemove.Set([]string{utils.Destination}, []*config.NMItem{ + for _, v := range tplFldsRemove { + v.ComputePath() + } + eMpRemove := utils.NewOrderedNavigableMap() + eMpRemove.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}, false, true) - eMpRemove.Set([]string{"RequestedUsage"}, []*config.NMItem{ + Config: tplFlds[2]}}) + eMpRemove.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}, false, true) - eMpRemove.Set([]string{"PaypalAccount"}, []*config.NMItem{ + Config: tplFlds[3]}}) + eMpRemove.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}, false, true) - eMpRemove.Set([]string{"MaxUsage"}, []*config.NMItem{ + Config: tplFlds[6]}}) + eMpRemove.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}, false, true) + Config: tplFlds[7]}}) if err := agReq.SetFields(tplFldsRemove); err != nil { t.Error(err) - } else if agReq.Reply.String() != eMpRemove.String() { // when compare ignore orders - t.Errorf("expecting: %+v,\n received: %+v", eMpRemove.String(), agReq.Reply.String()) + } else if !reflect.DeepEqual(agReq.Reply, eMpRemove) { // when compare ignore orders + t.Errorf("expecting: %+v,\n received: %+v", eMpRemove, agReq.Reply) } tplFldsRemove = []*config.FCTemplate{ - &config.FCTemplate{Path: utils.MetaRep, Type: utils.MetaRemoveAll}, + {Path: utils.MetaRep, Type: utils.MetaRemoveAll}, } - - eMpRemove = config.NewNavigableMap(nil) + tplFldsRemove[0].ComputePath() + eMpRemove = utils.NewOrderedNavigableMap() if err := agReq.SetFields(tplFldsRemove); err != nil { t.Error(err) - } else if !reflect.DeepEqual(agReq.Reply.Values(), eMpRemove.Values()) { + } else if !reflect.DeepEqual(agReq.Reply.GetOrder(), eMpRemove.GetOrder()) { t.Errorf("expecting: %+v,\n received: %+v", eMpRemove, agReq.Reply) } } @@ -1746,30 +1808,32 @@ func TestAgReqSetFieldsInCache(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) engine.NewCacheS(cfg, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaCache + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCache + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } if val, err := agReq.FieldAsInterface([]string{utils.MetaCache, utils.Tenant}); err != nil { t.Error(err) - } else if val.([]*config.NMItem)[0].Data != "cgrates.org" { + } else if (*val.(*utils.NMSlice))[0].Interface() != "cgrates.org" { t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", utils.ToJSON(val)) } if val, err := agReq.FieldAsInterface([]string{utils.MetaCache, utils.Account}); err != nil { t.Error(err) - } else if val.([]*config.NMItem)[0].Data != "1001" { + } else if (*val.(*utils.NMSlice))[0].Interface() != "1001" { t.Errorf("expecting: %+v, \n received: %+v ", "1001", utils.ToJSON(val)) } @@ -1787,30 +1851,32 @@ func TestAgReqSetFieldsInCacheWithTimeOut(t *testing.T) { cfg.CacheCfg().Partitions[utils.CacheUCH].TTL = 1 * time.Second engine.Cache = engine.NewCacheS(cfg, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Account, PathItems: utils.PathItems{{Field: utils.Account}}}, utils.NewNMData("1001")) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Tenant", + {Tag: "Tenant", Path: utils.MetaCache + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Account", + {Tag: "Account", Path: utils.MetaCache + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgreq.Account", true, utils.INFIELD_SEP)}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } if val, err := agReq.FieldAsInterface([]string{utils.MetaCache, utils.Tenant}); err != nil { t.Error(err) - } else if val.([]*config.NMItem)[0].Data != "cgrates.org" { + } else if (*val.(*utils.NMSlice))[0].Interface() != "cgrates.org" { t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", utils.ToJSON(val)) } if val, err := agReq.FieldAsInterface([]string{utils.MetaCache, utils.Account}); err != nil { t.Error(err) - } else if val.([]*config.NMItem)[0].Data != "1001" { + } else if (*val.(*utils.NMSlice))[0].Interface() != "1001" { t.Errorf("expecting: %+v, \n received: %+v ", "1001", utils.ToJSON(val)) } @@ -1880,16 +1946,18 @@ func TestAgReqFiltersInsideField(t *testing.T) { agReq := NewAgentRequest(newDADataProvider(nil, m), nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) tplFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "Usage", + {Tag: "Usage", Path: utils.MetaCgreq + utils.NestingSep + utils.Usage, Type: utils.MetaCCUsage, Value: config.NewRSRParsersMustCompile("~*req.CC-Request-Number;~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/;5m", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "AnswerTime", + {Tag: "AnswerTime", Path: utils.MetaCgreq + utils.NestingSep + utils.AnswerTime, Type: utils.MetaDifference, Filters: []string{"*gt:~*cgreq.Usage:0s"}, // populate answer time if usage is greater than zero Value: config.NewRSRParsersMustCompile("~*req.Event-Timestamp;~*cgreq.Usage", true, utils.INFIELD_SEP)}, } - + for _, v := range tplFlds { + v.ComputePath() + } if err := agReq.SetFields(tplFlds); err != nil { // here we get error //t.Error(err) diff --git a/agents/diamagent.go b/agents/diamagent.go index 5c8f3575e..5633f81a3 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -173,14 +173,14 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) { return } diamDP := newDADataProvider(c, m) - reqVars := map[string]interface{}{ - utils.OriginHost: da.cgrCfg.DiameterAgentCfg().OriginHost, // used in templates - utils.OriginRealm: da.cgrCfg.DiameterAgentCfg().OriginRealm, - utils.ProductName: da.cgrCfg.DiameterAgentCfg().ProductName, - utils.MetaApp: dApp.Name, - utils.MetaAppID: dApp.ID, - utils.MetaCmd: dCmd.Short + "R", - utils.RemoteHost: c.RemoteAddr().String(), + reqVars := utils.NavigableMap2{ + utils.OriginHost: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().OriginHost), // used in templates + utils.OriginRealm: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().OriginRealm), + utils.ProductName: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().ProductName), + utils.MetaApp: utils.NewNMData(dApp.Name), + utils.MetaAppID: utils.NewNMData(dApp.ID), + utils.MetaCmd: utils.NewNMData(dCmd.Short + "R"), + utils.RemoteHost: utils.NewNMData(c.RemoteAddr().String()), } // build the negative error answer diamErr, err := diamErr( @@ -229,16 +229,16 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) { da.aReqsLck.Unlock() }() } - cgrRplyNM := config.NewNavigableMap(nil) - rply := config.NewNavigableMap(nil) // share it among different processors - opts := config.NewNavigableMap(nil) + cgrRplyNM := utils.NavigableMap2{} + rply := utils.NewOrderedNavigableMap() // share it among different processors + opts := utils.NewOrderedNavigableMap() var processed bool for _, reqProcessor := range da.cgrCfg.DiameterAgentCfg().RequestProcessors { var lclProcessed bool lclProcessed, err = da.processRequest( reqProcessor, NewAgentRequest( - diamDP, reqVars, cgrRplyNM, rply, opts, + diamDP, reqVars, &cgrRplyNM, rply, opts, reqProcessor.Tenant, da.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, da.cgrCfg.GeneralCfg().DefaultTimezone), @@ -286,8 +286,8 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep) - opts := agReq.Opts.GetData() + cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep) + opts := config.NMAsMapInterface(agReq.Opts, utils.NestingSep) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, @@ -451,7 +451,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, if err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1ProcessCDR, &utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, rplyCDRs); err != nil { - agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) } } if err = agReq.SetFields(reqProcessor.ReplyFields); err != nil { @@ -515,11 +515,7 @@ func (da *DiameterAgent) sendASR(originID string, reply *string) (err error) { dmd := msg.(*diamMsgData) aReq := NewAgentRequest( newDADataProvider(dmd.c, dmd.m), - dmd.vars, - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - nil, + dmd.vars, nil, nil, nil, nil, da.cgrCfg.GeneralCfg().DefaultTenant, da.cgrCfg.GeneralCfg().DefaultTimezone, da.filterS, nil, nil) if err = aReq.SetFields(da.cgrCfg.DiameterAgentCfg().Templates[da.cgrCfg.DiameterAgentCfg().ASRTemplate]); err != nil { @@ -562,11 +558,7 @@ func (da *DiameterAgent) V1ReAuthorize(originID string, reply *string) (err erro dmd := msg.(*diamMsgData) aReq := NewAgentRequest( newDADataProvider(dmd.c, dmd.m), - dmd.vars, - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - nil, + dmd.vars, nil, nil, nil, nil, da.cgrCfg.GeneralCfg().DefaultTenant, da.cgrCfg.GeneralCfg().DefaultTimezone, da.filterS, nil, nil) if err = aReq.SetFields(da.cgrCfg.DiameterAgentCfg().Templates[da.cgrCfg.DiameterAgentCfg().RARTemplate]); err != nil { diff --git a/agents/diamagent_test.go b/agents/diamagent_test.go index 23be23b28..01f6ce046 100644 --- a/agents/diamagent_test.go +++ b/agents/diamagent_test.go @@ -60,8 +60,8 @@ func TestProcessRequest(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filters := engine.NewFilterS(config.CgrConfig(), nil, dm) // no need for filterS but still try to configure the dm :D - cgrRplyNM := config.NewNavigableMap(nil) - rply := config.NewNavigableMap(nil) + cgrRplyNM := utils.NavigableMap2{} + rply := utils.NewOrderedNavigableMap() diamDP := config.NewNavigableMap(map[string]interface{}{ "SessionId": "123456", "Account": "1001", @@ -73,44 +73,50 @@ func TestProcessRequest(t *testing.T) { Tenant: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP), Filters: []string{}, RequestFields: []*config.FCTemplate{ - &config.FCTemplate{Tag: utils.ToR, + {Tag: utils.ToR, Type: utils.META_CONSTANT, Path: utils.MetaCgreq + utils.NestingSep + utils.ToR, Value: config.NewRSRParsersMustCompile(utils.VOICE, true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: utils.OriginID, + {Tag: utils.OriginID, Type: utils.META_COMPOSED, Path: utils.MetaCgreq + utils.NestingSep + utils.OriginID, Value: config.NewRSRParsersMustCompile("~*req.SessionId", true, utils.INFIELD_SEP), Mandatory: true}, - &config.FCTemplate{Tag: utils.OriginHost, + {Tag: utils.OriginHost, Type: utils.MetaRemoteHost, Path: utils.MetaCgreq + utils.NestingSep + utils.OriginHost, Mandatory: true}, - &config.FCTemplate{Tag: utils.Category, + {Tag: utils.Category, Type: utils.META_CONSTANT, Path: utils.MetaCgreq + utils.NestingSep + utils.Category, Value: config.NewRSRParsersMustCompile(utils.CALL, true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: utils.Account, + {Tag: utils.Account, Type: utils.META_COMPOSED, Path: utils.MetaCgreq + utils.NestingSep + utils.Account, Value: config.NewRSRParsersMustCompile("~*req.Account", true, utils.INFIELD_SEP), Mandatory: true}, - &config.FCTemplate{Tag: utils.Destination, + {Tag: utils.Destination, Type: utils.META_COMPOSED, Path: utils.MetaCgreq + utils.NestingSep + utils.Destination, Value: config.NewRSRParsersMustCompile("~*req.Destination", true, utils.INFIELD_SEP), Mandatory: true}, - &config.FCTemplate{Tag: utils.Usage, + {Tag: utils.Usage, Type: utils.META_COMPOSED, Path: utils.MetaCgreq + utils.NestingSep + utils.Usage, Value: config.NewRSRParsersMustCompile("~*req.Usage", true, utils.INFIELD_SEP), Mandatory: true}, }, ReplyFields: []*config.FCTemplate{ - &config.FCTemplate{Tag: "ResultCode", + {Tag: "ResultCode", Type: utils.META_CONSTANT, Path: utils.MetaRep + utils.NestingSep + "ResultCode", Value: config.NewRSRParsersMustCompile("2001", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "GrantedUnits", + {Tag: "GrantedUnits", Type: utils.MetaVariable, Path: utils.MetaRep + utils.NestingSep + "Granted-Service-Unit.CC-Time", Value: config.NewRSRParsersMustCompile("~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP), Mandatory: true}, }, } - reqVars := map[string]interface{}{ - utils.OriginHost: config.CgrConfig().DiameterAgentCfg().OriginHost, - utils.OriginRealm: config.CgrConfig().DiameterAgentCfg().OriginRealm, - utils.ProductName: config.CgrConfig().DiameterAgentCfg().ProductName, - utils.MetaApp: "appName", - utils.MetaAppID: "appID", - utils.MetaCmd: "cmdR", + for _, v := range reqProcessor.RequestFields { + v.ComputePath() + } + for _, v := range reqProcessor.ReplyFields { + v.ComputePath() + } + reqVars := utils.NavigableMap2{ + utils.OriginHost: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().OriginHost), + utils.OriginRealm: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().OriginRealm), + utils.ProductName: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().ProductName), + utils.MetaApp: utils.NewNMData("appName"), + utils.MetaAppID: utils.NewNMData("appID"), + utils.MetaCmd: utils.NewNMData("cmdR"), } sS := &testMockSessionConn{calls: map[string]func(arg interface{}, rply interface{}) error{ @@ -434,7 +440,7 @@ func TestProcessRequest(t *testing.T) { }, }} reqProcessor.Flags, _ = utils.FlagsWithParamsFromSlice([]string{utils.MetaAuthorize, utils.MetaAccounts}) - agReq := NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, + agReq := NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -453,15 +459,15 @@ func TestProcessRequest(t *testing.T) { t.Error(err) } else if !pr { t.Errorf("Expected the request to be processed") - } else if len(rply.Values()) != 2 { + } else if len(rply.GetOrder()) != 2 { t.Errorf("Expected the reply to have 2 values received: %s", rply.String()) } reqProcessor.Flags, _ = utils.FlagsWithParamsFromSlice([]string{utils.MetaInitiate, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = config.NewNavigableMap(nil) - rply = config.NewNavigableMap(nil) + cgrRplyNM = utils.NavigableMap2{} + rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -470,15 +476,15 @@ func TestProcessRequest(t *testing.T) { t.Error(err) } else if !pr { t.Errorf("Expected the request to be processed") - } else if len(rply.Values()) != 2 { + } else if len(rply.GetOrder()) != 2 { t.Errorf("Expected the reply to have 2 values received: %s", rply.String()) } reqProcessor.Flags, _ = utils.FlagsWithParamsFromSlice([]string{utils.MetaUpdate, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = config.NewNavigableMap(nil) - rply = config.NewNavigableMap(nil) + cgrRplyNM = utils.NavigableMap2{} + rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -487,18 +493,21 @@ func TestProcessRequest(t *testing.T) { t.Error(err) } else if !pr { t.Errorf("Expected the request to be processed") - } else if len(rply.Values()) != 2 { + } else if len(rply.GetOrder()) != 2 { t.Errorf("Expected the reply to have 2 values received: %s", rply.String()) } reqProcessor.Flags, _ = utils.FlagsWithParamsFromSlice([]string{utils.MetaTerminate, utils.MetaAccounts, utils.MetaAttributes, utils.MetaCDRs}) - reqProcessor.ReplyFields = []*config.FCTemplate{&config.FCTemplate{Tag: "ResultCode", + reqProcessor.ReplyFields = []*config.FCTemplate{{Tag: "ResultCode", Type: utils.META_CONSTANT, Path: utils.MetaRep + utils.NestingSep + "ResultCode", Value: config.NewRSRParsersMustCompile("2001", true, utils.INFIELD_SEP)}} - cgrRplyNM = config.NewNavigableMap(nil) - rply = config.NewNavigableMap(nil) + for _, v := range reqProcessor.ReplyFields { + v.ComputePath() + } + cgrRplyNM = utils.NavigableMap2{} + rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -507,15 +516,15 @@ func TestProcessRequest(t *testing.T) { t.Error(err) } else if !pr { t.Errorf("Expected the request to be processed") - } else if len(rply.Values()) != 1 { + } else if len(rply.GetOrder()) != 1 { t.Errorf("Expected the reply to have one value received: %s", rply.String()) } reqProcessor.Flags, _ = utils.FlagsWithParamsFromSlice([]string{utils.MetaMessage, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = config.NewNavigableMap(nil) - rply = config.NewNavigableMap(nil) + cgrRplyNM = utils.NavigableMap2{} + rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -524,7 +533,7 @@ func TestProcessRequest(t *testing.T) { t.Error(err) } else if !pr { t.Errorf("Expected the request to be processed") - } else if len(rply.Values()) != 1 { + } else if len(rply.GetOrder()) != 1 { t.Errorf("Expected the reply to have one value received: %s", rply.String()) } diff --git a/agents/dnsagent.go b/agents/dnsagent.go index 275276191..753723942 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -91,14 +91,14 @@ func (da *DNSAgent) Reload() (err error) { // requests are reaching here asynchronously func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { dnsDP := newDNSDataProvider(req, w) - reqVars := make(map[string]interface{}) - reqVars[QueryType] = dns.TypeToString[req.Question[0].Qtype] + reqVars := make(utils.NavigableMap2) + reqVars[QueryType] = utils.NewNMData(dns.TypeToString[req.Question[0].Qtype]) rply := new(dns.Msg) rply.SetReply(req) // message preprocesing switch req.Question[0].Qtype { case dns.TypeNAPTR: - reqVars[QueryName] = req.Question[0].Name + reqVars[QueryName] = utils.NewNMData(req.Question[0].Name) e164, err := e164FromNAPTR(req.Question[0].Name) if err != nil { utils.Logger.Warning( @@ -108,13 +108,13 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { dnsWriteMsg(w, rply) return } - reqVars[E164Address] = e164 - reqVars[DomainName] = domainNameFromNAPTR(req.Question[0].Name) + reqVars[E164Address] = utils.NewNMData(e164) + reqVars[DomainName] = utils.NewNMData(domainNameFromNAPTR(req.Question[0].Name)) } - reqVars[utils.RemoteHost] = w.RemoteAddr().String() - cgrRplyNM := config.NewNavigableMap(nil) - rplyNM := config.NewNavigableMap(nil) // share it among different processors - opts := config.NewNavigableMap(nil) + reqVars[utils.RemoteHost] = utils.NewNMData(w.RemoteAddr().String()) + cgrRplyNM := utils.NavigableMap2{} + rplyNM := utils.NewOrderedNavigableMap() // share it among different processors + opts := utils.NewOrderedNavigableMap() var processed bool var err error for _, reqProcessor := range da.cgrCfg.DNSAgentCfg().RequestProcessors { @@ -122,7 +122,7 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { lclProcessed, err = da.processRequest( reqProcessor, NewAgentRequest( - dnsDP, reqVars, cgrRplyNM, rplyNM, + dnsDP, reqVars, &cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, da.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(da.cgrCfg.DNSAgentCfg().Timezone, @@ -177,8 +177,8 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep) - opts := agReq.Opts.GetData() + cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep) + opts := config.NMAsMapInterface(agReq.Opts, utils.NestingSep) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, @@ -348,7 +348,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, utils.SessionSv1ProcessCDR, &utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, &rplyCDRs); err != nil { - agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) } } if err := agReq.SetFields(reqProcessor.ReplyFields); err != nil { diff --git a/agents/httpagent.go b/agents/httpagent.go index 205197fa5..b6e3f2429 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -56,7 +56,6 @@ type HTTPAgent struct { // ServeHTTP implements http.Handler interface func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) { - reqVars := make(map[string]interface{}) dcdr, err := newHADataProvider(ha.reqPayload, req) // dcdr will provide information from request if err != nil { utils.Logger.Warning( @@ -64,12 +63,12 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) { utils.HTTPAgent, err.Error())) return } - cgrRplyNM := config.NewNavigableMap(nil) - rplyNM := config.NewNavigableMap(nil) - opts := config.NewNavigableMap(nil) - reqVars[utils.RemoteHost] = req.RemoteAddr + cgrRplyNM := utils.NavigableMap2{} + rplyNM := utils.NewOrderedNavigableMap() + opts := utils.NewOrderedNavigableMap() + reqVars := utils.NavigableMap2{utils.RemoteHost: utils.NewNMData(req.RemoteAddr)} for _, reqProcessor := range ha.reqProcessors { - agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, + agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ha.dfltTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), @@ -113,8 +112,8 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep) - opts := agReq.Opts.GetData() + cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep) + opts := config.NMAsMapInterface(agReq.Opts, utils.NestingSep) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, @@ -278,7 +277,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, &utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, rplyCDRs); err != nil { - agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) } } if err := agReq.SetFields(reqProcessor.ReplyFields); err != nil { diff --git a/agents/libdiam.go b/agents/libdiam.go index dda880f91..cbb69275b 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -307,12 +307,6 @@ func (dP *diameterDP) String() string { return dP.m.String() } -// AsNavigableMap is part of engine.DataProvider interface -func (dP *diameterDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // FieldAsString is part of engine.DataProvider interface func (dP *diameterDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} @@ -419,38 +413,22 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err } // updateDiamMsgFromNavMap will update the diameter message with items from navigable map -func updateDiamMsgFromNavMap(m *diam.Message, navMp *config.NavigableMap, tmz string) (err error) { +func updateDiamMsgFromNavMap(m *diam.Message, navMp *utils.OrderedNavigableMap, tmz string) (err error) { // write reply into message - pathIdx := make(map[string]int) // group items for same path - for _, val := range navMp.Values() { - nmItms, isNMItems := val.([]*config.NMItem) - if !isNMItems { + for el := navMp.GetFirstElement(); el != nil; el = el.Next() { + val := el.Value + var nmIt utils.NMInterface + if nmIt, err = navMp.Field(val); err != nil { + return + } + itm, isNMItem := nmIt.(*config.NMItem) + if !isNMItem { return fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val)) } - // find out the first itm which is not an attribute - var itm *config.NMItem - if len(nmItms) == 1 { - itm = nmItms[0] - } else { // only for groups - for i, cfgItm := range nmItms { - itmPath := strings.Join(cfgItm.Path, utils.NestingSep) - if i == 0 { // path is common, increase it only once - pathIdx[itmPath]++ - } - if i == pathIdx[itmPath]-1 { // revert from multiple items to only one per config path - itm = cfgItm - break - } - } - } - if itm == nil { continue // all attributes, not writable to diameter packet } - var newBranch bool - if itm.Config != nil && itm.Config.NewBranch { - newBranch = true - } + newBranch := itm.Config != nil && itm.Config.NewBranch if err = messageSetAVPsWithPath(m, itm.Path, utils.IfaceAsString(itm.Data), newBranch, tmz); err != nil { return fmt.Errorf("setting item with path: %+v got err: %s", itm.Path, err.Error()) @@ -461,7 +439,7 @@ func updateDiamMsgFromNavMap(m *diam.Message, navMp *config.NavigableMap, tmz st // diamAnswer builds up the answer to be sent back to the client func diamAnswer(m *diam.Message, resCode uint32, errFlag bool, - rply *config.NavigableMap, tmz string) (a *diam.Message, err error) { + rply *utils.OrderedNavigableMap, tmz string) (a *diam.Message, err error) { a = m.Answer(resCode) if errFlag { a.Header.CommandFlags = diam.ErrorFlag @@ -474,15 +452,13 @@ func diamAnswer(m *diam.Message, resCode uint32, errFlag bool, // negDiamAnswer is used to return the negative answer we need previous to func diamErr(m *diam.Message, resCode uint32, - reqVars map[string]interface{}, + reqVars utils.NavigableMap2, tpl []*config.FCTemplate, tnt, tmz string, filterS *engine.FilterS) (a *diam.Message, err error) { aReq := NewAgentRequest( newDADataProvider(nil, m), reqVars, - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - config.NewNavigableMap(nil), - nil, tnt, tmz, filterS, nil, nil) + nil, nil, nil, nil, + tnt, tmz, filterS, nil, nil) if err = aReq.SetFields(tpl); err != nil { return } @@ -512,5 +488,5 @@ func disectDiamListen(addrs string) (ipAddrs []net.IP) { type diamMsgData struct { c diam.Conn m *diam.Message - vars map[string]interface{} + vars utils.NavigableMap2 } diff --git a/agents/libdiam_test.go b/agents/libdiam_test.go index f75bcb39a..20b1b9055 100644 --- a/agents/libdiam_test.go +++ b/agents/libdiam_test.go @@ -21,6 +21,7 @@ package agents import ( "net" "reflect" + "strings" "testing" "time" @@ -426,24 +427,33 @@ func TestUpdateDiamMsgFromNavMap1(t *testing.T) { }, ) - nM := config.NewNavigableMap(nil) + nM := utils.NewOrderedNavigableMap() itm := &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) @@ -501,32 +511,44 @@ func TestUpdateDiamMsgFromNavMap2(t *testing.T) { }, ) - nM := config.NewNavigableMap(nil) + nM := utils.NewOrderedNavigableMap() itm := &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", Config: &config.FCTemplate{NewBranch: true}, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) - + nM.Set( + &utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem([]string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type[1]"}), + }, itm) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) } @@ -560,31 +582,43 @@ func TestUpdateDiamMsgFromNavMap3(t *testing.T) { m2 := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4, eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil) - nM := config.NewNavigableMap(nil) + nM := utils.NewOrderedNavigableMap() itm := &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) @@ -641,44 +675,62 @@ func TestUpdateDiamMsgFromNavMap4(t *testing.T) { m2 := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4, eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil) - nM := config.NewNavigableMap(nil) + nM := utils.NewOrderedNavigableMap() itm := &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) itm = &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) - itm = &config.NMItem{ + itm2 := &config.NMItem{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", Config: &config.FCTemplate{NewBranch: true}, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm, itm2}) itm = &config.NMItem{ Path: []string{"Granted-Service-Unit", "CC-Time"}, Data: datatype.Unsigned32(10), } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) diff --git a/agents/libdns.go b/agents/libdns.go index 9b9302778..a3e96d47b 100644 --- a/agents/libdns.go +++ b/agents/libdns.go @@ -79,12 +79,6 @@ func (dP *dnsDP) String() string { return utils.ToJSON(dP.req) } -// AsNavigableMap is part of engine.DataProvider interface -func (dP *dnsDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // FieldAsString is part of engine.DataProvider interface func (dP *dnsDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} @@ -159,17 +153,18 @@ func appendDNSAnswer(msg *dns.Msg) (err error) { } // updateDNSMsgFromNM will update DNS message with values from NavigableMap -func updateDNSMsgFromNM(msg *dns.Msg, nm *config.NavigableMap) (err error) { +func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) { msgFields := make(map[string]struct{}) // work around to NMap issue - for _, valX := range nm.Values() { - nmItms, cast := valX.([]*config.NMItem) + for el := nm.GetFirstElement(); el != nil; el = el.Next() { + val := el.Value + var nmIt utils.NMInterface + if nmIt, err = nm.Field(val); err != nil { + return + } + cfgItm, cast := nmIt.(*config.NMItem) if !cast { - return fmt.Errorf("cannot cast val: %s into []*config.NMItem", utils.ToJSON(valX)) + return fmt.Errorf("cannot cast val: %s into *config.NMItem", nmIt) } - if len(nmItms) == 0 { - continue - } - cfgItm := nmItms[0] // first item gives some config for the rest, cannot iterate through NMItems since they are multipled by order if len(cfgItm.Path) == 0 { return errors.New("empty path in config item") } @@ -183,10 +178,7 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *config.NavigableMap) (err error) { } msgFields = make(map[string]struct{}) // reset the fields inside since we have a new message } - itmData := nmItms[0].Data // populate default with first item's data - if len(nmItms) >= len(msg.Answer) { - itmData = nmItms[len(msg.Answer)-1].Data // data at same index as answer - } + itmData := cfgItm.Data switch cfgItm.Path[0] { case utils.Rcode: var itm int64 diff --git a/agents/libdns_test.go b/agents/libdns_test.go index 3ecc9ce5a..424823659 100644 --- a/agents/libdns_test.go +++ b/agents/libdns_test.go @@ -20,6 +20,7 @@ package agents import ( "reflect" + "strings" "testing" "github.com/cgrates/cgrates/config" @@ -175,30 +176,33 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m := new(dns.Msg) m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeNAPTR) - nM := config.NewNavigableMap(nil) + nM := utils.NewOrderedNavigableMap() itm := &config.NMItem{ Path: []string{}, Data: "Val1", } - nM.Set([]string{"Path"}, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{Path: "Path", PathItems: utils.PathItems{{Field: "Path"}}}, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != "empty path in config item" { t.Error(err) } - nM = config.NewNavigableMap(nil) - nM.Set([]string{"Path"}, "test", true, true) + nM = utils.NewOrderedNavigableMap() + nM.Set(&utils.FullPath{Path: "Path", PathItems: utils.PathItems{{Field: "Path"}}}, utils.NewNMData("test")) if err := updateDNSMsgFromNM(m, nM); err == nil || - err.Error() != `cannot cast val: "test" into []*config.NMItem` { + err.Error() != `cannot cast val: test into *config.NMItem` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Rcode}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err != nil { t.Error(err) } @@ -206,34 +210,43 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { t.Errorf("expecting: <10>, received: <%+v>", m.Rcode) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Rcode}, Data: "RandomValue", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Order}, Data: "RandomValue", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Preference}, Data: "RandomValue", } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) @@ -241,67 +254,85 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m = new(dns.Msg) m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeA) - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Order}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Preference}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Flags}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Service}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Regexp}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } - nM = config.NewNavigableMap(nil) + nM = utils.NewOrderedNavigableMap() itm = &config.NMItem{ Path: []string{utils.Replacement}, Data: 10, } - nM.Set(itm.Path, []*config.NMItem{itm}, true, true) + nM.Set(&utils.FullPath{ + Path: strings.Join(itm.Path, utils.NestingSep), + PathItems: utils.NewPathToItem(itm.Path), + }, &utils.NMSlice{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index 50d3417b2..5779ff11a 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -94,12 +94,6 @@ func (hU *httpUrlDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// AsNavigableMap is part of engine.DataProvider interface -func (hU *httpUrlDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of engine.DataProvider interface func (hU *httpUrlDP) RemoteHost() net.Addr { return utils.NewNetAddr("TCP", hU.req.RemoteAddr) @@ -188,12 +182,6 @@ func (hU *httpXmlDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// AsNavigableMap is part of engine.DataProvider interface -func (hU *httpXmlDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of engine.DataProvider interface func (hU *httpXmlDP) RemoteHost() net.Addr { return utils.NewNetAddr("TCP", hU.addr) @@ -202,7 +190,7 @@ func (hU *httpXmlDP) RemoteHost() net.Addr { // httpAgentReplyEncoder will encode []*engine.NMElement // and write content to http writer type httpAgentReplyEncoder interface { - Encode(*config.NavigableMap) error + Encode(*utils.OrderedNavigableMap) error } // newHAReplyEncoder constructs a httpAgentReqDecoder based on encoder type @@ -227,9 +215,9 @@ type haXMLEncoder struct { } // Encode implements httpAgentReplyEncoder -func (xE *haXMLEncoder) Encode(nM *config.NavigableMap) (err error) { +func (xE *haXMLEncoder) Encode(nM *utils.OrderedNavigableMap) (err error) { var xmlElmnts []*config.XMLElement - if xmlElmnts, err = nM.AsXMLElements(); err != nil { + if xmlElmnts, err = config.NMAsXMLElements(nM); err != nil { return } if len(xmlElmnts) == 0 { @@ -255,23 +243,21 @@ type haTextPlainEncoder struct { } // Encode implements httpAgentReplyEncoder -func (xE *haTextPlainEncoder) Encode(nM *config.NavigableMap) (err error) { +func (xE *haTextPlainEncoder) Encode(nM *utils.OrderedNavigableMap) (err error) { var str, nmPath string msgFields := make(map[string]string) // work around to NMap issue - for _, val := range nM.Values() { - nmItms, isNMItems := val.([]*config.NMItem) + for el := nM.GetFirstElement(); el != nil; el = el.Next() { + val := el.Value + var nmIt utils.NMInterface + if nmIt, err = nM.Field(val); err != nil { + return + } + nmItem, isNMItems := nmIt.(*config.NMItem) if !isNMItems { - return fmt.Errorf("value: %+v is not []*NMItem", val) - } - if len(nmItms) == 0 { - continue - } - for i, nmItem := range nmItms { - if i == 0 { // compose the path only 1 time - nmPath = strings.Join(nmItem.Path, utils.NestingSep) - } - msgFields[utils.ConcatenatedKey(nmPath, utils.IfaceAsString(nmItem.Data))] = utils.IfaceAsString(nmItem.Data) + return fmt.Errorf("value: %s is not *NMItem", val) } + nmPath = strings.Join(nmItem.Path, utils.NestingSep) + msgFields[utils.ConcatenatedKey(nmPath, utils.IfaceAsString(nmItem.Data))] = utils.IfaceAsString(nmItem.Data) } for key, val := range msgFields { str += fmt.Sprintf("%s=%s\n", strings.Split(key, utils.InInFieldSep)[0], val) diff --git a/agents/librad.go b/agents/librad.go index b23f1301e..c53c955fd 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -28,31 +28,32 @@ import ( ) // radReplyAppendAttributes appends attributes to a RADIUS reply based on predefined template -func radReplyAppendAttributes(reply *radigo.Packet, rplNM *config.NavigableMap) (err error) { - for _, val := range rplNM.Values() { - nmItms, isNMItems := val.([]*config.NMItem) - if !isNMItems { - return fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val)) +func radReplyAppendAttributes(reply *radigo.Packet, rplNM *utils.OrderedNavigableMap) (err error) { + for el := rplNM.GetFirstElement(); el != nil; el = el.Next() { + val := el.Value + var nmIt utils.NMInterface + if nmIt, err = rplNM.Field(val); err != nil { + return } - // find out the first itm which is not an attribute - var itm *config.NMItem - if len(nmItms) == 1 { - itm = nmItms[0] + cfgItm, cast := nmIt.(*config.NMItem) + if !cast { + return fmt.Errorf("cannot cast val: %s into *config.NMItem", nmIt) } - if itm.Path[0] == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply - if err = reply.SetCodeWithName(utils.IfaceAsString(itm.Data)); err != nil { + + if cfgItm.Path[0] == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply + if err = reply.SetCodeWithName(utils.IfaceAsString(cfgItm.Data)); err != nil { return err } continue } var attrName, vendorName string - if len(itm.Path) > 2 { - vendorName, attrName = itm.Path[0], itm.Path[1] + if len(cfgItm.Path) > 2 { + vendorName, attrName = cfgItm.Path[0], cfgItm.Path[1] } else { - attrName = itm.Path[0] + attrName = cfgItm.Path[0] } - if err = reply.AddAVPWithName(attrName, utils.IfaceAsString(itm.Data), vendorName); err != nil { + if err = reply.AddAVPWithName(attrName, utils.IfaceAsString(cfgItm.Data), vendorName); err != nil { return err } } @@ -108,12 +109,6 @@ func (pk *radiusDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// AsNavigableMap is part of engine.DataProvider interface -func (pk *radiusDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of engine.DataProvider interface func (pk *radiusDP) RemoteHost() net.Addr { return utils.NewNetAddr(pk.req.RemoteAddr().Network(), pk.req.RemoteAddr().String()) diff --git a/agents/librad_test.go b/agents/librad_test.go index 33fd4bd0d..bfa4d538f 100644 --- a/agents/librad_test.go +++ b/agents/librad_test.go @@ -79,17 +79,20 @@ func init() { func TestRadReplyAppendAttributes(t *testing.T) { rply := radigo.NewPacket(radigo.AccessRequest, 2, dictRad, coder, "CGRateS.org").Reply() rplyFlds := []*config.FCTemplate{ - &config.FCTemplate{Tag: "ReplyCode", Path: utils.MetaRep + utils.NestingSep + MetaRadReplyCode, + {Tag: "ReplyCode", Path: utils.MetaRep + utils.NestingSep + MetaRadReplyCode, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgrep.Attributes.RadReply", true, utils.INFIELD_SEP)}, - &config.FCTemplate{Tag: "Acct-Session-Time", Path: utils.MetaRep + utils.NestingSep + "Acct-Session-Time", + {Tag: "Acct-Session-Time", Path: utils.MetaRep + utils.NestingSep + "Acct-Session-Time", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP)}, } + for _, v := range rplyFlds { + v.ComputePath() + } agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", nil, nil, nil) - agReq.CGRReply.Set([]string{utils.CapMaxUsage}, time.Duration(time.Hour), false, false) - agReq.CGRReply.Set([]string{utils.CapAttributes, "RadReply"}, "AccessAccept", false, false) - agReq.CGRReply.Set([]string{utils.CapAttributes, utils.Account}, "1001", false, false) + agReq.CGRReply.Set(utils.NewPathToItem([]string{utils.CapMaxUsage}), utils.NewNMData(time.Duration(time.Hour))) + agReq.CGRReply.Set(utils.NewPathToItem([]string{utils.CapAttributes, "RadReply"}), utils.NewNMData("AccessAccept")) + agReq.CGRReply.Set(utils.NewPathToItem([]string{utils.CapAttributes, utils.Account}), utils.NewNMData("1001")) if err := agReq.SetFields(rplyFlds); err != nil { t.Error(err) diff --git a/agents/radagent.go b/agents/radagent.go index 0f87cb517..4c5e6ae40 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -75,23 +75,22 @@ type RadiusAgent struct { // handleAuth handles RADIUS Authorization request func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err error) { - reqVars := make(map[string]interface{}) req.SetAVPValues() // populate string values in AVPs dcdr := newRADataProvider(req) // dcdr will provide information from request rpl = req.Reply() rpl.Code = radigo.AccessAccept - cgrRplyNM := config.NewNavigableMap(nil) - rplyNM := config.NewNavigableMap(nil) - opts := config.NewNavigableMap(nil) + cgrRplyNM := utils.NavigableMap2{} + rplyNM := utils.NewOrderedNavigableMap() + opts := utils.NewOrderedNavigableMap() var processed bool - reqVars[utils.RemoteHost] = req.RemoteAddr().String() + reqVars := utils.NavigableMap2{utils.RemoteHost: utils.NewNMData(req.RemoteAddr().String())} for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, + agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), ra.filterS, nil, nil) - agReq.Vars.Set([]string{MetaRadReqType}, utils.StringToInterface(MetaRadAuth), false, true) + agReq.Vars.Set(utils.PathItems{{Field: MetaRadReqType}}, utils.NewNMData(MetaRadAuth)) var lclProcessed bool if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq, rpl); lclProcessed { processed = lclProcessed @@ -121,18 +120,17 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e // handleAcct handles RADIUS Accounting request // supports: Acct-Status-Type = Start, Interim-Update, Stop func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err error) { - reqVars := make(map[string]interface{}) req.SetAVPValues() // populate string values in AVPs dcdr := newRADataProvider(req) // dcdr will provide information from request rpl = req.Reply() rpl.Code = radigo.AccountingResponse - cgrRplyNM := config.NewNavigableMap(nil) - rplyNM := config.NewNavigableMap(nil) - opts := config.NewNavigableMap(nil) + cgrRplyNM := utils.NavigableMap2{} + rplyNM := utils.NewOrderedNavigableMap() + opts := utils.NewOrderedNavigableMap() var processed bool - reqVars[utils.RemoteHost] = req.RemoteAddr().String() + reqVars := utils.NavigableMap2{utils.RemoteHost: utils.NewNMData(req.RemoteAddr().String())} for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, + agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), @@ -172,8 +170,8 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep) - opts := agReq.Opts.GetData() + cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep) + opts := config.NMAsMapInterface(agReq.Opts, utils.NestingSep) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, @@ -309,7 +307,6 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R Flags: reqProcessor.Flags.SliceFlags(), CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher, - } needMaxUsage := reqProcessor.Flags.HasKey(utils.MetaAuth) || reqProcessor.Flags.HasKey(utils.MetaInit) || @@ -328,9 +325,9 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R case utils.MetaCDRs: // allow this method case utils.MetaRadauth: if pass, err := radauthReq(reqProcessor.Flags, req, agReq, rpl); err != nil { - agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) } else if !pass { - agReq.CGRReply.Set([]string{utils.Error}, utils.RadauthFailed, false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(utils.RadauthFailed)) } } // separate request so we can capture the Terminate/Event also here @@ -340,7 +337,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R &utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, rplyCDRs); err != nil { - agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false) + agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) } } diff --git a/config/fwvdp.go b/config/fwvdp.go index 3b7cf6b67..1ab306333 100644 --- a/config/fwvdp.go +++ b/config/fwvdp.go @@ -89,12 +89,6 @@ func (fP *FWVProvider) FieldAsString(fldPath []string) (data string, err error) return utils.IfaceAsString(valIface), nil } -// 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.utils.DataProvider interface func (fP *FWVProvider) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/config/navigablemap.go b/config/navigablemap.go index f9f48b701..499f35744 100644 --- a/config/navigablemap.go +++ b/config/navigablemap.go @@ -409,12 +409,6 @@ func (nM *NavigableMap) Values() (vals []interface{}) { return } -// AsNavigableMap implements both NavigableMapper as well as utils.DataProvider interfaces -func (nM *NavigableMap) AsNavigableMap( - tpl []*FCTemplate) (oNM *NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // Merge will update nM with values from a second one func (nM *NavigableMap) Merge(nM2 *NavigableMap) { if nM2 == nil { @@ -733,3 +727,151 @@ func (nM *NavigableMap) GetData() (mp map[string]interface{}) { } return } + +// NMAsXMLElements returns the values as []*XMLElement which can be later marshaled +// considers each value returned by .Values() in the form of []*NMItem, otherwise errors +func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err error) { + pathIdx := make(map[string]*XMLElement) // Keep the index of elements based on path + for el := nm.GetFirstElement(); el != nil; el = el.Next() { + path := el.Value + var nmIt utils.NMInterface + if nmIt, err = nm.Field(path); err != nil { + return + } + nmItm, isNMItem := nmIt.(*NMItem) + if !isNMItem { + return nil, fmt.Errorf("value: %+v is not []*NMItem", path) + } + if nmItm.Config != nil && nmItm.Config.NewBranch { + pathIdx = make(map[string]*XMLElement) // reset cache so we can start having other elements with same path + } + val := utils.IfaceAsString(nmItm.Data) + var pathCached bool + for i := len(nmItm.Path); i > 0; i-- { + var cachedElm *XMLElement + if cachedElm, pathCached = pathIdx[strings.Join(nmItm.Path[:i], "")]; !pathCached { + continue + } + if i == len(nmItm.Path) { // lastElmnt, overwrite value or add attribute + if nmItm.Config != nil && + nmItm.Config.AttributeID != "" { + cachedElm.Attributes = append(cachedElm.Attributes, + &xml.Attr{ + Name: xml.Name{Local: nmItm.Config.AttributeID}, + Value: val, + }) + } else { + cachedElm.Value = val + } + break + } + // create elements in reverse order so we can append already created + var newElm *XMLElement + for j := len(nmItm.Path); j > i; j-- { + elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[j-1]}} + pathIdx[strings.Join(nmItm.Path[:j], "")] = elm + if newElm == nil { + if nmItm.Config != nil && + nmItm.Config.AttributeID != "" { + elm.Attributes = append(elm.Attributes, + &xml.Attr{ + Name: xml.Name{Local: nmItm.Config.AttributeID}, + Value: val, + }) + } else { + elm.Value = val + } + newElm = elm // last element + } else { + elm.Elements = append(elm.Elements, newElm) + newElm = elm + } + } + cachedElm.Elements = append(cachedElm.Elements, newElm) + } + if !pathCached { // not an update but new element to be created + var newElm *XMLElement + for i := len(nmItm.Path); i > 0; i-- { + elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[i-1]}} + pathIdx[strings.Join(nmItm.Path[:i], "")] = elm + if newElm == nil { // last element, create data inside + if nmItm.Config != nil && + nmItm.Config.AttributeID != "" { + elm.Attributes = append(elm.Attributes, + &xml.Attr{ + Name: xml.Name{Local: nmItm.Config.AttributeID}, + Value: val, + }) + } else { + elm.Value = val + } + newElm = elm // last element + } else { + elm.Elements = append(elm.Elements, newElm) + newElm = elm + } + } + ents = append(ents, newElm) + } + } + return +} + +// NMAsCGREvent builds a CGREvent considering Time as time.Now() +// and Event as linear map[string]interface{} with joined paths +// treats particular case when the value of map is []*NMItem - used in agents/AgentRequest +func NMAsCGREvent(nM *utils.OrderedNavigableMap, tnt string, pathSep string) (cgrEv *utils.CGREvent) { + if nM == nil { + return + } + el := nM.GetFirstElement() + if el == nil { + return + } + cgrEv = &utils.CGREvent{ + Tenant: tnt, + ID: utils.UUIDSha1Prefix(), + Time: utils.TimePointer(time.Now()), + Event: make(map[string]interface{}), + } + for ; el != nil; el = el.Next() { + branchPath := el.Value + val, _ := nM.Field(branchPath) // this should never return error cause we get the path from the order + opath := utils.GetPathWithoutIndex(branchPath.String()) + if nmItm, isNMItem := val.(*NMItem); isNMItem { // special case when we have added multiple items inside a key, used in agents + if nmItm.Config != nil && + nmItm.Config.AttributeID != "" { + continue + } + } + if _, has := cgrEv.Event[opath]; !has { + cgrEv.Event[opath] = val.Interface() // first item which is not an attribute will become the value + } + } + return +} + +// NMAsMapInterface builds a linear map[string]interface{} with joined paths +// treats particular case when the value of map is []*NMItem - used in agents/AgentRequest +func NMAsMapInterface(nM *utils.OrderedNavigableMap, pathSep string) (mp map[string]interface{}) { + mp = make(map[string]interface{}) + el := nM.GetFirstElement() + if el == nil { + return + } + for ; el != nil; el = el.Next() { + branchPath := el.Value + val, _ := nM.Field(branchPath) // this should never return error cause we get the path from the order + opath := utils.GetPathWithoutIndex(branchPath.String()) + if nmItm, isNMItem := val.(*NMItem); isNMItem { // special case when we have added multiple items inside a key, used in agents + if nmItm.Config != nil && + nmItm.Config.AttributeID != "" { + continue + } + } + if _, has := mp[opath]; !has { + mp[opath] = val.Interface() // first item which is not an attribute will become the value + } + } + return +} diff --git a/config/navigablemap_test.go b/config/navigablemap_test.go index 6ac2a28eb..19dadf7b9 100644 --- a/config/navigablemap_test.go +++ b/config/navigablemap_test.go @@ -64,8 +64,8 @@ func TestNavMapGetFieldAsString(t *testing.T) { type myEv map[string]interface{} -func (ev myEv) AsNavigableMap() (*NavigableMap, error) { - return NewNavigableMap(ev), nil +func (ev myEv) AsNavigableMap() *NavigableMap { + return NewNavigableMap(ev) } func TestNavMapAsNavigableMap(t *testing.T) { @@ -111,7 +111,7 @@ func TestNavMapAsNavigableMap(t *testing.T) { }, } - if rcv, err := myData.AsNavigableMap(); err != nil { + if rcv := myData.AsNavigableMap(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eNavMap.data, rcv.data) { t.Errorf("Expecting: %+v, received: %+v", eNavMap.data, rcv.data) diff --git a/config/objdp.go b/config/objdp.go index 2e48dd7cf..567ea02f9 100644 --- a/config/objdp.go +++ b/config/objdp.go @@ -119,12 +119,6 @@ func (objDP *ObjectDP) FieldAsString(fldPath []string) (data string, err error) return utils.IfaceAsString(valIface), nil } -// 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.utils.DataProvider interface func (objDP *ObjectDP) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/config/slicedp.go b/config/slicedp.go index ecf70f20a..7dac8430e 100644 --- a/config/slicedp.go +++ b/config/slicedp.go @@ -79,12 +79,6 @@ func (cP *SliceDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// 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.utils.DataProvider interface func (cP *SliceDP) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/config/xmldp.go b/config/xmldp.go index 508c9681e..13bf8549a 100644 --- a/config/xmldp.go +++ b/config/xmldp.go @@ -91,12 +91,6 @@ func (xP *XmlProvider) FieldAsString(fldPath []string) (data string, err error) return utils.IfaceAsString(valIface), nil } -// 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.utils.DataProvider interface func (xP *XmlProvider) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/engine/account.go b/engine/account.go index f543e90d8..9795a593f 100644 --- a/engine/account.go +++ b/engine/account.go @@ -1139,30 +1139,6 @@ func (acc *Account) Publish() { } } -// AsNavigableMap converts the Account to NavigableMap -func (acc *Account) AsNavigableMap(_ []*config.FCTemplate) (*config.NavigableMap, error) { - mpIface := map[string]interface{}{ - "ID": acc.ID, - //"UnitCounters": acnt.UnitCounters, - "ActionTriggers": acc.ActionTriggers, - "AllowNegative": acc.AllowNegative, - "Disabled": acc.Disabled, - } - - balanceMap := make(map[string]interface{}, len(acc.BalanceMap)) - for key, balances := range acc.BalanceMap { - balSls := make([]*config.NavigableMap, len(balances)) - for i, balance := range balances { - balSls[i], _ = balance.AsNavigableMap(nil) - } - balanceMap[key] = balSls - } - mpIface["BalanceMap"] = balanceMap - - return config.NewNavigableMap(mpIface), nil - -} - // NewAccountSummaryFromJSON creates a new AcccountSummary from a json string func NewAccountSummaryFromJSON(jsn string) (acntSummary *AccountSummary, err error) { if !utils.SliceHasMember([]string{"", "null"}, jsn) { // Unmarshal only when content diff --git a/engine/account_test.go b/engine/account_test.go index b4d5d6daf..473b83b2e 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -2272,54 +2272,6 @@ func TestAccountGetMultipleBalancesForPrefixWithSameWeight(t *testing.T) { } } -func TestAccountAsNavigableMap(t *testing.T) { - acc := &Account{ - BalanceMap: map[string]Balances{ - utils.MONETARY: Balances{ - &Balance{ - ID: "SpecialBalance1", - Value: 10, - Weight: 10.0, - }, - &Balance{ - ID: "SpecialBalance2", - Value: 10, - Weight: 10.0, - }, - }, - }, - } - nM, _ := acc.AsNavigableMap(nil) - eVal := "SpecialBalance1" - if strVal, err := nM.FieldAsString( - []string{"BalanceMap", "*monetary[0]", "ID"}); err != nil { - t.Error(err) - } else if strVal != eVal { - t.Errorf("expecting: <%+v> received: <%+v>", eVal, strVal) - } - eVal = "10" - if strVal, err := nM.FieldAsString( - []string{"BalanceMap", "*monetary[0]", "Value"}); err != nil { - t.Error(err) - } else if strVal != eVal { - t.Errorf("expecting: <%+v> received: <%+v>", eVal, strVal) - } - eVal = "10" - if strVal, err := nM.FieldAsString( - []string{"BalanceMap", "*monetary[0]", "Weight"}); err != nil { - t.Error(err) - } else if strVal != eVal { - t.Errorf("expecting: <%+v> received: <%+v>", eVal, strVal) - } - eVal = "SpecialBalance2" - if strVal, err := nM.FieldAsString( - []string{"BalanceMap", "*monetary[1]", "ID"}); err != nil { - t.Error(err) - } else if strVal != eVal { - t.Errorf("expecting: <%+v> received: <%+v>", eVal, strVal) - } -} - func TestAccountClone(t *testing.T) { account := &Account{} eOut := &Account{} diff --git a/engine/action.go b/engine/action.go index 6305427bc..74bed805d 100644 --- a/engine/action.go +++ b/engine/action.go @@ -977,12 +977,6 @@ func (cdrP *cdrLogProvider) FieldAsString(fldPath []string) (data string, err er return utils.IfaceAsString(valIface), nil } -// AsNavigableMap is part of engine.DataProvider interface -func (cdrP *cdrLogProvider) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of engine.DataProvider interface func (cdrP *cdrLogProvider) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/engine/balances.go b/engine/balances.go index e111622d2..22e4cd761 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -185,25 +185,6 @@ func (b *Balance) Clone() *Balance { return n } -func (b *Balance) AsNavigableMap(_ []*config.FCTemplate) (*config.NavigableMap, error) { - return config.NewNavigableMap(map[string]interface{}{ - "Uuid": b.Uuid, - "ID": b.ID, - "Value": b.Value, - "ExpirationDate": b.ExpirationDate, - "Weight": b.Weight, - "DestinationIDs": b.DestinationIDs, - "RatingSubject": b.RatingSubject, - "Categories": b.Categories, - "SharedGroups": b.SharedGroups, - "Timings": b.Timings, - "TimingIDs": b.TimingIDs, - "Disabled": b.Disabled, - "Factor": b.Factor, - "Blocker": b.Blocker, - }), nil -} - func (b *Balance) getMatchingPrefixAndDestID(dest string) (prefix, destId string) { if len(b.DestinationIDs) != 0 && b.DestinationIDs[utils.ANY] == false { for _, p := range utils.SplitPrefix(dest, MIN_PREFIX_MATCH) { diff --git a/engine/calldesc.go b/engine/calldesc.go index ba63f4b41..536b7c97c 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -1051,11 +1051,6 @@ func (cd *CallDescriptor) String() string { return utils.ToJSON(cd) } -// AsNavigableMap is part of utils.DataProvider -func (cd *CallDescriptor) AsNavigableMap(tpl []*config.FCTemplate) (nM *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of utils.DataProvider func (cd *CallDescriptor) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/engine/eventcost.go b/engine/eventcost.go index abb6d7525..1a9725762 100644 --- a/engine/eventcost.go +++ b/engine/eventcost.go @@ -1080,11 +1080,6 @@ func (ec *EventCost) FieldAsString(fldPath []string) (string, error) { return utils.IfaceAsString(ival), nil } -// AsNavigableMap to implement Dataprovider -func (ec *EventCost) AsNavigableMap([]*config.FCTemplate) (*config.NavigableMap, error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost to implement Dataprovider func (ec *EventCost) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/engine/filters.go b/engine/filters.go index a28b4798b..5e5c56ae5 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -543,9 +543,7 @@ func (dDP *dynamicDP) FieldAsString(fldPath []string) (string, error) { } return utils.IfaceAsString(val), nil } -func (dDP *dynamicDP) AsNavigableMap([]*config.FCTemplate) (*config.NavigableMap, error) { - return nil, utils.ErrNotImplemented -} + func (dDP *dynamicDP) RemoteHost() net.Addr { return utils.LocalAddr() } diff --git a/engine/libroutes.go b/engine/libroutes.go index ec529e024..a77cda81f 100644 --- a/engine/libroutes.go +++ b/engine/libroutes.go @@ -23,7 +23,6 @@ import ( "sort" "strings" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -162,22 +161,30 @@ func (sSpls *SortedRoutes) Digest() string { return strings.Join(sSpls.RoutesWithParams(), utils.FIELDS_SEP) } -func (sSpls *SortedRoutes) AsNavigableMap() (nm *config.NavigableMap) { - mp := map[string]interface{}{ - utils.ProfileID: sSpls.ProfileID, - utils.Sorting: sSpls.Sorting, - utils.Count: sSpls.Count, +func (ss *SortedRoute) AsNavigableMap() (nm utils.NavigableMap2) { + nm = utils.NavigableMap2{ + utils.RouteID: utils.NewNMData(ss.RouteID), + utils.RouteParameters: utils.NewNMData(ss.RouteParameters), } - sr := make([]map[string]interface{}, len(sSpls.SortedRoutes)) + sd := utils.NavigableMap2{} + for k, d := range ss.SortingData { + sd[k] = utils.NewNMData(d) + } + nm[utils.SortingData] = sd + return +} +func (sSpls *SortedRoutes) AsNavigableMap() (nm utils.NavigableMap2) { + nm = utils.NavigableMap2{ + utils.ProfileID: utils.NewNMData(sSpls.ProfileID), + utils.Sorting: utils.NewNMData(sSpls.Sorting), + utils.Count: utils.NewNMData(sSpls.Count), + } + sr := make(utils.NMSlice, len(sSpls.SortedRoutes)) for i, ss := range sSpls.SortedRoutes { - sr[i] = map[string]interface{}{ - utils.RouteID: ss.RouteID, - utils.RouteParameters: ss.RouteParameters, - utils.SortingData: ss.SortingData, - } + sr[i] = ss.AsNavigableMap() } - mp[utils.SortedRoutes] = sr - return config.NewNavigableMap(mp) + nm[utils.SortedRoutes] = &sr + return } // RoutesSorter is the interface which needs to be implemented by routes sorters diff --git a/engine/mapevent.go b/engine/mapevent.go index 5eda54077..347605b5f 100644 --- a/engine/mapevent.go +++ b/engine/mapevent.go @@ -60,10 +60,6 @@ func (me MapEvent) FieldAsString(fldPath []string) (string, error) { return me.GetString(fldPath[0]) } -func (me MapEvent) AsNavigableMap([]*config.FCTemplate) (*config.NavigableMap, error) { - return config.NewNavigableMap(me), nil -} - func (me MapEvent) RemoteHost() net.Addr { return utils.LocalAddr() } diff --git a/engine/mapevent_test.go b/engine/mapevent_test.go index 1184c388b..59bf3896c 100644 --- a/engine/mapevent_test.go +++ b/engine/mapevent_test.go @@ -95,14 +95,6 @@ func TestMapEventFieldAsString(t *testing.T) { } } -func TestMapEventAsNavigableMap(t *testing.T) { - 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) - } -} - func TestMapEventRemoteHost(t *testing.T) { data := utils.DataProvider(mapEv) if rply, expected := data.RemoteHost(), utils.LocalAddr(); !reflect.DeepEqual(expected, rply) { diff --git a/engine/safevent.go b/engine/safevent.go index 7892b0586..02f02fdd9 100644 --- a/engine/safevent.go +++ b/engine/safevent.go @@ -70,13 +70,6 @@ func (se *SafEvent) FieldAsString(fldPath []string) (out string, err error) { return } -func (se *SafEvent) AsNavigableMap(fctemplate []*config.FCTemplate) (out *config.NavigableMap, err error) { - se.RLock() - out, err = se.Me.AsNavigableMap(fctemplate) - se.RUnlock() - return -} - func (se *SafEvent) RemoteHost() (out net.Addr) { se.RLock() out = se.Me.RemoteHost() diff --git a/engine/safevent_test.go b/engine/safevent_test.go index 265c1e340..ed1760aae 100644 --- a/engine/safevent_test.go +++ b/engine/safevent_test.go @@ -92,14 +92,6 @@ func TestSafEventFieldAsString(t *testing.T) { } } -func TestSafEventAsNavigableMap(t *testing.T) { - 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) - } -} - func TestSafEventRemoteHost(t *testing.T) { data := utils.DataProvider(safEv) if rply, expected := data.RemoteHost(), utils.LocalAddr(); !reflect.DeepEqual(expected, rply) { diff --git a/engine/task.go b/engine/task.go index 9635ce23d..ec8c8ef29 100644 --- a/engine/task.go +++ b/engine/task.go @@ -22,7 +22,6 @@ import ( "net" "strings" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -46,15 +45,6 @@ func (t *Task) String() string { return utils.ToJSON(t) } -// 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) - nm.Set([]string{utils.AccountID}, t.AccountID, false, false) - nm.Set([]string{utils.ActionsID}, t.ActionsID, false, false) - return -} - // FieldAsInterface implements utils.DataProvider // ToDo: support Action fields func (t *Task) FieldAsInterface(fldPath []string) (iface interface{}, err error) { diff --git a/engine/task_test.go b/engine/task_test.go index 67c246e99..1d515adad 100644 --- a/engine/task_test.go +++ b/engine/task_test.go @@ -23,7 +23,6 @@ import ( "reflect" "testing" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -40,38 +39,6 @@ func TestTaskString(t *testing.T) { } } -func TestTaskAsMavigableMap(t *testing.T) { - //empty check - task := new(Task) - eOut := config.NewNavigableMap(nil) - eOut.Set([]string{utils.UUID}, "", false, false) - eOut.Set([]string{utils.AccountID}, "", false, false) - eOut.Set([]string{utils.ActionsID}, "", false, false) - rcv, err := task.AsNavigableMap(nil) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %q, received: %q", eOut, rcv) - } - //normal check - task = &Task{ - Uuid: "test", - AccountID: "test2", - ActionsID: "test3", - } - eOut.Set([]string{utils.UUID}, "test", false, false) - eOut.Set([]string{utils.AccountID}, "test2", false, false) - eOut.Set([]string{utils.ActionsID}, "test3", false, false) - rcv, err = task.AsNavigableMap(nil) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %q, received: %q", eOut, rcv) - } -} - func TestTaskFieldAsinterface(t *testing.T) { //empty check task := new(Task) diff --git a/ers/filecsv.go b/ers/filecsv.go index b39c06f3f..0c3d2344e 100644 --- a/ers/filecsv.go +++ b/ers/filecsv.go @@ -139,7 +139,7 @@ func (rdr *CSVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} for { var record []string if record, err = csvReader.Read(); err != nil { @@ -167,9 +167,9 @@ func (rdr *CSVFileER) processFile(fPath, fName string) (err error) { continue } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ } diff --git a/ers/filefwv.go b/ers/filefwv.go index 7295d3ecb..7cdbd2969 100644 --- a/ers/filefwv.go +++ b/ers/filefwv.go @@ -139,7 +139,7 @@ func (rdr *FWVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} for { var hasHeader, hasTrailer bool @@ -212,9 +212,9 @@ func (rdr *FWVFileER) processFile(fPath, fName string) (err error) { } rdr.offset += rdr.lineLen // increase the offset rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ @@ -281,10 +281,9 @@ func (rdr *FWVFileER) processTrailer(file *os.File, rowNr, evsPosted int, absPat return fmt.Errorf("In trailer, line len: %d, have read: %d instead of: %d", rdr.trailerOffset, nRead, len(buf)) } record := string(buf) - reqVars := make(map[string]interface{}) rdr.trailerDP = config.NewFWVProvider(record) agReq := agents.NewAgentRequest( - nil, reqVars, nil, nil, nil, + nil, nil, nil, nil, nil, rdr.Config().Tenant, rdr.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(rdr.Config().Timezone, @@ -301,9 +300,9 @@ func (rdr *FWVFileER) processTrailer(file *os.File, rowNr, evsPosted int, absPat return err } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ // reset the cursor after process the trailer @@ -322,10 +321,9 @@ func (rdr *FWVFileER) processHeader(file *os.File, rowNr, evsPosted int, absPath } func (rdr *FWVFileER) createHeaderMap(record string, rowNr, evsPosted int, absPath string, hdrFields []*config.FCTemplate) (err error) { - reqVars := make(map[string]interface{}) rdr.headerDP = config.NewFWVProvider(record) agReq := agents.NewAgentRequest( - nil, reqVars, nil, nil, nil, + nil, nil, nil, nil, nil, rdr.Config().Tenant, rdr.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(rdr.Config().Timezone, @@ -344,9 +342,9 @@ func (rdr *FWVFileER) createHeaderMap(record string, rowNr, evsPosted int, absPa } rdr.offset += rdr.headerOffset // increase the offset rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ return diff --git a/ers/filejson.go b/ers/filejson.go index 71be30708..2afacbf17 100644 --- a/ers/filejson.go +++ b/ers/filejson.go @@ -140,7 +140,7 @@ func (rdr *JSONFileER) processFile(fPath, fName string) (err error) { } evsPosted := 0 - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} agReq := agents.NewAgentRequest( config.NewNavigableMap(data), reqVars, @@ -160,9 +160,9 @@ func (rdr *JSONFileER) processFile(fPath, fName string) (err error) { return } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ diff --git a/ers/filexml.go b/ers/filexml.go index caf869ef0..17c341a0d 100644 --- a/ers/filexml.go +++ b/ers/filexml.go @@ -137,7 +137,7 @@ func (rdr *XMLFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} for _, xmlElmt := range xmlElmts { rowNr++ // increment the rowNr after checking if it's not the end of file agReq := agents.NewAgentRequest( @@ -158,9 +158,9 @@ func (rdr *XMLFileER) processFile(fPath, fName string) (err error) { continue } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ } diff --git a/ers/flatstore.go b/ers/flatstore.go index 9dd3fdc02..5520505ac 100644 --- a/ers/flatstore.go +++ b/ers/flatstore.go @@ -146,7 +146,7 @@ func (rdr *FlatstoreER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} for { var record []string if record, err = csvReader.Read(); err != nil { @@ -207,9 +207,9 @@ func (rdr *FlatstoreER) processFile(fPath, fName string) (err error) { } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ } diff --git a/ers/kafka.go b/ers/kafka.go index c923f3f69..7709f6802 100644 --- a/ers/kafka.go +++ b/ers/kafka.go @@ -158,9 +158,8 @@ func (rdr *KafkaER) processMessage(msg []byte) (err error) { return } - reqVars := make(map[string]interface{}) agReq := agents.NewAgentRequest( - config.NewNavigableMap(decodedMessage), reqVars, + config.NewNavigableMap(decodedMessage), nil, nil, nil, nil, rdr.Config().Tenant, rdr.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(rdr.Config().Timezone, @@ -175,9 +174,9 @@ func (rdr *KafkaER) processMessage(msg []byte) (err error) { return } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } return } diff --git a/ers/partial_csv.go b/ers/partial_csv.go index bcbfec9d4..d83765858 100644 --- a/ers/partial_csv.go +++ b/ers/partial_csv.go @@ -158,7 +158,7 @@ func (rdr *PartialCSVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := map[string]interface{}{utils.FileName: fName} + reqVars := utils.NavigableMap2{utils.FileName: utils.NewNMData(fName)} for { var record []string if record, err = csvReader.Read(); err != nil { @@ -207,23 +207,23 @@ func (rdr *PartialCSVFileER) processFile(fPath, fName string) (err error) { if val, has := rdr.cache.Get(cgrID); !has { if utils.IsSliceMember([]string{"false", utils.EmptyString}, partial) { // complete CDR rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } evsPosted++ } else { rdr.cache.Set(cgrID, []*cgrEventWithOpts{{ - CGREvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), - Opts: agReq.Opts.GetData(), + CGREvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), + Opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), }}, nil) } } else { origCgrEvs := val.([]*cgrEventWithOpts) origCgrEvs = append(origCgrEvs, &cgrEventWithOpts{ - CGREvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), - Opts: agReq.Opts.GetData(), + CGREvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), + Opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), }) if utils.IsSliceMember([]string{"false", utils.EmptyString}, partial) { // complete CDR //sort CGREvents based on AnswertTime and SetupTime diff --git a/ers/sql.go b/ers/sql.go index 7b2e9579f..e47d11744 100644 --- a/ers/sql.go +++ b/ers/sql.go @@ -185,9 +185,8 @@ func (rdr *SQLEventReader) readLoop(db *gorm.DB) { } func (rdr *SQLEventReader) processMessage(msg map[string]interface{}) (err error) { - reqVars := make(map[string]interface{}) agReq := agents.NewAgentRequest( - config.NewNavigableMap(msg), reqVars, + config.NewNavigableMap(msg), nil, nil, nil, nil, rdr.Config().Tenant, rdr.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(rdr.Config().Timezone, @@ -202,9 +201,9 @@ func (rdr *SQLEventReader) processMessage(msg map[string]interface{}) (err error return } rdr.rdrEvents <- &erEvent{ - cgrEvent: agReq.CGRRequest.AsCGREvent(agReq.Tenant, utils.NestingSep), + cgrEvent: config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep), rdrCfg: rdr.Config(), - opts: agReq.Opts.GetData(), + opts: config.NMAsMapInterface(agReq.Opts, utils.NestingSep), } return } diff --git a/loaders/libloader.go b/loaders/libloader.go index 8985d0c12..57632db41 100644 --- a/loaders/libloader.go +++ b/loaders/libloader.go @@ -139,12 +139,6 @@ func (cP *csvProvider) FieldAsString(fldPath []string) (data string, err error) return utils.IfaceAsString(valIface), nil } -// AsNavigableMap is part of engine.DataProvider interface -func (cP *csvProvider) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - // RemoteHost is part of engine.DataProvider interface func (cP *csvProvider) RemoteHost() net.Addr { return utils.LocalAddr() diff --git a/sessions/sessions.go b/sessions/sessions.go index 00bc553a0..fcdb18425 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -1797,37 +1797,44 @@ type V1AuthorizeReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1AuthReply *V1AuthorizeReply) AsNavigableMap( - ignr []*config.FCTemplate) (*config.NavigableMap, error) { - cgrReply := make(map[string]interface{}) +func (v1AuthReply *V1AuthorizeReply) AsNavigableMap() utils.NavigableMap2 { + cgrReply := make(utils.NavigableMap2) if v1AuthReply != nil { if v1AuthReply.Attributes != nil { - attrs := make(map[string]interface{}) + attrs := make(utils.NavigableMap2) for _, fldName := range v1AuthReply.Attributes.AlteredFields { fldName = strings.TrimPrefix(fldName, utils.MetaReq+utils.NestingSep) if v1AuthReply.Attributes.CGREvent.HasField(fldName) { - attrs[fldName] = v1AuthReply.Attributes.CGREvent.Event[fldName] + attrs[fldName] = utils.NewNMData(v1AuthReply.Attributes.CGREvent.Event[fldName]) } } cgrReply[utils.CapAttributes] = attrs } if v1AuthReply.ResourceAllocation != nil { - cgrReply[utils.CapResourceAllocation] = *v1AuthReply.ResourceAllocation + cgrReply[utils.CapResourceAllocation] = utils.NewNMData(*v1AuthReply.ResourceAllocation) } if v1AuthReply.MaxUsage != nil { - cgrReply[utils.CapMaxUsage] = *v1AuthReply.MaxUsage + cgrReply[utils.CapMaxUsage] = utils.NewNMData(*v1AuthReply.MaxUsage) } if v1AuthReply.Routes != nil { cgrReply[utils.CapRoutes] = v1AuthReply.Routes.AsNavigableMap() } if v1AuthReply.ThresholdIDs != nil { - cgrReply[utils.CapThresholds] = *v1AuthReply.ThresholdIDs + thIDs := make(utils.NMSlice, len(*v1AuthReply.ThresholdIDs)) + for i, v := range *v1AuthReply.ThresholdIDs { + thIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapThresholds] = &thIDs } if v1AuthReply.StatQueueIDs != nil { - cgrReply[utils.CapStatQueues] = *v1AuthReply.StatQueueIDs + stIDs := make(utils.NMSlice, len(*v1AuthReply.StatQueueIDs)) + for i, v := range *v1AuthReply.StatQueueIDs { + stIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapStatQueues] = &stIDs } } - return config.NewNavigableMap(cgrReply), nil + return cgrReply } // BiRPCv1AuthorizeEvent performs authorization for CGREvent based on specific components @@ -2071,34 +2078,42 @@ type V1InitSessionReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1InitSessionReply) AsNavigableMap( - ignr []*config.FCTemplate) (*config.NavigableMap, error) { - cgrReply := make(map[string]interface{}) +func (v1Rply *V1InitSessionReply) AsNavigableMap() utils.NavigableMap2 { + cgrReply := make(utils.NavigableMap2) if v1Rply != nil { if v1Rply.Attributes != nil { - attrs := make(map[string]interface{}) + attrs := make(utils.NavigableMap2) for _, fldName := range v1Rply.Attributes.AlteredFields { fldName = strings.TrimPrefix(fldName, utils.MetaReq+utils.NestingSep) if v1Rply.Attributes.CGREvent.HasField(fldName) { - attrs[fldName] = v1Rply.Attributes.CGREvent.Event[fldName] + attrs[fldName] = utils.NewNMData(v1Rply.Attributes.CGREvent.Event[fldName]) } } cgrReply[utils.CapAttributes] = attrs } if v1Rply.ResourceAllocation != nil { - cgrReply[utils.CapResourceAllocation] = *v1Rply.ResourceAllocation + cgrReply[utils.CapResourceAllocation] = utils.NewNMData(*v1Rply.ResourceAllocation) } if v1Rply.MaxUsage != nil { - cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage + cgrReply[utils.CapMaxUsage] = utils.NewNMData(*v1Rply.MaxUsage) } + if v1Rply.ThresholdIDs != nil { - cgrReply[utils.CapThresholds] = *v1Rply.ThresholdIDs + thIDs := make(utils.NMSlice, len(*v1Rply.ThresholdIDs)) + for i, v := range *v1Rply.ThresholdIDs { + thIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapThresholds] = &thIDs } if v1Rply.StatQueueIDs != nil { - cgrReply[utils.CapStatQueues] = *v1Rply.StatQueueIDs + stIDs := make(utils.NMSlice, len(*v1Rply.StatQueueIDs)) + for i, v := range *v1Rply.StatQueueIDs { + stIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapStatQueues] = &stIDs } } - return config.NewNavigableMap(cgrReply), nil + return cgrReply } // BiRPCv1InitiateSession initiates a new session @@ -2302,25 +2317,24 @@ type V1UpdateSessionReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1UpdateSessionReply) AsNavigableMap( - ignr []*config.FCTemplate) (*config.NavigableMap, error) { - cgrReply := make(map[string]interface{}) +func (v1Rply *V1UpdateSessionReply) AsNavigableMap() utils.NavigableMap2 { + cgrReply := make(utils.NavigableMap2) if v1Rply != nil { if v1Rply.Attributes != nil { - attrs := make(map[string]interface{}) + attrs := make(utils.NavigableMap2) for _, fldName := range v1Rply.Attributes.AlteredFields { fldName = strings.TrimPrefix(fldName, utils.MetaReq+utils.NestingSep) if v1Rply.Attributes.CGREvent.HasField(fldName) { - attrs[fldName] = v1Rply.Attributes.CGREvent.Event[fldName] + attrs[fldName] = utils.NewNMData(v1Rply.Attributes.CGREvent.Event[fldName]) } } cgrReply[utils.CapAttributes] = attrs } if v1Rply.MaxUsage != nil { - cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage + cgrReply[utils.CapMaxUsage] = utils.NewNMData(*v1Rply.MaxUsage) } } - return config.NewNavigableMap(cgrReply), nil + return cgrReply } // BiRPCv1UpdateSession updates an existing session, returning the duration which the session can still last @@ -2781,22 +2795,21 @@ type V1ProcessMessageReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1ProcessMessageReply) AsNavigableMap( - ignr []*config.FCTemplate) (*config.NavigableMap, error) { - cgrReply := make(map[string]interface{}) +func (v1Rply *V1ProcessMessageReply) AsNavigableMap() utils.NavigableMap2 { + cgrReply := make(utils.NavigableMap2) if v1Rply != nil { if v1Rply.MaxUsage != nil { - cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage + cgrReply[utils.CapMaxUsage] = utils.NewNMData(*v1Rply.MaxUsage) } if v1Rply.ResourceAllocation != nil { - cgrReply[utils.CapResourceAllocation] = *v1Rply.ResourceAllocation + cgrReply[utils.CapResourceAllocation] = utils.NewNMData(*v1Rply.ResourceAllocation) } if v1Rply.Attributes != nil { - attrs := make(map[string]interface{}) + attrs := make(utils.NavigableMap2) for _, fldName := range v1Rply.Attributes.AlteredFields { fldName = strings.TrimPrefix(fldName, utils.MetaReq+utils.NestingSep) if v1Rply.Attributes.CGREvent.HasField(fldName) { - attrs[fldName] = v1Rply.Attributes.CGREvent.Event[fldName] + attrs[fldName] = utils.NewNMData(v1Rply.Attributes.CGREvent.Event[fldName]) } } cgrReply[utils.CapAttributes] = attrs @@ -2805,13 +2818,21 @@ func (v1Rply *V1ProcessMessageReply) AsNavigableMap( cgrReply[utils.CapRoutes] = v1Rply.Routes.AsNavigableMap() } if v1Rply.ThresholdIDs != nil { - cgrReply[utils.CapThresholds] = *v1Rply.ThresholdIDs + thIDs := make(utils.NMSlice, len(*v1Rply.ThresholdIDs)) + for i, v := range *v1Rply.ThresholdIDs { + thIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapThresholds] = &thIDs } if v1Rply.StatQueueIDs != nil { - cgrReply[utils.CapStatQueues] = *v1Rply.StatQueueIDs + stIDs := make(utils.NMSlice, len(*v1Rply.StatQueueIDs)) + for i, v := range *v1Rply.StatQueueIDs { + stIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapStatQueues] = &stIDs } } - return config.NewNavigableMap(cgrReply), nil + return cgrReply } // BiRPCv1ProcessMessage processes one event with the right subsystems based on arguments received @@ -2952,22 +2973,21 @@ type V1ProcessEventReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1ProcessEventReply) AsNavigableMap( - ignr []*config.FCTemplate) (*config.NavigableMap, error) { - cgrReply := make(map[string]interface{}) +func (v1Rply *V1ProcessEventReply) AsNavigableMap() utils.NavigableMap2 { + cgrReply := make(utils.NavigableMap2) if v1Rply != nil { if v1Rply.MaxUsage != nil { - cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage + cgrReply[utils.CapMaxUsage] = utils.NewNMData(*v1Rply.MaxUsage) } if v1Rply.ResourceMessage != nil { - cgrReply[utils.CapResourceMessage] = *v1Rply.ResourceMessage + cgrReply[utils.CapResourceMessage] = utils.NewNMData(*v1Rply.ResourceMessage) } if v1Rply.Attributes != nil { - attrs := make(map[string]interface{}) + attrs := make(utils.NavigableMap2) for _, fldName := range v1Rply.Attributes.AlteredFields { fldName = strings.TrimPrefix(fldName, utils.MetaReq+utils.NestingSep) if v1Rply.Attributes.CGREvent.HasField(fldName) { - attrs[fldName] = v1Rply.Attributes.CGREvent.Event[fldName] + attrs[fldName] = utils.NewNMData(v1Rply.Attributes.CGREvent.Event[fldName]) } } cgrReply[utils.CapAttributes] = attrs @@ -2976,16 +2996,24 @@ func (v1Rply *V1ProcessEventReply) AsNavigableMap( cgrReply[utils.CapRoutes] = v1Rply.Routes.AsNavigableMap() } if v1Rply.ThresholdIDs != nil { - cgrReply[utils.CapThresholds] = *v1Rply.ThresholdIDs + thIDs := make(utils.NMSlice, len(*v1Rply.ThresholdIDs)) + for i, v := range *v1Rply.ThresholdIDs { + thIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapThresholds] = &thIDs } if v1Rply.StatQueueIDs != nil { - cgrReply[utils.CapStatQueues] = *v1Rply.StatQueueIDs + stIDs := make(utils.NMSlice, len(*v1Rply.StatQueueIDs)) + for i, v := range *v1Rply.StatQueueIDs { + stIDs[i] = utils.NewNMData(v) + } + cgrReply[utils.CapStatQueues] = &stIDs } if v1Rply.Cost != nil { - cgrReply[utils.Cost] = *v1Rply.Cost + cgrReply[utils.Cost] = utils.NewNMData(*v1Rply.Cost) } } - return config.NewNavigableMap(cgrReply), nil + return cgrReply } // BiRPCv1ProcessEvent processes one event with the right subsystems based on arguments received diff --git a/sessions/sessions_test.go b/sessions/sessions_test.go index 0fc1adb97..78b7cc8b4 100644 --- a/sessions/sessions_test.go +++ b/sessions/sessions_test.go @@ -1193,21 +1193,18 @@ func TestSessionSV1AuthorizeReplyAsNavigableMap(t *testing.T) { thIDs := &[]string{"THD_RES_1", "THD_STATS_1", "THD_STATS_2", "THD_CDRS_1"} statIDs := &[]string{"Stats2", "Stats1", "Stats3"} v1AuthRpl := new(V1AuthorizeReply) - expected := config.NewNavigableMap(map[string]interface{}{}) - if rply, _ := v1AuthRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected := utils.NavigableMap2{} + if rply := v1AuthRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1AuthRpl.Attributes = attrs - expected.Set([]string{utils.CapAttributes}, - map[string]interface{}{"OfficeGroup": "Marketing"}, - false, false) - if rply, _ := v1AuthRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapAttributes] = utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")} + if rply := v1AuthRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1AuthRpl.MaxUsage = utils.DurationPointer(5 * time.Minute) - expected.Set([]string{utils.CapMaxUsage}, - 5*time.Minute, false, false) - if rply, _ := v1AuthRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapMaxUsage] = utils.NewNMData(5 * time.Minute) + if rply := v1AuthRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1AuthRpl = &V1AuthorizeReply{ @@ -1218,15 +1215,15 @@ func TestSessionSV1AuthorizeReplyAsNavigableMap(t *testing.T) { ThresholdIDs: thIDs, StatQueueIDs: statIDs, } - expected = config.NewNavigableMap(map[string]interface{}{ - utils.CapAttributes: map[string]interface{}{"OfficeGroup": "Marketing"}, - utils.CapResourceAllocation: "ResGr1", - utils.CapMaxUsage: 5 * time.Minute, + expected = utils.NavigableMap2{ + utils.CapAttributes: utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")}, + utils.CapResourceAllocation: utils.NewNMData("ResGr1"), + utils.CapMaxUsage: utils.NewNMData(5 * time.Minute), utils.CapRoutes: splrs.AsNavigableMap(), - utils.CapThresholds: *thIDs, - utils.CapStatQueues: *statIDs, - }) - if rply, _ := v1AuthRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + utils.CapThresholds: &utils.NMSlice{utils.NewNMData("THD_RES_1"), utils.NewNMData("THD_STATS_1"), utils.NewNMData("THD_STATS_2"), utils.NewNMData("THD_CDRS_1")}, + utils.CapStatQueues: &utils.NMSlice{utils.NewNMData("Stats2"), utils.NewNMData("Stats1"), utils.NewNMData("Stats3")}, + } + if rply := v1AuthRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } } @@ -1235,21 +1232,18 @@ func TestSessionSV1InitSessionReplyAsNavigableMap(t *testing.T) { thIDs := &[]string{"THD_RES_1", "THD_STATS_1", "THD_STATS_2", "THD_CDRS_1"} statIDs := &[]string{"Stats2", "Stats1", "Stats3"} v1InitRpl := new(V1InitSessionReply) - expected := config.NewNavigableMap(map[string]interface{}{}) - if rply, _ := v1InitRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected := utils.NavigableMap2{} + if rply := v1InitRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1InitRpl.Attributes = attrs - expected.Set([]string{utils.CapAttributes}, - map[string]interface{}{"OfficeGroup": "Marketing"}, - false, false) - if rply, _ := v1InitRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapAttributes] = utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")} + if rply := v1InitRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1InitRpl.MaxUsage = utils.DurationPointer(5 * time.Minute) - expected.Set([]string{utils.CapMaxUsage}, - 5*time.Minute, false, false) - if rply, _ := v1InitRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapMaxUsage] = utils.NewNMData(5 * time.Minute) + if rply := v1InitRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1InitRpl = &V1InitSessionReply{ @@ -1259,61 +1253,58 @@ func TestSessionSV1InitSessionReplyAsNavigableMap(t *testing.T) { ThresholdIDs: thIDs, StatQueueIDs: statIDs, } - expected = config.NewNavigableMap(map[string]interface{}{ - utils.CapAttributes: map[string]interface{}{"OfficeGroup": "Marketing"}, - utils.CapResourceAllocation: "ResGr1", - utils.CapMaxUsage: 5 * time.Minute, - utils.CapThresholds: *thIDs, - utils.CapStatQueues: *statIDs, - }) - if rply, _ := v1InitRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected = utils.NavigableMap2{ + utils.CapAttributes: utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")}, + utils.CapResourceAllocation: utils.NewNMData("ResGr1"), + utils.CapMaxUsage: utils.NewNMData(5 * time.Minute), + utils.CapThresholds: &utils.NMSlice{utils.NewNMData("THD_RES_1"), utils.NewNMData("THD_STATS_1"), utils.NewNMData("THD_STATS_2"), utils.NewNMData("THD_CDRS_1")}, + utils.CapStatQueues: &utils.NMSlice{utils.NewNMData("Stats2"), utils.NewNMData("Stats1"), utils.NewNMData("Stats3")}, + } + if rply := v1InitRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } } func TestSessionSV1UpdateSessionReplyAsNavigableMap(t *testing.T) { v1UpdtRpl := new(V1UpdateSessionReply) - expected := config.NewNavigableMap(map[string]interface{}{}) - if rply, _ := v1UpdtRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected := utils.NavigableMap2{} + if rply := v1UpdtRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1UpdtRpl.Attributes = attrs - expected.Set([]string{utils.CapAttributes}, - map[string]interface{}{"OfficeGroup": "Marketing"}, - false, false) - if rply, _ := v1UpdtRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapAttributes] = utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")} + if rply := v1UpdtRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1UpdtRpl.MaxUsage = utils.DurationPointer(5 * time.Minute) - expected.Set([]string{utils.CapMaxUsage}, - 5*time.Minute, false, false) - if rply, _ := v1UpdtRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapMaxUsage] = utils.NewNMData(5 * time.Minute) + if rply := v1UpdtRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } } func TestSessionSV1ProcessMessageReplyAsNavigableMap(t *testing.T) { v1PrcEvRpl := new(V1ProcessMessageReply) - expected := config.NewNavigableMap(map[string]interface{}{}) - if rply, _ := v1PrcEvRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected := utils.NavigableMap2{} + if rply := v1PrcEvRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1PrcEvRpl.Attributes = attrs - expected.Set([]string{utils.CapAttributes}, map[string]interface{}{"OfficeGroup": "Marketing"}, false, false) - if rply, _ := v1PrcEvRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapAttributes] = utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")} + if rply := v1PrcEvRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1PrcEvRpl.MaxUsage = utils.DurationPointer(5 * time.Minute) - expected.Set([]string{utils.CapMaxUsage}, 5*time.Minute, false, false) - if rply, _ := v1PrcEvRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapMaxUsage] = utils.NewNMData(5 * time.Minute) + if rply := v1PrcEvRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } v1PrcEvRpl.ResourceAllocation = utils.StringPointer("ResGr1") - expected.Set([]string{utils.CapResourceAllocation}, "ResGr1", false, false) - if rply, _ := v1PrcEvRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapResourceAllocation] = utils.NewNMData("ResGr1") + if rply := v1PrcEvRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } @@ -1327,11 +1318,11 @@ func TestSessionSV1ProcessMessageReplyAsNavigableMap(t *testing.T) { v1PrcEvRpl.Routes = tmpRoutes v1PrcEvRpl.ThresholdIDs = &tmpTresholdIDs v1PrcEvRpl.StatQueueIDs = &tmpStatQueueIDs - expected.Set([]string{utils.CapResourceAllocation}, "ResGr1", false, false) - expected.Set([]string{utils.CapRoutes}, tmpRoutes.AsNavigableMap(), false, false) - expected.Set([]string{utils.CapThresholds}, tmpTresholdIDs, false, false) - expected.Set([]string{utils.CapStatQueues}, tmpStatQueueIDs, false, false) - if rply, _ := v1PrcEvRpl.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapResourceAllocation] = utils.NewNMData("ResGr1") + expected[utils.CapRoutes] = tmpRoutes.AsNavigableMap() + expected[utils.CapThresholds] = &utils.NMSlice{utils.NewNMData("ID1"), utils.NewNMData("ID2")} + expected[utils.CapStatQueues] = &utils.NMSlice{utils.NewNMData("Que1"), utils.NewNMData("Que2")} + if rply := v1PrcEvRpl.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } } @@ -1339,26 +1330,26 @@ func TestSessionSV1ProcessMessageReplyAsNavigableMap(t *testing.T) { func TestV1ProcessEventReplyAsNavigableMap(t *testing.T) { //empty check v1per := new(V1ProcessEventReply) - expected := config.NewNavigableMap(map[string]interface{}{}) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected := utils.NavigableMap2{} + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //max usage check v1per.MaxUsage = utils.DurationPointer(5 * time.Minute) - expected.Set([]string{utils.CapMaxUsage}, 5*time.Minute, false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapMaxUsage] = utils.NewNMData(5 * time.Minute) + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //resource message check v1per.ResourceMessage = utils.StringPointer("Resource") - expected.Set([]string{utils.CapResourceMessage}, "Resource", false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapResourceMessage] = utils.NewNMData("Resource") + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //attributes check v1per.Attributes = attrs - expected.Set([]string{utils.CapAttributes}, map[string]interface{}{"OfficeGroup": "Marketing"}, false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapAttributes] = utils.NavigableMap2{"OfficeGroup": utils.NewNMData("Marketing")} + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //routes check @@ -1367,22 +1358,22 @@ func TestV1ProcessEventReplyAsNavigableMap(t *testing.T) { Count: 1, } v1per.Routes = tmpRoutes - expected.Set([]string{utils.CapRoutes}, tmpRoutes.AsNavigableMap(), false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapRoutes] = tmpRoutes.AsNavigableMap() + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //tmpTresholdIDs check tmpTresholdIDs := []string{"ID1", "ID2"} v1per.ThresholdIDs = &tmpTresholdIDs - expected.Set([]string{utils.CapThresholds}, tmpTresholdIDs, false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapThresholds] = &utils.NMSlice{utils.NewNMData("ID1"), utils.NewNMData("ID2")} + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) } //StatQueue check tmpStatQueueIDs := []string{"Que1", "Que2"} v1per.StatQueueIDs = &tmpStatQueueIDs - expected.Set([]string{utils.CapStatQueues}, tmpStatQueueIDs, false, false) - if rply, _ := v1per.AsNavigableMap(nil); !reflect.DeepEqual(expected, rply) { + expected[utils.CapStatQueues] = &utils.NMSlice{utils.NewNMData("Que1"), utils.NewNMData("Que2")} + if rply := v1per.AsNavigableMap(); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting \n%+v\n, received: \n%+v", expected, rply) }