github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/appdef/impl_field.go (about) 1 /* 2 * Copyright (c) 2021-present Sigma-Soft, Ltd. 3 * @author: Nikolay Nikitin 4 * @author: Maxim Geraskin 5 */ 6 7 package appdef 8 9 import ( 10 "errors" 11 "fmt" 12 "strconv" 13 "strings" 14 ) 15 16 // # Implements: 17 // - IField 18 type field struct { 19 comment 20 name FieldName 21 data IData 22 required bool 23 verifiable bool 24 verify map[VerificationKind]bool 25 constraints map[ConstraintKind]IConstraint 26 } 27 28 func makeField(name FieldName, data IData, required bool, comments ...string) field { 29 f := field{ 30 comment: makeComment(comments...), 31 name: name, 32 data: data, 33 required: required, 34 verifiable: false, 35 constraints: data.Constraints(true), 36 } 37 return f 38 } 39 40 func newField(name FieldName, data IData, required bool, comments ...string) *field { 41 f := makeField(name, data, required, comments...) 42 return &f 43 } 44 45 func (fld *field) Constraints() map[ConstraintKind]IConstraint { 46 return fld.constraints 47 } 48 49 func (fld *field) Data() IData { return fld.data } 50 51 func (fld *field) DataKind() DataKind { return fld.Data().DataKind() } 52 53 func (fld *field) IsFixedWidth() bool { 54 return fld.DataKind().IsFixed() 55 } 56 57 func (fld *field) IsSys() bool { 58 return IsSysField(fld.Name()) 59 } 60 61 func (fld *field) Name() FieldName { return fld.name } 62 63 func (fld *field) Required() bool { return fld.required } 64 65 func (fld field) String() string { 66 return fmt.Sprintf("%s-field «%s»", fld.DataKind().TrimString(), fld.Name()) 67 } 68 69 func (fld *field) Verifiable() bool { return fld.verifiable } 70 71 func (fld *field) VerificationKind(vk VerificationKind) bool { 72 return fld.verifiable && fld.verify[vk] 73 } 74 75 func (fld *field) setVerify(k ...VerificationKind) { 76 fld.verify = make(map[VerificationKind]bool) 77 for _, kind := range k { 78 fld.verify[kind] = true 79 } 80 fld.verifiable = len(fld.verify) > 0 81 } 82 83 // Returns is field system 84 func IsSysField(n FieldName) bool { 85 return strings.HasPrefix(n, SystemPackagePrefix) && // fast check 86 // then more accuracy 87 ((n == SystemField_QName) || 88 (n == SystemField_ID) || 89 (n == SystemField_ParentID) || 90 (n == SystemField_Container) || 91 (n == SystemField_IsActive)) 92 } 93 94 // # Implements: 95 // - IFields 96 type fields struct { 97 app *appDef 98 typeKind TypeKind 99 fields map[FieldName]interface{} 100 fieldsOrdered []IField 101 refFields []IRefField 102 } 103 104 // Makes new fields instance 105 func makeFields(app *appDef, typeKind TypeKind) fields { 106 ff := fields{ 107 app: app, 108 typeKind: typeKind, 109 fields: make(map[FieldName]interface{}), 110 fieldsOrdered: make([]IField, 0), 111 refFields: make([]IRefField, 0)} 112 return ff 113 } 114 115 func (ff *fields) Field(name FieldName) IField { 116 if ff, ok := ff.fields[name]; ok { 117 return ff.(IField) 118 } 119 return nil 120 } 121 122 func (ff *fields) FieldCount() int { 123 return len(ff.fieldsOrdered) 124 } 125 126 func (ff *fields) Fields() []IField { 127 return ff.fieldsOrdered 128 } 129 130 func (ff *fields) RefField(name FieldName) (rf IRefField) { 131 if fld := ff.Field(name); fld != nil { 132 if fld.DataKind() == DataKind_RecordID { 133 if fld, ok := fld.(IRefField); ok { 134 rf = fld 135 } 136 } 137 } 138 return rf 139 } 140 141 func (ff *fields) RefFields() []IRefField { 142 return ff.refFields 143 } 144 145 func (ff *fields) UserFieldCount() int { 146 cnt := 0 147 for _, fld := range ff.fieldsOrdered { 148 if !fld.IsSys() { 149 cnt++ 150 } 151 } 152 return cnt 153 } 154 155 func (ff *fields) addDataField(name FieldName, data QName, required bool, constraints ...IConstraint) { 156 d := ff.app.Data(data) 157 if d == nil { 158 panic(ErrTypeNotFound(data)) 159 } 160 if len(constraints) > 0 { 161 d = newAnonymousData(ff.app, d.DataKind(), data, constraints...) 162 } 163 f := newField(name, d, required) 164 ff.appendField(name, f) 165 } 166 167 func (ff *fields) addField(name FieldName, kind DataKind, required bool, constraints ...IConstraint) { 168 d := ff.app.SysData(kind) 169 if d == nil { 170 panic(ErrNotFound("system data type for data kind «%s»", kind.TrimString())) 171 } 172 if len(constraints) > 0 { 173 d = newAnonymousData(ff.app, d.DataKind(), d.QName(), constraints...) 174 } 175 f := newField(name, d, required) 176 ff.appendField(name, f) 177 } 178 179 func (ff *fields) addRefField(name FieldName, required bool, ref ...QName) { 180 d := ff.app.SysData(DataKind_RecordID) 181 f := newRefField(name, d, required, ref...) 182 ff.appendField(name, f) 183 } 184 185 // Appends specified field. 186 // 187 // # Panics: 188 // - if field name is empty, 189 // - if field with specified name is already exists 190 // - if user field name is invalid 191 // - if user field data kind is not allowed by structured type kind 192 func (ff *fields) appendField(name FieldName, fld interface{}) { 193 if name == NullName { 194 panic(ErrMissed("field name")) 195 } 196 if ff.Field(name) != nil { 197 panic(ErrAlreadyExists("field «%v»", name)) 198 } 199 if len(ff.fields) >= MaxTypeFieldCount { 200 panic(ErrTooMany("fields, maximum is %d", MaxTypeFieldCount)) 201 } 202 203 if !IsSysField(name) { 204 if ok, err := ValidFieldName(name); !ok { 205 panic(fmt.Errorf("field name «%v» is invalid: %w", name, err)) 206 } 207 dk := fld.(IField).DataKind() 208 if (ff.typeKind != TypeKind_null) && !ff.typeKind.FieldKindAvailable(dk) { 209 panic(ErrIncompatible("data kind «%s» with fields of «%v»", dk.TrimString(), ff.typeKind.TrimString())) 210 } 211 } 212 213 ff.fields[name] = fld 214 ff.fieldsOrdered = append(ff.fieldsOrdered, fld.(IField)) 215 216 if rf, ok := fld.(IRefField); ok { 217 ff.refFields = append(ff.refFields, rf) 218 } 219 } 220 221 // Makes system fields. Called after making structures fields 222 func (ff *fields) makeSysFields() { 223 if exists, required := ff.typeKind.HasSystemField(SystemField_QName); exists { 224 ff.addField(SystemField_QName, DataKind_QName, required) 225 } 226 227 if exists, required := ff.typeKind.HasSystemField(SystemField_ID); exists { 228 ff.addField(SystemField_ID, DataKind_RecordID, required) 229 } 230 231 if exists, required := ff.typeKind.HasSystemField(SystemField_ParentID); exists { 232 ff.addField(SystemField_ParentID, DataKind_RecordID, required) 233 } 234 235 if exists, required := ff.typeKind.HasSystemField(SystemField_Container); exists { 236 ff.addField(SystemField_Container, DataKind_string, required) 237 } 238 239 if exists, required := ff.typeKind.HasSystemField(SystemField_IsActive); exists { 240 ff.addField(SystemField_IsActive, DataKind_bool, required) 241 } 242 } 243 244 func (ff *fields) setFieldComment(name FieldName, comment ...string) { 245 fld := ff.fields[name] 246 if fld == nil { 247 panic(ErrFieldNotFound(name)) 248 } 249 if fld, ok := fld.(interface{ setComment(comment ...string) }); ok { 250 fld.setComment(comment...) 251 } 252 } 253 254 func (ff *fields) setFieldVerify(name FieldName, vk ...VerificationKind) { 255 fld := ff.fields[name] 256 if fld == nil { 257 panic(ErrFieldNotFound(name)) 258 } 259 vf := fld.(interface{ setVerify(k ...VerificationKind) }) 260 vf.setVerify(vk...) 261 } 262 263 // # Implements: 264 // - IFieldsBuilder 265 type fieldsBuilder struct { 266 *fields 267 } 268 269 func makeFieldsBuilder(fields *fields) fieldsBuilder { 270 return fieldsBuilder{ 271 fields: fields, 272 } 273 } 274 275 func (fb *fieldsBuilder) AddDataField(name FieldName, data QName, required bool, constraints ...IConstraint) IFieldsBuilder { 276 fb.fields.addDataField(name, data, required, constraints...) 277 return fb 278 } 279 280 func (fb *fieldsBuilder) AddField(name FieldName, kind DataKind, required bool, constraints ...IConstraint) IFieldsBuilder { 281 fb.fields.addField(name, kind, required, constraints...) 282 return fb 283 } 284 285 func (fb *fieldsBuilder) AddRefField(name FieldName, required bool, ref ...QName) IFieldsBuilder { 286 fb.fields.addRefField(name, required, ref...) 287 return fb 288 } 289 290 func (fb *fieldsBuilder) SetFieldComment(name FieldName, comment ...string) IFieldsBuilder { 291 fb.fields.setFieldComment(name, comment...) 292 return fb 293 } 294 295 func (fb *fieldsBuilder) SetFieldVerify(name FieldName, vk ...VerificationKind) IFieldsBuilder { 296 fb.fields.setFieldVerify(name, vk...) 297 return fb 298 } 299 300 // # Implements: 301 // - IRefField 302 type refField struct { 303 field 304 refs QNames 305 } 306 307 func newRefField(name FieldName, data IData, required bool, ref ...QName) *refField { 308 f := &refField{ 309 field: makeField(name, data, required), 310 refs: QNames{}, 311 } 312 f.refs.Add(ref...) 313 return f 314 } 315 316 func (f refField) Ref(n QName) bool { 317 l := len(f.refs) 318 if l == 0 { 319 return true // any ref available 320 } 321 return f.refs.Contains(n) 322 } 323 324 func (f refField) Refs() QNames { return f.refs } 325 326 // Validates specified fields. 327 // 328 // # Validation: 329 // - every RefField must refer to known types, 330 // - every referenced by RefField type must be record type 331 func validateTypeFields(t IType) (err error) { 332 if ff, ok := t.(IFields); ok { 333 // resolve reference types 334 for _, rf := range ff.RefFields() { 335 for _, n := range rf.Refs() { 336 refType := t.App().TypeByName(n) 337 if refType == nil { 338 err = errors.Join(err, 339 ErrNotFound("%v reference field «%s» type «%v»", t, rf.Name(), n)) 340 continue 341 } 342 if _, ok := refType.(IRecord); !ok { 343 err = errors.Join(err, 344 ErrInvalid("%v reference field «%s» type «%v» is not a record type", t, n, refType)) 345 continue 346 } 347 } 348 } 349 } 350 return err 351 } 352 353 type nullFields struct{} 354 355 func (f *nullFields) Field(FieldName) IField { return nil } 356 func (f *nullFields) FieldCount() int { return 0 } 357 func (f *nullFields) Fields() []IField { return []IField{} } 358 func (f *nullFields) RefField(FieldName) IRefField { return nil } 359 func (f *nullFields) RefFields() []IRefField { return []IRefField{} } 360 func (f *nullFields) UserFieldCount() int { return 0 } 361 362 func (k VerificationKind) MarshalJSON() ([]byte, error) { 363 var s string 364 if k < VerificationKind_FakeLast { 365 s = strconv.Quote(k.String()) 366 } else { 367 const base = 10 368 s = strconv.FormatUint(uint64(k), base) 369 } 370 return []byte(s), nil 371 } 372 373 // Renders an VerificationKind in human-readable form, without "VerificationKind_" prefix, 374 // suitable for debugging or error messages 375 func (k VerificationKind) TrimString() string { 376 const pref = "VerificationKind_" 377 return strings.TrimPrefix(k.String(), pref) 378 } 379 380 func (k *VerificationKind) UnmarshalJSON(data []byte) (err error) { 381 text := string(data) 382 if t, err := strconv.Unquote(text); err == nil { 383 text = t 384 for v := VerificationKind(0); v < VerificationKind_FakeLast; v++ { 385 if v.String() == text { 386 *k = v 387 return nil 388 } 389 } 390 } 391 392 var i uint64 393 const base, wordBits = 10, 16 394 i, err = strconv.ParseUint(text, base, wordBits) 395 if err == nil { 396 *k = VerificationKind(i) 397 } 398 return err 399 }