39 |
class ConditionNotSupported (ConditionError): |
class ConditionNotSupported (ConditionError): |
40 |
pass |
pass |
41 |
|
|
|
# |
|
|
# Build a condition tree using a dict |
|
|
# as a source. Assumes keys are field |
|
|
# names and values are constants. |
|
|
# |
|
|
def buildConditionFromDict (dict, comparison=None): |
|
|
cond = GCondition() |
|
|
lastParent = cond |
|
|
|
|
|
if len(dict.keys()): |
|
|
lastParent = GCand(lastParent) |
|
|
|
|
|
for key in dict.keys(): |
|
|
eq = (comparison or GCeq)(lastParent) |
|
|
GCField(eq, key) |
|
|
GCConst(eq, dict[key]) |
|
|
|
|
|
return cond |
|
|
|
|
|
# |
|
|
# Combine two conditions with an and clause. |
|
|
# NOTE: This modifies cond1 (and also returns it) |
|
|
# |
|
|
def combineConditions (cond1, cond2): |
|
|
if cond1 == None or cond1 == {}: |
|
|
return cond2 |
|
|
elif cond2 == None or cond2 == {}: |
|
|
return cond1 |
|
|
|
|
|
if type(cond1) == type({}): |
|
|
cond1 = buildConditionFromDict(cond1) |
|
|
if type(cond2) == type({}): |
|
|
cond1 = buildConditionFromDict(cond2) |
|
|
|
|
|
if not len(cond1._children): |
|
|
cond1._children = cond2._children |
|
|
return cond1 |
|
|
elif len(cond2._children): |
|
|
children = cond1._children[:] |
|
|
cond1._children = [] |
|
|
_and = GCand(cond1) |
|
|
_and._children = children |
|
|
if len(cond2._children) > 1: |
|
|
_and2 = GCand(cond1) |
|
|
_and2._children = cond2._children[:] |
|
|
else: |
|
|
cond1._children.append(cond2._children[0]) |
|
|
|
|
|
return cond1 |
|
|
|
|
|
|
|
|
# creates an GCondition Tree out of an list of tokens in a prefix |
|
|
# order. |
|
|
|
|
|
def buildTreeFromPrefix(term): |
|
|
|
|
|
# create a GCondition object as top object in the object stack |
|
|
parent={0:(GCondition())} |
|
|
|
|
|
# GCondition will have only one parameter |
|
|
# add paramcount=1 to the parameter count stack |
|
|
paramcount={0:1} |
|
|
|
|
|
# set start level for stack to zero |
|
|
level=0 |
|
|
for i in term: |
|
|
|
|
|
# convert type into an object |
|
|
if conditionElements.has_key(i[0]): |
|
|
e=conditionElements[i[0]][2](parent[level]) |
|
|
level=level+1 |
|
|
# get parameter count |
|
|
paramcount[level]=conditionElements[i[0]][0] |
|
|
parent[level]=e |
|
|
elif i[0]=="field": |
|
|
e=GCField(parent[level], i[1]) |
|
|
paramcount[level]=paramcount[level]-1 |
|
|
if paramcount[level]==0: |
|
|
level=level-1 |
|
|
elif i[0]=="const": |
|
|
e=GCConst(parent[level], i[1]) |
|
|
paramcount.update({level:(paramcount[level]-1)}) |
|
|
if paramcount[level]==0: |
|
|
level=level-1 |
|
|
# print "NAME: %s VALUE: %s LEVEL: %s PCOUNT: %s" % \ |
|
|
# (i[0],i[1],level,paramcount[level]) |
|
|
|
|
|
return parent[0]; |
|
|
|
|
|
|
|
|
def buildPrefixFromTree(conditionTree): |
|
|
if type(conditionTree) != types.InstanceType: |
|
|
raise ConditionError, "No valid condition tree" |
|
|
else: |
|
|
otype = string.lower(conditionTree._type[2:]) |
|
|
|
|
|
# |
|
|
# care for objects without children |
|
|
# |
|
|
if otype == 'cfield': |
|
|
return [('field',"%s" % conditionTree.name)] |
|
|
|
|
|
elif otype == 'cconst': |
|
|
return [('const',conditionTree.value)] |
|
|
|
|
|
elif otype == 'param': |
|
|
return [('param', conditionTree.getValue())] |
|
|
|
|
|
# |
|
|
# if its an conditional object, then process it's children |
|
|
# |
|
|
elif conditionElements.has_key(otype): |
|
|
result=[] |
|
|
|
|
|
# first add operator to the list |
|
|
result.append((otype,'')); # ,None)); |
|
|
|
|
|
|
|
|
# change operations with more than there minimal element no into |
|
|
# multiple operations with minimal elements |
|
|
# reason: to prevent a b c d AND OR being not well defined |
|
|
# because it can be a"a b c d AND AND OR" or "a b c d AND OR OR" |
|
|
paramcount=len(conditionTree._children) |
|
|
while (paramcount > \ |
|
|
conditionElements[otype][0]): |
|
|
paramcount=paramcount-1 |
|
|
result.append((otype,'')); |
|
|
|
|
|
|
|
|
# then add children |
|
|
for i in range(0, len(conditionTree._children)): |
|
|
result = result + \ |
|
|
buildPrefixFromTree(conditionTree._children[i]) |
|
|
|
|
|
# |
|
|
# check for integrity of condition |
|
|
# |
|
|
if len(conditionTree._children) < conditionElements[otype][0]: |
|
|
raise GConditions.ConditionError, \ |
|
|
_('Condition element "%s" expects at least %s arguments; found %s') % \ |
|
|
(otype, conditionElements[otype][0], len(conditionTree._children)) |
|
|
|
|
|
if len(conditionTree._children) > conditionElements[otype][1]: |
|
|
raise GConditions.ConditionError, \ |
|
|
_('Condition element "%s" expects at most %s arguments; found %s') % \ |
|
|
(otype, conditionElements[otype][1], len(conditionTree._children)) |
|
|
|
|
|
|
|
|
# return combination |
|
|
return result; |
|
|
|
|
|
else: |
|
|
raise GConditions.ConditionNotSupported, \ |
|
|
_('Condition clause "%s" is not supported '+ |
|
|
'by the condition to prefix table conversion.') % otype |
|
|
|
|
|
|
|
42 |
|
|
43 |
class GCondition(GObj): |
class GCondition(GObj): |
44 |
def __init__(self, parent=None, type="GCCondition"): |
def __init__(self, parent=None, type="GCCondition"): |
162 |
|
|
163 |
def getXMLelements(updates={}): |
def getXMLelements(updates={}): |
164 |
xmlElements = { |
xmlElements = { |
165 |
|
## 'conditions': { |
166 |
|
## 'BaseClass': GConditions, |
167 |
|
## 'SingleInstance': 1, |
168 |
|
## 'ParentTags': None }, |
169 |
|
|
170 |
'conditions': { |
'conditions': { |
171 |
'BaseClass': GConditions, |
'BaseClass': GCondition, |
172 |
'SingleInstance': 1, |
'ParentTags': ('conditions','and','or','not','negate'), |
173 |
'ParentTags': None }, |
'Deprecated': 'Use the <condition> tag instead.', |
174 |
|
}, |
175 |
'condition': { |
'condition': { |
176 |
'BaseClass': GCondition, |
'BaseClass': GCondition, |
177 |
'ParentTags': ('conditions','and','or','not','negate') }, |
'ParentTags': ('conditions','and','or','not','negate') }, |
181 |
'name': { |
'name': { |
182 |
'Required': 1, |
'Required': 1, |
183 |
'Typecast': GTypecast.name } }, |
'Typecast': GTypecast.name } }, |
184 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
185 |
'like','notlike','between','notbetween') }, |
'div','like','notlike','between','notbetween') }, |
186 |
'cparam': { |
'cparam': { |
187 |
'BaseClass': GCParam, |
'BaseClass': GCParam, |
188 |
'Attributes': { |
'Attributes': { |
190 |
'Required': 1, |
'Required': 1, |
191 |
'Unique': 1, |
'Unique': 1, |
192 |
'Typecast': GTypecast.name } }, |
'Typecast': GTypecast.name } }, |
193 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
194 |
'like','notlike','between','notbetween') }, |
'div','like','notlike','between','notbetween') }, |
195 |
'cconst': { |
'cconst': { |
196 |
'BaseClass': GCConst, |
'BaseClass': GCConst, |
197 |
'Attributes': { |
'Attributes': { |
198 |
'value': { |
'value': { |
199 |
'Required': 1, |
'Required': 1, |
200 |
'Typecast': GTypecast.text } }, |
'Typecast': GTypecast.text } }, |
201 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
202 |
'like','notlike','between','notbetween') }, |
'div','like','notlike','between','notbetween') }, |
203 |
|
'add': { |
204 |
|
'BaseClass': GCadd, |
205 |
|
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
206 |
|
'div','like','notlike','between','notbetween') }, |
207 |
|
'sub': { |
208 |
|
'BaseClass': GCsub, |
209 |
|
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
210 |
|
'div','like','notlike','between','notbetween') }, |
211 |
|
'mul': { |
212 |
|
'BaseClass': GCmul, |
213 |
|
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
214 |
|
'div','like','notlike','between','notbetween') }, |
215 |
|
'div': { |
216 |
|
'BaseClass': GCdiv, |
217 |
|
'ParentTags': ('eq','ne','lt','le','gt','ge','add','sub','mul', |
218 |
|
'div','like','notlike','between','notbetween') }, |
219 |
'and': { |
'and': { |
220 |
'BaseClass': GCand, |
'BaseClass': GCand, |
221 |
'ParentTags': ('condition','and','or','not','negate') }, |
'ParentTags': ('condition','and','or','not','negate') }, |
230 |
'ParentTags': ('condition','and','or','not','negate') }, |
'ParentTags': ('condition','and','or','not','negate') }, |
231 |
'eq': { |
'eq': { |
232 |
'BaseClass': GCeq, |
'BaseClass': GCeq, |
233 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
234 |
'ne': { |
'ne': { |
235 |
'BaseClass': GCne, |
'BaseClass': GCne, |
236 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
237 |
'gt': { |
'gt': { |
238 |
'BaseClass': GCgt, |
'BaseClass': GCgt, |
239 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
240 |
'ge': { |
'ge': { |
241 |
'BaseClass': GCge, |
'BaseClass': GCge, |
242 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
243 |
'lt': { |
'lt': { |
244 |
'BaseClass': GClt, |
'BaseClass': GClt, |
245 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
246 |
'le': { |
'le': { |
247 |
'BaseClass': GCle, |
'BaseClass': GCle, |
248 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
249 |
'like': { |
'like': { |
250 |
'BaseClass': GClike, |
'BaseClass': GClike, |
251 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
252 |
'notlike': { |
'notlike': { |
253 |
'BaseClass': GCnotlike, |
'BaseClass': GCnotlike, |
254 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
255 |
'between': { |
'between': { |
256 |
'BaseClass': GCbetween, |
'BaseClass': GCbetween, |
257 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
258 |
'notbetween': { |
'notbetween': { |
259 |
'BaseClass': GCnotbetween, |
'BaseClass': GCnotbetween, |
260 |
'ParentTags': ('eq','ne','lt','le','gt','ge', |
'ParentTags': ('condition','and','or','not','negate') }, |
|
'like','notlike','between','notbetween') }, |
|
261 |
'null': { |
'null': { |
262 |
'BaseClass': GCnull, |
'BaseClass': GCnull, |
263 |
'ParentTags': ('FIXME') }, |
'ParentTags': ('FIXME') }, |
285 |
'or': (2, 999, GCor ), |
'or': (2, 999, GCor ), |
286 |
'not': (1, 1, GCnot ), |
'not': (1, 1, GCnot ), |
287 |
'negate': (1, 1, GCnegate ), |
'negate': (1, 1, GCnegate ), |
|
'null': (1, 1, GCnull ), |
|
|
'notnull': (1, 1, GCnotnull ), |
|
288 |
'eq': (2, 2, GCeq ), |
'eq': (2, 2, GCeq ), |
289 |
'ne': (2, 2, GCne ), |
'ne': (2, 2, GCne ), |
290 |
'gt': (2, 2, GCgt ), |
'gt': (2, 2, GCgt ), |
293 |
'le': (2, 2, GCle ), |
'le': (2, 2, GCle ), |
294 |
'like': (2, 2, GClike ), |
'like': (2, 2, GClike ), |
295 |
'notlike': (2, 2, GCnotlike ), |
'notlike': (2, 2, GCnotlike ), |
296 |
'between': (3, 3, GCbetween ), |
'between': (3, 3, GCbetween ) |
|
'notbetween': (3, 3, GCnotbetween ), |
|
297 |
} |
} |
298 |
|
|
299 |
|
|
300 |
|
############################################################################# |
301 |
|
############################################################################# |
302 |
|
#### Convenience Methods ## |
303 |
|
############################################################################# |
304 |
|
############################################################################# |
305 |
|
|
306 |
|
|
307 |
|
# |
308 |
|
# Build a condition tree using a dict |
309 |
|
# as a source. Assumes keys are field |
310 |
|
# names and values are constants. |
311 |
|
# |
312 |
|
def buildConditionFromDict (dict, comparison=GCeq, logic=GCand): |
313 |
|
cond = GCondition() |
314 |
|
lastParent = cond |
315 |
|
|
316 |
|
if len(dict.keys()): |
317 |
|
lastParent = logic(lastParent) |
318 |
|
|
319 |
|
for key in dict.keys(): |
320 |
|
eq = comparison(lastParent) |
321 |
|
GCField(eq, key) |
322 |
|
GCConst(eq, dict[key]) |
323 |
|
|
324 |
|
return cond |
325 |
|
|
326 |
|
# |
327 |
|
# Combine two conditions with an and clause. |
328 |
|
# NOTE: This modifies cond1 (and also returns it) |
329 |
|
# |
330 |
|
def combineConditions (cond1, cond2): |
331 |
|
if cond1 == None or cond1 == {}: |
332 |
|
return cond2 |
333 |
|
elif cond2 == None or cond2 == {}: |
334 |
|
return cond1 |
335 |
|
|
336 |
|
if type(cond1) == type({}): |
337 |
|
cond1 = buildConditionFromDict(cond1) |
338 |
|
if type(cond2) == type({}): |
339 |
|
cond1 = buildConditionFromDict(cond2) |
340 |
|
|
341 |
|
if not len(cond1._children): |
342 |
|
cond1._children = cond2._children |
343 |
|
return cond1 |
344 |
|
elif len(cond2._children): |
345 |
|
children = cond1._children[:] |
346 |
|
cond1._children = [] |
347 |
|
_and = GCand(cond1) |
348 |
|
_and._children = children |
349 |
|
if len(cond2._children) > 1: |
350 |
|
_and2 = GCand(cond1) |
351 |
|
_and2._children = cond2._children[:] |
352 |
|
else: |
353 |
|
cond1._children.append(cond2._children[0]) |
354 |
|
|
355 |
|
return cond1 |
356 |
|
|
357 |
|
|
358 |
|
# creates an GCondition Tree out of an list of tokens in a prefix |
359 |
|
# order. |
360 |
|
|
361 |
|
def buildTreeFromPrefix(term): |
362 |
|
|
363 |
|
# create a GCondition object as top object in the object stack |
364 |
|
parent={0:(GCondition())} |
365 |
|
|
366 |
|
# GCondition will have only one parameter |
367 |
|
# add paramcount=1 to the parameter count stack |
368 |
|
paramcount={0:1} |
369 |
|
|
370 |
|
# set start level for stack to zero |
371 |
|
level=0 |
372 |
|
for i in term: |
373 |
|
|
374 |
|
# convert type into an object |
375 |
|
if conditionElements.has_key(i[0]): |
376 |
|
e=conditionElements[i[0]][2](parent[level]) |
377 |
|
level=level+1 |
378 |
|
# get parameter count |
379 |
|
paramcount[level]=conditionElements[i[0]][0] |
380 |
|
parent[level]=e |
381 |
|
elif i[0]=="field": |
382 |
|
e=GCField(parent[level], i[1]) |
383 |
|
paramcount[level]=paramcount[level]-1 |
384 |
|
if paramcount[level]==0: |
385 |
|
level=level-1 |
386 |
|
elif i[0]=="const": |
387 |
|
e=GCConst(parent[level], i[1]) |
388 |
|
paramcount.update({level:(paramcount[level]-1)}) |
389 |
|
if paramcount[level]==0: |
390 |
|
level=level-1 |
391 |
|
# print "NAME: %s VALUE: %s LEVEL: %s PCOUNT: %s" % \ |
392 |
|
# (i[0],i[1],level,paramcount[level]) |
393 |
|
|
394 |
|
return parent[0]; |
395 |
|
|
396 |
|
|
397 |
|
def buildPrefixFromTree(conditionTree): |
398 |
|
if type(conditionTree) != types.InstanceType: |
399 |
|
raise ConditionError, "No valid condition tree" |
400 |
|
else: |
401 |
|
otype = string.lower(conditionTree._type[2:]) |
402 |
|
|
403 |
|
# |
404 |
|
# care for objects without children |
405 |
|
# |
406 |
|
if otype == 'cfield': |
407 |
|
return [('field',"%s" % conditionTree.name)] |
408 |
|
|
409 |
|
elif otype == 'cconst': |
410 |
|
return [('const',conditionTree.value)] |
411 |
|
|
412 |
|
elif otype == 'param': |
413 |
|
return [('param', conditionTree.getValue())] |
414 |
|
|
415 |
|
# |
416 |
|
# if its an conditional object, then process it's children |
417 |
|
# |
418 |
|
elif conditionElements.has_key(otype): |
419 |
|
result=[] |
420 |
|
|
421 |
|
# first add operator to the list |
422 |
|
result.append((otype,'')); # ,None)); |
423 |
|
|
424 |
|
|
425 |
|
# change operations with more than there minimal element no into |
426 |
|
# multiple operations with minimal elements |
427 |
|
# reason: to prevent a b c d AND OR being not well defined |
428 |
|
# because it can be a"a b c d AND AND OR" or "a b c d AND OR OR" |
429 |
|
paramcount=len(conditionTree._children) |
430 |
|
while (paramcount > \ |
431 |
|
conditionElements[otype][0]): |
432 |
|
paramcount=paramcount-1 |
433 |
|
result.append((otype,'')); |
434 |
|
|
435 |
|
|
436 |
|
# then add children |
437 |
|
for i in range(0, len(conditionTree._children)): |
438 |
|
result = result + \ |
439 |
|
buildPrefixFromTree(conditionTree._children[i]) |
440 |
|
|
441 |
|
# |
442 |
|
# check for integrity of condition |
443 |
|
# |
444 |
|
if len(conditionTree._children) < conditionElements[otype][0]: |
445 |
|
raise GConditions.ConditionError, \ |
446 |
|
_('Condition element "%s" expects at least %s arguments; found %s') % \ |
447 |
|
(otype, conditionElements[otype][0], len(conditionTree._children)) |
448 |
|
|
449 |
|
if len(conditionTree._children) > conditionElements[otype][1]: |
450 |
|
raise GConditions.ConditionError, \ |
451 |
|
_('Condition element "%s" expects at most %s arguments; found %s') % \ |
452 |
|
(otype, conditionElements[otype][1], len(conditionTree._children)) |
453 |
|
|
454 |
|
|
455 |
|
# return combination |
456 |
|
return result; |
457 |
|
|
458 |
|
else: |
459 |
|
raise GConditions.ConditionNotSupported, \ |
460 |
|
_('Condition clause "%s" is not supported '+ |
461 |
|
'by the condition to prefix table conversion.') % otype |
462 |
|
|
463 |
|
|