OWBI1_WQLSelectStatement.cpp

Go to the documentation of this file.
00001 //%/////////////////////////////////////////////////////////////////////////////
00002 //
00003 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
00004 // The Open Group, Tivoli Systems
00005 // Portions Copyright (C) 2003-2004 Vintela, Inc. All rights reserved.
00006 //
00007 // Permission is hereby granted, free of charge, to any person obtaining a copy
00008 // of this software and associated documentation files (the "Software"), to
00009 // deal in the Software without restriction, including without limitation the
00010 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00011 // sell copies of the Software, and to permit persons to whom the Software is
00012 // furnished to do so, subject to the following conditions:
00013 // 
00014 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
00015 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
00016 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
00017 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
00018 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00019 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00020 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00021 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 //
00023 //==============================================================================
00024 //
00025 // Author: Mike Brasher (mbrasher@bmc.com)
00026 //
00027 // Modified By: Dan Nuffer
00028 //
00029 //%/////////////////////////////////////////////////////////////////////////////
00030 #include "OWBI1_config.h"
00031 #include "OWBI1_StringBuffer.hpp"
00032 #include "OWBI1_WQLSelectStatement.hpp"
00033 #include "OWBI1_WQLCompile.hpp"
00034 #include "OW_Assertion.hpp"
00035 
00036 #include <stack>
00037 #if defined(OWBI1_HAVE_OSTREAM)
00038 #include <ostream>
00039 #else
00040 #include <iostream>
00041 #endif
00042 
00043 namespace OWBI1
00044 {
00045 using namespace OpenWBEM;
00046 
00047 template<class T>
00048 inline static bool _Compare(const T& x, const T& y, WQLOperation op)
00049 {
00050    switch (op)
00051    {
00052       case WQL_EQ: 
00053          return x == y;
00054       case WQL_NE: 
00055          return x != y;
00056       case WQL_LT: 
00057          return x < y;
00058       case WQL_LE: 
00059          return x <= y;
00060       case WQL_GT: 
00061          return x > y;
00062       case WQL_GE: 
00063          return x >= y;
00064       default:
00065          OW_ASSERT(0);
00066    }
00067    return false;
00068 }
00069 static bool _Evaluate(
00070       const WQLOperand& lhs, 
00071       const WQLOperand& rhs, 
00072       WQLOperation op)
00073 {
00074    switch (lhs.getType())
00075    {
00076       case WQLOperand::NULL_VALUE:
00077          {
00078             // return true if the op is WQL_EQ and the rhs is NULL
00079             // also if op is WQL_NE and rhs is not NULL
00080             return !(op == WQL_EQ) ^ (rhs.getType() == WQLOperand::NULL_VALUE);
00081             break;
00082          }
00083       case WQLOperand::INTEGER_VALUE:
00084          {
00085             return _Compare(
00086                   lhs.getIntegerValue(),
00087                   rhs.getIntegerValue(),
00088                   op);
00089          }
00090       case WQLOperand::DOUBLE_VALUE:
00091          {
00092             return _Compare(
00093                   lhs.getDoubleValue(),
00094                   rhs.getDoubleValue(),
00095                   op);
00096          }
00097       case WQLOperand::BOOLEAN_VALUE:
00098          {
00099             return _Compare(
00100                   lhs.getBooleanValue(),
00101                   rhs.getBooleanValue(),
00102                   op);
00103          }
00104       case WQLOperand::STRING_VALUE:
00105          {
00106             return _Compare(
00107                   lhs.getStringValue(),
00108                   rhs.getStringValue(),
00109                   op);
00110          }
00111       default:
00112          OW_ASSERT(0);
00113    }
00114    return false;
00115 }
00116 WQLSelectStatement::WQLSelectStatement()
00117 {
00118    _operStack.reserve(32);
00119 }
00120 WQLSelectStatement::~WQLSelectStatement()
00121 {
00122 }
00123 void WQLSelectStatement::clear()
00124 {
00125    _className.erase();
00126    _selectPropertyNames.clear();
00127    _operStack.clear();
00128 }
00129 bool WQLSelectStatement::appendWherePropertyName(const String& x)
00130 {
00131    //
00132    // Reject duplicate property names by returning false.
00133    //
00134    for (size_t i = 0, n = _wherePropertyNames.size(); i < n; i++)
00135    {
00136       if (_wherePropertyNames[i] == x)
00137       {
00138          return false;
00139       }
00140    }
00141    //
00142    // Append the new property.
00143    //
00144    _wherePropertyNames.append(x);
00145    return true;
00146 }
00147 static inline void _ResolveProperty(
00148       WQLOperand& op,
00149       const WQLPropertySource* source)
00150 {
00151    //
00152    // Resolve the operand: if it's a property name, look up its value:
00153    //
00154    if (op.getType() == WQLOperand::PROPERTY_NAME)
00155    {
00156       const String& propertyName = op.getPropertyName();
00157       // it's up to the source to handle embedded properties.
00158       if (!source->getValue(propertyName, op))
00159       {
00160          OWBI1_THROW(NoSuchPropertyException, propertyName.c_str());
00161       }
00162    }
00163 }
00164 bool WQLSelectStatement::evaluateWhereClause(
00165       const WQLPropertySource* source) const
00166 {
00167    if (!hasWhereClause())
00168    {
00169       return true;
00170    }
00171    std::stack<WQLOperand> stack;
00172    //
00173    // Process each of the operations:
00174    //
00175    for (UInt32 i = 0, n = _operStack.size(); i < n; i++)
00176    {
00177       const WQLSelectStatement::OperandOrOperation& curItem = _operStack[i];
00178       if (curItem.m_type == WQLSelectStatement::OperandOrOperation::OPERAND)
00179       {
00180          // put it onto the stack
00181          stack.push(curItem.m_operand);
00182       }
00183       else
00184       {
00185          WQLOperation op = curItem.m_operation;
00186          switch (op)
00187          {
00188             case WQL_OR:
00189                {
00190                   OW_ASSERT(stack.size() >= 2);
00191                   WQLOperand op1 = stack.top();
00192                   stack.pop();
00193                   WQLOperand& op2 = stack.top();
00194                   bool b1 = op1.getBooleanValue();
00195                   bool b2 = op2.getBooleanValue();
00196                   stack.top() = WQLOperand(b1 || b2, WQL_BOOLEAN_VALUE_TAG);
00197                   break;
00198                }
00199             case WQL_AND:
00200                {
00201                   OW_ASSERT(stack.size() >= 2);
00202                   WQLOperand op1 = stack.top();
00203                   stack.pop();
00204                   WQLOperand& op2 = stack.top();
00205                   bool b1 = op1.getBooleanValue();
00206                   bool b2 = op2.getBooleanValue();
00207                   stack.top() = WQLOperand(b1 && b2, WQL_BOOLEAN_VALUE_TAG);
00208                   break;
00209                }
00210             case WQL_NOT:
00211                {
00212                   OW_ASSERT(stack.size() >= 1);
00213                   WQLOperand& op = stack.top();
00214                   bool b1 = op.getBooleanValue();
00215                   stack.top() = WQLOperand(!b1, WQL_BOOLEAN_VALUE_TAG);
00216                   break;
00217                }
00218             case WQL_EQ:
00219             case WQL_NE:
00220             case WQL_LT:
00221             case WQL_LE:
00222             case WQL_GT:
00223             case WQL_GE:
00224                {
00225                   OW_ASSERT(stack.size() >= 2);
00226                   //
00227                   // Resolve the left-hand-side to a value (if not already
00228                   // a value).
00229                   //
00230                   WQLOperand lhs = stack.top();
00231                   stack.pop();
00232                   _ResolveProperty(lhs, source);
00233                   //
00234                   // Resolve the right-hand-side to a value (if not already
00235                   // a value).
00236                   //
00237                   WQLOperand& rhs = stack.top();
00238                   _ResolveProperty(rhs, source);
00239                   //
00240                   // Check for a type mismatch:
00241                   //
00242                   if (rhs.getType() != lhs.getType())
00243                   {
00244                      OWBI1_THROW(TypeMismatchException, "");
00245                   }
00246                   //
00247                   // Now that the types are known to be alike, apply the
00248                   // operation:
00249                   //
00250                   stack.top() = WQLOperand(_Evaluate(lhs, rhs, op), WQL_BOOLEAN_VALUE_TAG);
00251                   break;
00252                }
00253             case WQL_ISA:
00254                {
00255                   OW_ASSERT(stack.size() >= 2);
00256                   WQLOperand lhs = stack.top();
00257                   stack.pop();
00258                   if (lhs.getType() != WQLOperand::PROPERTY_NAME)
00259                   {
00260                      OWBI1_THROW(TypeMismatchException, "First argument of ISA must be a property name");
00261                   }
00262                   WQLOperand& rhs = stack.top();
00263                   String className;
00264                   if (rhs.getType() == WQLOperand::PROPERTY_NAME)
00265                   {
00266                      className = rhs.getPropertyName();
00267                   }
00268                   else if (rhs.getType() == WQLOperand::STRING_VALUE)
00269                   {
00270                      className = rhs.getStringValue();
00271                   }
00272                   else
00273                   {
00274                      OWBI1_THROW(TypeMismatchException, "Second argument of ISA must be a property name or string constant");
00275                   }
00276                   stack.top() = WQLOperand(source->evaluateISA(lhs.getPropertyName(), className), WQL_BOOLEAN_VALUE_TAG);
00277                   break;
00278                   break;
00279                }
00280             case WQL_DO_NOTHING:
00281                {
00282                   OW_ASSERT(0); // should never happen
00283                   break;
00284                }
00285          }
00286       }
00287    }
00288    OW_ASSERT(stack.size() == 1);
00289    return stack.top().getBooleanValue();
00290 }
00291 void WQLSelectStatement::print(std::ostream& ostr) const
00292 {
00293    ostr << "WQLSelectStatement\n";
00294    ostr << "{\n";
00295    ostr << "   _className: \"" << _className << "\"\n";
00296    for (size_t i = 0; i < _selectPropertyNames.size(); i++)
00297    {
00298       if (i == 0)
00299       {
00300          ostr << '\n';
00301       }
00302       ostr << "   _selectPropertyNames[" << i << "]: ";
00303       ostr << '"' << _selectPropertyNames[i] << '"' << '\n';
00304    }
00305    // Print the operations/operands
00306    for (size_t i = 0; i < _operStack.size(); i++)
00307    {
00308       if (i == 0)
00309       {
00310          ostr << '\n';
00311       }
00312       ostr << "   _operStack[" << i << "]: ";
00313       ostr << '"' << _operStack[i].toString() << '"' << '\n';
00314    }
00315    ostr << "}" << std::endl;
00316 }
00317 String WQLSelectStatement::toString() const
00318 {
00319    StringBuffer buf("select ");
00320    if (_selectPropertyNames.size())
00321    {
00322       for (size_t i = 0; i < _selectPropertyNames.size(); i++)
00323       {
00324          if (i != 0)
00325          {
00326             buf += ", ";
00327          }
00328          buf += _selectPropertyNames[i];
00329       }
00330    }
00331    else
00332    {
00333       // can this happen?
00334       buf += " *";
00335    }
00336    buf += " from ";
00337    buf += _className;
00338    // Print the operations/operands
00339    for (size_t i = 0; i < _operStack.size(); i++)
00340    {
00341       if (i == 0)
00342       {
00343          buf += "\n";
00344       }
00345       buf += " _operStack[" + String(UInt32(i)) + "]: ";
00346       buf += "\"" + _operStack[i].toString() + "\"\n";
00347    }
00348    buf += ")";
00349    return buf.toString();
00350 }
00351 void WQLSelectStatement::compileWhereClause(
00352       const WQLPropertySource* /*source*/, WQLCompile& wcl)
00353 {
00354    wcl.compile(this);
00355 }
00356 
00357 } // end namespace OWBI1
00358 

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