rui_orig/properties.go

200 lines
5.0 KiB
Go

package rui
import (
"iter"
"slices"
"strings"
)
// Properties interface of properties map
type Properties interface {
// Get returns a value of the property with name defined by the argument.
// The type of return value depends on the property. If the property is not set then nil is returned.
Get(tag PropertyName) any
getRaw(tag PropertyName) any
// Set sets the value (second argument) of the property with name defined by the first argument.
// Return "true" if the value has been set, in the opposite case "false" are returned and
// a description of the error is written to the log
Set(tag PropertyName, value any) bool
setRaw(tag PropertyName, value any)
// Remove removes the property with name defined by the argument
Remove(tag PropertyName)
// Clear removes all properties
Clear()
// All returns an iterator to access the properties
All() iter.Seq2[PropertyName, any]
// AllTags returns an array of the set properties
AllTags() []PropertyName
IsEmpty() bool
}
type propertyList struct {
properties map[PropertyName]any
normalize func(PropertyName) PropertyName
}
type dataProperty struct {
propertyList
supportedProperties []PropertyName
get func(Properties, PropertyName) any
set func(Properties, PropertyName, any) []PropertyName
remove func(Properties, PropertyName) []PropertyName
}
func defaultNormalize(tag PropertyName) PropertyName {
return PropertyName(strings.ToLower(strings.Trim(string(tag), " \t")))
}
func (properties *propertyList) init() {
properties.properties = map[PropertyName]any{}
properties.normalize = defaultNormalize
//properties.getFunc = properties.getRaw
//properties.set = propertiesSet
//properties.remove = propertiesRemove
}
func (properties *propertyList) IsEmpty() bool {
return len(properties.properties) == 0
}
func (properties *propertyList) getRaw(tag PropertyName) any {
if value, ok := properties.properties[tag]; ok {
return value
}
return nil
}
func (properties *propertyList) setRaw(tag PropertyName, value any) {
if value == nil {
delete(properties.properties, tag)
} else {
properties.properties[tag] = value
}
}
/*
func (properties *propertyList) Remove(tag PropertyName) {
properties.remove(properties, properties.normalize(tag))
}
*/
func (properties *propertyList) Clear() {
properties.properties = map[PropertyName]any{}
}
func (properties *propertyList) All() iter.Seq2[PropertyName, any] {
return func(yield func(PropertyName, any) bool) {
for tag, value := range properties.properties {
if !yield(tag, value) {
return
}
}
}
}
func (properties *propertyList) AllTags() []PropertyName {
tags := make([]PropertyName, 0, len(properties.properties))
for tag := range properties.properties {
tags = append(tags, tag)
}
slices.Sort(tags)
return tags
}
func (properties *propertyList) writeToBuffer(buffer *strings.Builder,
indent string, objectTag string, tags []PropertyName) {
buffer.WriteString(objectTag)
buffer.WriteString(" {\n")
indent2 := indent + "\t"
for _, tag := range tags {
if value, ok := properties.properties[tag]; ok {
text := propertyValueToString(tag, value, indent2)
if text != "" {
buffer.WriteString(indent2)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
buffer.WriteString(",\n")
}
}
}
buffer.WriteString(indent)
buffer.WriteString("}")
}
func parseProperties(properties Properties, object DataObject) {
for node := range object.Properties() {
switch node.Type() {
case TextNode:
properties.Set(PropertyName(node.Tag()), node.Text())
case ObjectNode:
properties.Set(PropertyName(node.Tag()), node.Object())
case ArrayNode:
properties.Set(PropertyName(node.Tag()), node.Array())
}
}
}
func propertiesGet(properties Properties, tag PropertyName) any {
return properties.getRaw(tag)
}
func propertiesRemove(properties Properties, tag PropertyName) []PropertyName {
if properties.getRaw(tag) == nil {
return []PropertyName{}
}
properties.setRaw(tag, nil)
return []PropertyName{tag}
}
func (data *dataProperty) init() {
data.propertyList.init()
data.get = propertiesGet
data.set = propertiesSet
data.remove = propertiesRemove
}
func (data *dataProperty) Get(tag PropertyName) any {
return data.get(data, data.normalize(tag))
}
func (data *dataProperty) Remove(tag PropertyName) {
data.remove(data, data.normalize(tag))
}
func (data *dataProperty) writeToBuffer(buffer *strings.Builder, indent string, objectName string, tags []PropertyName) {
buffer.WriteString(objectName)
buffer.WriteString("{ ")
comma := false
for _, tag := range tags {
if value, ok := data.properties[tag]; ok {
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
}
}
buffer.WriteString(" }")
}
func (data *dataProperty) writeString(buffer *strings.Builder, indent string) {
data.writeToBuffer(buffer, indent, "_", data.AllTags())
}