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