Add support for per field value mapping
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -98,6 +100,27 @@ func Migrator() *cobra.Command {
|
||||
mm.Name = name
|
||||
mm.Join = file
|
||||
|
||||
mg = migrateableAdd(mg, mm)
|
||||
} else if strings.HasSuffix(info.Name(), ".value.json") {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ext := filepath.Ext(info.Name())
|
||||
// @todo improve this!!
|
||||
name := info.Name()[0 : len(info.Name())-len(ext)-6]
|
||||
mm := migrateableSource(mg, name)
|
||||
mm.Name = name
|
||||
|
||||
var vmp map[string]map[string]string
|
||||
src, _ := ioutil.ReadAll(file)
|
||||
err = json.Unmarshal(src, &vmp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mm.ValueMap = vmp
|
||||
|
||||
mg = migrateableAdd(mg, mm)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -129,3 +129,35 @@ When creating a `.map.json` file, values from the join operation are available u
|
||||
}
|
||||
]
|
||||
----
|
||||
|
||||
== Value Mapping
|
||||
|
||||
The system allows us to map a specific value from the provided `.csv` file into a value used by the system.
|
||||
For example; we can map `In Progress` into `in_progress`.
|
||||
The mapping also supports a default value, by using the `*` wildcard.
|
||||
|
||||
=== Algorithrm
|
||||
|
||||
* unmarshal the given `.value.json`
|
||||
* before applying a value for the given field, attempt to map the value
|
||||
** if mapping is successful, use the mapped value,
|
||||
** else if default value exists, use the default value,
|
||||
** else use the original value.
|
||||
|
||||
=== Example
|
||||
|
||||
.source.values.json
|
||||
|
||||
The following value mapping maps `sys_status` field's values; the left one into the right one, with a default of `"new"` (`"*": "new"`).
|
||||
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"sys_status": {
|
||||
"In Progress": "in_progress",
|
||||
"Send to QA": "qa_pending",
|
||||
"Submit Job": "qa_approved",
|
||||
"*": "new"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -117,6 +117,7 @@ func Migrate(mg []types.Migrateable, ns *cct.Namespace, ctx context.Context) err
|
||||
Header: header,
|
||||
Lock: &sync.Mutex{},
|
||||
FieldMap: m.FieldMap,
|
||||
ValueMap: m.ValueMap,
|
||||
}
|
||||
n = mig.AddNode(n)
|
||||
|
||||
|
||||
@@ -162,6 +162,7 @@ func splitStream(m types.Migrateable) ([]types.Migrateable, error) {
|
||||
Header: &v.header,
|
||||
FieldMap: m.FieldMap,
|
||||
AliasMap: m.AliasMap,
|
||||
ValueMap: m.ValueMap,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -29,5 +29,9 @@ type (
|
||||
FieldMap map[string]JoinedNodeRecords
|
||||
// helps us determine what value field to use for linking
|
||||
AliasMap map[string]string
|
||||
|
||||
// value is used for field value mapping
|
||||
// field: value from: value to
|
||||
ValueMap map[string]map[string]string
|
||||
}
|
||||
)
|
||||
|
||||
@@ -57,6 +57,9 @@ type (
|
||||
|
||||
// field: recordID: [value]
|
||||
FieldMap map[string]JoinedNodeRecords
|
||||
|
||||
// field: value from: value to
|
||||
ValueMap map[string]map[string]string
|
||||
}
|
||||
|
||||
// map between migrated ID and Corteza ID
|
||||
@@ -173,6 +176,9 @@ func (n *Node) Merge(nn *Node) {
|
||||
if nn.FieldMap != nil {
|
||||
n.FieldMap = nn.FieldMap
|
||||
}
|
||||
if nn.ValueMap != nil {
|
||||
n.ValueMap = nn.ValueMap
|
||||
}
|
||||
}
|
||||
|
||||
// link the two nodes
|
||||
@@ -519,6 +525,14 @@ func importNodeSource(n *Node, users map[string]uint64, repo repository.RecordRe
|
||||
}
|
||||
|
||||
for i, v := range values {
|
||||
if fmp, ok := n.ValueMap[h]; ok {
|
||||
if mpv, ok := fmp[v]; ok {
|
||||
v = mpv
|
||||
} else if mpv, ok := fmp["*"]; ok {
|
||||
v = mpv
|
||||
}
|
||||
}
|
||||
|
||||
vals = append(vals, &types.RecordValue{
|
||||
Name: h,
|
||||
Value: v,
|
||||
|
||||
Reference in New Issue
Block a user