OW_WQLCompile.cpp

Go to the documentation of this file.
00001 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
00002 // Copyright (c) 2002 Vintela, Inc..
00003 //
00004 // Permission is hereby granted, free of charge, to any person obtaining a copy
00005 // of this software and associated documentation files (the "Software"), to
00006 // deal in the Software without restriction, including without limitation the
00007 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00008 // sell copies of the Software, and to permit persons to whom the Software is
00009 // furnished to do so, subject to the following conditions:
00010 // 
00011 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
00012 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
00013 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
00014 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
00015 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00016 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00017 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00018 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00019 //  
00020 //==============================================================================//
00021 // Author: Markus Mueller (sedgewick_de@yahoo.de)
00022 //
00023 // Modified By: Dan Nuffer
00024 //
00026 #include "OW_config.h"
00027 #include "OW_Assertion.hpp"
00028 #include "OW_WQLOperation.hpp"
00029 #include "OW_WQLOperand.hpp"
00030 #include "OW_WQLCompile.hpp"
00031 #include "OW_Format.hpp"
00032 #include "OW_Stack.hpp"
00033 #ifdef OW_HAVE_OSTREAM
00034 #include <ostream>
00035 #else
00036 #include <iostream>
00037 #endif
00038 #include <algorithm> // for std::unique
00039 
00040 namespace OW_NAMESPACE
00041 {
00042 
00043 //
00044 // Terminal element methods 
00045 //
00046 void WQLCompile::term_el::negate()
00047 {
00048    switch (op)
00049    {
00050       case WQL_EQ: op = WQL_NE; break;
00051       case WQL_NE: op = WQL_EQ; break;
00052       case WQL_LT: op = WQL_GE; break;
00053       case WQL_LE: op = WQL_GT; break;
00054       case WQL_GT: op = WQL_LE; break;
00055       case WQL_GE: op = WQL_LT; break;
00056       default: break;
00057    }
00058 };
00059 bool operator==(const WQLCompile::term_el& x, const WQLCompile::term_el& y)
00060 {
00061    return x.op == y.op && x.opn1 == y.opn1 && x.opn2 == y.opn2;
00062 }
00063 bool operator!=(const WQLCompile::term_el& x, const WQLCompile::term_el& y)
00064 {
00065    return !(x == y);
00066 }
00067 //
00068 // Evaluation heap element methods 
00069 //
00070 WQLCompile::stack_el
00071 WQLCompile::eval_el::getFirst()
00072 {
00073    return stack_el(opn1, is_terminal1);
00074 }
00075 WQLCompile::stack_el
00076 WQLCompile::eval_el::getSecond()
00077 {
00078    return stack_el(opn2, is_terminal2);
00079 }
00080 void WQLCompile::eval_el::setFirst(const WQLCompile::stack_el s)
00081 {
00082    opn1 = s.opn;
00083    is_terminal1 = s.type;
00084 }
00085 void WQLCompile::eval_el::setSecond(const WQLCompile::stack_el s)
00086 {
00087    opn2 = s.opn;
00088    is_terminal2 = s.type;
00089 }
00090 void WQLCompile::eval_el::assign_unary_to_first(const WQLCompile::eval_el & assignee)
00091 {
00092    opn1 = assignee.opn1;
00093    is_terminal1 = assignee.is_terminal1;
00094 }
00095 void WQLCompile::eval_el::assign_unary_to_second(const WQLCompile::eval_el & assignee)
00096 {
00097    opn2 = assignee.opn1;
00098    is_terminal2 = assignee.is_terminal1;
00099 }
00100 // Ordering operators, so that op1 > op2 for all non-terminals
00101 // and terminals appear in the second operand first
00102 void WQLCompile::eval_el::order()
00103 {
00104    if ((is_terminal1 == EVAL_HEAP) && (is_terminal2 == EVAL_HEAP))
00105    {
00106       if (opn2 > opn1)
00107       {
00108          std::swap(opn1, opn2);
00109       }
00110    }
00111    else if ((is_terminal1 != EVAL_HEAP) && (is_terminal2 == EVAL_HEAP))
00112    {
00113       if (opn2 > opn1)
00114       {
00115          std::swap(opn1, opn2);
00116          std::swap(is_terminal1, is_terminal2);
00117       }
00118    }
00119 }
00120 //
00121 // Helper function copied from WQLSelectStatement
00122 // 
00123 template<class T>
00124 inline static bool _Compare(const T& x, const T& y, WQLOperation op)
00125 {
00126    switch (op)
00127    {
00128       case WQL_EQ: 
00129          return x == y;
00130       case WQL_NE: 
00131          return x != y;
00132       case WQL_LT: 
00133          return x < y;
00134       case WQL_LE: 
00135          return x <= y;
00136       case WQL_GT: 
00137          return x > y;
00138       case WQL_GE: 
00139          return x >= y;
00140       default:
00141          OW_ASSERT(0);
00142    }
00143    return false;
00144 }
00145 static bool _Evaluate(
00146 const WQLOperand& lhs, 
00147 const WQLOperand& rhs, 
00148 WQLOperation op)
00149 {
00150    switch (lhs.getType())
00151    {
00152       case WQLOperand::NULL_VALUE:
00153       {
00154          // return true if the op is WQL_EQ and the rhs is NULL
00155          // also if op is WQL_NE and rhs is not NULL
00156          return !(op == WQL_EQ) ^ (rhs.getType() == WQLOperand::NULL_VALUE);
00157          break;
00158       }
00159       case WQLOperand::INTEGER_VALUE:
00160       {
00161          return _Compare(
00162          lhs.getIntegerValue(),
00163          rhs.getIntegerValue(),
00164          op);
00165       }
00166       case WQLOperand::DOUBLE_VALUE:
00167       {
00168          return _Compare(
00169          lhs.getDoubleValue(),
00170          rhs.getDoubleValue(),
00171          op);
00172       }
00173       case WQLOperand::BOOLEAN_VALUE:
00174       {
00175          return _Compare(
00176          lhs.getBooleanValue(),
00177          rhs.getBooleanValue(),
00178          op);
00179       }
00180       case WQLOperand::STRING_VALUE:
00181       {
00182          return _Compare(
00183          lhs.getStringValue(),
00184          rhs.getStringValue(),
00185          op);
00186       }
00187       default:
00188       OW_ASSERT(0);
00189    }
00190    return false;
00191 }
00192 //
00193 // WQL Compiler methods
00194 //
00195 WQLCompile::WQLCompile()
00196 {
00197 }
00198 WQLCompile::WQLCompile(const WQLSelectStatement & wqs)
00199 {
00200    compile(&wqs);
00201 }
00202 WQLCompile::~WQLCompile()
00203 {
00204 }
00205 void WQLCompile::compile(const WQLSelectStatement * wqs)
00206 {
00207    if (!wqs->hasWhereClause())   
00208    {
00209       return;
00210    }
00211    _tableau.clear();
00212    _buildEvalHeap(wqs);
00213    _pushNOTDown();
00214    _factoring();
00215    Array<stack_el> disj;
00216    _gatherDisj(disj);
00217    if (disj.size() == 0)
00218    {
00219       if (terminal_heap.size() > 0)
00220       {
00221          // point to the remaining terminal element
00222          disj.append(stack_el(0, TERMINAL_HEAP));
00223       }
00224    }
00225 
00226    for (UInt32 i=0, n =disj.size(); i< n; i++)
00227    {
00228       TableauRow tr;
00229       Array<stack_el> conj;
00230       if (disj[i].type == EVAL_HEAP)
00231       {
00232          _gatherConj(conj, disj[i]);
00233          for ( UInt32 j=0, m = conj.size(); j < m; j++)
00234          {
00235             tr.append(terminal_heap[conj[j].opn]);
00236          }
00237       }
00238       else
00239       {
00240          tr.append(terminal_heap[disj[i].opn]);
00241       }
00242       _tableau.append(tr);
00243    }
00244    eval_heap.clear();
00245    //printTableau();
00246    _sortTableau();
00247 }
00248 bool WQLCompile::evaluate(const WQLPropertySource& source) const
00249 {
00250    WQLOperand lhs, rhs;
00251    UInt32 tableauSize = _tableau.size();
00252    if (tableauSize == 0)
00253    {
00254       return true;
00255    }
00256    for (UInt32 i = 0; i < tableauSize; i++)
00257    {
00258       TableauRow tr = _tableau[i];
00259       bool b = true;
00260       for (UInt32 j=0,m = tr.size(); b && j < m; j++)
00261       {
00262          if (tr[j].op == WQL_ISA)
00263          {
00264             String propertyName = tr[j].opn1.getPropertyName();
00265             String className;
00266             if (tr[j].opn2.getType() == WQLOperand::PROPERTY_NAME)
00267             {
00268                className = tr[j].opn2.getPropertyName();
00269             }
00270             else
00271             {
00272                className = tr[j].opn2.getStringValue(); // this will throw if it's not a string
00273             }
00274             b = source.evaluateISA(propertyName, className);
00275          }
00276          else
00277          {
00278             lhs = tr[j].opn1;
00279             WQLCompile::_ResolveProperty(lhs,source);
00280             rhs = tr[j].opn2;
00281             WQLCompile::_ResolveProperty(rhs,source);
00282             if (rhs.getType() != lhs.getType())
00283             {
00284                OW_THROW(TypeMismatchException, Format("Type mismatch: lhs: %1 rhs: %2", lhs.toString(), rhs.toString()).c_str());
00285             }
00286             b = _Evaluate(lhs, rhs, tr[j].op);
00287          }
00288       }
00289 
00290       if (b)
00291       {
00292          return true;
00293       }
00294    }
00295    return false;
00296 }
00297 void WQLCompile::print(std::ostream& ostr)
00298 {
00299    for (UInt32 i=0, n=eval_heap.size();i < n;i++)
00300    {
00301       WQLOperation wop = eval_heap[i].op; 
00302       if (wop == WQL_DO_NOTHING) 
00303       {
00304          continue;
00305       }
00306       ostr << "Eval element " << i << ": "; 
00307       if (eval_heap[i].is_terminal1 == TERMINAL_HEAP) 
00308       {
00309          ostr << "T(";
00310       }
00311       else if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00312       {
00313          ostr << "E(";
00314       }
00315       else
00316       {
00317          ostr << "O(";
00318       }
00319       ostr << eval_heap[i].opn1 << ") "; 
00320       ostr << WQLOperationToString(eval_heap[i].op); 
00321       if (eval_heap[i].is_terminal2 == TERMINAL_HEAP) 
00322       {
00323          ostr << " T(";
00324       }
00325       else if (eval_heap[i].is_terminal2 == EVAL_HEAP)
00326       {
00327          ostr << "E(";
00328       }
00329       else
00330       {
00331          ostr << "O(";
00332       }
00333       ostr << eval_heap[i].opn2 << ")" << std::endl; 
00334    } 
00335    for (UInt32 i=0, n=terminal_heap.size();i < n;i++)
00336    {
00337       ostr << "Terminal expression " << i << ": "; 
00338       ostr << terminal_heap[i].opn1.toString() << " "; 
00339       ostr << WQLOperationToString(terminal_heap[i].op) << " " 
00340          << terminal_heap[i].opn2.toString() << std::endl; 
00341    }
00342 }
00343 void WQLCompile::printTableau(std::ostream& ostr)
00344 {
00345    for (UInt32 i=0, n = _tableau.size(); i < n; i++)
00346    {
00347       ostr << "Tableau " << i << std::endl;
00348       TableauRow tr = _tableau[i];
00349       for (UInt32 j=0, m = tr.size(); j < m; j++)
00350       {
00351          ostr << tr[j].opn1.toString() << " "; 
00352          ostr << WQLOperationToString(tr[j].op) << " " 
00353             << tr[j].opn2.toString() << std::endl; 
00354       }
00355    }
00356 }
00357 void WQLCompile::_buildEvalHeap(const WQLSelectStatement * wqs)
00358 {
00359    Stack<stack_el> stack;
00360    for (UInt32 i = 0, n = wqs->_operStack.size(); i < n; i++)
00361    {
00362       const WQLSelectStatement::OperandOrOperation& curItem = wqs->_operStack[i];
00363       if (curItem.m_type == WQLSelectStatement::OperandOrOperation::OPERAND)
00364       {
00365          // put pointer to it onto the stack
00366          stack.push(stack_el(i, OPERAND));
00367       }
00368       else
00369       {
00370          WQLOperation op = curItem.m_operation;
00371    
00372          switch (op)
00373          {
00374             // unary
00375             case WQL_NOT:
00376                {
00377                   OW_ASSERT(stack.size() >= 1);
00378    
00379                   stack_el op1 = stack.top();
00380    
00381                   // generate Eval expression
00382                   eval_heap.append(eval_el(false, op, op1.opn, op1.type,
00383                      -1, TERMINAL_HEAP));
00384    
00385                   stack.top() = stack_el(eval_heap.size()-1, EVAL_HEAP);
00386    
00387                   break;
00388                }
00389    
00390             // binary
00391             case WQL_OR:
00392             case WQL_AND:
00393             case WQL_EQ:
00394             case WQL_NE:
00395             case WQL_LT:
00396             case WQL_LE:
00397             case WQL_GT:
00398             case WQL_GE:
00399             case WQL_ISA:
00400                {
00401                   OW_ASSERT(stack.size() >= 2);
00402    
00403                   stack_el op2 = stack.top();
00404                   stack.pop();
00405    
00406                   stack_el op1 = stack.top();
00407                   if (op1.type == OPERAND && op2.type == OPERAND)
00408                   {
00409                      OW_ASSERT(op1.type == OPERAND);
00410                      OW_ASSERT(wqs->_operStack[op1.opn].m_type == WQLSelectStatement::OperandOrOperation::OPERAND);
00411                      WQLOperand lhs = wqs->_operStack[op1.opn].m_operand;
00412                      OW_ASSERT(op2.type == OPERAND);
00413                      OW_ASSERT(wqs->_operStack[op2.opn].m_type == WQLSelectStatement::OperandOrOperation::OPERAND);
00414                      WQLOperand rhs = wqs->_operStack[op2.opn].m_operand;
00415                      terminal_heap.push_back(term_el(false, op, lhs, rhs));
00416                      stack.top() = stack_el(terminal_heap.size()-1, TERMINAL_HEAP);
00417                   }
00418                   else
00419                   {
00420                      // generate Eval expression
00421                      eval_heap.append(eval_el(false, op, op1.opn, op1.type,
00422                         op2.opn , op2.type));
00423                      stack.top() = stack_el(eval_heap.size()-1, EVAL_HEAP);
00424                   }
00425    
00426                   break;
00427                }
00428             case WQL_DO_NOTHING:
00429                {
00430                   OW_ASSERT(0); // this should never happen
00431                   break;
00432                }
00433          }
00434       }
00435    }
00436    OW_ASSERT(stack.size() == 1);
00437 }
00438 void WQLCompile::_pushNOTDown()
00439 {
00440    for (Int32 i=eval_heap.size()-1; i >= 0; i--)
00441    {
00442       bool _found = false;
00443       // Order all operators, so that op1 > op2 for non-terminals
00444       // and terminals appear as second operand
00445       eval_heap[i].order();
00446       // First solve the unary NOT operator
00447       if (eval_heap[i].op == WQL_NOT)
00448       {
00449          // This serves as the equivalent of an empty operator
00450          eval_heap[i].op = WQL_DO_NOTHING;
00451          // Substitute this expression in all higher order eval statements
00452          // so that this node becomes disconnected from the tree
00453          for (Int32 j=eval_heap.size()-1; j > i;j--)
00454          {
00455             // Test first operand
00456             if ((eval_heap[j].is_terminal1 == EVAL_HEAP) && (eval_heap[j].opn1 == i))
00457             {
00458                eval_heap[j].assign_unary_to_first(eval_heap[i]);
00459             }
00460             // Test second operand
00461             if ((eval_heap[j].is_terminal2 == EVAL_HEAP) && (eval_heap[j].opn2 == i))
00462             {
00463                eval_heap[j].assign_unary_to_second(eval_heap[i]);
00464             }
00465          }
00466          // Test: Double NOT created by moving down
00467          if (eval_heap[i].mark)
00468          {
00469             eval_heap[i].mark = false;
00470          }
00471          else
00472          {
00473             _found = true;
00474          }
00475          // else indicate a pending NOT to be pushed down further
00476       }
00477       // Simple NOT created by moving down
00478       if (eval_heap[i].mark)
00479       {
00480          // Remove the mark, indicate a pending NOT to be pushed down
00481          // further and switch operators (AND / OR)
00482          eval_heap[i].mark=false;
00483          if (eval_heap[i].op == WQL_OR) 
00484          {
00485             eval_heap[i].op = WQL_AND;
00486          }
00487          else if (eval_heap[i].op == WQL_AND) 
00488          {
00489             eval_heap[i].op = WQL_OR;
00490          }
00491          // NOT operator is already ruled out
00492          _found = true;
00493       }
00494       // Push a pending NOT further down
00495       if (_found)
00496       {
00497          // First operand
00498          int j = eval_heap[i].opn1;
00499          if (eval_heap[i].is_terminal1 == TERMINAL_HEAP)
00500          {
00501             // Flip NOT mark
00502             terminal_heap[j].negate();
00503          }
00504          else if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00505          {
00506             eval_heap[j].mark = !(eval_heap[j].mark);
00507          }
00508          //Second operand (if it exists)
00509          if ((j = eval_heap[i].opn2) >= 0)
00510          {
00511             if (eval_heap[i].is_terminal2 == TERMINAL_HEAP)
00512             {
00513                // Flip NOT mark
00514                terminal_heap[j].negate();
00515             }
00516             else if (eval_heap[i].is_terminal2 == EVAL_HEAP)
00517             {
00518                eval_heap[j].mark = !(eval_heap[j].mark);
00519             }
00520          }
00521       }
00522    }
00523 }
00524 void WQLCompile::_factoring()
00525 {
00526    int i = 0,n = eval_heap.size();
00527    //for (int i=eval_heap.size()-1; i >= 0; i--)
00528    while (i < n)
00529    {
00530       int _found = 0;
00531       int index = 0;
00532       // look for expressions (A | B) & C  ---> A & C | A & B
00533       if (eval_heap[i].op == WQL_AND)
00534       {
00535          if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00536          {
00537             index = eval_heap[i].opn1; // remember the index
00538             if (eval_heap[index].op == WQL_OR) 
00539             {
00540                _found = 1;
00541             }
00542          }
00543          if ((_found == 0) && (eval_heap[i].is_terminal2 == EVAL_HEAP))
00544          {
00545             index = eval_heap[i].opn2; // remember the index
00546             if (eval_heap[index].op == WQL_OR) 
00547             {
00548                _found = 2;
00549             }
00550          }
00551          if (_found != 0)
00552          {
00553             stack_el s;
00554             if (_found == 1)
00555             {
00556                s = eval_heap[i].getSecond();
00557             }
00558             else
00559             {
00560                s = eval_heap[i].getFirst();
00561             }
00562             // insert two new expression before entry i
00563             eval_el evl(false, WQL_OR, i+1, EVAL_HEAP, i, EVAL_HEAP);
00564             if (i < static_cast<int>(eval_heap.size())-1)
00565             {
00566                eval_heap.insert(i+1, evl);
00567             }
00568             else
00569             {
00570                eval_heap.append(evl);
00571             }
00572             eval_heap.insert(i+1, evl);
00573             for (int j=eval_heap.size()-1; j > i + 2; j--)
00574             {
00575                //eval_heap[j] = eval_heap[j-2];
00576                // adjust pointers
00577                if ((eval_heap[j].is_terminal1 == EVAL_HEAP) &&
00578                   (eval_heap[j].opn1 >= i))
00579                {
00580                   eval_heap[j].opn1 += 2;
00581                }
00582                if ((eval_heap[j].is_terminal2 == EVAL_HEAP) &&
00583                   (eval_heap[j].opn2 >= i))
00584                {
00585                   eval_heap[j].opn2 += 2;
00586                }
00587             }
00588             n+=2; // increase size of array
00589             // generate the new expressions : new OR expression
00590             // first new AND expression
00591             eval_heap[i+1].mark = false;
00592             eval_heap[i+1].op = WQL_AND;
00593             eval_heap[i+1].setFirst(s);
00594             eval_heap[i+1].setSecond( eval_heap[index].getFirst());
00595             eval_heap[i+1].order();
00596             // second new AND expression
00597             eval_heap[i].mark = false;
00598             eval_heap[i].op = WQL_AND;
00599             eval_heap[i].setFirst(s);
00600             eval_heap[i].setSecond( eval_heap[index].getSecond());
00601             eval_heap[i].order();
00602             // mark the indexed expression as inactive
00603             //eval_heap[index].op = WQL_IS_TRUE; possible disconnects
00604             i--;
00605          } /* endif _found > 0 */
00606       } /* endif found AND operator */
00607       i++; // increase pointer
00608    }
00609 }
00610 void WQLCompile::_gatherDisj(Array<stack_el>& stk)
00611 {
00612    _gather(stk, stack_el(0, TERMINAL_HEAP), true);
00613 }
00614 void WQLCompile::_gatherConj(Array<stack_el>& stk, stack_el sel)
00615 {
00616    _gather(stk, sel, false);
00617 }
00618 void WQLCompile::_gather(Array<stack_el>& stk, stack_el sel, bool or_flag)
00619 {
00620    UInt32 i = 0;
00621    stk.empty();
00622    if ((i = eval_heap.size()) == 0) 
00623    {
00624       return;
00625    }
00626    while (eval_heap[i-1].op == WQL_DO_NOTHING)
00627    {
00628       eval_heap.remove(i-1);
00629       i--;
00630       if (i == 0) 
00631       {
00632          return;
00633       }
00634    }
00635    if (or_flag)
00636    {
00637       stk.append(stack_el(i-1, EVAL_HEAP));
00638    }
00639    else
00640    {
00641       if (sel.type != EVAL_HEAP) 
00642       {
00643          return;
00644       }
00645       stk.append(sel);
00646    }
00647    i = 0;
00648    while (i<stk.size())
00649    {
00650       int k = stk[i].opn;
00651       if ((k < 0) || (stk[i].type != EVAL_HEAP))
00652       {
00653          i++;
00654       }
00655       else
00656       {
00657          if ( ((eval_heap[k].op != WQL_OR) && (or_flag)) ||
00658             ((eval_heap[k].op != WQL_AND) && (!or_flag))  )
00659          {
00660             i++;
00661          }
00662          else
00663          {
00664             // replace the element with disjunction
00665             stk[i] = eval_heap[k].getSecond();
00666             stk.insert(i, eval_heap[k].getFirst());
00667             if (or_flag)
00668             {
00669                eval_heap[k].op = WQL_DO_NOTHING;
00670             }
00671          }
00672       }
00673    }
00674 }
00675 void WQLCompile::_sortTableau()
00676 {
00677    // sorting key is lexical scope of properties
00678    // Bubblesort should be sufficient for tableauRows
00679    for (UInt32 i = 0, n = _tableau.size(); i < n; i++)
00680    {
00681       TableauRow tr = _tableau[i];
00682       WQLOperand wop;
00683       WQLOperation wopt;
00684       // try to order row, so that properties are (preferrably) first args
00685       // comparisons of two properties are moved to the end
00686       for (UInt32 j = 0, m = tr.size(); j < m; j++)
00687       {
00688          if (tr[j].opn2.getType() == WQLOperand::PROPERTY_NAME)
00689          {
00690             if (tr[j].opn1.getType() != WQLOperand::PROPERTY_NAME)
00691             {
00692                wop = tr[j].opn1;
00693                tr[j].opn1 = tr[j].opn2;
00694                tr[j].opn2 = wop;
00695                // turn operator
00696                switch (tr[j].op)
00697                {
00698                   case WQL_LT: tr[j].op = WQL_GT; break;
00699                   case WQL_GT: tr[j].op = WQL_LT; break;
00700                   case WQL_LE: tr[j].op = WQL_GE; break;
00701                   case WQL_GE: tr[j].op = WQL_LE; break;
00702                   default: break;
00703                }
00704             }
00705          }
00706       }
00707       String key1, key2;
00708       // switch this to use std::sort ?
00709       for (UInt32 j = 0, m = tr.size(); j < m; j++)
00710       {
00711          if ((tr[j].opn1.getType() == WQLOperand::PROPERTY_NAME)
00712             && (tr[j].opn2.getType() != WQLOperand::PROPERTY_NAME))
00713          {
00714             key1 = tr[j].opn1.getPropertyName();
00715          }
00716          else
00717          {
00718             key1.erase();
00719          }
00720          for (UInt32 k = j; k < m; k++)
00721          {
00722             if ((tr[k].opn1.getType() == WQLOperand::PROPERTY_NAME)
00723                && (tr[k].opn2.getType() != WQLOperand::PROPERTY_NAME))
00724             {
00725                key2 = tr[k].opn1.getPropertyName();
00726             }
00727             else
00728             {
00729                key2.erase();
00730             }
00731             if (key1 > key2)
00732             {
00733                wop = tr[j].opn1;
00734                tr[j].opn1 = tr[k].opn1;
00735                tr[k].opn1 = wop;
00736                wop = tr[j].opn2;
00737                tr[j].opn2 = tr[k].opn2;
00738                tr[k].opn2 = wop;
00739                wopt = tr[j].op;
00740                tr[j].op = tr[k].op;
00741                tr[k].op = wopt;
00742             }
00743          }
00744       }
00745       // remove duplicates
00746       tr.erase(std::unique(tr.begin(), tr.end()), tr.end());
00747       // save it
00748       _tableau[i] = tr;
00749    }
00750 }
00751 
00752 } // end namespace OW_NAMESPACE
00753 

Generated on Thu Feb 9 08:48:17 2006 for openwbem by  doxygen 1.4.6