| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | 
							- package ii
 
- import (
 
- 	"fmt"
 
- 	"reflect"
 
- 	"strings"
 
- 	"golib/features/mo"
 
- )
 
- var (
 
- 	errUnknownFiled = func(name Name, key string) error {
 
- 		return fmt.Errorf("unknown filed: %s.%s", name, key)
 
- 	}
 
- )
 
- // ItemInfo XML 配置, 每个 XML 应当包含 _id 字段
 
- type ItemInfo struct {
 
- 	Name   Name        `xml:"Name,attr"`
 
- 	Label  string      `xml:"Label,attr"`
 
- 	Fields []FieldInfo `xml:"Fields>Field"`
 
- 	FieldMap    map[string]int
 
- 	RequiredMap map[string]int // 必填
 
- 	UniqueMap   map[string]int // 需要调用 SetUnique 设置唯一键
 
- }
 
- // Open 使用 Name 包含的数据库和表然后打开一个操作
 
- func (c *ItemInfo) Open(client *mo.Client) *mo.Shortcut {
 
- 	return mo.NewShortcut(client.Database(c.Name.Database()).Collection(c.Name.Collection()))
 
- }
 
- // PrepareNew 创一个列表, 包含所有 Fields 的 name 和默认值
 
- func (c *ItemInfo) PrepareNew() mo.D {
 
- 	f := make(mo.D, len(c.Fields))
 
- 	for i, field := range c.Fields {
 
- 		f[i] = mo.E{Key: field.Name, Value: field.DefaultValue()}
 
- 	}
 
- 	return f
 
- }
 
- // PrepareInsert 准备插入的数据
 
- func (c *ItemInfo) PrepareInsert(doc mo.M, u User) error {
 
- 	for key, val := range doc {
 
- 		field, ok := c.Field(key)
 
- 		if !ok {
 
- 			// 特殊处理 _id
 
- 			if key == mo.ID.Key() {
 
- 				if oid, ok := val.(mo.ObjectID); !(ok && !oid.IsZero()) {
 
- 					return fmt.Errorf("invalid ObjectID: %s(%v)", reflect.TypeOf(val), val)
 
- 				}
 
- 			}
 
- 			// 不允许添加配置文件中不存在的字段
 
- 			return errUnknownFiled(c.Name, key)
 
- 		}
 
- 		// 校验和格式化数据
 
- 		if err := field.Validate(val); err != nil {
 
- 			val, err = field.Convert(val)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		doc[field.Name] = val
 
- 	}
 
- 	// 校验必填
 
- 	for key := range c.RequiredMap {
 
- 		if _, ok := doc[key]; !ok {
 
- 			return errRequired(key, doc)
 
- 		}
 
- 	}
 
- 	// 填充配置文件中已存在的字段
 
- 	fList := c.PrepareNew()
 
- 	for _, e := range fList {
 
- 		if _, ok := doc[e.Key]; ok {
 
- 			continue
 
- 		}
 
- 		doc[e.Key] = e.Value
 
- 	}
 
- 	doc[Creator] = u.ID()
 
- 	doc[CreationTime] = mo.NewDateTime()
 
- 	return nil
 
- }
 
- // PrepareUpdate 准备更新的数据
 
- func (c *ItemInfo) PrepareUpdate(doc mo.M, u User) error {
 
- 	for k, v := range doc {
 
- 		field, ok := c.Field(k)
 
- 		if !ok {
 
- 			return errUnknownFiled(c.Name, k)
 
- 		}
 
- 		if err := field.Validate(v); err != nil {
 
- 			v, err = field.Convert(v)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		doc[k] = v
 
- 	}
 
- 	doc[LastUpdater] = u.ID()
 
- 	return nil
 
- }
 
- // PrepareFilter 检查 key 是否包在 itemName 中, 防止 SQL 注入
 
- func (c *ItemInfo) PrepareFilter(filter mo.D) error {
 
- 	for _, ele := range filter {
 
- 		// 不检查包含 . 的字段, 用于子 map 查找
 
- 		if strings.ContainsRune(ele.Key, '.') {
 
- 			continue
 
- 		}
 
- 		if _, ok := c.Field(ele.Key); !ok {
 
- 			return errUnknownFiled(c.Name, ele.Key)
 
- 		}
 
- 	}
 
- 	return nil
 
- }
 
- func (c *ItemInfo) Field(name string) (FieldInfo, bool) {
 
- 	if field, ok := internalField[name]; ok {
 
- 		if idx, o := c.FieldMap[name]; o {
 
- 			return c.Fields[idx], true
 
- 		}
 
- 		return field, true
 
- 	}
 
- 	idx, ok := c.FieldMap[name]
 
- 	if !ok {
 
- 		return FieldInfo{}, false
 
- 	}
 
- 	return c.Fields[idx], true
 
- }
 
- func (c *ItemInfo) FieldType(t mo.Type) []FieldInfo {
 
- 	fields := make([]FieldInfo, 0)
 
- 	for _, field := range c.Fields {
 
- 		if field.Type == t {
 
- 			fields = append(fields, field)
 
- 		}
 
- 	}
 
- 	return fields
 
- }
 
 
  |