github.com/boki/go-xmp@v1.0.1/xmp/filter.go (about) 1 // Copyright (c) 2017-2018 Alexander Eichhorn 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package xmp 16 17 import ( 18 "fmt" 19 "reflect" 20 "strings" 21 ) 22 23 type Filter struct { 24 include NamespaceList 25 exclude NamespaceList 26 } 27 28 func NewFilter(include, exclude NamespaceList) *Filter { 29 return &Filter{ 30 include: include, 31 exclude: exclude, 32 } 33 } 34 35 func ParseFilterStrict(s string) (*Filter, error) { 36 f := NewFilter(nil, nil) 37 if len(s) == 0 { 38 return f, nil 39 } 40 for _, v := range strings.Split(s, ",") { 41 if v == "" { 42 continue 43 } 44 switch v[0] { 45 case '-': 46 v = v[1:] 47 // 1st try parsing as group 48 if g := ParseNamespaceGroup(v); g != NoMetadata { 49 f.exclude = append(f.exclude, g.Namespaces()...) 50 break 51 } 52 // 2nd try as namespace 53 if ns, err := GetNamespace(v); err == nil { 54 f.exclude = append(f.exclude, ns) 55 } else { 56 return nil, fmt.Errorf("no registered xmp namespace %s", v) 57 } 58 case '+': 59 v = v[1:] 60 fallthrough 61 default: 62 // 1st try parsing as group 63 if g := ParseNamespaceGroup(v); g != NoMetadata { 64 f.include = append(f.include, g.Namespaces()...) 65 break 66 } 67 // 2nd try as namespace 68 if ns, err := GetNamespace(v); err == nil { 69 f.include = append(f.include, ns) 70 } else { 71 return nil, fmt.Errorf("no registered xmp namespace %s", v) 72 } 73 } 74 } 75 return f, nil 76 } 77 78 func ParseFilter(s string) *Filter { 79 f := NewFilter(nil, nil) 80 if len(s) == 0 { 81 return f 82 } 83 for _, v := range strings.Split(s, ",") { 84 if v == "" { 85 continue 86 } 87 switch v[0] { 88 case '-': 89 v = v[1:] 90 // 1st try parsing as group 91 if g := ParseNamespaceGroup(v); g != NoMetadata { 92 f.exclude = append(f.exclude, g.Namespaces()...) 93 break 94 } 95 // 2nd try as namespace 96 if ns, err := GetNamespace(v); err == nil { 97 f.exclude = append(f.exclude, ns) 98 } else { 99 f.exclude = append(f.exclude, &Namespace{Name: v}) 100 } 101 case '+', ' ': // treat space as '+' to because of URL unescaping 102 v = v[1:] 103 fallthrough 104 default: 105 // 1st try parsing as group 106 if g := ParseNamespaceGroup(v); g != NoMetadata { 107 f.include = append(f.include, g.Namespaces()...) 108 break 109 } 110 // 2nd try as namespace 111 if ns, err := GetNamespace(v); err == nil { 112 f.include = append(f.include, ns) 113 } else { 114 f.include = append(f.include, &Namespace{Name: v}) 115 } 116 } 117 } 118 return f 119 } 120 121 func (x *Filter) UnmarshalText(b []byte) error { 122 f := ParseFilter(string(b)) 123 *x = *f 124 return nil 125 } 126 127 func (x Filter) String() string { 128 s := make([]string, 0, len(x.include)+len(x.exclude)) 129 for _, v := range x.include { 130 s = append(s, fmt.Sprintf("+%s", v.GetName())) 131 } 132 for _, v := range x.exclude { 133 s = append(s, fmt.Sprintf("-%s", v.GetName())) 134 } 135 return strings.Join(s, ",") 136 } 137 138 func (x Filter) Apply(d *Document) bool { 139 var removed bool 140 if len(x.include) > 0 { 141 r := d.FilterNamespaces(x.include) 142 removed = removed || r 143 } 144 if len(x.exclude) > 0 { 145 r := d.RemoveNamespaces(x.exclude) 146 removed = removed || r 147 } 148 return removed 149 } 150 151 // converter function for Gorilla schema; will become unnecessary once 152 // https://github.com/gorilla/schema/issues/57 is fixed 153 // 154 // register with decoder.RegisterConverter(Filter(""), ConvertFilter) 155 func ConvertFilter(value string) reflect.Value { 156 v := ParseFilter(value) 157 return reflect.ValueOf(*v) 158 }