-
Notifications
You must be signed in to change notification settings - Fork 1
/
glue.go
113 lines (108 loc) · 3.13 KB
/
glue.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package glue
import (
"fmt"
iface "github.com/opesun/nocrud/frame/interfaces"
"github.com/opesun/nocrud/frame/lang"
"github.com/opesun/nocrud/frame/lang/speaker"
"github.com/opesun/nocrud/frame/mod"
"github.com/opesun/nocrud/frame/verbinfo"
)
type Descriptor struct {
Route *lang.Route
Sentence *lang.Sentence
VerbLocation string // Name of the module with the verb.
nounOpt map[string]interface{}
}
func moduleHasVerb(modname string, verbname string) bool {
mo := mod.NewModule(modname)
if !mo.Exists() {
return false
}
return mo.Instance().HasMethod(verbname)
}
func Identify(path string, nouns map[string]interface{}, inp map[string]interface{}) (*Descriptor, error) {
desc := &Descriptor{}
r, err := lang.NewRoute(path, inp)
if err != nil {
return nil, err
}
desc.Route = r
speaker := speaker.New(moduleHasVerb, nouns)
sentence, err := lang.NewSentence(r, speaker)
if err != nil {
return nil, err
}
desc.Sentence = sentence
nounOpt, has := nouns[sentence.Noun].(map[string]interface{})
if !has {
return nil, fmt.Errorf("Noun opt is missing or not a map.")
}
desc.nounOpt = nounOpt
loc := speaker.VerbLocation(sentence.Noun, sentence.Verb)
if loc == "" {
return nil, fmt.Errorf("Verb %v in noun %v is not defined.", sentence.Verb, sentence.Noun)
}
desc.VerbLocation = loc
return desc, nil
}
// Returns error if input is not valid according to the rules found in d.nouns
func (d *Descriptor) CreateInputs(filterCreator func(string, map[string]interface{}) (iface.Filter, error)) ([]interface{}, map[string]interface{}, error) {
module := mod.NewModule(d.VerbLocation)
if !module.Exists() {
return nil, nil, fmt.Errorf("Module named %v does not exist.", d.VerbLocation)
}
ins := module.Instance()
verb := ins.Method(d.Sentence.Verb)
an := verbinfo.NewAnalyzer(verb)
ac := an.ArgCount()
if len(d.Route.Queries) < ac {
return nil, nil, fmt.Errorf("Not enough input to supply.")
}
if ac == 0 {
return nil, nil, nil
}
fc := an.FilterCount()
if fc > 0 && filterCreator == nil {
return nil, nil, fmt.Errorf("filterCreator is needed but it is nil.")
}
var inp []interface{}
var data map[string]interface{}
source := []map[string]interface{}{}
for _, v := range d.Route.Queries {
source = append(source, v)
}
if an.NeedsData() {
data = source[len(source)-1]
if data == nil {
data = map[string]interface{}{} // !Important.
}
}
if fc > 0 {
if fc != 1 && len(source) != fc {
return nil, nil, fmt.Errorf("Got %v inputs, but method %v needs only %v filters. Currently filters can only be reduced to 1.", len(source), d.Sentence.Verb, fc)
}
filters := []iface.Filter{}
for i, v := range source {
if d.Sentence.Verb != "Get" && d.Sentence.Verb != "GetSingle" && i == len(source)-1 {
break
}
filt, err := filterCreator(d.Route.Words[i], v)
if err != nil {
return nil, nil, err
}
filters = append(filters, filt)
}
if len(filters) > 1 {
filter := filters[0]
red, err := filter.Reduce(filters[1:]...)
if err != nil {
return nil, nil, err
}
filters = []iface.Filter{red}
}
for _, v := range filters {
inp = append(inp, v)
}
}
return inp, data, nil
}