diff --git a/go/seatdef/callers.go b/go/seatdef/callers.go index 177e4c16..ba60222d 100644 --- a/go/seatdef/callers.go +++ b/go/seatdef/callers.go @@ -101,6 +101,28 @@ func CallerEntryProblem(e string) string { "holder:@same-node", e) } +// DefaultCallers are the callers a verb that names none takes by its class (design 47 G §391): a read takes invokers, +// persons and sessions; an act the operator and sessions; a warrant the operator. A verb that names no class is a +// read. +func DefaultCallers(class string) []string { + switch class { + case ClassAct: + return []string{CallerOperator, CallerSessions} + case ClassWarrant: + return []string{CallerOperator} + } + return []string{CallerInvokers, CallerPersons, CallerSessions} +} + +// EffectiveCallers are the callers the verb is open to: the list it names, or the default of its class. A verb whose +// callers are text, as the definitions before G wrote them, names no list and takes the default. +func (v Verb) EffectiveCallers() []string { + if v.Callers != nil && !v.Callers.IsText() { + return v.Callers.List + } + return DefaultCallers(v.Class) +} + // The classes of a verb (design 47 G §391). const ( ClassRead = "read" diff --git a/go/seatdef/seatdef_test.go b/go/seatdef/seatdef_test.go index abaa9720..206db19f 100644 --- a/go/seatdef/seatdef_test.go +++ b/go/seatdef/seatdef_test.go @@ -283,3 +283,22 @@ func TestAKeptEventsStreamIsNamedFromTheSeatAndTheEvent(t *testing.T) { t.Errorf("the stream is %s", got) } } + +// Design 47 G §391: a verb that names no callers takes its class's default, a verb that names them keeps them. +func TestAVerbWithoutCallersTakesItsClassDefault(t *testing.T) { + for _, c := range []struct { + verb Verb + want string + }{ + {Verb{}, "invokers persons sessions"}, + {Verb{Class: ClassRead}, "invokers persons sessions"}, + {Verb{Class: ClassAct}, "operator sessions"}, + {Verb{Class: ClassWarrant}, "operator"}, + {Verb{Class: ClassAct, Callers: &Callers{List: []string{"seat:mesh-broker"}}}, "seat:mesh-broker"}, + {Verb{Class: ClassWarrant, Callers: &Callers{Text: "a person"}}, "operator"}, + } { + if got := strings.Join(c.verb.EffectiveCallers(), " "); got != c.want { + t.Errorf("%+v is open to %q, want %q", c.verb, got, c.want) + } +} +}