package list import ( "sort" "strings" "github.com/photoprism/photoprism/pkg/enum" ) // Attr represents a list of key-value attributes. type Attr []*KeyValue // ParseAttr parses a string into a new Attr slice and returns it. func ParseAttr(s string) Attr { fields := strings.Fields(s) result := make(Attr, 0, len(fields)) // Append an attribute for each field. for _, v := range fields { f := ParseKeyValue(v) if f != nil { result = append(result, f) } } return result } // String returns the attributes as string. func (list Attr) String() string { return strings.Join(list.Strings(), " ") } // Strings returns the attributes as string slice. func (list Attr) Strings() []string { result := make([]string, 0, len(list)) list.Sort() var i int var l int for _, f := range list { s := f.String() if s == "" { continue } if i > 0 && result[i-1] == s { continue } l += len(s) if l > StringLengthLimit { break } result = append(result, s) i++ } return result } // Sort sorts the attributes by key. func (list Attr) Sort() Attr { sort.Slice(list, func(i, j int) bool { switch { case list[i].Key == list[j].Key: return list[i].Value < list[j].Value case list[i].Key == Any: return false case list[j].Key == Any: return true default: return list[i].Key < list[j].Key } }) return list } // Contains tests if the list contains the attribute provided as string. func (list Attr) Contains(s string) bool { attr := list.Find(s) if attr.Key == "" || attr.Value == enum.False { return false } return true } // Find returns the matching KeyValue attribute if found. func (list Attr) Find(s string) (a KeyValue) { if len(list) == 0 || s == "" { return a } else if s == Any { return KeyValue{Key: Any, Value: ""} } attr := ParseKeyValue(s) // Return if key is invalid. if attr == nil { return a } else if attr.Key == "" { return a } // Find and return first match. if attr.Value == "" || attr.Value == Any { for i := range list { if strings.EqualFold(attr.Key, list[i].Key) { return *list[i] } else if list[i].Key == Any { a = *list[i] } } } else { for i := range list { if strings.EqualFold(attr.Key, list[i].Key) { switch { case attr.Value == enum.True && list[i].Value == enum.False: return KeyValue{Key: "", Value: ""} case attr.Value == list[i].Value: return *list[i] case list[i].Value == Any: a = *list[i] } } else if list[i].Key == Any && attr.Value != enum.False { a = *list[i] } } } return a }