Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

SQLtoLDAPPredicateTree.cpp

00001                               /* SQLtoLDAPPredicateTree.cpp */
00002 
00003 /*
00004  *  Implementation of SQLtoLDAPPredicateTree.h
00005  */
00006 #include "SQLtoLDAPPredicateTree.h"
00007 
00008 using namespace LcgInfo;
00009 using namespace std;
00010    
00011 
00012 /*********************  METHODS FOR CLASS SQLtoLDAPPredicateTree **********************/
00013 
00014 SQLtoLDAPPredicateTree::SQLtoLDAPPredicateTree()
00015 :SQLPredicateTree(){
00016 }
00017 
00018 SQLtoLDAPPredicateTree::~SQLtoLDAPPredicateTree(){
00019 }
00020 
00021 SQLtoLDAPPredicateTree* SQLtoLDAPPredicateTree::create(){
00022    return new SQLtoLDAPPredicateTree();
00023 }
00024 
00025 SQLtoLDAPPredicateTree * SQLtoLDAPPredicateTree::clone(){
00026    SQLtoLDAPPredicateTree * aux=create();
00027 
00028    //copy this node values
00029    aux->setValue(value());
00030    aux->setType(type());
00031    aux->setDepth(depth());
00032 
00033   //clone children
00034   if(left()!=NULL)
00035       aux->setLeft(left()->clone());
00036    else
00037       aux->setLeft(NULL);
00038    if(right()!=NULL)
00039       aux->setRight(right()->clone());
00040    else
00041       aux->setRight(NULL);    
00042 
00043    return aux;
00044 }
00045 
00046 string SQLtoLDAPPredicateTree::evaluate(vector<string> & pQueries){
00047    if(depth()==0) pQueries.clear();
00048    string aux; 
00049    switch (this->type()){
00050       case COMPARISON:
00051          //switch depending on the comparison...
00052          if((this->value()=="=") || (this->value()==">=") || (this->value()=="<=")){
00053             aux='(' + left()->evaluate(pQueries) ;
00054             aux+= this->value() + right()->evaluate(pQueries) + ')';
00055          }
00056          if(this->value()==">"){  // ">" is the same as "NOT <="
00057             aux="(! (" + left()->evaluate(pQueries) + "<=";
00058             aux+= right()->evaluate(pQueries) + "))";
00059          }
00060          if(this->value()=="<"){
00061             aux="(! (" + left()->evaluate(pQueries) + ">=";
00062             aux+= right()->evaluate(pQueries) + "))";
00063          }
00064          if(this->value()=="<>"){ // and "<>" is the same as "NOT ="
00065             aux="(! (" + left()->evaluate(pQueries) + "=";
00066             aux+= right()->evaluate(pQueries) + "))";
00067          }
00068          if(nocaseCompare(this->value(),"LIKE")) {
00069             //Substitute SQL's % wildcard for LDAP's * (the _ has no equivalent)
00070             string temp=right()->evaluate(pQueries);
00071             string::size_type pos = temp.find_first_of("%", 0);
00072             while (pos != string::npos){
00073                int count=0; 
00074                for(int i=pos-1; temp.at(i)=='\\'; i--, count++); //count escape chars
00075                if(count>0){
00076                   temp.erase(pos-count/2,count/2); //delete half of the "\"
00077                   pos-=count/2;                    // adjust index (elements were eliminated)
00078                   if(count%2==0)                   // the "%" was not escaped, substitute it 
00079                      temp.replace(pos,1,"*");
00080                   else                             //the "%" was escaped, just delete 1 more "\"
00081                      temp.erase(pos-1,1);
00082                }
00083                else temp.replace(pos,1,"*");            // no "\", substitute the "%"
00084                
00085                pos = temp.find_first_of("%", pos+1);   // go for next one 
00086             }
00087             aux='(' + left()->evaluate(pQueries) + " = " + temp + ')'; 
00088          }
00089          break;
00090 
00091       case BOOLEAN: 
00092          if (nocaseCompare(this->value(),"NOT")){
00093             if(right()->relatesTables())              
00094                aux="(! " + substituteSubquery(right(), 0, pQueries) + ')'; //modify only child(sense?)
00095             else
00096                aux="(! " + right()->evaluate(pQueries) + ')';
00097          }
00098 
00099          else if (nocaseCompare(this->value(),"AND")){
00100            //first check for NULL children (usually coming from identities)
00101            if((right()==0)&&(left()==0)) return "";
00102            if(right()==0) aux = left()->evaluate(pQueries);
00103            else if(left()==0){ aux = right()->evaluate(pQueries);}
00104             
00105             //check if any of the children is a relation among keys
00106            else if((left()->relatesTables())&&(!(right()->relatesTables()))){  //modify left
00107                aux=substituteSubquery(left(), right(), pQueries);
00108             }
00109             else if((right()->relatesTables())&&(!(left()->relatesTables()))){ //modify right
00110                aux=substituteSubquery(right(), left(), pQueries);
00111             }
00112             else if((right()->relatesTables())&&(left()->relatesTables())){    //modify both (sense?)
00113                aux = "(& " + substituteSubquery(left(), 0, pQueries);
00114                aux += substituteSubquery(right(), 0, pQueries) + ')';
00115             }
00116             else{                                                          //modify none
00117                aux="(& " + left()->evaluate(pQueries);
00118                aux+=right()->evaluate(pQueries) + ')';
00119             }
00120          }//end if(AND)
00121 
00122          else if (nocaseCompare(this->value(),"OR")){
00123            //first check for NULL children (usually coming from identities)
00124            if((right()==0) || (left()==0)) return "";
00125  
00126             aux="(| " + left()->evaluate(pQueries) + right()->evaluate(pQueries) + ')';
00127          }
00128          break;
00129 
00130       case LEAF:
00131             //first, remove the determinant objectclass (table) name, that is before the last "."
00132             string::size_type pos=0;
00133             if((!isLiteral(value())) && (!isNumber(value()))){
00134                pos=value().find_last_of('.', value().size()-1);
00135                if(pos!=string::npos)
00136                   aux=value().substr(pos+1);
00137                else 
00138                   aux=value();
00139             }
00140 
00141             //Now, remove the "'" chars
00142             if(isLiteral(value()))
00143                aux=value().substr(1,value().size()-2);         
00144 
00145             //finally, need to escape the "#" chars
00146             if(depth()!=-1){
00147                string::size_type pos=aux.find('#',0); 
00148                while (pos != string::npos){
00149                   aux.insert(pos,"\\");              
00150                   pos=aux.find('#',pos+2);
00151                }
00152             }
00153    }//end of switch(type)
00154 
00155    if(aux.empty()){
00156       string msg="Parsing error. The node could not be evaluated.";
00157       msg += "\nThis node's value: " + value() + "\nThis node's depth: " + int2str(depth());
00158       throw QueryTranslationException(msg,__FILE__,__LINE__);
00159    }
00160    
00161    return aux;
00162 };//end of recurEval()
00163 
00164 
00165 string SQLtoLDAPPredicateTree::substituteSubquery(PredicateTree * pNode,
00166                      PredicateTree * pTheOther, vector<string> & pQueries){
00167 
00168    string temp, result, subquery;
00169    string tempType;
00170    int tempDepth;
00171 
00172    if(pTheOther!=0){
00173       subquery=pTheOther->evaluate(pQueries) + " ";
00174 //      subquery+= pNode->right()->evaluate(pQueries);
00175       subquery+= pNode->right()->value();
00176    }
00177    else 
00178       subquery=pNode->right()->evaluate(pQueries);
00179    pQueries.push_back(subquery);
00180 
00181    temp=pNode->right()->value();  // store what there was on the right child
00182    tempDepth=pNode->right()->depth();
00183    // change it by the ldap query identifier 
00184    pNode->right()->setValue("\'#" + int2str(pQueries.size()-1) + "#\'");
00185    pNode->right()->setDepth(-1); //dirty trick to make evaluate() not to escape the previous #s
00186    result=pNode->evaluate(pQueries);
00187    pNode->right()->setValue(temp);     // restore the node's original value and depth
00188    pNode->right()->setDepth(tempDepth);
00189 
00190    return result;
00191 }

Generated on Tue Oct 5 14:42:45 2004 for LCG Information System Interface by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002