/**
  * Constructs an instance of the Response class.
  * @param CPS_Connection &$connection CPS connection object
  * @param CPS_Request &$request The original request that the response is to
  * @param string &$responseXml The raw XML response
  * @param bool $noCdata set this to TRUE if you want cdata returned as text
  */
 public function __construct(CPS_Connection &$connection, CPS_Request &$request, &$responseXml, $noCdata = FALSE)
 {
     try {
         $this->_simpleXml = @new SimpleXMLElement($responseXml, ($noCdata ? LIBXML_NOCDATA : 0) | LIBXML_COMPACT | LIBXML_PARSEHUGE);
     } catch (Exception $e) {
         throw new CPS_Exception(array(array('long_message' => 'Invalid response XML', 'code' => ERROR_CODE_INVALID_RESPONSE, 'level' => 'ERROR', 'source' => 'CPS_API')), $e);
     }
     $cpsChildren = $this->_simpleXml->children('www.clusterpoint.com');
     if (count($cpsChildren) == 0) {
         throw new CPS_Exception(array(array('long_message' => 'Invalid response XML', 'code' => ERROR_CODE_INVALID_RESPONSE, 'level' => 'ERROR', 'source' => 'CPS_API')));
     }
     $this->_textParamNames = array('hits', 'from', 'to', 'found', 'real_query', 'iterator_id', 'more', 'cursor_id', 'cursor_data');
     $this->_connection = $connection;
     $this->_storageName = (string) $cpsChildren->storage;
     $this->_command = (string) $cpsChildren->command;
     $this->_seconds = (double) $cpsChildren->seconds;
     $this->_errors = $cpsChildren->error;
     $errors = array();
     foreach ($this->_errors as $error) {
         $error = $error->children();
         if ($error->level == 'REJECTED' || $error->level == 'FAILED' || $error->level == 'ERROR' || $error->level == 'FATAL') {
             $errorArray = array('long_message' => (string) $error->message, 'short_message' => (string) $error->text, 'code' => (int) $error->code, 'source' => (string) $error->source, 'level' => (string) $error->level);
             if (isset($error->document_id)) {
                 $errorArray['document_id'] = (string) $error->document_id;
                 // this line = backwards compatibility
                 $errorArray['document_ids'] = array();
                 foreach ($error->document_id as $errDocId) {
                     $errorArray['document_ids'][] = (string) $errDocId;
                 }
             }
             $errors[] = $errorArray;
         }
     }
     if (count($errors) > 0) {
         throw new CPS_Exception($errors);
     }
     $this->_documents = array();
     $this->_facets = array();
     $this->_aggregate = array();
     $this->_textParams = array();
     $this->_words = array();
     $this->_wordCounts = array();
     $this->_contentArray = array();
     $this->_paths = array();
     if (isset($cpsChildren->content)) {
         $cpsContent = $cpsChildren->content->children();
         $docs = NULL;
         $saveDocs = true;
         // extracting documents / document IDs
         $idPath = $connection->getDocumentIdXpath();
         switch ($this->_command) {
             case 'update':
             case 'insert':
                 $this->_contentArray = CPS_Response::simpleXmlToArray($cpsContent);
             case 'delete':
             case 'partial-replace':
             case 'partial-xreplace':
             case 'replace':
                 $docs = $cpsContent;
                 $idPath[0] = 'document';
                 // TODO: Jasalabo datubazes puse lai atgriez korekti
             // TODO: Jasalabo datubazes puse lai atgriez korekti
             case 'lookup':
                 if (!isset($cpsContent->results)) {
                     $docs = $cpsContent;
                 }
                 if ($this->_command != 'lookup') {
                     $saveDocs = false;
                 }
             case 'search':
             case 'retrieve':
             case 'retrieve-last':
             case 'retrieve-first':
             case 'list-last':
             case 'list-first':
             case 'similar':
             case 'show-history':
             case 'cursor-next-batch':
                 if (is_null($docs)) {
                     if (isset($cpsContent->results)) {
                         $docs = $cpsContent->results[0];
                     } else {
                         $docs = array();
                     }
                 }
                 $this->_rawResults = $docs;
                 $curpos = 0;
                 foreach ($docs as $rootTag => $doc) {
                     if ($rootTag == $idPath[0]) {
                         if ($this->_command == 'show-history') {
                             $id = (string) $doc->children('www.clusterpoint.com')->revision_id;
                         } else {
                             $id = '';
                             $cur = $doc;
                             for ($i = 1; $i < count($idPath); ++$i) {
                                 $path = $idPath[$i];
                                 if (!isset($cur->{$path})) {
                                     break;
                                 }
                                 if ($i == count($idPath) - 1) {
                                     $id = (string) $cur->{$path};
                                 } else {
                                     $cur = $cur->{$path};
                                 }
                             }
                         }
                         if (strlen($id) > 0) {
                             $index = $id;
                         } else {
                             $index = $curpos;
                         }
                         $this->_documents[$index] = $saveDocs ? $doc : NULL;
                     }
                     ++$curpos;
                 }
                 break;
             case 'alternatives':
                 if (isset($cpsContent->alternatives_list)) {
                     foreach ($cpsContent->alternatives_list->alternatives as $alt) {
                         $alts = array();
                         foreach ($alt->word as $word) {
                             $alts[(string) $word] = array('h' => (string) $word['h'], 'idif' => (string) $word['idif'], 'cr' => (string) $word['cr'], 'count' => (string) $word['count']);
                         }
                         $this->_words[(string) $alt->to] = $alts;
                         $this->_wordCounts[(string) $alt->to] = intval($alt->count);
                     }
                 }
                 break;
             case 'list-words':
                 if (isset($cpsContent->list)) {
                     foreach ($cpsContent->list as $list) {
                         $words = array();
                         foreach ($list->word as $word) {
                             $words[(string) $word] = (string) $word['count'];
                         }
                         $this->_words[(string) $list['to']] = $words;
                     }
                 }
                 break;
             case 'status':
             case 'list-backups':
             case 'make-backup':
             case 'restore':
             case 'list-paths':
             case 'list-databases':
             case 'list-collections':
             case 'create-database':
             case 'create-collection':
             case 'edit-database':
             case 'edit-collection':
             case 'edit-database-layout':
             case 'rename-database':
             case 'rename-collection':
             case 'drop-database':
             case 'drop-collection':
             case 'list-nodes':
             case 'list-hubs':
             case 'list-hosts':
             case 'set-offline':
             case 'set-online':
             case 'list-accounts':
             case 'list-users':
             case 'create-account':
             case 'create-user':
             case 'edit-user':
             case 'delete-user':
             case 'get-account-info':
             case 'get-user-info':
             case 'get-verification-code':
             case 'get-password-reset-code':
             case 'password-reset':
             case 'verify-user':
             case 'verify-account':
             case 'login':
             case 'list-alerts':
             case 'reset-hmac-keys':
             case 'get-hmac-keys':
             case 'delete-operation':
                 $this->_contentArray = CPS_Response::simpleXmlToArray($cpsContent);
                 break;
             case 'describe-database':
             case 'describe-collection':
                 $this->_contentArray = CPS_Response::simpleXmlToArray($cpsContent);
                 $rawDataModelXML = substr($responseXml, strpos($responseXml, '<overrides>') + 11, strpos($responseXml, '</overrides>') - strpos($responseXml, '<overrides>') - 11);
                 $this->_contentArray['overrides'] = $rawDataModelXML;
                 break;
             case 'begin-transaction':
                 $connection->setTransactionId((string) $cpsContent->transaction_id);
                 $this->_contentArray = CPS_Response::simpleXmlToArray($cpsContent);
                 break;
             case 'commit-transaction':
             case 'rollback-transaction':
                 $connection->setTransactionId(null);
                 $this->_contentArray = CPS_Response::simpleXmlToArray($cpsContent);
                 break;
             default:
                 // no special parsing
         }
         if ($this->_command == 'search' || $this->_command == 'list-facets') {
             if (isset($cpsContent->facet)) {
                 foreach ($cpsContent->facet as $facet) {
                     $path = (string) $facet['path'];
                     $terms = array();
                     foreach ($facet->term as $term) {
                         if ($this->_command == 'search') {
                             $terms[(string) $term] = intval($term['hits']);
                         } else {
                             if ($this->_command == 'list-facets') {
                                 $terms[] = (string) $term;
                             }
                         }
                     }
                     $this->_facets[$path] = $terms;
                 }
             }
             if (isset($cpsContent->aggregate)) {
                 foreach ($cpsContent->aggregate as $aggr) {
                     $this->_aggregate[(string) $aggr->query] = $aggr->data;
                 }
             }
         }
         $this->_textParams = array();
         foreach ($cpsContent as $name => $value) {
             if (in_array($name, $this->_textParamNames)) {
                 $this->_textParams[$name] = (string) $value;
             }
         }
     }
 }