173 lines
3.7 KiB
Go
173 lines
3.7 KiB
Go
package mgoapi
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"gitbase.de/gopackage/mgocrud"
|
|
"github.com/gin-gonic/gin"
|
|
mgo "gopkg.in/mgo.v2"
|
|
"gopkg.in/mgo.v2/bson"
|
|
)
|
|
|
|
func errorObject(err error) bson.M {
|
|
o := bson.M{"error": err.Error()}
|
|
if e, ok := err.(*mgocrud.ErrorWithStack); ok {
|
|
o["stack"] = e.Stack()
|
|
}
|
|
return o
|
|
}
|
|
|
|
func modelTypeOf(m interface{}) reflect.Type {
|
|
return reflect.TypeOf(
|
|
reflect.ValueOf(m).Elem().Interface(),
|
|
)
|
|
}
|
|
|
|
func newModelOf(m interface{}) interface{} {
|
|
return reflect.New(
|
|
modelTypeOf(m),
|
|
).Interface()
|
|
}
|
|
|
|
func string2ObjectID(id string) (objectID *bson.ObjectId, err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
switch x := r.(type) {
|
|
case string:
|
|
err = errors.New(x)
|
|
case error:
|
|
err = x
|
|
default:
|
|
err = errors.New("Unknown panic in: string2ObjectID")
|
|
}
|
|
}
|
|
}()
|
|
oID := bson.ObjectIdHex(id)
|
|
return &oID, err
|
|
}
|
|
|
|
func getStructMeta(s reflect.Type, dontRecurse map[string]bool) []map[string]interface{} {
|
|
if s.Kind() == reflect.Ptr {
|
|
s = s.Elem()
|
|
}
|
|
|
|
numField := s.NumField()
|
|
meta := make([]map[string]interface{}, 0, numField+3)
|
|
|
|
for i := 0; i < numField; i++ {
|
|
f := s.Field(i)
|
|
jsonTag := strings.Split(f.Tag.Get("json"), ",")
|
|
|
|
if jsonTag[0] != "-" {
|
|
_type := f.Type
|
|
|
|
kind := f.Type.Kind()
|
|
if kind == reflect.Ptr {
|
|
_type = _type.Elem()
|
|
}
|
|
|
|
if f.Anonymous {
|
|
// embed directly
|
|
embed := getStructMeta(_type, dontRecurse)
|
|
for _, e := range embed {
|
|
meta = append(meta, e)
|
|
}
|
|
} else {
|
|
fMeta := make(map[string]interface{})
|
|
|
|
fName := f.Name
|
|
if jsonTag[0] != "" {
|
|
fName = jsonTag[0]
|
|
}
|
|
fMeta["name"] = fName
|
|
|
|
fType := _type.Name()
|
|
if fType == "" {
|
|
fType = _type.String()
|
|
}
|
|
//fType = strings.Replace(fType, "*", "", -1)
|
|
fType = regexp.MustCompile("\\*[a-zA-Z0-9]*\\.?").ReplaceAllString(fType, "")
|
|
fMeta["type"] = fType
|
|
kind = _type.Kind()
|
|
fMeta["kind"] = kind.String()
|
|
|
|
if vT := f.Tag.Get("validator"); vT != "" {
|
|
fMeta["validator"] = strings.Split(vT, ",")
|
|
}
|
|
/*
|
|
|
|
if vT := f.Tag.Get("class"); vT != "" {
|
|
fMeta["class"] = strings.Split(vT, ",")
|
|
}
|
|
|
|
if lT := f.Tag.Get("label"); lT != "" {
|
|
fMeta["label"] = lT
|
|
}
|
|
*/
|
|
if vM := f.Tag.Get("meta"); vM != "" {
|
|
m := strings.Split(vM, ";")
|
|
for _, mP := range m {
|
|
p := strings.Split(mP, "=")
|
|
if len(p) > 1 {
|
|
pp := strings.Split(p[1], ",")
|
|
if len(pp) == 1 {
|
|
fMeta[p[0]] = pp[0]
|
|
} else {
|
|
fMeta[p[0]] = pp
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if kind == reflect.Struct && !dontRecurse[fType] {
|
|
dontRecurse[fType] = true
|
|
fMeta[kind.String()+"Of"] = getStructMeta(_type, dontRecurse)
|
|
} else if kind == reflect.Slice && !dontRecurse[fType] {
|
|
sliceEl := _type.Elem()
|
|
if sliceEl.Kind() == reflect.Ptr {
|
|
sliceEl = sliceEl.Elem()
|
|
}
|
|
if sliceEl.Kind() == reflect.Struct {
|
|
dontRecurse[fType] = true
|
|
fMeta[kind.String()+"Of"] = getStructMeta(sliceEl, dontRecurse)
|
|
} else {
|
|
fMeta[kind.String()+"Of"] = sliceEl.String()
|
|
}
|
|
}
|
|
|
|
meta = append(meta, fMeta)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return meta
|
|
}
|
|
|
|
func getModelMeta(m mgocrud.ModelInterface) []map[string]interface{} {
|
|
dontRecurse := map[string]bool{
|
|
"Time": true,
|
|
"ObjectId": true,
|
|
}
|
|
modelType := reflect.ValueOf(m).Elem().Type()
|
|
|
|
return getStructMeta(modelType, dontRecurse)
|
|
}
|
|
|
|
func getDocument(c *gin.Context, db *mgo.Database, m mgocrud.ModelInterface, selector bson.M) (mgocrud.ModelInterface, error) {
|
|
objectID, err := string2ObjectID(c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newM := newModelOf(m).(mgocrud.ModelInterface)
|
|
newM.SetID(objectID)
|
|
err = mgocrud.ReadDocument(db, newM, selector)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newM, nil
|
|
}
|