forked from cgrates/cgrates
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
578 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments | ||
Copyright (C) ITsysCOM GmbH | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/> | ||
*/ | ||
|
||
package utils | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
// NewDynamicDataProvider constructs a dynamic data provider | ||
func NewDynamicDataProvider(dp DataProvider) *DynamicDataProvider { | ||
return &DynamicDataProvider{ | ||
DataProvider: dp, | ||
cache: make(map[string]interface{}), | ||
} | ||
} | ||
|
||
// DynamicDataProvider is a data source from multiple formats | ||
type DynamicDataProvider struct { | ||
DataProvider | ||
cache map[string]interface{} | ||
} | ||
|
||
// FieldAsInterface to overwrite the FieldAsInterface function from the given DataProvider | ||
func (ddp *DynamicDataProvider) FieldAsInterface(fldPath []string) (out interface{}, err error) { | ||
path := strings.Join(fldPath, NestingSep) // join the path so we can check it in cache and parse it more easy | ||
if val, has := ddp.cache[path]; has { // check if we have the path in cache | ||
return val, nil | ||
} | ||
var newPath string | ||
if newPath, err = ddp.proccesFieldPath(path); err != nil { // proccess the path | ||
return | ||
} | ||
if newPath == EmptyString { // no new path means no dynamic path so just take the value from the data provider | ||
return ddp.DataProvider.FieldAsInterface(fldPath) | ||
} | ||
// split the new path and get that field | ||
if out, err = ddp.DataProvider.FieldAsInterface(strings.Split(newPath, NestingSep)); err != nil { | ||
return | ||
} | ||
// if no error save in cache the path | ||
ddp.cache[path] = out | ||
return | ||
} | ||
|
||
func (ddp *DynamicDataProvider) proccesFieldPath(fldPath string) (newPath string, err error) { | ||
idx := strings.Index(fldPath, IdxStart) | ||
if idx == -1 { | ||
return // no proccessing requred | ||
} | ||
newPath = fldPath[:idx+1] // add the first path of the path with the "[" included | ||
for idx != -1 { // stop when we do not find any "[" | ||
fldPath = fldPath[idx+1:] // move the path to the begining of the index | ||
nextBeginIdx := strings.Index(fldPath, IdxStart) // get the next "[" if any | ||
nextEndIdx := strings.Index(fldPath, IdxEnd) // get the next "]" if any | ||
if nextEndIdx == -1 { // no end index found so return error | ||
err = ErrWrongPath | ||
newPath = EmptyString | ||
return | ||
} | ||
|
||
// parse the rest of the field path until we match the [ ] | ||
bIdx, eIdx := nextBeginIdx, nextEndIdx | ||
for nextBeginIdx != -1 && nextBeginIdx < nextEndIdx { // do this until no new [ is found or the next begining [ is after the end ] | ||
nextBeginIdx = strings.Index(fldPath[bIdx+1:], IdxStart) // get the next "[" if any | ||
nextEndIdx = strings.Index(fldPath[eIdx+1:], IdxEnd) // get the next "]" if any | ||
if nextEndIdx == -1 { // no end index found so return error | ||
err = ErrWrongPath | ||
newPath = EmptyString | ||
return | ||
} | ||
if nextBeginIdx == -1 { // if no index found do not increment but replace it | ||
bIdx = -1 | ||
} else { | ||
bIdx += nextBeginIdx + 1 | ||
} | ||
// increment the indexes | ||
eIdx += nextEndIdx + 1 | ||
} | ||
var val string | ||
for _, path := range strings.Split(fldPath[:eIdx], PipeSep) { // proccess the found path | ||
var iface interface{} | ||
if iface, err = DPDynamicInterface(path, ddp); err != nil { | ||
newPath = EmptyString | ||
return | ||
} | ||
val += IfaceAsString(iface) // compose the value | ||
} | ||
if bIdx == -1 { // if is the last ocurence add the rest of the path and exit | ||
newPath += val + fldPath[eIdx:] | ||
} else { | ||
// else just add until the next [ | ||
newPath += val + fldPath[eIdx:bIdx+1] | ||
} | ||
idx = bIdx | ||
} | ||
return | ||
} |
Oops, something went wrong.