Package ZenEvents :: Module WhereClause
[hide private]
[frames] | no frames]

Source Code for Module ZenEvents.WhereClause

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13  import types 
 14  from Products.ZenUtils.json import json 
 15   
 16  negativeModes = ( 
 17      '!',    # is not 
 18      '!~',   # does not contain 
 19      '!^',   # does not begin with 
 20      ) 
 21   
22 -def q(s):
23 # turn string "fo'o" -> "'fo''o'" 24 return "'%s'" % "''".join(s.split("'"))
25
26 -class Error(Exception): pass
27
28 -class WhereJavaScript:
29 "Base class for converting to/from javascript" 30 type = 'unknown'
31 - def __init__(self, label):
32 self.label = label
33 - def genProperties(self, name):
34 return '%s:{type:"%s",label:"%s"}' % (name, self.type, self.label)
35 - def buildClause(self, name, value, mode):
36 foundNegativeMatch = False 37 result = [] 38 for v in value: 39 if not v: return None 40 if mode in negativeModes: foundNegativeMatch = True 41 result.append(self.buildClause1(name, v, mode)) 42 if not result: 43 return None 44 if foundNegativeMatch: 45 return ' and '.join(result) 46 else: 47 return ' or '.join(result)
48
49 -class Text(WhereJavaScript):
50 "Convert to/from javascript for text entries" 51 type = 'text'
52 - def toJS(self, mode, value):
53 if mode == 'like': 54 if value.startswith('%') and not value.endswith('%'): 55 return '$', [value[1:]] 56 elif not value.startswith('%') and value.endswith('%'): 57 return '^', [value[:-1]] 58 elif value.startswith('%') and value.endswith('%'): 59 return '~', [value[1:-1]] 60 if mode == 'not like': 61 return '!~', [value[1:-1]] 62 if mode == '=': 63 return '', [value] 64 if mode == '!=': 65 return '!', [value]
66 - def buildClause1(self, name, v, mode):
67 if mode == '~': 68 return "%s like %s" % (name, q('%' + v + '%')) 69 if mode == '^': 70 return "%s like %s" % (name, q(v + '%')) 71 if mode == '$': 72 return "%s like %s" % (name, q('%' + v)) 73 if mode == '!~': 74 return "%s not like %s" % (name, q('%' + v + '%')) 75 if mode == '': 76 return "%s = %s" % (name, q(v)) 77 if mode == '!': 78 return "%s != %s" % (name, q(v))
79 80
81 -class Select(WhereJavaScript):
82 "Convert to/from javascript and where clause element for select entries" 83 type = 'select'
84 - def __init__(self, label, options):
85 WhereJavaScript.__init__(self, label) 86 if options: 87 if type(options[0]) != type(()): 88 options = zip(range(len(options)), options) 89 self.options = options
90 - def labelFromValue(self, value):
91 return dict(self.options).get(value, 'Unknown')
92 - def valueFromLabel(self, value):
93 return dict([(v, l) for l, v in self.options]).get(value, -1)
94 - def toJS(self, operator, value):
95 if operator == '=': 96 return ('', [self.labelFromValue(value)]) 97 if operator == '!=': 98 return ('!', [self.labelFromValue(value)]) 99 result = [] 100 if operator in ('<', '>', '<=', '>='): 101 for i, name in self.options: 102 if eval('%d %s %d' % (i, operator, value)): 103 result.append(name) 104 return ('', result)
105 - def genProperties(self, name):
106 return '%s:{type:"%s",label:"%s", options:%r}' % ( 107 name, self.type, self.label, [s[1] for s in self.options])
108 - def buildClause1(self, name, v, mode):
109 v = self.valueFromLabel(v) 110 if type(v) in types.StringTypes: 111 v = q(v) 112 if mode == '': 113 return "%s = %s" % (name, v) 114 else: 115 return "%s != %s" % (name, v)
116
117 -class Compare(WhereJavaScript):
118 "Convert to/from javascript and where clause elements for numeric comparisons" 119 type = 'compare'
120 - def toJS(self, operator, value):
121 return operator, [value]
122 - def buildClause1(self, name, v, mode):
123 return "%s %s %s" % (name, mode, v)
124
125 -class DeviceGroup(Select):
126 - def toJS(self, operator, value):
127 if operator == 'like': 128 return ['', [value[2:-1]]] 129 if operator == 'not like': 130 return ['!', [value[2:-1]]]
131 - def buildClause1(self, name, v, mode):
132 if mode == '': 133 return "%s like %s" % (name, q('%|' + v + '%')) 134 else: 135 return "%s not like %s" % (name, q('%|' + v + '%'))
136
137 -class EventClass(Select):
138 type = 'evtClass'
139 - def toJS(self, operator, value):
140 value = value.rstrip('%') 141 if operator == '=': 142 return ['', [value]] 143 if operator == '!=': 144 return ['!', [value]] 145 if operator == 'like': 146 return ['^', [value]] 147 if operator == 'not like': 148 return ['!^', [value]]
149 - def buildClause1(self, name, v, mode):
150 if mode == '': 151 return "%s = %s" % (name, q(v)) 152 elif mode == '^': 153 return "%s like %s" % (name, q(v + '%')) 154 elif mode == '!^': 155 return "%s not like %s" % (name, q(v + '%')) 156 else: 157 return "%s != %s" % (name, q(v))
158 159 160
161 -class Enumerated(Select):
162 "Convert to/from javascript and where clause elements for enumerated types" 163 type='cselect'
164 - def toJS(self, operator, value):
165 return operator, [self.labelFromValue(value)]
166 - def buildClause1(self, name, v, mode):
167 return "%s %s %s" % (name, mode, self.valueFromLabel(v))
168 169 _Definitions = r''' 170 def u(s): 171 # turn string "'fo''o'" -> "fo'o" 172 c = s[0] 173 s = c.join(s.split(c+c)) 174 return s[1:-1] 175 176 ''' 177 178 _ParseSpec = r''' 179 parser WhereClause: 180 ignore: "[ \r\t\n]+" 181 token END: "$" 182 token NUM: "[0-9]+" 183 token VAR: "[a-zA-Z0-9_]+" 184 token BIN: ">=|<=|==|=|<|>|!=|<>" 185 token STR: r'"([^\\"]+|\\.)*"' 186 token STR2: r"'([^\\']+|\\.)*'" 187 188 rule goal: andexp ? END {{ return locals().get('andexp', None) }} 189 190 rule andexp: orexp {{ e = orexp }} 191 ( "and" orexp {{ e = ('and', e, orexp) }} 192 )* {{ return e }} 193 194 rule orexp: binary {{ e = binary }} 195 ( "or" binary {{ e = ('or', e, binary) }} 196 )* {{ return e }} 197 198 rule binary: term {{ e = term }} 199 ( BIN term {{ e = (BIN, e, term) }} 200 | 'like' term {{ e = ('like', e, term) }} 201 | 'not' 'like' term 202 {{ e = ('not like', e, term) }} 203 )* {{ return e }} 204 205 rule term: NUM {{ return int(NUM) }} 206 | VAR {{ return VAR }} 207 | STR {{ return u(STR) }} 208 | STR2 {{ return u(STR2) }} 209 | "\\(" andexp "\\)" {{ return andexp }} 210 ''' 211 212
213 -class _Parser:
214 - def __init__(self, spec):
215 from yapps import grammar, yappsrt 216 from StringIO import StringIO 217 scanner = grammar.ParserDescriptionScanner(spec) 218 parser = grammar.ParserDescription(scanner) 219 parser = yappsrt.wrap_error_reporter(parser, 'Parser') 220 parser.preparser = _Definitions 221 parser.output = StringIO() 222 parser.generate_output() 223 exec parser.output.getvalue() in self.__dict__
224 225 where = _Parser(_ParseSpec) 226 227 @json
228 -def toJavaScript(meta, clause):
229 # sql is case insensitive, map column names to lower-case versions 230 lmeta = dict([(n.lower(), n) for n in meta.keys()]) 231 tree = where.parse('goal', clause) 232 def recurse(root, result): 233 if type(root) == types.TupleType: 234 n = len(root) 235 if n == 1: 236 recurse(root[0], result) 237 op, name, value = root 238 if op in ('and', 'or'): 239 recurse(root[1], result) 240 recurse(root[2], result) 241 else: 242 name = lmeta.get(name.lower(), None) 243 if name is not None: 244 op, value = meta[name].toJS(op, value) 245 result.append([name, op, value])
246 result = [] 247 recurse(tree, result) 248 result.sort() 249 return result 250
251 -def fromFormVariables(meta, form):
252 result = [] 253 for n, attrType in meta.items(): 254 if form.has_key(n): 255 value = form[n] 256 if type(value) != type([]): 257 value = [value] 258 mode = form.get(n + "_mode", None) 259 clause = attrType.buildClause(n, value, mode) 260 if clause: 261 result.append('(%s)' % clause) 262 return ' and '.join(result);
263 264 265 if __name__ == '__main__': 266 meta = {} 267 toJavaScript(meta, 'severity = 3 or severity = 4') 268 toJavaScript(meta, "severity >= 4 and eventState = 0 and prodState = 1000") 269 toJavaScript(meta, "severity >= 2 and eventState = 0 and prodState = 1000") 270 print toJavaScript(meta, '(prodState = 1000) and (eventState = 0 or eventState = 1) and (severity >= 3)') 271 print fromFormVariables(meta, 272 dict(severity='Info', 273 severity_mode='>', 274 eventState='New', 275 eventState_mode='=', 276 prodState='Production', 277 prodState_mode='=')) 278