Migrate Typer and type-detection functions to vocab

This helps ensure that the code to detect specific ActivityStream types
continues to live in the code-generation algorithms, reducing
maintenance burdens.
このコミットが含まれているのは:
Cory Slep 2018-06-12 23:29:30 +02:00
コミット fb16747c4e
7個のファイルの変更1299行の追加465行の削除

ファイルの表示

@ -308,7 +308,7 @@ func (f *federator) PostOutbox(c context.Context, w http.ResponseWriter, r *http
if err != nil {
return true, err
}
if !isActivityType(typer) {
if !vocab.IsActivityType(typer) {
actorIri, err := f.SocialAPI.ActorIRI(c, r)
if err != nil {
return true, err

ファイルの表示

@ -125,7 +125,7 @@ func serveActivityPubObject(c context.Context, a Application, clock Clock, w htt
return
}
addResponseHeaders(w.Header(), clock, b)
if hasType(pObj, tombstone) {
if vocab.HasTypeTombstone(pObj) {
w.WriteHeader(http.StatusGone)
} else {
w.WriteHeader(http.StatusOK)

ファイルの表示

@ -307,8 +307,7 @@ type PubObject interface {
// Typer is an object that has a type.
type Typer interface {
TypeLen() (l int)
GetType(index int) (v interface{})
vocab.Typer
}
// typeIder is a Typer with additional generic capabilities.

ファイルの表示

@ -208,7 +208,7 @@ func postToOutbox(c HttpClient, b []byte, to *url.URL, agent string, creds *cred
func (f *federator) addNewIds(c context.Context, a vocab.ActivityType) {
newId := f.App.NewId(c, a)
a.SetId(newId)
if hasType(a, create) {
if vocab.HasTypeCreate(a) {
for i := 0; i < a.ObjectLen(); i++ {
if a.IsObject(i) {
obj := a.GetObject(i)
@ -2123,39 +2123,3 @@ func clearSensitiveFields(obj vocab.ObjectType) {
}
}
}
// TODO: Move this to vocab package.
var activityTypes = []string{"Accept", "Add", "Announce", "Arrive", "Block", "Create", "Delete", "Dislike", "Flag", "Follow", "Ignore", "Invite", "Join", "Leave", "Like", "Listen", "Move", "Offer", "Question", "Reject", "Read", "Remove", "TentativeReject", "TentativeAccept", "Travel", "Undo", "Update", "View"}
const (
tombstone = "Tombstone"
create = "Create"
)
func isActivityType(t Typer) bool {
hasType := make(map[string]bool, 1)
for i := 0; i < t.TypeLen(); i++ {
v := t.GetType(i)
if s, ok := v.(string); ok {
hasType[s] = true
}
}
for _, t := range activityTypes {
if hasType[t] {
return true
}
}
return false
}
func hasType(t Typer, kind string) bool {
for i := 0; i < t.TypeLen(); i++ {
v := t.GetType(i)
if s, ok := v.(string); ok {
if s == kind {
return true
}
}
}
return false
}

ファイルの表示

@ -1942,3 +1942,18 @@ func AnyURIValueTypeName() string {
func IRIFuncs() []*FunctionDef {
return []*FunctionDef{IriValueType.DeserializeFn, IriValueType.SerializeFn}
}
func IsActivity(t *Type) bool {
var recur func(t *Type) bool
recur = func(t *Type) bool {
for _, e := range t.Extends {
if e == activityType {
return true
} else if recur(e) {
return true
}
}
return false
}
return recur(t)
}

ファイルの表示

@ -7,6 +7,7 @@ import (
"fmt"
"github.com/go-fed/activity/tools/defs"
"go/format"
"strings"
)
const (
@ -44,6 +45,8 @@ func GenerateImplementations(types []*defs.Type, properties []*defs.PropertyType
p.F = append(p.F, v.DeserializeFn, v.SerializeFn)
}
p.F = append(p.F, defs.IRIFuncs()...)
p.F = append(p.F, generateHasTypeFuncs(types)...)
p.I = append(p.I, generateTyperInterface())
// Add functions to resolve string 'name' into concrete types
p.F = append(p.F, generateResolveObjectFunction(types))
@ -60,6 +63,78 @@ func GenerateImplementations(types []*defs.Type, properties []*defs.PropertyType
return format.Source([]byte(p.Generate()))
}
func generateTyperInterface() *defs.InterfaceDef {
return &defs.InterfaceDef{
Typename: "Typer",
Comment: "Typer supports common functions for determining an ActivityStream type",
F: []*defs.FunctionDef{
{
Name: "TypeLen",
Return: []*defs.FunctionVarDef{{Name: "l", Type: "int"}},
},
{
Name: "GetType",
Args: []*defs.FunctionVarDef{{Name: "index", Type: "int"}},
Return: []*defs.FunctionVarDef{{Name: "v", Type: "interface{}"}},
},
},
}
}
func generateHasTypeFuncs(types []*defs.Type) (f []*defs.FunctionDef) {
var activityTypes []string
for _, t := range types {
t := t
if defs.IsActivity(t) {
activityTypes = append(activityTypes, t.Name)
}
f = append(f, &defs.FunctionDef{
Name: fmt.Sprintf("HasType%s", t.Name),
Comment: fmt.Sprintf("HasType%s returns true if the Typer has a type of %s.", t.Name, t.Name),
Args: []*defs.FunctionVarDef{{Name: "t", Type: "Typer"}},
Return: []*defs.FunctionVarDef{{Name: "b", Type: "bool"}},
Body: func() string {
var b bytes.Buffer
b.WriteString("for i := 0; i < t.TypeLen(); i++ {\n")
b.WriteString("v := t.GetType(i)\n")
b.WriteString("if s, ok := v.(string); ok {\n")
b.WriteString(fmt.Sprintf("if s == \"%s\" {\n", t.Name))
b.WriteString("return true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("return false\n")
return b.String()
},
})
}
f = append(f, &defs.FunctionDef{
Name: "IsActivityType",
Comment: "Returns true if the provided Typer is an Activity.",
Args: []*defs.FunctionVarDef{{Name: "t", Type: "Typer"}},
Return: []*defs.FunctionVarDef{{Name: "b", Type: "bool"}},
Body: func() string {
var b bytes.Buffer
b.WriteString(fmt.Sprintf("var activityTypes = []string{\"%s\"}\n", strings.Join(activityTypes, "\", \"")))
b.WriteString("hasType := make(map[string]bool, 1)\n")
b.WriteString("for i := 0; i < t.TypeLen(); i++ {\n")
b.WriteString("v := t.GetType(i)\n")
b.WriteString("if s, ok := v.(string); ok {\n")
b.WriteString("hasType[s] = true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("for _, t := range activityTypes {\n")
b.WriteString("if hasType[t] {\n")
b.WriteString("return true\n")
b.WriteString("}\n")
b.WriteString("}\n")
b.WriteString("return false\n")
return b.String()
},
})
return
}
func generatePackageDefinition() *defs.PackageDef {
return &defs.PackageDef{
Name: "vocab",

ファイル差分が大きすぎるため省略します 差分を読み込み