github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/selector.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package fields 18 19 import ( 20 "fmt" 21 "sort" 22 "strings" 23 ) 24 25 // Selector represents a field selector. 26 type Selector interface { 27 // Matches returns true if this selector matches the given set of fields. 28 Matches(Fields) bool 29 30 // Empty returns true if this selector does not restrict the selection space. 31 Empty() bool 32 33 // RequiresExactMatch allows a caller to introspect whether a given selector 34 // requires a single specific field to be set, and if so returns the value it 35 // requires. 36 RequiresExactMatch(field string) (value string, found bool) 37 38 // Transform returns a new copy of the selector after TransformFunc has been 39 // applied to the entire selector, or an error if fn returns an error. 40 Transform(fn TransformFunc) (Selector, error) 41 42 // String returns a human readable string that represents this selector. 43 String() string 44 } 45 46 // Everything returns a selector that matches all fields. 47 func Everything() Selector { 48 return andTerm{} 49 } 50 51 type hasTerm struct { 52 field, value string 53 } 54 55 func (t *hasTerm) Matches(ls Fields) bool { 56 return ls.Get(t.field) == t.value 57 } 58 59 func (t *hasTerm) Empty() bool { 60 return false 61 } 62 63 func (t *hasTerm) RequiresExactMatch(field string) (value string, found bool) { 64 if t.field == field { 65 return t.value, true 66 } 67 return "", false 68 } 69 70 func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) { 71 field, value, err := fn(t.field, t.value) 72 if err != nil { 73 return nil, err 74 } 75 return &hasTerm{field, value}, nil 76 } 77 78 func (t *hasTerm) String() string { 79 return fmt.Sprintf("%v=%v", t.field, t.value) 80 } 81 82 type notHasTerm struct { 83 field, value string 84 } 85 86 func (t *notHasTerm) Matches(ls Fields) bool { 87 return ls.Get(t.field) != t.value 88 } 89 90 func (t *notHasTerm) Empty() bool { 91 return false 92 } 93 94 func (t *notHasTerm) RequiresExactMatch(field string) (value string, found bool) { 95 return "", false 96 } 97 98 func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) { 99 field, value, err := fn(t.field, t.value) 100 if err != nil { 101 return nil, err 102 } 103 return ¬HasTerm{field, value}, nil 104 } 105 106 func (t *notHasTerm) String() string { 107 return fmt.Sprintf("%v!=%v", t.field, t.value) 108 } 109 110 type andTerm []Selector 111 112 func (t andTerm) Matches(ls Fields) bool { 113 for _, q := range t { 114 if !q.Matches(ls) { 115 return false 116 } 117 } 118 return true 119 } 120 121 func (t andTerm) Empty() bool { 122 if t == nil { 123 return true 124 } 125 if len([]Selector(t)) == 0 { 126 return true 127 } 128 for i := range t { 129 if !t[i].Empty() { 130 return false 131 } 132 } 133 return true 134 } 135 136 func (t andTerm) RequiresExactMatch(field string) (string, bool) { 137 if t == nil || len([]Selector(t)) == 0 { 138 return "", false 139 } 140 for i := range t { 141 if value, found := t[i].RequiresExactMatch(field); found { 142 return value, found 143 } 144 } 145 return "", false 146 } 147 148 func (t andTerm) Transform(fn TransformFunc) (Selector, error) { 149 next := make([]Selector, len([]Selector(t))) 150 for i, s := range []Selector(t) { 151 n, err := s.Transform(fn) 152 if err != nil { 153 return nil, err 154 } 155 next[i] = n 156 } 157 return andTerm(next), nil 158 } 159 160 func (t andTerm) String() string { 161 var terms []string 162 for _, q := range t { 163 terms = append(terms, q.String()) 164 } 165 return strings.Join(terms, ",") 166 } 167 168 // SelectorFromSet returns a Selector which will match exactly the given Set. A 169 // nil Set is considered equivalent to Everything(). 170 func SelectorFromSet(ls Set) Selector { 171 if ls == nil { 172 return Everything() 173 } 174 items := make([]Selector, 0, len(ls)) 175 for field, value := range ls { 176 items = append(items, &hasTerm{field: field, value: value}) 177 } 178 if len(items) == 1 { 179 return items[0] 180 } 181 return andTerm(items) 182 } 183 184 // ParseSelectorOrDie takes a string representing a selector and returns an 185 // object suitable for matching, or panic when an error occur. 186 func ParseSelectorOrDie(s string) Selector { 187 selector, err := ParseSelector(s) 188 if err != nil { 189 panic(err) 190 } 191 return selector 192 } 193 194 // ParseSelector takes a string representing a selector and returns an 195 // object suitable for matching, or an error. 196 func ParseSelector(selector string) (Selector, error) { 197 return parseSelector(selector, 198 func(lhs, rhs string) (newLhs, newRhs string, err error) { 199 return lhs, rhs, nil 200 }) 201 } 202 203 // Parses the selector and runs them through the given TransformFunc. 204 func ParseAndTransformSelector(selector string, fn TransformFunc) (Selector, error) { 205 return parseSelector(selector, fn) 206 } 207 208 // Function to transform selectors. 209 type TransformFunc func(field, value string) (newField, newValue string, err error) 210 211 func try(selectorPiece, op string) (lhs, rhs string, ok bool) { 212 pieces := strings.Split(selectorPiece, op) 213 if len(pieces) == 2 { 214 return pieces[0], pieces[1], true 215 } 216 return "", "", false 217 } 218 219 func parseSelector(selector string, fn TransformFunc) (Selector, error) { 220 parts := strings.Split(selector, ",") 221 sort.StringSlice(parts).Sort() 222 var items []Selector 223 for _, part := range parts { 224 if part == "" { 225 continue 226 } 227 if lhs, rhs, ok := try(part, "!="); ok { 228 items = append(items, ¬HasTerm{field: lhs, value: rhs}) 229 } else if lhs, rhs, ok := try(part, "=="); ok { 230 items = append(items, &hasTerm{field: lhs, value: rhs}) 231 } else if lhs, rhs, ok := try(part, "="); ok { 232 items = append(items, &hasTerm{field: lhs, value: rhs}) 233 } else { 234 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part) 235 } 236 } 237 if len(items) == 1 { 238 return items[0].Transform(fn) 239 } 240 return andTerm(items).Transform(fn) 241 } 242 243 // OneTermEqualSelector returns an object that matches objects where one field/field equals one value. 244 // Cannot return an error. 245 func OneTermEqualSelector(k, v string) Selector { 246 return &hasTerm{field: k, value: v} 247 }