Documentation
¶
Index ¶
- func FieldTypeSettingCover(s, s2 FieldTypeSetting) bool
- func GetFieldTypeSetting[T FieldTypeSetting](f *Field) (T, error)
- func NewFields[T ThingGetter](fs ...T) (*dictionary.SelfKeyed[CodeName, T], error)
- func NewFields0[T ThingGetter]() *dictionary.SelfKeyed[CodeName, T]
- func NewObjects[T ObjectGetter](objs ...T) (*dictionary.SelfKeyed[CodeName, T], error)
- func NewObjects0[T ThingGetter]() *dictionary.SelfKeyed[CodeName, T]
- func Pick[T any](picker *Picker, values I18nGetter[T]) (language.Tag, bool)
- func RangeRanges(g FieldGroupGetter, f func(r Range) error) error
- type BinarySetting
- type BooleanSetting
- type CodeName
- type CombinationSetting
- type Condition
- type Domain
- type DomainGetter
- type Field
- type FieldGroup
- type FieldGroupGetter
- type FieldType
- type FieldTypeSetting
- type I18n
- type I18nGetter
- type Identity
- type IntegerSetting
- type ListSetting
- type NameTree
- type Object
- type ObjectGetter
- type ObjectNamePath
- type Op
- type PartialOrder
- type Path
- type Picker
- type Query
- type Range
- type RealSetting
- type RealStandard
- type ReferenceField
- type ReferenceSetting
- type ReferenceTrackingAction
- type ReferenceTrackingOption
- type StringSetting
- type Thing
- type ThingGetter
- type TimeStampSetting
- type Unit
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FieldTypeSettingCover ¶
func FieldTypeSettingCover(s, s2 FieldTypeSetting) bool
func GetFieldTypeSetting ¶
func GetFieldTypeSetting[T FieldTypeSetting](f *Field) (T, error)
func NewFields ¶
func NewFields[T ThingGetter](fs ...T) (*dictionary.SelfKeyed[CodeName, T], error)
NewFields build a self keyed dictionary with field rules, such as FieldGroup.Fields It errors if values added violate field naming rules.
func NewFields0 ¶
func NewFields0[T ThingGetter]() *dictionary.SelfKeyed[CodeName, T]
NewFields0 is the zero argument version of NewFields, it also does not error
func NewObjects ¶
func NewObjects[T ObjectGetter](objs ...T) (*dictionary.SelfKeyed[CodeName, T], error)
func NewObjects0 ¶
func NewObjects0[T ThingGetter]() *dictionary.SelfKeyed[CodeName, T]
NewObjects0 is the zero argument version of NewObjects, it also does not error
func Pick ¶
Pick picks the best value from I18n by the picker's preference. If no languages matched, then (und, false) is returned.
func RangeRanges ¶
func RangeRanges(g FieldGroupGetter, f func(r Range) error) error
Types ¶
type BinarySetting ¶
func (BinarySetting) Covers ¶
func (s BinarySetting) Covers(s2 BinarySetting) bool
Covers returns true if s can support all values in s2
type BooleanSetting ¶
type BooleanSetting struct{}
func (BooleanSetting) Covers ¶
func (s BooleanSetting) Covers(s2 BooleanSetting) bool
Covers returns true if s can support all values in s2
type CodeName ¶
type CodeName string
CodeName marks a string as expected to follow seed naming rules. See ./dictionary for details.
type CombinationSetting ¶
type CombinationSetting = FieldGroup // Reuse FieldGroup
type Condition ¶
type Condition struct { Op Op // condition operator Children []Condition FieldPaths []Path Literal any // if null, the literal is skipped }
Condition represents boolean operations on branch nodes and value to boolean operations on leaves.
The root condition can use any operator except PushUp. PushUp sudo condition exist only in the physical representation of tree, not in the logical.
func MakeDirectedCondition ¶
MakeDirectedCondition create a Condition tree from a list of operands for a directional operator. If types match, MakeDirectedCondition sees the operand as a child condition or field path, otherwise the operand is a literal. Operands should not contain any nil pointers. MakeDirectedCondition encapsulate the order of operands so Condition builders don't need to worry about it.
Both []Condition and Condition matches Children. Both []Path and Path matches FieldPaths
func (Condition) ForEach ¶
ForEach loops through each operand to call a function to handle each case. `PushUp` sudo conditions are recursed so the condition handler function will never see a `PushUp`, while the invariant Op of c applies to all handler function calls. The literal handler function will never be called if Literal is the unset nil.
type Domain ¶
type Domain struct { Thing Objects *dictionary.SelfKeyed[CodeName, *Object] }
Domain holds a collection of objects, equivalent to all create table statements in a SQL database. Only one Domain is needed for most use cases.
Domain is expected to be build once and never modified after first use. Data migration to support changing domain will not be done through direct modifications to domain.
func (*Domain) GetObjects ¶
func (d *Domain) GetObjects() dictionary.Getter[CodeName, ObjectGetter]
type DomainGetter ¶
type DomainGetter interface { ThingGetter GetObjects() dictionary.Getter[CodeName, ObjectGetter] }
DomainGetter describes a read only interface to a domain, upto the level of Field. As a compormized between interface complexity and extenablity of domain meta data.
type Field ¶
type Field struct { Thing FieldTypeSetting FieldType IsI18n bool // if true, different values for different locals is possible. Only String and Binary need to be supported. Nullable bool // if true, difference between null and zero values are significate. }
type FieldGroup ¶
type FieldGroup struct { Fields *dictionary.SelfKeyed[CodeName, *Field] // List each fields. The ordering of fields is not relevant for behavior but preserved for implementation details. Identities []Identity // required for object definitions and CombinationSetting on fields referred to in parent identity. Ranges []Range // if any ranges is left out of identities, it can be described here. }
FieldGroup describe a collection of fields.
Identities and Ranges have optional names, which allow them to be referred to if set.
func (*FieldGroup) GetFields ¶
func (g *FieldGroup) GetFields() dictionary.Getter[CodeName, *Field]
func (*FieldGroup) GetIdentities ¶
func (g *FieldGroup) GetIdentities() []Identity
func (*FieldGroup) GetRanges ¶
func (g *FieldGroup) GetRanges() []Range
type FieldGroupGetter ¶
type FieldType ¶
type FieldType int8
const ( FieldTypeUnset FieldType = iota String Binary Boolean TimeStamp Integer Real Reference List Combination FieldTypeMax = Combination )
type FieldTypeSetting ¶
type FieldTypeSetting any
FieldTypeSetting is any of:
String StringSetting Binary BinarySetting Boolean BooleanSetting TimeStamp TimeStampSetting Integer IntegerSetting Real RealSetting Reference ReferenceSetting List ListSetting Combination CombinationSetting
type I18n ¶
I18n[T any] is used for internationalization, such as text and icons displayed to users.
func NewI18n ¶
func NewI18n[T any](from I18nGetter[T]) I18n[T]
type I18nGetter ¶
type Identity ¶
Identity is used to mark a subset of fields in an object or a combination field as capable of identifying an single instance (a license plate number can ID a car), or uniqueness is required for correct modeling of state (two philosophers can not use the same fork at the same time).
All values in Identity.Thing is optional
type IntegerSetting ¶
func Int64Setting ¶
func Int64Setting() IntegerSetting
func (IntegerSetting) Covers ¶
func (s IntegerSetting) Covers(s2 IntegerSetting) bool
Covers returns true if s can support all values in s2
type ListSetting ¶
type ListSetting struct { MinLength int64 MaxLength int64 IsOrdered bool // if true, the items ordering is preserved. IsUnique bool // if true, repeated items should be ignored. ItemType FieldType ItemTypeSetting FieldTypeSetting }
ListSetting describes a collection of the same type:
| IsOrdered | IsUnique | collection type | | false | false | counted set | | false | true | set | | true | any | list |
func (ListSetting) Covers ¶
func (s ListSetting) Covers(s2 ListSetting) bool
func (ListSetting) ItemField ¶
func (s ListSetting) ItemField(parent *Field) *Field
type ObjectGetter ¶
type ObjectGetter interface { ThingGetter FieldGroupGetter }
type ObjectNamePath ¶
type Op ¶
type Op uint8
Op defines condition operators. All Op, except PushUp, has an inverse. A large number of operators are defined for ease of writing and manipulating conditions. When realizing conditions, conditions should be simplified to match closely with underling implementation.
const ( // Push up elements to the parent Condition, useful for custom ordering of operands. // When evaluated, PushUp can not be the top condition's operator. PushUp Op = iota // Unidirectional boolean operators. // // Care is taken to give sensible results when there are less operands than common definition to decrease // special case handling code. (|E| stands for the number of operands) // // Conceptually, removing an operand from `And` should only move the statement in the true direction. // Well removing an operand from `Or` should only move the statement in the false direction. // // When used to concatenate variable conditions, `And` is often used to concatenate filters, // without any filter defined, all value should be returned. So filter should be true for all values. // `Or` is often used to concatenate authorisation rules from roles. When no role is found, // user should not have access to any data. // // Implantation wise, `And` can be check by returning false on first false operand encountered, // true on exhaustion (unless null is also encountered). // `Or` can be check by returning true on first true operand encountered, false on exhaustion. And // all operands are true, if |E| = 0, always true Nand // if |E| = 0, always false Or // one or more operands is true, if |E| = 0, always false Nor // if |E| = 0, always true Eq // all operands are equal, if |E| < 2, always true Neq // if |E| < 2, always false // A nil Literal can't be used, so use *Null for comparison against nil values. // When other operators encounter nil values, it is viewed as unknown. // ie: Eq(nil, nil) = nil; And(true, nil) = true; And(false, nil) = nil. AndIsNull // true iff all values are nil. If |E| = 0, always true. Inverse of OrNotNull OrIsNull // true iff any values are nil. If |E| = 0, always false. Inverse of AndNotNull AndNotNull // true iff no values are nil. If |E| = 0, always true. Inverse of OrIsNull OrNotNull // true iff any values is not nil. If |E| = 0, always false. Inverse of AndIsNull // Set operators work on sets, `In` does intersects and return true iff intersect is not empty. // Operands that are not sets are automatically promoted to a set containing it self. In // if |E| = 0, always true. But if any operand is empty, always false. NotIn // inverse of In // Directional operators apply Children first, then FieldPaths, and Literal last. // All operands must be of the same orderable type to be comparable. // If |E| > 2, such as {a<b<c}, it is considered equivalent to {(a<b)&(b<c)}. // Even though {a<b} is inversed of {a>=b}, this is not true for {a<b<c} vs {a>=b>=c}. // For example: {1<3<2} and {1>=3>=2} are both false. So directional operators get their own // inverse N* operators instead of using the more common conversions. // // For Lt,Lte,Gt,and Gte; if |E| < 2, always true. Meaning operand list is total or partial ordered. // For their inverses (N*); if |E| < 2, always false. Lt Nlt Lte Nlte Gt Ngt Gte Ngte OpMax = Ngte )
func (Op) IsDirectional ¶
type PartialOrder ¶
type Picker ¶
type Picker struct {
// contains filtered or unexported fields
}
Picker is an inverse language.Matcher, where user request language is static but supported language is dynamic.
Picker is safe to use concurrently.
func NewPicker ¶
NewPicker creates a language picker by confidence, then by natural order of the preferred list. If no matches are found, fallback is used.
func SystemLogPicker ¶
func SystemLogPicker() *Picker
SystemLogPicker picks the language based on the configuration of the local environment.
type Query ¶
type Query struct { ObjectName ObjectNamePath Fields NameTree Condition Condition Count bool Order []PartialOrder Offset int64 Limit int64 // future: use order and last row data for offset condition }
type Range ¶
Range marks two fields by name as describing a range of values. Start and End must reference two comparable fields of the same type.
All values in Range.Thing is optional
- If IncludeEndValue = false, then Start < End. (range must have none zero length)
- If IncludeEndValue = true, then Start <= End.
Currently, the only for seen usage of Range is to support time ranges. Under this context, the end value of a time range can create ambiguities:
- When a room is booked from 1 to 2 o'clock, it can be booked from 2 onwards. Here the end value is excluded from the range.
- When a person is busy from Monday to Friday, he is still busy on Friday. Here the end value is included in the range.
Although it's possible to only support one type of range on the backend and only convert to the users' expectation on display, this crates a horrible off-by-one trap that can only be fixed once on the display path. By adding an IncludeEndValue option, the most human friendly interpretation of end value is preserved thought-out.
type RealSetting ¶
type RealSetting struct { Standard RealStandard Base uint8 // base 2 and 10 are most common, others are unlikely to be supported. MinMantissa *big.Int MaxMantissa *big.Int MinExponent *int64 // pointer to diff zero vs not set MaxExponent *int64 // Alternative settings for RealStandard of Float32 or Float64 to replace *Mantissa and *Exponent. // The full range is supported if not set. MinFloat *float64 MaxFloat *float64 Unit *Unit }
func (RealSetting) Covers ¶
func (s RealSetting) Covers(s2 RealSetting) bool
Covers returns true if s can support all values in s2.
func (*RealSetting) Valid ¶
func (s *RealSetting) Valid() bool
type RealStandard ¶
type RealStandard int8
const ( CustomReal RealStandard = iota Float32 Float64 )
func (RealStandard) Covers ¶
func (s RealStandard) Covers(s2 RealStandard) bool
Covers returns true if s can support all values in s2.
func (RealStandard) String ¶
func (s RealStandard) String() string
type ReferenceField ¶
type ReferenceSetting ¶
type ReferenceSetting struct { Object CodeName // target object. Identity CodeName // target identity or field name (if an identity has just this field) PromotionMap []ReferenceField // Promote selected fields to parent level, if already exist, field settings must match. ReferenceTrackingOption }
ReferenceSetting allow one object to refer to an other.
func (ReferenceSetting) Covers ¶
func (s ReferenceSetting) Covers(s2 ReferenceSetting) bool
Covers returns true if s can support all values in s2.
type ReferenceTrackingAction ¶
type ReferenceTrackingAction uint8
const ( ActionRestrict ReferenceTrackingAction = iota // This is the default to protect data. ActionCascade // Only supported for OnUpdate. ActionSetNull // Only supported for OnDelete. ActionIgnore // Nothing happens, the reference is only a suggestion. )
type ReferenceTrackingOption ¶
type ReferenceTrackingOption struct { OnUpdate ReferenceTrackingAction OnDelete ReferenceTrackingAction }
type StringSetting ¶
func (StringSetting) Covers ¶
func (s StringSetting) Covers(s2 StringSetting) bool
Covers returns true if s can support all values in s2
type Thing ¶
type Thing struct { Name CodeName // name is the long term api name of the thing, name is locally unique. Label I18n[string] // used for displaying input label or column header. Description I18n[string] // used for displaying addition information. }
Thing is a base type for anything that can be identified.
func NewThing ¶
func NewThing(from ThingGetter) Thing
func (Thing) GetDescription ¶
func (t Thing) GetDescription() I18nGetter[string]
func (Thing) GetLabel ¶
func (t Thing) GetLabel() I18nGetter[string]
func (Thing) GetThing ¶
func (t Thing) GetThing() ThingGetter
type ThingGetter ¶
type ThingGetter interface { GetName() CodeName GetLabel() I18nGetter[string] GetDescription() I18nGetter[string] }
type TimeStampSetting ¶
type TimeStampSetting struct { Min time.Time Max time.Time Scale time.Duration // >= 24h: date only; >= 1s: datetime; < 1s: support fraction seconds WithTimeZoneOffset bool // if false always UTC }
func (TimeStampSetting) Covers ¶
func (s TimeStampSetting) Covers(s2 TimeStampSetting) bool
Covers returns true if s can support all values in s2
type Unit ¶
func (*Unit) Covers ¶
Covers returns true if s can support all values in s2.
For unit comparisons, no value ranges are checked, So *Unit.Covers has a different meaning. For most use cases, receiver s should be nil, since it describes the ability to handle a set of values without care to the unit. But in case it does care about the unit, we protect against mixing units by returning false if s2 is different from s.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
demo
|
|
dictionary implements a collection to hold field and object definitions and checks CodeName character and namespace rules.
|
dictionary implements a collection to hold field and object definitions and checks CodeName character and namespace rules. |
persistence
|
|
seederrors is mostly a warper around github.com/cockroachdb/errors to use a subset of the features.
|
seederrors is mostly a warper around github.com/cockroachdb/errors to use a subset of the features. |