mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
AttributeS with Compile method and attributesIdx, Substitute as utils.RSRParsers
This commit is contained in:
@@ -168,15 +168,18 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) (
|
||||
rply = &AttrSProcessEventReply{
|
||||
MatchedProfiles: []string{attrPrf.ID},
|
||||
CGREvent: args.Clone()}
|
||||
for fldName, initialMp := range attrPrf.attributes {
|
||||
for fldName, initialMp := range attrPrf.attributesIdx {
|
||||
initEvValIf, has := args.Event[fldName]
|
||||
if !has {
|
||||
anyInitial, hasAny := initialMp[utils.ANY]
|
||||
if hasAny && anyInitial.Append &&
|
||||
initialMp[utils.ANY].Substitute.Id() != utils.META_NONE {
|
||||
rply.CGREvent.Event[fldName] = anyInitial.Substitute.Id()
|
||||
if hasAny && anyInitial.Append { // add field name
|
||||
substitute, err := anyInitial.Substitute.ParseEvent(args.Event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rply.CGREvent.Event[fldName] = substitute
|
||||
rply.AlteredFields = append(rply.AlteredFields, fldName)
|
||||
}
|
||||
rply.AlteredFields = append(rply.AlteredFields, fldName)
|
||||
continue
|
||||
}
|
||||
attrVal, has := initialMp[initEvValIf]
|
||||
@@ -184,10 +187,14 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) (
|
||||
attrVal, has = initialMp[utils.ANY]
|
||||
}
|
||||
if has {
|
||||
if attrVal.Substitute.Id() == utils.META_NONE {
|
||||
substitute, err := attrVal.Substitute.ParseEvent(args.Event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if substitute == utils.META_NONE {
|
||||
delete(rply.CGREvent.Event, fldName)
|
||||
} else {
|
||||
rply.CGREvent.Event[fldName] = attrVal.Substitute.Id()
|
||||
rply.CGREvent.Event[fldName] = substitute
|
||||
}
|
||||
rply.AlteredFields = append(rply.AlteredFields, fldName)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ var (
|
||||
utils.META_ANY: &Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1010", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
@@ -101,12 +101,12 @@ var (
|
||||
&Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1010", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
attributes: mapSubstitutes,
|
||||
Weight: 20,
|
||||
attributesIdx: mapSubstitutes,
|
||||
},
|
||||
&AttributeProfile{
|
||||
Tenant: config.CgrConfig().DefaultTenant,
|
||||
@@ -121,12 +121,12 @@ var (
|
||||
&Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1010", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
attributes: mapSubstitutes,
|
||||
Weight: 20,
|
||||
attributesIdx: mapSubstitutes,
|
||||
},
|
||||
&AttributeProfile{
|
||||
Tenant: config.CgrConfig().DefaultTenant,
|
||||
@@ -141,12 +141,12 @@ var (
|
||||
&Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1010", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
attributes: mapSubstitutes,
|
||||
Weight: 20,
|
||||
attributesIdx: mapSubstitutes,
|
||||
Weight: 20,
|
||||
},
|
||||
&AttributeProfile{
|
||||
Tenant: config.CgrConfig().DefaultTenant,
|
||||
@@ -161,12 +161,12 @@ var (
|
||||
&Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1010", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
attributes: mapSubstitutes,
|
||||
Weight: 20,
|
||||
attributesIdx: mapSubstitutes,
|
||||
Weight: 20,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -463,20 +463,14 @@ func TestAttributeIndexer(t *testing.T) {
|
||||
},
|
||||
Attributes: []*Attribute{
|
||||
&Attribute{
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Append: true,
|
||||
FieldName: utils.Account,
|
||||
Initial: utils.META_ANY,
|
||||
Substitute: utils.NewRSRParsersMustCompile("1010", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
}
|
||||
//populate Substitute from attributes
|
||||
rsrFields, err := utils.ParseRSRFields("^1010", utils.INFIELD_SEP)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
attrPrf.Attributes[0].Substitute = rsrFields
|
||||
|
||||
if err := dmAtr.SetAttributeProfile(attrPrf, true); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -1068,7 +1068,7 @@ func (dm *DataManager) RemoveSupplierProfile(tenant, id, transactionID string, w
|
||||
}
|
||||
|
||||
func (dm *DataManager) GetAttributeProfile(tenant, id string, skipCache bool,
|
||||
transactionID string) (alsPrf *AttributeProfile, err error) {
|
||||
transactionID string) (attrPrfl *AttributeProfile, err error) {
|
||||
tntID := utils.ConcatenatedKey(tenant, id)
|
||||
if !skipCache {
|
||||
if x, ok := Cache.Get(utils.CacheAttributeProfiles, tntID); ok {
|
||||
@@ -1078,7 +1078,7 @@ func (dm *DataManager) GetAttributeProfile(tenant, id string, skipCache bool,
|
||||
return x.(*AttributeProfile), nil
|
||||
}
|
||||
}
|
||||
alsPrf, err = dm.dataDB.GetAttributeProfileDrv(tenant, id)
|
||||
attrPrfl, err = dm.dataDB.GetAttributeProfileDrv(tenant, id)
|
||||
if err != nil {
|
||||
if err == utils.ErrNotFound {
|
||||
Cache.Set(utils.CacheAttributeProfiles, tntID, nil, nil,
|
||||
@@ -1086,17 +1086,10 @@ func (dm *DataManager) GetAttributeProfile(tenant, id string, skipCache bool,
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
alsPrf.attributes = make(map[string]map[interface{}]*Attribute)
|
||||
for _, attr := range alsPrf.Attributes {
|
||||
alsPrf.attributes[attr.FieldName] = make(map[interface{}]*Attribute)
|
||||
alsPrf.attributes[attr.FieldName][attr.Initial] = &Attribute{
|
||||
FieldName: attr.FieldName,
|
||||
Initial: attr.Initial,
|
||||
Substitute: attr.Substitute,
|
||||
Append: attr.Append,
|
||||
}
|
||||
if err = attrPrfl.Compile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Cache.Set(utils.CacheAttributeProfiles, tntID, alsPrf, nil,
|
||||
Cache.Set(utils.CacheAttributeProfiles, tntID, attrPrfl, nil,
|
||||
cacheCommit(transactionID), transactionID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
type Attribute struct {
|
||||
FieldName string
|
||||
Initial interface{}
|
||||
Substitute utils.RSRFields
|
||||
Substitute utils.RSRParsers
|
||||
Append bool
|
||||
}
|
||||
|
||||
@@ -36,10 +36,37 @@ type AttributeProfile struct {
|
||||
ID string
|
||||
Contexts []string // bind this AttributeProfile to multiple contexts
|
||||
FilterIDs []string
|
||||
ActivationInterval *utils.ActivationInterval // Activation interval
|
||||
attributes map[string]map[interface{}]*Attribute // map[FieldName][InitialValue]*Attribute
|
||||
ActivationInterval *utils.ActivationInterval // Activation interval
|
||||
Attributes []*Attribute
|
||||
Weight float64
|
||||
|
||||
attributesIdx map[string]map[interface{}]*Attribute // map[FieldName][InitialValue]*Attribute, used as event match index
|
||||
}
|
||||
|
||||
// computeAttributesIndex populates .attributes
|
||||
func (ap *AttributeProfile) computeAttributesIndex() {
|
||||
ap.attributesIdx = make(map[string]map[interface{}]*Attribute)
|
||||
for _, attr := range ap.Attributes {
|
||||
if _, has := ap.attributesIdx[attr.FieldName]; !has {
|
||||
ap.attributesIdx[attr.FieldName] = make(map[interface{}]*Attribute)
|
||||
}
|
||||
ap.attributesIdx[attr.FieldName][attr.Initial] = attr
|
||||
}
|
||||
}
|
||||
|
||||
func (ap *AttributeProfile) compileSubstitutes() (err error) {
|
||||
for _, attr := range ap.Attributes {
|
||||
if err = attr.Substitute.Compile(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Compile is a wrapper for convenience setting up the AttributeProfile
|
||||
func (ap *AttributeProfile) Compile() error {
|
||||
ap.computeAttributesIndex()
|
||||
return ap.compileSubstitutes()
|
||||
}
|
||||
|
||||
func (als *AttributeProfile) TenantID() string {
|
||||
|
||||
@@ -2803,31 +2803,17 @@ func APItoAttributeProfile(tpTH *utils.TPAttributeProfile, timezone string) (th
|
||||
for _, context := range tpTH.Contexts {
|
||||
th.Contexts = append(th.Contexts, context)
|
||||
}
|
||||
th.attributes = make(map[string]map[interface{}]*Attribute)
|
||||
for _, reqAttr := range tpTH.Attributes {
|
||||
th.Attributes = append(th.Attributes, &Attribute{
|
||||
Append: reqAttr.Append,
|
||||
FieldName: reqAttr.FieldName,
|
||||
Initial: reqAttr.Initial,
|
||||
Substitute: utils.RSRFields{
|
||||
&utils.RSRField{
|
||||
Id: reqAttr.Substitute,
|
||||
RSRules: []*utils.ReSearchReplace{}, //from mongo we get empty slice and from redis nil
|
||||
},
|
||||
},
|
||||
})
|
||||
th.attributes[reqAttr.FieldName] = make(map[interface{}]*Attribute)
|
||||
th.attributes[reqAttr.FieldName][reqAttr.Initial] = &Attribute{
|
||||
FieldName: reqAttr.FieldName,
|
||||
Initial: reqAttr.Initial,
|
||||
Substitute: utils.RSRFields{
|
||||
&utils.RSRField{
|
||||
Id: reqAttr.Substitute,
|
||||
RSRules: []*utils.ReSearchReplace{}, //from mongo we get empty slice and from redis nil
|
||||
},
|
||||
},
|
||||
Append: reqAttr.Append,
|
||||
sbstPrsr, err := utils.NewRSRParsers(reqAttr.Substitute, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
th.Attributes = append(th.Attributes, &Attribute{
|
||||
Append: reqAttr.Append,
|
||||
FieldName: reqAttr.FieldName,
|
||||
Initial: reqAttr.Initial,
|
||||
Substitute: sbstPrsr,
|
||||
})
|
||||
}
|
||||
if tpTH.ActivationInterval != nil {
|
||||
if th.ActivationInterval, err = tpTH.ActivationInterval.AsActivationInterval(timezone); err != nil {
|
||||
|
||||
@@ -1475,7 +1475,7 @@ func TestAPItoAttributeProfile(t *testing.T) {
|
||||
mapSubstitutes["FL1"]["In1"] = &Attribute{
|
||||
FieldName: "FL1",
|
||||
Initial: "In1",
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "Al1", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("Al1", true),
|
||||
Append: true,
|
||||
}
|
||||
expected := &AttributeProfile{
|
||||
@@ -1490,12 +1490,11 @@ func TestAPItoAttributeProfile(t *testing.T) {
|
||||
&Attribute{
|
||||
FieldName: "FL1",
|
||||
Initial: "In1",
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "Al1", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("Al1", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
attributes: mapSubstitutes,
|
||||
Weight: 20,
|
||||
}
|
||||
if rcv, err := APItoAttributeProfile(tpAlsPrf, "UTC"); err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -112,13 +112,13 @@ cgrates.org,TestLoader1,lcr,*string:Account:1008;*string:Account:1009,,Subject,*
|
||||
&engine.Attribute{
|
||||
FieldName: "Account",
|
||||
Initial: utils.ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1001", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1001", true),
|
||||
Append: false,
|
||||
},
|
||||
&engine.Attribute{
|
||||
FieldName: "Subject",
|
||||
Initial: utils.ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1001", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1001", true),
|
||||
Append: true,
|
||||
}},
|
||||
Weight: 10.0,
|
||||
@@ -207,7 +207,7 @@ func TestLoaderProcessContentMultiFiles(t *testing.T) {
|
||||
&engine.Attribute{
|
||||
FieldName: "Subject",
|
||||
Initial: utils.ANY,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "1001", RSRules: []*utils.ReSearchReplace{}}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("1001", true),
|
||||
Append: true,
|
||||
}},
|
||||
Weight: 10.0,
|
||||
|
||||
@@ -80,7 +80,10 @@ func (m *Migrator) migrateV1Attributes() (err error) {
|
||||
break
|
||||
}
|
||||
if v1Attr != nil {
|
||||
attrPrf := v1Attr.AsAttributeProfile()
|
||||
attrPrf, err := v1Attr.AsAttributeProfile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m.dryRun != true {
|
||||
if err := m.dmOut.DataManager().DataDB().SetAttributeProfileDrv(attrPrf); err != nil {
|
||||
return err
|
||||
@@ -137,7 +140,7 @@ func (m *Migrator) migrateAttributeProfile() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (v1AttrPrf v1AttributeProfile) AsAttributeProfile() (attrPrf *engine.AttributeProfile) {
|
||||
func (v1AttrPrf v1AttributeProfile) AsAttributeProfile() (attrPrf *engine.AttributeProfile, err error) {
|
||||
attrPrf = &engine.AttributeProfile{
|
||||
Tenant: v1AttrPrf.Tenant,
|
||||
ID: v1AttrPrf.ID,
|
||||
@@ -149,10 +152,14 @@ func (v1AttrPrf v1AttributeProfile) AsAttributeProfile() (attrPrf *engine.Attrib
|
||||
for _, mp := range v1AttrPrf.Attributes {
|
||||
for _, attr := range mp {
|
||||
initIface := utils.StringToInterface(attr.Initial)
|
||||
sbstPrsr, err := utils.NewRSRParsers(attr.Substitute, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attrPrf.Attributes = append(attrPrf.Attributes, &engine.Attribute{
|
||||
FieldName: attr.FieldName,
|
||||
Initial: initIface,
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: attr.Substitute}},
|
||||
Substitute: sbstPrsr,
|
||||
Append: attr.Append,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -65,13 +65,15 @@ func Testv1AttributeProfileAsAttributeProfile(t *testing.T) {
|
||||
&engine.Attribute{
|
||||
FieldName: "FL1",
|
||||
Initial: "In1",
|
||||
Substitute: utils.RSRFields{&utils.RSRField{Id: "Al1"}},
|
||||
Substitute: utils.NewRSRParsersMustCompile("Al1", true),
|
||||
Append: true,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
}
|
||||
if !reflect.DeepEqual(attrPrf, v1Attribute.AsAttributeProfile()) {
|
||||
t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(attrPrf), utils.ToJSON(v1Attribute.AsAttributeProfile()))
|
||||
if ap, err := v1Attribute.AsAttributeProfile(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(attrPrf, ap) {
|
||||
t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(attrPrf), utils.ToJSON(ap))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,15 @@ func NewRSRParsersMustCompile(parsersRules string, allFiltersMatch bool) (prsrs
|
||||
// RSRParsers is a set of RSRParser
|
||||
type RSRParsers []*RSRParser
|
||||
|
||||
func (prsrs RSRParsers) Compile() (err error) {
|
||||
for _, prsr := range prsrs {
|
||||
if err = prsr.Compile(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ParseValue will parse the value out considering converters and filters
|
||||
func (prsrs RSRParsers) ParseValue(value interface{}) (out string, err error) {
|
||||
for _, prsr := range prsrs {
|
||||
|
||||
Reference in New Issue
Block a user