object.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package domain
  2. import (
  3. "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger"
  4. "git.sxidc.com/go-framework/baize/framework/core/tag/check"
  5. "git.sxidc.com/go-tools/utils/reflectutils"
  6. "git.sxidc.com/go-tools/utils/strutils"
  7. "git.sxidc.com/go-tools/utils/template"
  8. "github.com/iancoleman/strcase"
  9. "github.com/pkg/errors"
  10. "reflect"
  11. )
  12. const (
  13. WhenCreate = "create"
  14. WhenDelete = "delete"
  15. WhenUpdate = "update"
  16. )
  17. // Object 领域对象接口
  18. type Object interface {
  19. // DomainCNName 返回领域的中文名称
  20. DomainCNName() string
  21. // DomainCamelName 返回领域的大写驼峰式名称
  22. DomainCamelName() string
  23. // 获取字段解释map
  24. GetFieldMap() map[string]string
  25. }
  26. // HasField 校验领域对象中是否有某一个字段
  27. // 参数:
  28. // - object: 领域对象
  29. // - fieldName: 字段名
  30. // 返回值:
  31. // - 是否存在
  32. func HasField(object Object, fieldName string) bool {
  33. return hasField(object, fieldName)
  34. }
  35. // CheckFieldsForCreate 为创建校验领域对象字段
  36. // 参数:
  37. // - object: 领域对象
  38. // - fieldMap: 字段说明map
  39. // 返回值:
  40. // - 错误
  41. func CheckFieldsForCreate(object Object, fieldMap map[string]string) error {
  42. return CheckWhen(object, fieldMap, WhenCreate)
  43. }
  44. // CheckFieldsForDelete 为删除校验领域对象字段
  45. //
  46. // 参数:
  47. // - object: 领域对象
  48. // - fieldMap: 字段说明map
  49. // 返回值:
  50. // - 错误
  51. func CheckFieldsForDelete(object Object, fieldMap map[string]string) error {
  52. return CheckWhen(object, fieldMap, WhenDelete)
  53. }
  54. // CheckFieldsForUpdate 为更新校验领域对象字段
  55. //
  56. // 参数:
  57. // - object: 领域对象
  58. // - fieldMap: 字段说明map
  59. // 返回值:
  60. // - 错误
  61. func CheckFieldsForUpdate(object Object, fieldMap map[string]string) error {
  62. return CheckFieldsWhen(object, fieldMap, WhenUpdate, func(fieldName string) bool {
  63. fieldValue, err := getFieldValue(object, fieldName)
  64. if err != nil {
  65. logger.GetInstance().Error(err)
  66. return false
  67. }
  68. if !fieldValue.IsValid() {
  69. return false
  70. }
  71. if fieldValue.IsZero() {
  72. return false
  73. }
  74. if fieldValue.IsNil() {
  75. return false
  76. }
  77. return true
  78. })
  79. }
  80. // Check 校验领域对象
  81. // 参数:
  82. // - object: 领域对象
  83. // - fieldMap: 字段说明map
  84. // - when: 何时校验
  85. // 返回值:
  86. // - 错误
  87. func Check(object Object, fieldMap map[string]string) error {
  88. err := check.Struct(object, fieldMap).CheckWhen("")
  89. if err != nil {
  90. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  91. }
  92. return nil
  93. }
  94. // CheckField 校验领域对象字段
  95. // 参数:
  96. // - object: 领域对象
  97. // - fieldName: 字段名
  98. // - fieldMap: 字段说明map
  99. // 返回值:
  100. // - 错误
  101. func CheckField(object Object, fieldName string, fieldMap map[string]string) error {
  102. err := check.Struct(object, fieldMap).CheckFieldWhen("", func(fieldName string) bool {
  103. if fieldName == fieldName {
  104. return true
  105. }
  106. return false
  107. })
  108. if err != nil {
  109. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  110. }
  111. return nil
  112. }
  113. // CheckFields 校验领域对象字段
  114. // 参数:
  115. // - object: 领域对象
  116. // - fieldMap: 字段说明map
  117. // - checkFunc: 检查函数,返回true检查该字段,返回false不检查该字段
  118. // 返回值:
  119. // - 错误
  120. func CheckFields(object Object, fieldMap map[string]string, checkFunc func(fieldName string) bool) error {
  121. err := check.Struct(object, fieldMap).CheckFieldWhen("", checkFunc)
  122. if err != nil {
  123. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  124. }
  125. return nil
  126. }
  127. // CheckWhen 校验领域对象
  128. // 参数:
  129. // - object: 领域对象
  130. // - fieldMap: 字段说明map
  131. // - when: 何时校验
  132. // 返回值:
  133. // - 错误
  134. func CheckWhen(object Object, fieldMap map[string]string, when string) error {
  135. err := check.Struct(object, fieldMap).CheckWhen(when)
  136. if err != nil {
  137. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  138. }
  139. return nil
  140. }
  141. // CheckFieldWhen 校验领域对象字段
  142. // 参数:
  143. // - object: 领域对象
  144. // - fieldName: 字段名
  145. // - fieldMap: 字段说明map
  146. // - when: 何时校验
  147. // 返回值:
  148. // - 错误
  149. func CheckFieldWhen(object Object, fieldName string, fieldMap map[string]string, when string) error {
  150. err := check.Struct(object, fieldMap).CheckFieldWhen(when, func(fieldName string) bool {
  151. if fieldName == fieldName {
  152. return true
  153. }
  154. return false
  155. })
  156. if err != nil {
  157. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  158. }
  159. return nil
  160. }
  161. // CheckFieldsWhen 校验领域对象字段
  162. // 参数:
  163. // - object: 领域对象
  164. // - fieldMap: 字段说明map
  165. // - when: 何时校验
  166. // - checkFunc: 检查函数,返回true检查该字段,返回false不检查该字段
  167. // 返回值:
  168. // - 错误
  169. func CheckFieldsWhen(object Object, fieldMap map[string]string, when string, checkFunc func(fieldName string) bool) error {
  170. err := check.Struct(object, fieldMap).CheckFieldWhen(when, checkFunc)
  171. if err != nil {
  172. return errors.New(object.DomainCNName() + ":\n" + err.Error())
  173. }
  174. return nil
  175. }
  176. // SetField 设置领域对象对应字段的值
  177. // 类型参数:
  178. // - T: 字段值的类型
  179. // 参数:
  180. // - object: 领域对象
  181. // - fieldName: 要设置值的字段名
  182. // - value: 设置的值
  183. // 返回值:
  184. // - 错误
  185. func SetField[T any](object Object, fieldName string, value T) error {
  186. if object == nil {
  187. return errors.New("领域对象为nil")
  188. }
  189. fieldValue, err := getFieldValue(object, fieldName)
  190. if err != nil {
  191. return err
  192. }
  193. if !fieldValue.IsValid() || !fieldValue.CanSet() {
  194. return errors.New("领域对象" + fieldValue.Type().String() + "的字段" + fieldName + "无法赋值")
  195. }
  196. fieldValue.Set(reflect.ValueOf(value))
  197. return nil
  198. }
  199. // Field 获取领域对象对应字段的值
  200. // 类型参数:
  201. // - T: 字段值的类型
  202. // 参数:
  203. // - object: 领域对象
  204. // - fieldName: 要获取值的字段名
  205. // 返回值:
  206. // - 错误
  207. func Field[T any](object Object, fieldName string) (T, error) {
  208. zero := reflectutils.Zero[T]()
  209. if object == nil {
  210. return zero, errors.New("领域对象为nil")
  211. }
  212. fieldValue, err := getFieldValue(object, fieldName)
  213. if err != nil {
  214. return zero, err
  215. }
  216. if !fieldValue.IsValid() {
  217. return zero, errors.New("领域对象" + fieldValue.Type().String() + "的字段" + fieldName + "无法赋值")
  218. }
  219. retValue, ok := fieldValue.Interface().(T)
  220. if !ok {
  221. return zero, errors.New("转换字段类型失败")
  222. }
  223. return retValue, nil
  224. }
  225. // ToConcrete 将领域对象转换为具体类型
  226. // 类型参数:
  227. // - T: 要转换到的类型
  228. // 参数:
  229. // - object: 领域对象
  230. // 返回值:
  231. // - 转换出的类型
  232. // - 错误
  233. func ToConcrete[T Object](object Object) (T, error) {
  234. zero := reflectutils.Zero[T]()
  235. if object == nil {
  236. return zero, errors.New("领域对象为nil")
  237. }
  238. concrete, ok := object.(T)
  239. if !ok {
  240. return zero, errors.New("领域对象转化失败")
  241. }
  242. return concrete, nil
  243. }
  244. // TableName 基于领域对象生成表名,实际是将领域对象的驼峰式名称转换为蛇形复数形式,如classes
  245. // 参数:
  246. // - schema: 数据库的schema
  247. // - object: 领域对象
  248. // 返回值:
  249. // - 表名
  250. func TableName(schema string, object Object) string {
  251. if strutils.IsStringEmpty(schema) {
  252. return template.Plural(strcase.ToSnake(template.Id(object.DomainCamelName())))
  253. } else {
  254. return schema + "." + template.Plural(strcase.ToSnake(template.Id(object.DomainCamelName())))
  255. }
  256. }
  257. // RelationTableName 生成两个领域对象的关联表名,实际是将两个领域对象的驼峰式名称转换为蛇形并使用and连接,如:class_and_student
  258. // 参数:
  259. // - schema: 数据库的schema
  260. // - left: 左领域对象
  261. // - right: 右领域对象
  262. // 返回值:
  263. // - 关联表名
  264. func RelationTableName(schema string, left Object, right Object) string {
  265. if strutils.IsStringEmpty(schema) {
  266. return strcase.ToSnake(template.Id(left.DomainCamelName())) + "_and_" + strcase.ToSnake(template.Id(right.DomainCamelName()))
  267. } else {
  268. return schema + "." + strcase.ToSnake(template.Id(left.DomainCamelName())) + "_and_" + strcase.ToSnake(template.Id(right.DomainCamelName()))
  269. }
  270. }
  271. // ColumnName 生成对应字段的列名,实际为字段名转换为蛇形,如StudentNum会转化为student_num
  272. // 参数:
  273. // - fieldName: 字段名
  274. // 返回值:
  275. // - 列名
  276. func ColumnName(fieldName string) string {
  277. return strcase.ToSnake(template.Id(fieldName))
  278. }
  279. // RelationColumnName 基于领域对象生成关联列名,实际为字段名转换为蛇形后加_id,如Student生成的关联列名为student_id
  280. // 参数:
  281. // - object: 领域对象
  282. // 返回值:
  283. // - 关联列名
  284. func RelationColumnName(object Object) string {
  285. return strcase.ToSnake(template.Id(object.DomainCamelName())) + "_id"
  286. }
  287. // RelativeDomainPath 基于领域对象生成领域URL路径,实际为字段名转换为左小写驼峰式前面加/,如Student生成的领域URL路径为/student
  288. // 参数:
  289. // - object: 领域对象
  290. // 返回值:
  291. // - 领域URL路径
  292. func RelativeDomainPath(object Object) string {
  293. return "/" + strcase.ToLowerCamel(template.Id(object.DomainCamelName()))
  294. }
  295. // SnakeDomainName 基于领域对象生成蛇形领域名称,如Student生成的蛇形领域名称为/student
  296. // 参数:
  297. // - object: 领域对象
  298. // 返回值:
  299. // - 蛇形领域名称
  300. func SnakeDomainName(object Object) string {
  301. return strcase.ToSnake(template.Id(object.DomainCamelName()))
  302. }
  303. func hasField(object Object, fieldName string) bool {
  304. if object == nil {
  305. return false
  306. }
  307. objectValue := reflect.ValueOf(object)
  308. if !reflectutils.IsValueStructOrStructPointer(objectValue) {
  309. return false
  310. }
  311. fieldValue := reflectutils.PointerValueElem(objectValue).FieldByName(fieldName)
  312. if !fieldValue.IsValid() {
  313. return false
  314. }
  315. return true
  316. }
  317. func getFieldValue(object Object, fieldName string) (*reflect.Value, error) {
  318. if object == nil {
  319. return nil, errors.New("领域对象为nil")
  320. }
  321. objectValue := reflect.ValueOf(object)
  322. if !reflectutils.IsValueStructOrStructPointer(objectValue) {
  323. return nil, errors.New("领域对象必须是结构或结构指针")
  324. }
  325. fieldValue := reflectutils.PointerValueElem(objectValue).FieldByName(fieldName)
  326. return &fieldValue, nil
  327. }