OqlParser.class.php

Go to the documentation of this file.
00001 <?php
00002 /****************************************************************************
00003  *   Copyright (C) 2008-2009 by Vladlen Y. Koshelev                         *
00004  *                                                                          *
00005  *   This program is free software; you can redistribute it and/or modify   *
00006  *   it under the terms of the GNU Lesser General Public License as         *
00007  *   published by the Free Software Foundation; either version 3 of the     *
00008  *   License, or (at your option) any later version.                        *
00009  *                                                                          *
00010  ****************************************************************************/
00011 
00015     abstract class OqlParser
00016     {
00017         const INITIAL_STATE = 254;
00018         const FINAL_STATE   = 255;
00019         
00020         // class map
00021         const PREFIX_UNARY_EXPRESSION   = 1;
00022         const POSTFIX_UNARY_EXPRESSION  = 2;
00023         const BINARY_EXPRESSION         = 3;
00024         const BETWEEN_EXPRESSION        = 4;
00025         
00026         private static $classMap = array(
00027             self::PREFIX_UNARY_EXPRESSION   => 'PrefixUnaryExpression',
00028             self::POSTFIX_UNARY_EXPRESSION  => 'PostfixUnaryExpression',
00029             self::BINARY_EXPRESSION         => 'BinaryExpression',
00030             self::BETWEEN_EXPRESSION        => 'LogicalBetween'
00031         );
00032         
00033         // binary operator map
00034         private static $binaryOperatorMap = array(
00035             '='                 => BinaryExpression::EQUALS,
00036             '!='                => BinaryExpression::NOT_EQUALS,
00037             'and'               => BinaryExpression::EXPRESSION_AND,
00038             'or'                => BinaryExpression::EXPRESSION_OR,
00039             '>'                 => BinaryExpression::GREATER_THAN,
00040             '>='                => BinaryExpression::GREATER_OR_EQUALS,
00041             '<'                 => BinaryExpression::LOWER_THAN,
00042             '<='                => BinaryExpression::LOWER_OR_EQUALS,
00043             'like'              => BinaryExpression::LIKE,
00044             'not like'          => BinaryExpression::NOT_LIKE,
00045             'ilike'             => BinaryExpression::ILIKE,
00046             'not ilike'         => BinaryExpression::NOT_ILIKE,
00047             'similar to'        => BinaryExpression::SIMILAR_TO,
00048             'not similar to'    => BinaryExpression::NOT_SIMILAR_TO,
00049             '+'                 => BinaryExpression::ADD,
00050             '-'                 => BinaryExpression::SUBSTRACT,
00051             '*'                 => BinaryExpression::MULTIPLY,
00052             '/'                 => BinaryExpression::DIVIDE
00053         );
00054         
00055         // boolean operators priority
00056         const LOGIC_PRIORITY_OR         = 1;
00057         const LOGIC_PRIORITY_AND        = 2;
00058         const LOGIC_PRIORITY_LT_GT      = 3;
00059         const LOGIC_PRIORITY_EQ         = 4;
00060         const LOGIC_PRIORITY_TERMINAL   = 5;
00061         
00062         const LOGIC_PRIORITY_LOWEST     = self::LOGIC_PRIORITY_OR;
00063         const LOGIC_PRIORITY_UNARY_NOT  = self::LOGIC_PRIORITY_LT_GT;
00064         
00065         private static $logicPriorityMap = array(
00066             self::LOGIC_PRIORITY_OR         => 'or',
00067             self::LOGIC_PRIORITY_AND        => 'and',
00068             self::LOGIC_PRIORITY_LT_GT      => array('>', '<', '>=', '<='),
00069             self::LOGIC_PRIORITY_EQ         => array('=', '!='),
00070             self::LOGIC_PRIORITY_TERMINAL   => null
00071         );
00072         
00073         // arithmetic operators priority
00074         const ARITHMETIC_PRIORITY_ADD       = 1;
00075         const ARITHMETIC_PRIORITY_MUL       = 2;
00076         const ARITHMETIC_PRIORITY_TERMINAL  = 3;
00077         
00078         const ARITHMETIC_PRIORITY_LOWEST    = self::ARITHMETIC_PRIORITY_ADD;
00079         
00080         private static $arithmeticPriorityMap = array(
00081             self::ARITHMETIC_PRIORITY_ADD       => array('+', '-'),
00082             self::ARITHMETIC_PRIORITY_MUL       => array('*', '/'),
00083             self::ARITHMETIC_PRIORITY_TERMINAL  => null
00084         );
00085         
00086         protected $state        = null;
00087         protected $tokenizer    = null;
00088         protected $oqlObject    = null;
00089         
00090         protected $parentheses  = null;
00091         
00095         abstract protected function makeOqlObject();
00096         
00097         abstract protected function handleState();
00098         
00102         public function parse($string = null)
00103         {
00104             if ($string === null) {
00105                 Assert::isNotNull($this->tokenizer);
00106             
00107             } else {
00108                 Assert::isString($string);
00109                 $this->tokenizer = new OqlTokenizer($string);
00110             }
00111             
00112             $this->state = self::INITIAL_STATE;
00113             $this->oqlObject = $this->makeOqlObject();
00114             $this->parentheses = 0;
00115             
00116             while ($this->state != self::FINAL_STATE)
00117                 $this->state = $this->handleState();
00118             
00119             $this->checkParentheses();
00120             
00121             return $this->oqlObject;
00122         }
00123         
00127         public function getTokenizer()
00128         {
00129             return $this->tokenizer;
00130         }
00131         
00135         public function setTokenizer(OqlTokenizer $tokenizer)
00136         {
00137             $this->tokenizer = $tokenizer;
00138             
00139             return $this;
00140         }
00141         
00142         protected function getTokenValue($token, $raw = false)
00143         {
00144             if ($token instanceof OqlToken)
00145                 return $raw
00146                     ? $token->getRawValue()
00147                     : $token->getValue();
00148                 
00149             return null;
00150         }
00151         
00152         protected function checkToken($token, $type, $value = null)
00153         {
00154             if (
00155                 $token instanceof OqlToken
00156                 && $token->getType() == $type
00157             ) {
00158                 if ($value === null) {
00159                     return true;
00160                     
00161                 } elseif (is_array($value)) {
00162                     return in_array($token->getValue(), $value);
00163                     
00164                 } else {
00165                     return $token->getValue() == $value;
00166                 }
00167             }
00168             
00169             return false;
00170         }
00171         
00172         protected function checkKeyword($token, $value)
00173         {
00174             return $this->checkToken($token, OqlToken::KEYWORD, $value);
00175         }
00176         
00177         protected function checkIdentifier($token)
00178         {
00179             if ($token instanceof OqlToken) {
00180                 if ($token->getType() == OqlToken::IDENTIFIER)
00181                     return true;
00182                 
00183                 // fix token value if identifier name is equal to
00184                 // reserved word or aggregate function name
00185                 elseif (
00186                     $token->getType() == OqlToken::KEYWORD
00187                     || $token->getType() == OqlToken::AGGREGATE_FUNCTION
00188                 ) {
00189                     $token->setValue($token->getRawValue());
00190                     
00191                     return true;
00192                 }
00193             }
00194             
00195             return false;
00196         }
00197         
00198         protected function checkConstant($token)
00199         {
00200             return
00201                 $token instanceof OqlToken
00202                 && (
00203                     $token->getType() == OqlToken::STRING
00204                     || $token->getType() == OqlToken::NUMBER
00205                     || $token->getType() == OqlToken::BOOLEAN
00206                     || $token->getType() == OqlToken::NULL
00207                     || $token->getType() == OqlToken::SUBSTITUTION
00208                 );
00209         }
00210         
00211         protected function checkUnaryMinus($token)
00212         {
00213             return $this->checkToken($token, OqlToken::ARITHMETIC_OPERATOR, '-');
00214         }
00215         
00219         protected function checkParentheses($message = null)
00220         {
00221             if ($this->openParentheses(false, $message)) {
00222                 $this->error("unexpected '('", $message);
00223                 
00224             } elseif ($this->closeParentheses(false, $message)) {
00225                 $this->error("unexpected ')'", $message);
00226             }
00227                 
00228             if ($this->parentheses > 0)
00229                 $this->error("unexpected '('", $message);
00230             
00231             return true;
00232         }
00233         
00237         protected function openParentheses($required, $message = null)
00238         {
00239             if (
00240                 $this->checkToken($this->tokenizer->peek(), OqlToken::PARENTHESES, '(')
00241             ) {
00242                 $this->tokenizer->next();
00243                 $this->parentheses++;
00244                 
00245                 return true;
00246                 
00247             } elseif ($required) {
00248                 $this->error("expecting ')'", $message);
00249             }
00250             
00251             return false;
00252         }
00253         
00257         protected function closeParentheses($required, $message = null)
00258         {
00259             if (
00260                 $this->checkToken($this->tokenizer->peek(), OqlToken::PARENTHESES, ')')
00261             ) {
00262                 $this->tokenizer->next();
00263                 $this->parentheses--;
00264                 if ($this->parentheses < 0)
00265                     $this->error("unexpected ')'", $message);
00266                 
00267                 return true;
00268                 
00269             } elseif ($required) {
00270                 $this->error("expecting ')'", $message);
00271             }
00272             
00273             return false;
00274         }
00275         
00279         protected function getIdentifierExpression()
00280         {
00281             if ($isUnaryMinus = $this->checkUnaryMinus($this->tokenizer->peek()))
00282                 $this->tokenizer->next();
00283             
00284             $token = $this->tokenizer->peek();
00285             
00286             if ($this->checkIdentifier($token)) {
00287                 $this->tokenizer->next();
00288                 
00289                 return $this->makeQuerySignedExpression($token, $isUnaryMinus);
00290             }
00291             
00292             return null;
00293         }
00294         
00298         protected function getConstantExpression()
00299         {
00300             if ($isUnaryMinus = $this->checkUnaryMinus($this->tokenizer->peek()))
00301                 $this->tokenizer->next();
00302             
00303             $token = $this->tokenizer->peek();
00304             
00305             if (
00306                 $token instanceof OqlToken
00307                 && (
00308                     (
00309                         !$isUnaryMinus
00310                         && (
00311                             $token->getType() == OqlToken::STRING
00312                             || $token->getType() == OqlToken::BOOLEAN
00313                             || $token->getType() == OqlToken::NULL
00314                         )
00315                     ) || (
00316                         $token->getType() == OqlToken::NUMBER
00317                         || $token->getType() == OqlToken::SUBSTITUTION
00318                     )
00319                 )
00320             ) {
00321                 $this->tokenizer->next();
00322                 
00323                 return $this->makeQuerySignedExpression($token, $isUnaryMinus);
00324             }
00325             
00326             return null;
00327         }
00328         
00332         protected function getLogicExpression(
00333             $priority = self::LOGIC_PRIORITY_LOWEST
00334         )
00335         {
00336             $expression = null;
00337             
00338             // terminal boolean expressions
00339             if ($priority == self::LOGIC_PRIORITY_TERMINAL) {
00340                 $token = $this->tokenizer->peek();
00341                 if (!$token)
00342                     return null;
00343                 
00344                 // arithmetic expression
00345                 if ($this->isArithmeticExpression())
00346                     return $this->getArithmeticExpression();
00347                 
00348                 // parentheses
00349                 if ($this->openParentheses(false)) {
00350                     $expression = $this->getLogicExpression();
00351                     $this->closeParentheses(true, 'in expression');
00352                     
00353                     return $expression;
00354                 }
00355                 
00356                 // prefix unary 'not'
00357                 if ($this->checkKeyword($token, 'not')) {
00358                     $this->tokenizer->next();
00359                     
00360                     if (
00361                         $argument = $this->getLogicExpression(self::LOGIC_PRIORITY_UNARY_NOT)
00362                     ) {
00363                         return $this->makeQueryExpression(
00364                             self::$classMap[self::PREFIX_UNARY_EXPRESSION],
00365                             PrefixUnaryExpression::NOT,
00366                             $argument
00367                         );
00368                     
00369                     } else {
00370                         $this->error('expecting argument in expression: not');
00371                     }
00372                 }
00373                 
00374                 // first argument
00375                 if (
00376                     !($expression = $this->getIdentifierExpression())
00377                     && !($expression = $this->getConstantExpression())
00378                 ) {
00379                     $this->error(
00380                         'expecting first argument in expression:',
00381                         $this->getTokenValue($this->tokenizer->peek(), true)
00382                     );
00383                 }
00384                 
00385                 // not (like|ilike|between|similar to|in)
00386                 $operator = $this->tokenizer->peek();
00387                 if ($this->checkKeyword($operator, 'not')) {
00388                     $this->tokenizer->next();
00389                     $operator = $this->tokenizer->peek();
00390                     $isNot = true;
00391                 
00392                 } else {
00393                     $isNot = false;
00394                 }
00395                 
00396                 // is ([not] null|true|false)
00397                 if (
00398                     !$isNot
00399                     && $this->checkKeyword($operator, 'is')
00400                 ) {
00401                     $this->tokenizer->next();
00402                     
00403                     $logic = null;
00404                     
00405                     if ($this->checkKeyword($this->tokenizer->peek(), 'not')) {
00406                         $this->tokenizer->next();
00407                         $isNot = true;
00408                     
00409                     } else {
00410                         $isNot = false;
00411                     }
00412                     
00413                     if ($this->checkToken($this->tokenizer->peek(), OqlToken::NULL)) {
00414                         $this->tokenizer->next();
00415                         $logic = $isNot
00416                             ? PostfixUnaryExpression::IS_NOT_NULL
00417                             : PostfixUnaryExpression::IS_NULL;
00418                         
00419                     } elseif (
00420                         !$isNot
00421                         && $this->checkToken($this->tokenizer->peek(), OqlToken::BOOLEAN)
00422                     ) {
00423                         $logic = $this->tokenizer->next()->getValue() === true
00424                             ? PostfixUnaryExpression::IS_TRUE
00425                             : PostfixUnaryExpression::IS_FALSE;
00426                     }
00427                     
00428                     if ($logic) {
00429                         return $this->makeQueryExpression(
00430                             self::$classMap[self::POSTFIX_UNARY_EXPRESSION],
00431                             $expression,
00432                             $logic
00433                         );
00434                     
00435                     } else {
00436                         $this->error("expecting 'null', 'not null', 'true' or 'false'");
00437                     }
00438                 
00439                 // [not] in
00440                 } elseif ($this->checkKeyword($operator, 'in')) {
00441                     $isNotString = ($isNot ? 'not ' : '');
00442                     $this->tokenizer->next();
00443                     
00444                     $this->openParentheses(true, 'in expression: '.$isNotString.'in');
00445                     
00446                     $list = $this->getCommaSeparatedList(
00447                         array($this, 'getConstantExpression'),
00448                         'expecting constant or substitution in expression: '
00449                         .$isNotString.'in'
00450                     );
00451                     
00452                     if (is_array($list) && count($list) == 1)
00453                         $list = reset($list);
00454                     
00455                     $this->closeParentheses(true, 'in expression: '.$isNotString.'in');
00456                     
00457                     return new OqlInExpression(
00458                         $expression,
00459                         $this->makeQueryParameter($list),
00460                         $isNot ? InExpression::NOT_IN : InExpression::IN
00461                     );
00462                     
00463                 // [not] (like|ilike|similar to)
00464                 } elseif (
00465                     $this->checkKeyword($operator, array('like', 'ilike', 'similar to'))
00466                 ) {
00467                     $this->tokenizer->next();
00468                     
00469                     $isNotString = ($isNot ? 'not ' : '');
00470                     $argument = $this->tokenizer->next();
00471                     
00472                     if (
00473                         $this->checkToken($argument, OqlToken::STRING)
00474                         || $this->checkToken($argument, OqlToken::SUBSTITUTION)
00475                     ) {
00476                         return $this->makeQueryExpression(
00477                             self::$classMap[self::BINARY_EXPRESSION],
00478                             $expression,
00479                             $argument,
00480                             self::$binaryOperatorMap[
00481                                 $isNotString
00482                                 .$this->getTokenValue($operator)
00483                             ]
00484                         );
00485                     
00486                     } else {
00487                         $this->error(
00488                             'expecting string constant or substitution:',
00489                             $isNotString.$this->getTokenValue($operator, true)
00490                         );
00491                     }
00492                 
00493                 // between
00494                 } elseif (
00495                     !$isNot
00496                     && $this->checkKeyword($operator, 'between')
00497                 ) {
00498                     $this->tokenizer->next();
00499                     
00500                     if (
00501                         ($argument1 = $this->getIdentifierExpression())
00502                         || ($argument1 = $this->getConstantExpression())
00503                     ) {
00504                         if ($this->checkKeyword($this->tokenizer->next(), 'and')) {
00505                             if (
00506                                 ($argument2 = $this->getIdentifierExpression())
00507                                 || ($argument2 = $this->getConstantExpression())
00508                             ) {
00509                                 return $this->makeQueryExpression(
00510                                     self::$classMap[self::BETWEEN_EXPRESSION],
00511                                     $expression,
00512                                     $argument1,
00513                                     $argument2
00514                                 );
00515                             
00516                             } else {
00517                                 $this->error(
00518                                     'expecting second argument in expression: between'
00519                                 );
00520                             }
00521                         
00522                         } else {
00523                             $this->error(
00524                                 "expecting 'and' in expression: between"
00525                             );
00526                         }
00527                     
00528                     } else {
00529                         $this->error(
00530                             'expecting first argument in expression: between'
00531                         );
00532                     }
00533                 }
00534                 
00535                 if ($isNot)
00536                     $this->error('expecting in, like, ilike or similar to');
00537             
00538             // and|or|comparison expression chain
00539             } else {
00540                 $operatorList = self::$logicPriorityMap[$priority];
00541                 $higherPriority = $priority + 1;
00542                 
00543                 if (!($expression = $this->getLogicExpression($higherPriority))) {
00544                     $this->error(
00545                         'expecting first argument in expression:',
00546                         is_array($operatorList)
00547                             ? implode('|', $operatorList)
00548                             : $operatorList
00549                     );
00550                 }
00551                 
00552                 $tokenType =
00553                     $priority == self::LOGIC_PRIORITY_OR
00554                     || $priority == self::LOGIC_PRIORITY_AND
00555                         ? OqlToken::KEYWORD
00556                         : OqlToken::COMPARISON_OPERATOR;
00557                 
00558                 while (
00559                     $this->checkToken(
00560                         $this->tokenizer->peek(),
00561                         $tokenType,
00562                         $operatorList
00563                     )
00564                 ) {
00565                     $operator = $this->tokenizer->next();
00566                     
00567                     if ($expression2 = $this->getLogicExpression($higherPriority)) {
00568                         $expression = $this->makeQueryExpression(
00569                             self::$classMap[self::BINARY_EXPRESSION],
00570                             $expression,
00571                             $expression2,
00572                             self::$binaryOperatorMap[$operator->getValue()]
00573                         );
00574                     
00575                     } else {
00576                         $this->error(
00577                             'expecting second argument in expression:',
00578                             $this->getTokenValue($operator, true)
00579                         );
00580                     }
00581                 }
00582             }
00583             
00584             return $expression;
00585         }
00586         
00590         protected function getArithmeticExpression(
00591             $priority = self::ARITHMETIC_PRIORITY_LOWEST
00592         )
00593         {
00594             // terminal arithmetic expressions
00595             if ($priority == self::ARITHMETIC_PRIORITY_TERMINAL) {
00596                 $token = $this->tokenizer->peek();
00597                 if (!$token)
00598                     return null;
00599                 
00600                 // unary minus
00601                 if ($isUnaryMinus = $this->checkUnaryMinus($token))
00602                     $this->tokenizer->next();
00603                 
00604                 // parentheses
00605                 if ($this->openParentheses(false)) {
00606                     $expression = $this->getArithmeticExpression();
00607                     $this->closeParentheses(true, 'in expression');
00608                 
00609                 // argument
00610                 } elseif ($expression = $this->getArithmeticArgumentExpression()) {
00611                     // $expression
00612                 
00613                 } else {
00614                     $this->error(
00615                         'expecting argument in expression:',
00616                         $this->getTokenValue($this->tokenizer->peek(), true)
00617                     );
00618                 }
00619                 
00620                 $expression = $this->makeQuerySignedExpression($expression, $isUnaryMinus);
00621             
00622             // +|-|*|/ expression chain
00623             } else {
00624                 $operatorList = self::$arithmeticPriorityMap[$priority];
00625                 $higherPriority = $priority + 1;
00626                 
00627                 if (!($expression = $this->getArithmeticExpression($higherPriority))) {
00628                     $this->error(
00629                         'expecting first argument in expression:',
00630                         implode('|', $operatorList)
00631                     );
00632                 }
00633                 
00634                 while (
00635                     $this->checkToken(
00636                         $this->tokenizer->peek(),
00637                         OqlToken::ARITHMETIC_OPERATOR,
00638                         $operatorList
00639                     )
00640                 ) {
00641                     $operator = $this->tokenizer->next();
00642                     
00643                     if ($expression2 = $this->getArithmeticExpression($higherPriority)) {
00644                         $expression = $this->makeQueryExpression(
00645                             self::$classMap[self::BINARY_EXPRESSION],
00646                             $expression,
00647                             $expression2,
00648                             self::$binaryOperatorMap[$operator->getValue()]
00649                         );
00650                     
00651                     } else {
00652                         $this->error(
00653                             'expecting second argument in expression:',
00654                             $this->getTokenValue($operator, true)
00655                         );
00656                     }
00657                 }
00658             }
00659             
00660             return $expression;
00661         }
00662         
00663         protected function getCommaSeparatedList($callback, $message)
00664         {
00665             $isComma = false;
00666             $list = array();
00667             
00668             do {
00669                 if ($isComma)
00670                     $this->tokenizer->next();
00671                 
00672                 if ($argument = call_user_func($callback))
00673                     $list[] = $argument;
00674                 else
00675                     $this->error($message);
00676                 
00677             } while (
00678                 $isComma
00679                 = $this->checkToken($this->tokenizer->peek(), OqlToken::PUNCTUATION, ',')
00680             );
00681             
00682             return $list;
00683         }
00684         
00688         protected function makeQueryExpression($className /*, ... */)
00689         {
00690             $expression = OqlQueryExpression::create()->
00691                 setClassName($className);
00692             
00693             $arguments = func_get_args();
00694             reset($arguments);
00695             $argument = next($arguments);
00696             
00697             while ($argument) {
00698                 $expression->addParameter(
00699                     $this->makeQueryParameter($argument)
00700                 );
00701                 
00702                 $argument = next($arguments);
00703             }
00704             
00705             return $expression;
00706         }
00707         
00711         protected function makeQuerySignedExpression($argument, $isUnaryMinus)
00712         {
00713             $expression = $this->makeQueryParameter($argument);
00714             if ($isUnaryMinus)
00715                 $expression = new OqlPrefixMinusExpression($expression);
00716             
00717             return $expression;
00718         }
00719         
00723         protected function makeQueryParameter($argument)
00724         {
00725             if ($argument instanceof OqlQueryParameter) {
00726                 return $argument;
00727             
00728             } elseif ($argument instanceof OqlToken) {
00729                 return OqlQueryParameter::create()->
00730                     setValue($argument->getValue())->
00731                     setBindable($argument->getType() == OqlToken::SUBSTITUTION);
00732             
00733             } else {
00734                 return OqlQueryParameter::create()->
00735                     setValue($argument);
00736             }
00737         }
00738         
00742         protected function error($message, $extraMessage = null)
00743         {
00744             if ($extraMessage)
00745                 $message .= ' '.$extraMessage;
00746             
00747             throw new SyntaxErrorException(
00748                 $message,
00749                 $this->tokenizer->getLine(),
00750                 $this->tokenizer->getPosition()
00751             );
00752         }
00753         
00754         private function isArithmeticExpression()
00755         {
00756             $index = $this->tokenizer->getIndex();
00757             
00758             // skip open parentheses
00759             while (
00760                 $this->checkToken($this->tokenizer->peek(), OqlToken::PARENTHESES, '(')
00761             ) {
00762                 $this->tokenizer->next();
00763             }
00764             
00765             // skip unary minus
00766             if ($this->checkUnaryMinus($this->tokenizer->peek()))
00767                 $this->tokenizer->next();
00768             
00769             $result =
00770                 $this->getArithmeticArgumentExpression()
00771                 && $this->checkToken($this->tokenizer->peek(), OqlToken::ARITHMETIC_OPERATOR);
00772             
00773             $this->tokenizer->setIndex($index);
00774             
00775             return $result;
00776         }
00777         
00781         private function getArithmeticArgumentExpression()
00782         {
00783             $token = $this->tokenizer->peek();
00784             
00785             if (
00786                 $this->checkIdentifier($token)
00787                 || $this->checkToken($token, OqlToken::NUMBER)
00788                 || $this->checkToken($token, OqlToken::SUBSTITUTION)
00789             ) {
00790                 $this->tokenizer->next();
00791                 
00792                 return $this->makeQueryParameter($token);
00793             }
00794             
00795             return null;
00796         }
00797     }
00798 ?>