123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- package domain
- import (
- "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger"
- "git.sxidc.com/go-framework/baize/framework/core/tag/check"
- "git.sxidc.com/go-tools/utils/reflectutils"
- "git.sxidc.com/go-tools/utils/strutils"
- "git.sxidc.com/go-tools/utils/template"
- "github.com/iancoleman/strcase"
- "github.com/pkg/errors"
- "reflect"
- )
- const (
- WhenCreate = "create"
- WhenDelete = "delete"
- WhenUpdate = "update"
- )
- // Object 领域对象接口
- type Object interface {
- // DomainCNName 返回领域的中文名称
- DomainCNName() string
- // DomainCamelName 返回领域的大写驼峰式名称
- DomainCamelName() string
- // GetFieldMap 获取字段解释map
- GetFieldMap() map[string]string
- }
- // HasField 校验领域对象中是否有某一个字段
- // 参数:
- // - object: 领域对象
- // - fieldName: 字段名
- // 返回值:
- // - 是否存在
- func HasField(object Object, fieldName string) bool {
- return hasField(object, fieldName)
- }
- // CheckFieldsForCreate 为创建校验领域对象字段
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // 返回值:
- // - 错误
- func CheckFieldsForCreate(object Object, fieldMap map[string]string) error {
- return CheckWhen(object, fieldMap, WhenCreate)
- }
- // CheckFieldsForDelete 为删除校验领域对象字段
- //
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // 返回值:
- // - 错误
- func CheckFieldsForDelete(object Object, fieldMap map[string]string) error {
- return CheckWhen(object, fieldMap, WhenDelete)
- }
- // CheckFieldsForUpdate 为更新校验领域对象字段
- //
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // 返回值:
- // - 错误
- func CheckFieldsForUpdate(object Object, fieldMap map[string]string) error {
- return CheckFieldsWhen(object, fieldMap, WhenUpdate, func(fieldName string) bool {
- fieldValue, err := getFieldValue(object, fieldName)
- if err != nil {
- logger.GetInstance().Error(err)
- return false
- }
- if !fieldValue.IsValid() {
- return false
- }
- if fieldValue.IsZero() {
- return false
- }
- if fieldValue.Kind() == reflect.Pointer && fieldValue.IsNil() {
- return false
- }
- return true
- })
- }
- // Check 校验领域对象
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // - when: 何时校验
- // 返回值:
- // - 错误
- func Check(object Object, fieldMap map[string]string) error {
- err := check.Struct(object, fieldMap).CheckWhen("")
- if err != nil {
- return errors.New(object.DomainCNName() + ": " + err.Error())
- }
- return nil
- }
- // CheckField 校验领域对象字段
- // 参数:
- // - object: 领域对象
- // - fieldName: 字段名
- // - fieldMap: 字段说明map
- // 返回值:
- // - 错误
- func CheckField(object Object, fieldName string, fieldMap map[string]string) error {
- err := check.Struct(object, fieldMap).CheckFieldWhen("", func(fn string) bool {
- if fieldName == fn {
- return true
- }
- return false
- })
- if err != nil {
- return errors.New(object.DomainCNName() + ": " + err.Error())
- }
- return nil
- }
- // CheckFields 校验领域对象字段
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // - checkFunc: 检查函数,返回true检查该字段,返回false不检查该字段
- // 返回值:
- // - 错误
- func CheckFields(object Object, fieldMap map[string]string, checkFunc func(fieldName string) bool) error {
- err := check.Struct(object, fieldMap).CheckFieldWhen("", checkFunc)
- if err != nil {
- return errors.New(object.DomainCNName() + ": " + err.Error())
- }
- return nil
- }
- // CheckWhen 校验领域对象
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // - when: 何时校验
- // 返回值:
- // - 错误
- func CheckWhen(object Object, fieldMap map[string]string, when string) error {
- err := check.Struct(object, fieldMap).CheckWhen(when)
- if err != nil {
- return errors.New(object.DomainCNName() + ": " + err.Error())
- }
- return nil
- }
- // CheckFieldWhen 校验领域对象字段
- // 参数:
- // - object: 领域对象
- // - fieldName: 字段名
- // - fieldMap: 字段说明map
- // - when: 何时校验
- // 返回值:
- // - 错误
- func CheckFieldWhen(object Object, fieldName string, fieldMap map[string]string, when string) error {
- err := check.Struct(object, fieldMap).CheckFieldWhen(when, func(fn string) bool {
- if fieldName == fn {
- return true
- }
- return false
- })
- if err != nil {
- return errors.New(object.DomainCNName() + ":\n" + err.Error())
- }
- return nil
- }
- // CheckFieldsWhen 校验领域对象字段
- // 参数:
- // - object: 领域对象
- // - fieldMap: 字段说明map
- // - when: 何时校验
- // - checkFunc: 检查函数,返回true检查该字段,返回false不检查该字段
- // 返回值:
- // - 错误
- func CheckFieldsWhen(object Object, fieldMap map[string]string, when string, checkFunc func(fieldName string) bool) error {
- err := check.Struct(object, fieldMap).CheckFieldWhen(when, checkFunc)
- if err != nil {
- return errors.New(object.DomainCNName() + ": " + err.Error())
- }
- return nil
- }
- // SetField 设置领域对象对应字段的值
- // 类型参数:
- // - T: 字段值的类型
- // 参数:
- // - object: 领域对象
- // - fieldName: 要设置值的字段名
- // - value: 设置的值
- // 返回值:
- // - 错误
- func SetField[T any](object Object, fieldName string, value T) error {
- if object == nil {
- return errors.New("领域对象为nil")
- }
- fieldValue, err := getFieldValue(object, fieldName)
- if err != nil {
- return err
- }
- if !fieldValue.IsValid() || !fieldValue.CanSet() {
- return errors.New("领域对象" + fieldValue.Type().String() + "的字段" + fieldName + "无法赋值")
- }
- fieldValue.Set(reflect.ValueOf(value))
- return nil
- }
- // Field 获取领域对象对应字段的值
- // 类型参数:
- // - T: 字段值的类型
- // 参数:
- // - object: 领域对象
- // - fieldName: 要获取值的字段名
- // 返回值:
- // - 错误
- func Field[T any](object Object, fieldName string) (T, error) {
- zero := reflectutils.Zero[T]()
- if object == nil {
- return zero, errors.New("领域对象为nil")
- }
- fieldValue, err := getFieldValue(object, fieldName)
- if err != nil {
- return zero, err
- }
- if !fieldValue.IsValid() {
- return zero, errors.New("领域对象" + fieldValue.Type().String() + "的字段" + fieldName + "无法赋值")
- }
- retValue, ok := fieldValue.Interface().(T)
- if !ok {
- return zero, errors.New("转换字段类型失败")
- }
- return retValue, nil
- }
- // ToConcrete 将领域对象转换为具体类型
- // 类型参数:
- // - T: 要转换到的类型
- // 参数:
- // - object: 领域对象
- // 返回值:
- // - 转换出的类型
- // - 错误
- func ToConcrete[T Object](object Object) (T, error) {
- zero := reflectutils.Zero[T]()
- if object == nil {
- return zero, errors.New("领域对象为nil")
- }
- concrete, ok := object.(T)
- if !ok {
- return zero, errors.New("领域对象转化失败")
- }
- return concrete, nil
- }
- // TableName 基于领域对象生成表名,实际是将领域对象的驼峰式名称转换为蛇形复数形式,如classes
- // 参数:
- // - schema: 数据库的schema
- // - object: 领域对象
- // 返回值:
- // - 表名
- func TableName(schema string, object Object) string {
- if strutils.IsStringEmpty(schema) {
- return template.Plural(strcase.ToSnake(template.Id(object.DomainCamelName())))
- } else {
- return schema + "." + template.Plural(strcase.ToSnake(template.Id(object.DomainCamelName())))
- }
- }
- // RelationTableName 生成两个领域对象的关联表名,实际是将两个领域对象的驼峰式名称转换为蛇形并使用and连接,如:class_and_student
- // 参数:
- // - schema: 数据库的schema
- // - left: 左领域对象
- // - right: 右领域对象
- // 返回值:
- // - 关联表名
- func RelationTableName(schema string, left Object, right Object) string {
- if strutils.IsStringEmpty(schema) {
- return strcase.ToSnake(template.Id(left.DomainCamelName())) + "_and_" + strcase.ToSnake(template.Id(right.DomainCamelName()))
- } else {
- return schema + "." + strcase.ToSnake(template.Id(left.DomainCamelName())) + "_and_" + strcase.ToSnake(template.Id(right.DomainCamelName()))
- }
- }
- // ColumnName 生成对应字段的列名,实际为字段名转换为蛇形,如StudentNum会转化为student_num
- // 参数:
- // - fieldName: 字段名
- // 返回值:
- // - 列名
- func ColumnName(fieldName string) string {
- return strcase.ToSnake(template.Id(fieldName))
- }
- // RelationColumnName 基于领域对象生成关联列名,实际为字段名转换为蛇形后加_id,如Student生成的关联列名为student_id
- // 参数:
- // - object: 领域对象
- // 返回值:
- // - 关联列名
- func RelationColumnName(object Object) string {
- return strcase.ToSnake(template.Id(object.DomainCamelName())) + "_id"
- }
- // RelativeDomainPath 基于领域对象生成领域URL路径,实际为字段名转换为左小写驼峰式前面加/,如Student生成的领域URL路径为/student
- // 参数:
- // - object: 领域对象
- // 返回值:
- // - 领域URL路径
- func RelativeDomainPath(object Object) string {
- return "/" + strcase.ToLowerCamel(template.Id(object.DomainCamelName()))
- }
- // SnakeDomainName 基于领域对象生成蛇形领域名称,如Student生成的蛇形领域名称为/student
- // 参数:
- // - object: 领域对象
- // 返回值:
- // - 蛇形领域名称
- func SnakeDomainName(object Object) string {
- return strcase.ToSnake(template.Id(object.DomainCamelName()))
- }
- func hasField(object Object, fieldName string) bool {
- if object == nil {
- return false
- }
- objectValue := reflect.ValueOf(object)
- if !reflectutils.IsValueStructOrStructPointer(objectValue) {
- return false
- }
- fieldValue := reflectutils.PointerValueElem(objectValue).FieldByName(fieldName)
- if !fieldValue.IsValid() {
- return false
- }
- return true
- }
- func getFieldValue(object Object, fieldName string) (*reflect.Value, error) {
- if object == nil {
- return nil, errors.New("领域对象为nil")
- }
- objectValue := reflect.ValueOf(object)
- if !reflectutils.IsValueStructOrStructPointer(objectValue) {
- return nil, errors.New("领域对象必须是结构或结构指针")
- }
- fieldValue := reflectutils.PointerValueElem(objectValue).FieldByName(fieldName)
- return &fieldValue, nil
- }
|