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  }