From bfbd16073529ff7c470c97b55fff17e9c11f0e3f Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Thu, 6 Aug 2020 13:27:30 -0700 Subject: [PATCH] Link generator using the 'subgroup' element from the Gen3 schema --- schema/generate.go | 131 ++++++++++++++++++++++++++------------------- schema/loader.go | 1 + 2 files changed, 76 insertions(+), 56 deletions(-) diff --git a/schema/generate.go b/schema/generate.go index 35b04ba..cd3ca0e 100644 --- a/schema/generate.go +++ b/schema/generate.go @@ -55,6 +55,78 @@ func (s Schema) Validate(data map[string]interface{}) (map[string]interface{}, e } +func (l Link) Generate(gid string, data map[string]interface{}) ([]GraphElement, error) { + if l.Name == "" && len(l.Subgroup) > 0 { + out := make([]GraphElement, 0, 1) + for _, s := range l.Subgroup { + e, err := s.Generate(gid, data) + if err == nil { + out = append(out, e...) + } + } + return out, nil + } + out := make([]GraphElement, 0, 1) + dst := []string{} + if v, ok := data[l.Name]; ok { + if vString, ok := v.(string); ok { + dst = []string{vString} + } else if vStringArray, ok := v.([]string); ok { + dst = vStringArray + } else if vObjectArray, ok := v.([]interface{}); ok { + for _, x := range vObjectArray { + if y, ok := x.(string); ok { + dst = append(dst, y) + } + } + } else if vObject, ok := v.(map[string]interface{}); ok { + if d, ok := vObject["submitter_id"]; ok { //BUG: this is hard coded to expect Gen3 behavior + if dStr, ok := d.(string); ok { + dst = append(dst, dStr) + } + } + } else { + log.Printf("Class link field %s Unknown property type: %#v", l.Name, v) + } + } + /* + //TODO: This code tries to get the link values using the types found in the schema definition + //which is technically correct, but much harder. This code currently breaks on cases where schema uses + //`anyOf` definitions. So, for now using the previously mentioned version that doesnt check the schema, + //and assumes a string or list of strings + if s.Props[l.Name].Element.Type.Type == "string" { + if x, ok := data[l.Name].(string); ok { + dst = []string{ x } + } else { + log.Printf("Wrong: %s", data[l.Name]) + } + } else if s.Props[l.Name].Element.Type.Type == "array" { + if x, ok := data[l.Name].([]string); ok { + dst = x + } else if x, ok := data[l.Name].([]interface{}); ok { + for _, a := range x { + if aStr, ok := a.(string); ok { + dst = append(dst, aStr) + } + } + } else { + log.Printf("Unknown type: %s %s %s", data[l.Name], l.Name, data) + } + } else { + log.Printf("Class %s field %s Unknown property type: %s", s.Id, l.Name, s.Props[l.Name].Element.Type.Type) + } + */ + for _, d := range dst { + e := gripql.Edge{From:gid, To: d, Label:l.Label} + out = append(out, GraphElement{Edge:&e}) + if l.Backref != "" { + e := gripql.Edge{To:gid, From: d, Label:l.Backref} + out = append(out, GraphElement{Edge:&e}) + } + } + return out, nil +} + func (s Schema) Generate(data map[string]interface{}) ([]GraphElement, error) { out := make([]GraphElement, 0, 1+len(s.Links)*2) outData := map[string]interface{}{} @@ -106,62 +178,9 @@ func (s Schema) Generate(data map[string]interface{}) ([]GraphElement, error) { out = append(out, GraphElement{Vertex:&v}) for _, l := range s.Links { - dst := []string{} - if v, ok := outData[l.Name]; ok { - if vString, ok := v.(string); ok { - dst = []string{vString} - } else if vStringArray, ok := v.([]string); ok { - dst = vStringArray - } else if vObjectArray, ok := v.([]interface{}); ok { - for _, x := range vObjectArray { - if y, ok := x.(string); ok { - dst = append(dst, y) - } - } - } else if vObject, ok := v.(map[string]interface{}); ok { - if d, ok := vObject["submitter_id"]; ok { //BUG: this is hard coded to expect Gen3 behavior - if dStr, ok := d.(string); ok { - dst = append(dst, dStr) - } - } - } else { - log.Printf("Class %s link field %s Unknown property type: %#v", s.Id, l.Name, v) - } - } - /* - //TODO: This code tries to get the link values using the types found in the schema definition - //which is technically correct, but much harder. This code currently breaks on cases where schema uses - //`anyOf` definitions. So, for now using the previously mentioned version that doesnt check the schema, - //and assumes a string or list of strings - if s.Props[l.Name].Element.Type.Type == "string" { - if x, ok := data[l.Name].(string); ok { - dst = []string{ x } - } else { - log.Printf("Wrong: %s", data[l.Name]) - } - } else if s.Props[l.Name].Element.Type.Type == "array" { - if x, ok := data[l.Name].([]string); ok { - dst = x - } else if x, ok := data[l.Name].([]interface{}); ok { - for _, a := range x { - if aStr, ok := a.(string); ok { - dst = append(dst, aStr) - } - } - } else { - log.Printf("Unknown type: %s %s %s", data[l.Name], l.Name, data) - } - } else { - log.Printf("Class %s field %s Unknown property type: %s", s.Id, l.Name, s.Props[l.Name].Element.Type.Type) - } - */ - for _, d := range dst { - e := gripql.Edge{From:gid, To: d, Label:l.Label} - out = append(out, GraphElement{Edge:&e}) - if l.Backref != "" { - e := gripql.Edge{To:gid, From: d, Label:l.Backref} - out = append(out, GraphElement{Edge:&e}) - } + lo, err := l.Generate(gid, outData) + if err == nil { + out = append(out, lo...) } } } diff --git a/schema/loader.go b/schema/loader.go index b06f83e..05a0990 100644 --- a/schema/loader.go +++ b/schema/loader.go @@ -18,6 +18,7 @@ type Link struct { TargetType string `json:"target_type"` Multiplicity string `json:multiplicity` Required bool `json:"required"` + Subgroup []Link `json:"subgroup"` } type Value struct {