public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         // Make sure this is not an ontology dataset
         $query = "select ?holdOntology\n                        from <" . $this->ws->wsf_graph . "datasets/>\n                        where\n                        {\n                          <" . $this->ws->datasetUri . "> <http://purl.org/ontology/wsf#holdOntology> ?holdOntology .\n                        }";
         $resultset = @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array('holdOntology'), FALSE));
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, odbc_errormsg(), $this->ws->errorMessenger->_306->level);
             return;
         } else {
             while (odbc_fetch_row($resultset)) {
                 $holdOntology = odbc_result($resultset, 1);
                 if (strtolower($holdOntology) == "true") {
                     $this->ws->conneg->setStatus(400);
                     $this->ws->conneg->setStatusMsg("Bad Request");
                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, odbc_errormsg(), $this->ws->errorMessenger->_306->level);
                     return;
                 }
             }
         }
         unset($resultset);
         // Remove  all the possible other meta descriptions
         // of the dataset introduced by the wsf:meta property.
         $query = "  delete from <" . $this->ws->wsf_graph . "datasets/> \n                { \n                  ?meta ?p_meta ?o_meta.\n                }\n                where\n                {\n                  graph <" . $this->ws->wsf_graph . "datasets/>\n                  {\n                    <" . $this->ws->datasetUri . "> <http://purl.org/ontology/wsf#meta> ?meta.\n                    ?meta ?p_meta ?o_meta.\n                  }\n                }";
         @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array(), FALSE));
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_300->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_300->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_300->name, $this->ws->errorMessenger->_300->description, odbc_errormsg(), $this->ws->errorMessenger->_300->level);
             return;
         }
         // Remove the Graph description in the ".../datasets/"
         $query = "  delete from <" . $this->ws->wsf_graph . "datasets/> \n                { \n                  <" . $this->ws->datasetUri . "> ?p ?o.\n                }\n                where\n                {\n                  graph <" . $this->ws->wsf_graph . "datasets/>\n                  {\n                    <" . $this->ws->datasetUri . "> ?p ?o.\n                  }\n                }";
         @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array(), FALSE));
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_301->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_301->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_301->name, $this->ws->errorMessenger->_301->description, odbc_errormsg(), $this->ws->errorMessenger->_301->level);
             return;
         }
         // Removing all accesses for this graph
         $ws_ara = new AuthRegistrarAccess("", "", $this->ws->datasetUri, "delete_all", "", "", $this->ws->registered_ip);
         $ws_ara->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
         $ws_ara->process();
         if ($ws_ara->pipeline_getResponseHeaderStatus() != 200) {
             $this->ws->conneg->setStatus($ws_ara->pipeline_getResponseHeaderStatus());
             $this->ws->conneg->setStatusMsg($ws_ara->pipeline_getResponseHeaderStatusMsg());
             $this->ws->conneg->setStatusMsgExt($ws_ara->pipeline_getResponseHeaderStatusMsgExt());
             $this->ws->conneg->setError($ws_ara->pipeline_getError()->id, $ws_ara->pipeline_getError()->webservice, $ws_ara->pipeline_getError()->name, $ws_ara->pipeline_getError()->description, $ws_ara->pipeline_getError()->debugInfo, $ws_ara->pipeline_getError()->level);
             return;
         }
         // Drop the entire graph
         $query = "sparql clear graph <" . $this->ws->datasetUri . ">";
         @$this->ws->db->query($query);
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_302->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, odbc_errormsg(), $this->ws->errorMessenger->_302->level);
             return;
         }
         // Drop the reification graph related to this dataset
         $query = "sparql clear graph <" . $this->ws->datasetUri . "reification/>";
         @$this->ws->db->query($query);
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt("Error #dataset-delete-105");
             $this->ws->conneg->setError($this->ws->errorMessenger->_303->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_303->name, $this->ws->errorMessenger->_303->description, odbc_errormsg(), $this->ws->errorMessenger->_303->level);
             return;
         }
         // Remove all documents from the solr index for this Dataset
         $solr = new Solr($this->ws->wsf_solr_core, $this->ws->solr_host, $this->ws->solr_port, $this->ws->fields_index_folder);
         if (!$solr->flushDataset($this->ws->datasetUri)) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_304->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_304->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_304->name, $this->ws->errorMessenger->_304->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_304->level);
             return;
         }
         if ($this->ws->solr_auto_commit === FALSE) {
             if (!$solr->commit()) {
                 $this->ws->conneg->setStatus(500);
                 $this->ws->conneg->setStatusMsg("Internal Error");
                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                 $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_305->level);
                 return;
             }
         }
         /*      
               if(!$solr->optimize())
               {
                 $this->ws->conneg->setStatus(500);
                 $this->ws->conneg->setStatusMsg("Internal Error");
                 $this->ws->conneg->setStatusMsgExt("Error #dataset-delete-104");  
                 return;          
               }      
         */
     }
 }
 public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $this->ws->validateQuery();
         // If the query is still valid
         if ($this->ws->conneg->getStatus() == 200) {
             // Track the record description changes
             if ($this->ws->track_delete === TRUE) {
                 // First check if the record is already existing for this record, within this dataset.
                 $ws_cr = new CrudRead($this->ws->resourceUri, $this->ws->dataset, FALSE, TRUE, $this->ws->registered_ip, $this->ws->requester_ip);
                 $ws_cr->ws_conneg("application/rdf+xml", "utf-8", "identity", "en");
                 $ws_cr->process();
                 $oldRecordDescription = $ws_cr->ws_serialize();
                 $ws_cr_error = $ws_cr->pipeline_getError();
                 if ($ws_cr->pipeline_getResponseHeaderStatus() != 200) {
                     // An error occured. Since we can't get the past state of a record, we have to send an error
                     // for the CrudUpdate call since we can't create a tracking record for this record.
                     $this->ws->conneg->setStatus(400);
                     $this->ws->conneg->setStatusMsg("Bad Request");
                     $this->ws->conneg->setError($this->ws->errorMessenger->_303->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_303->name, $this->ws->errorMessenger->_303->description, "We can't create a track record for the following record: " . $this->ws->resourceUri, $this->ws->errorMessenger->_303->level);
                     break;
                 }
                 $endpoint = "";
                 if ($this->ws->tracking_endpoint != "") {
                     // We send the query to a remove tracking endpoint
                     $endpoint = $this->ws->tracking_endpoint . "create/";
                 } else {
                     // We send the query to a local tracking endpoint
                     $endpoint = $this->ws->wsf_base_url . "/ws/tracker/create/";
                 }
                 $wsq = new WebServiceQuerier($endpoint, "post", "text/xml", "from_dataset=" . urlencode($this->ws->dataset) . "&record=" . urlencode($this->ws->resourceUri) . "&action=delete" . "&previous_state=" . urlencode($oldRecordDescription) . "&previous_state_mime=" . urlencode("application/rdf+xml") . "&performer=" . urlencode($this->ws->registered_ip) . "&registered_ip=self");
                 if ($wsq->getStatus() != 200) {
                     $this->ws->conneg->setStatus($wsq->getStatus());
                     $this->ws->conneg->setStatusMsg($wsq->getStatusMessage());
                     /*
                     $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws,
                       $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, odbc_errormsg(),
                       $this->ws->errorMessenger->_302->level);                
                     */
                 }
                 unset($wsq);
             }
             // Delete all triples for this URI in that dataset
             $query = "delete from <" . $this->ws->dataset . ">\n                  { \n                    <" . $this->ws->resourceUri . "> ?p ?o. \n                  }\n                  where\n                  {\n                    <" . $this->ws->resourceUri . "> ?p ?o. \n                  }";
             @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array(), FALSE));
             if (odbc_error()) {
                 $this->ws->conneg->setStatus(500);
                 $this->ws->conneg->setStatusMsg("Internal Error");
                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_300->name);
                 $this->ws->conneg->setError($this->ws->errorMessenger->_300->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_300->name, $this->ws->errorMessenger->_300->description, odbc_errormsg(), $this->ws->errorMessenger->_300->level);
                 return;
             }
             // Delete the Solr document in the Solr index
             $solr = new Solr($this->ws->wsf_solr_core, $this->ws->solr_host, $this->ws->solr_port, $this->ws->fields_index_folder);
             if (!$solr->deleteInstanceRecord($this->ws->resourceUri, $this->ws->dataset)) {
                 $this->ws->conneg->setStatus(500);
                 $this->ws->conneg->setStatusMsg("Internal Error");
                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_301->name);
                 $this->ws->conneg->setError($this->ws->errorMessenger->_301->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_301->name, $this->ws->errorMessenger->_301->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_301->level);
                 return;
             }
             if ($this->ws->solr_auto_commit === FALSE) {
                 if (!$solr->commit()) {
                     $this->ws->conneg->setStatus(500);
                     $this->ws->conneg->setStatusMsg("Internal Error");
                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_302->name);
                     $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_302->level);
                     return;
                 }
             }
         }
     }
 }
 public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $this->ws->validateQuery();
         // If the query is still valid
         if ($this->ws->conneg->getStatus() == 200) {
             // Get triples from ARC for some offline processing.
             include_once "../../framework/arc2/ARC2.php";
             $parser = ARC2::getRDFParser();
             $parser->parse($this->ws->dataset, $this->ws->document);
             $rdfxmlSerializer = ARC2::getRDFXMLSerializer();
             $resourceIndex = $parser->getSimpleIndex(0);
             if (count($parser->getErrors()) > 0) {
                 $errorsOutput = "";
                 $errors = $parser->getErrors();
                 foreach ($errors as $key => $error) {
                     $errorsOutput .= "[Error #{$key}] {$error}\n";
                 }
                 $this->ws->conneg->setStatus(400);
                 $this->ws->conneg->setStatusMsg("Bad Request");
                 $this->ws->conneg->setError($this->ws->errorMessenger->_301->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_301->name, $this->ws->errorMessenger->_301->description, $errorsOutput, $this->ws->errorMessenger->_301->level);
                 return;
             }
             // First: check for a void:Dataset description to add to the "dataset description graph" of structWSF
             $break = FALSE;
             $datasetUri = "";
             foreach ($resourceIndex as $resource => $description) {
                 foreach ($description as $predicate => $values) {
                     if ($predicate == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") {
                         foreach ($values as $value) {
                             if ($value["type"] == "uri" && $value["value"] == "http://rdfs.org/ns/void#Dataset") {
                                 $datasetUri = $resource;
                                 break;
                             }
                         }
                     }
                     if ($break) {
                         break;
                     }
                 }
                 if ($break) {
                     break;
                 }
             }
             // Second: get all the reification statements
             $break = FALSE;
             $statementsUri = array();
             foreach ($resourceIndex as $resource => $description) {
                 foreach ($description as $predicate => $values) {
                     if ($predicate == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") {
                         foreach ($values as $value) {
                             if ($value["type"] == "uri" && $value["value"] == "http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement") {
                                 array_push($statementsUri, $resource);
                                 break;
                             }
                         }
                     }
                     if ($break) {
                         break;
                     }
                 }
                 if ($break) {
                     break;
                 }
             }
             // Third, get all references of all instance records resources (except for the statement resources)
             $irsUri = array();
             foreach ($resourceIndex as $resource => $description) {
                 if ($resource != $datasetUri && array_search($resource, $statementsUri) === FALSE) {
                     array_push($irsUri, $resource);
                 }
             }
             // Fourth: Track the record description changes
             if ($this->ws->track_create === TRUE) {
                 foreach ($irsUri as $uri) {
                     // First check if the record is already existing for this record, within this dataset.
                     $ws_cr = new CrudRead($uri, $this->ws->dataset, FALSE, TRUE, $this->ws->registered_ip, $this->ws->requester_ip);
                     $ws_cr->ws_conneg("application/rdf+xml", "utf-8", "identity", "en");
                     $ws_cr->process();
                     $oldRecordDescription = $ws_cr->ws_serialize();
                     $ws_cr_error = $ws_cr->pipeline_getError();
                     if ($ws_cr->pipeline_getResponseHeaderStatus() == 400 && $ws_cr_error->id == "WS-CRUD-READ-300") {
                         // The record is not existing within this dataset, so we simply move-on
                         continue;
                     } elseif ($ws_cr->pipeline_getResponseHeaderStatus() != 200) {
                         // An error occured. Since we can't get the past state of a record, we have to send an error
                         // for the CrudCreate call since we can't create a tracking record for this record.
                         $this->ws->conneg->setStatus(400);
                         $this->ws->conneg->setStatusMsg("Bad Request");
                         $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "We can't create a track record for the following record: {$uri}", $this->ws->errorMessenger->_305->level);
                         break;
                     }
                     $endpoint = "";
                     if ($this->ws->tracking_endpoint != "") {
                         // We send the query to a remove tracking endpoint
                         $endpoint = $this->ws->tracking_endpoint . "create/";
                     } else {
                         // We send the query to a local tracking endpoint
                         $endpoint = $this->ws->wsf_base_url . "/ws/tracker/create/";
                     }
                     $wsq = new WebServiceQuerier($endpoint, "post", "text/xml", "from_dataset=" . urlencode($this->ws->dataset) . "&record=" . urlencode($uri) . "&action=create" . "&previous_state=" . urlencode($oldRecordDescription) . "&previous_state_mime=" . urlencode("application/rdf+xml") . "&performer=" . urlencode($this->ws->registered_ip) . "&registered_ip=self");
                     if ($wsq->getStatus() != 200) {
                         $this->ws->conneg->setStatus($wsq->getStatus());
                         $this->ws->conneg->setStatusMsg($wsq->getStatusMessage());
                         /*
                         $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws,
                           $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, odbc_errormsg(),
                           $this->ws->errorMessenger->_302->level);                
                         */
                     }
                     unset($wsq);
                 }
             }
             // If the query is still valid
             if ($this->ws->conneg->getStatus() == 200) {
                 // Index all the instance records in the dataset
                 if ($this->ws->mode == "full" || $this->ws->mode == "triplestore") {
                     $irs = array();
                     foreach ($irsUri as $uri) {
                         $irs[$uri] = $resourceIndex[$uri];
                     }
                     $this->ws->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" . str_replace("'", "\\'", $rdfxmlSerializer->getSerializedIndex($irs)) . "', '" . $this->ws->dataset . "', '" . $this->ws->dataset . "')");
                     if (odbc_error()) {
                         $this->ws->conneg->setStatus(400);
                         $this->ws->conneg->setStatusMsg("Bad Request");
                         $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, odbc_errormsg(), $this->ws->errorMessenger->_302->level);
                         return;
                     }
                     unset($irs);
                     // Index all the reification statements into the statements graph
                     $statements = array();
                     foreach ($statementsUri as $uri) {
                         $statements[$uri] = $resourceIndex[$uri];
                     }
                     $this->ws->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" . str_replace("'", "\\'", $rdfxmlSerializer->getSerializedIndex($statements)) . "', '" . $this->ws->dataset . "reification/', '" . $this->ws->dataset . "reification/')");
                     if (odbc_error()) {
                         $this->ws->conneg->setStatus(400);
                         $this->ws->conneg->setStatusMsg("Bad Request");
                         $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, odbc_errormsg(), $this->ws->errorMessenger->_302->level);
                         return;
                     }
                     unset($statements);
                     /* Link the dataset description of the file, by using the wsf:meta property, 
                           to its internal description (dataset graph description)
                        */
                     if ($datasetUri != "") {
                         $datasetRes[$datasetUri] = $resourceIndex[$datasetUri];
                         $datasetRes[$this->ws->dataset] = array("http://purl.org/ontology/wsf#meta" => array(array("value" => $datasetUri, "type" => "uri")));
                         $datasetDescription = $resourceIndex[$datasetRes];
                         /*  Make the link between the dataset description and its "meta" description (all other 
                                 information than its basic description)
                             */
                         $this->ws->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" . str_replace("'", "\\'", $rdfxmlSerializer->getSerializedIndex($datasetRes)) . "', '" . $this->ws->wsf_graph . "datasets/', '" . $this->ws->wsf_graph . "datasets/')");
                         if (odbc_error()) {
                             $this->ws->conneg->setStatus(400);
                             $this->ws->conneg->setStatusMsg("Bad Request");
                             $this->ws->conneg->setError($this->ws->errorMessenger->_302->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_302->name, $this->ws->errorMessenger->_302->description, "", $this->ws->errorMessenger->_302->level);
                             return;
                         }
                         unset($datasetRes);
                     }
                 }
                 // Index everything in Solr
                 if ($this->ws->mode == "full" || $this->ws->mode == "searchindex") {
                     $labelProperties = array(Namespaces::$iron . "prefLabel", Namespaces::$iron . "altLabel", Namespaces::$skos_2008 . "prefLabel", Namespaces::$skos_2008 . "altLabel", Namespaces::$skos_2004 . "prefLabel", Namespaces::$skos_2004 . "altLabel", Namespaces::$rdfs . "label", Namespaces::$dcterms . "title", Namespaces::$foaf . "name", Namespaces::$foaf . "givenName", Namespaces::$foaf . "family_name");
                     $descriptionProperties = array(Namespaces::$iron . "description", Namespaces::$dcterms . "description", Namespaces::$skos_2008 . "definition", Namespaces::$skos_2004 . "definition");
                     $filename = rtrim($this->ws->ontological_structure_folder, "/") . "/classHierarchySerialized.srz";
                     $file = fopen($filename, "r");
                     $classHierarchy = fread($file, filesize($filename));
                     $classHierarchy = unserialize($classHierarchy);
                     fclose($file);
                     if ($classHierarchy === FALSE) {
                         $this->ws->conneg->setStatus(500);
                         $this->ws->conneg->setStatusMsg("Internal Error");
                         $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                         return;
                     }
                     // Index in Solr
                     $solr = new Solr($this->ws->wsf_solr_core, $this->ws->solr_host, $this->ws->solr_port, $this->ws->fields_index_folder);
                     // Used to detect if we will be creating a new field. If we are, then we will
                     // update the fields index once the new document will be indexed.
                     $indexedFields = $solr->getFieldsIndex();
                     $newFields = FALSE;
                     foreach ($irsUri as $subject) {
                         // Skip Bnodes indexation in Solr
                         // One of the prerequise is that each records indexed in Solr (and then available in Search and Browse)
                         // should have a URI. Bnodes are simply skiped.
                         if (stripos($subject, "_:arc") !== FALSE) {
                             continue;
                         }
                         $add = "<add><doc><field name=\"uid\">" . md5($this->ws->dataset . $subject) . "</field>";
                         $add .= "<field name=\"uri\">" . $this->ws->xmlEncode($subject) . "</field>";
                         $add .= "<field name=\"dataset\">" . $this->ws->dataset . "</field>";
                         // Get types for this subject.
                         $types = array();
                         foreach ($resourceIndex[$subject]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"] as $value) {
                             array_push($types, $value["value"]);
                             $add .= "<field name=\"type\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                             $add .= "<field name=\"" . urlencode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") . "_attr_facets\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                         }
                         // Use the first defined type to add the the single-valued fiedl in the Solr schema.
                         // This will be used to enabled sorting on (the first) type
                         $add .= "<field name=\"type_single_valued\">" . $this->ws->xmlEncode($resourceIndex[$subject]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"][0]["value"]) . "</field>";
                         // get the preferred and alternative labels for this resource
                         $prefLabelFound = array();
                         foreach ($this->ws->supportedLanguages as $lang) {
                             $prefLabelFound[$lang] = FALSE;
                         }
                         foreach ($labelProperties as $property) {
                             if (isset($resourceIndex[$subject][$property])) {
                                 foreach ($resourceIndex[$subject][$property] as $value) {
                                     $lang = "";
                                     if (isset($value["lang"])) {
                                         if (array_search($value["lang"], $this->ws->supportedLanguages) !== FALSE) {
                                             // The language used for this string is supported by the system, so we index it in
                                             // the good place
                                             $lang = $value["lang"];
                                         } else {
                                             // The language used for this string is not supported by the system, so we
                                             // index it in the default language
                                             $lang = $this->ws->supportedLanguages[0];
                                         }
                                     } else {
                                         // The language is not defined for this string, so we simply consider that it uses
                                         // the default language supported by the structWSF instance
                                         $lang = $this->ws->supportedLanguages[0];
                                     }
                                     if (!$prefLabelFound[$lang]) {
                                         $prefLabelFound[$lang] = TRUE;
                                         $add .= "<field name=\"prefLabel_" . $lang . "\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                         $add .= "<field name=\"prefLabelAutocompletion_" . $lang . "\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                         $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "prefLabel") . "</field>";
                                         $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "prefLabel")) . "_attr_facets\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                     } else {
                                         $add .= "<field name=\"altLabel_" . $lang . "\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                         $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "altLabel") . "</field>";
                                         $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "altLabel")) . "_attr_facets\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                     }
                                 }
                             }
                         }
                         // If no labels are found for this resource, we use the ending of the URI as the label
                         if (!$prefLabelFound) {
                             $lang = $this->ws->supportedLanguages[0];
                             if (strrpos($subject, "#")) {
                                 $add .= "<field name=\"prefLabel_" . $lang . "\">" . substr($subject, strrpos($subject, "#") + 1) . "</field>";
                                 $add .= "<field name=\"prefLabelAutocompletion_" . $lang . "\">" . substr($subject, strrpos($subject, "#") + 1) . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "prefLabel") . "</field>";
                                 $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "prefLabel")) . "_attr_facets\">" . $this->ws->xmlEncode(substr($subject, strrpos($subject, "#") + 1)) . "</field>";
                             } elseif (strrpos($subject, "/")) {
                                 $add .= "<field name=\"prefLabel_" . $lang . "\">" . substr($subject, strrpos($subject, "/") + 1) . "</field>";
                                 $add .= "<field name=\"prefLabelAutocompletion_" . $lang . "\">" . substr($subject, strrpos($subject, "/") + 1) . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "prefLabel") . "</field>";
                                 $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "prefLabel")) . "_attr_facets\">" . $this->ws->xmlEncode(substr($subject, strrpos($subject, "/") + 1)) . "</field>";
                             }
                         }
                         // get the description of the resource
                         foreach ($descriptionProperties as $property) {
                             if (isset($resourceIndex[$subject][$property])) {
                                 $lang = "";
                                 foreach ($resourceIndex[$subject][$property] as $value) {
                                     if (isset($value["lang"])) {
                                         if (array_search($value["lang"], $this->ws->supportedLanguages) !== FALSE) {
                                             // The language used for this string is supported by the system, so we index it in
                                             // the good place
                                             $lang = $value["lang"];
                                         } else {
                                             // The language used for this string is not supported by the system, so we
                                             // index it in the default language
                                             $lang = $this->ws->supportedLanguages[0];
                                         }
                                     } else {
                                         // The language is not defined for this string, so we simply consider that it uses
                                         // the default language supported by the structWSF instance
                                         $lang = $this->ws->supportedLanguages[0];
                                     }
                                     $add .= "<field name=\"description_" . $lang . "\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                     $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "description") . "</field>";
                                     $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "description")) . "_attr_facets\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                 }
                             }
                         }
                         // Add the prefURL if available
                         if (isset($resourceIndex[$subject][Namespaces::$iron . "prefURL"])) {
                             $add .= "<field name=\"prefURL\">" . $this->ws->xmlEncode($resourceIndex[$subject][Namespaces::$iron . "prefURL"][0]["value"]) . "</field>";
                             $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$iron . "prefURL") . "</field>";
                             $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$iron . "prefURL")) . "_attr_facets\">" . $this->ws->xmlEncode($resourceIndex[$subject][Namespaces::$iron . "prefURL"][0]["value"]) . "</field>";
                         }
                         // If enabled, and supported by the structWSF setting, let's add any lat/long positionning to the index.
                         if ($this->ws->geoEnabled) {
                             // Check if there exists a lat-long coordinate for that resource.
                             if (isset($resourceIndex[$subject][Namespaces::$geo . "lat"]) && isset($resourceIndex[$subject][Namespaces::$geo . "long"])) {
                                 $lat = str_replace(",", ".", $resourceIndex[$subject][Namespaces::$geo . "lat"][0]["value"]);
                                 $long = str_replace(",", ".", $resourceIndex[$subject][Namespaces::$geo . "long"][0]["value"]);
                                 // Add Lat/Long
                                 $add .= "<field name=\"lat\">" . $this->ws->xmlEncode($lat) . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "lat") . "</field>";
                                 $add .= "<field name=\"long\">" . $this->ws->xmlEncode($long) . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "long") . "</field>";
                                 // Add hashcode
                                 $add .= "<field name=\"geohash\">" . "{$lat},{$long}" . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$sco . "geohash") . "</field>";
                                 // Add cartesian tiers
                                 // Note: Cartesian tiers are not currently supported. The Lucene Java API
                                 //       for this should be ported to PHP to enable this feature.
                             }
                             $coordinates = array();
                             // Check if there is a polygonCoordinates property
                             if (isset($resourceIndex[$subject][Namespaces::$sco . "polygonCoordinates"])) {
                                 foreach ($resourceIndex[$subject][Namespaces::$sco . "polygonCoordinates"] as $polygonCoordinates) {
                                     $coordinates = explode(" ", $polygonCoordinates["value"]);
                                     $add .= "<field name=\"polygonCoordinates\">" . $this->ws->xmlEncode($polygonCoordinates["value"]) . "</field>";
                                     $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$sco . "polygonCoordinates") . "</field>";
                                 }
                             }
                             // Check if there is a polylineCoordinates property
                             if (isset($resourceIndex[$subject][Namespaces::$sco . "polylineCoordinates"])) {
                                 foreach ($resourceIndex[$subject][Namespaces::$sco . "polylineCoordinates"] as $polylineCoordinates) {
                                     $coordinates = array_merge($coordinates, explode(" ", $polylineCoordinates["value"]));
                                     $add .= "<field name=\"polylineCoordinates\">" . $this->ws->xmlEncode($polylineCoordinates["value"]) . "</field>";
                                     $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$sco . "polylineCoordinates") . "</field>";
                                 }
                             }
                             if (count($coordinates) > 0) {
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "lat") . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "long") . "</field>";
                                 foreach ($coordinates as $key => $coordinate) {
                                     $points = explode(",", $coordinate);
                                     if ($points[0] != "" && $points[1] != "") {
                                         // Add Lat/Long
                                         $add .= "<field name=\"lat\">" . $this->ws->xmlEncode($points[1]) . "</field>";
                                         $add .= "<field name=\"long\">" . $this->ws->xmlEncode($points[0]) . "</field>";
                                         // Add altitude
                                         if (isset($points[2]) && $points[2] != "") {
                                             $add .= "<field name=\"alt\">" . $this->ws->xmlEncode($points[2]) . "</field>";
                                             if ($key == 0) {
                                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "alt") . "</field>";
                                             }
                                         }
                                         // Add hashcode
                                         $add .= "<field name=\"geohash\">" . $points[1] . "," . $points[0] . "</field>";
                                         if ($key == 0) {
                                             $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$sco . "geohash") . "</field>";
                                         }
                                         // Add cartesian tiers
                                         // Note: Cartesian tiers are not currently supported. The Lucene Java API
                                         //       for this should be ported to PHP to enable this feature.
                                     }
                                 }
                             }
                             // Check if there is any geonames:locatedIn assertion for that resource.
                             if (isset($resourceIndex[$subject][Namespaces::$geoname . "locatedIn"])) {
                                 $add .= "<field name=\"located_in\">" . $this->ws->xmlEncode($resourceIndex[$subject][Namespaces::$geoname . "locatedIn"][0]["value"]) . "</field>";
                                 $add .= "<field name=\"" . urlencode($this->ws->xmlEncode(Namespaces::$geoname . "locatedIn")) . "_attr_facets\">" . $this->ws->xmlEncode($resourceIndex[$subject][Namespaces::$geoname . "locatedIn"][0]["value"]) . "</field>";
                             }
                             // Check if there is any wgs84_pos:alt assertion for that resource.
                             if (isset($resourceIndex[$subject][Namespaces::$geo . "alt"])) {
                                 $add .= "<field name=\"alt\">" . $this->ws->xmlEncode($resourceIndex[$subject][Namespaces::$geo . "alt"][0]["value"]) . "</field>";
                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode(Namespaces::$geo . "alt") . "</field>";
                             }
                         }
                         $filename = rtrim($this->ws->ontological_structure_folder, "/") . "/propertyHierarchySerialized.srz";
                         $file = fopen($filename, "r");
                         $propertyHierarchy = fread($file, filesize($filename));
                         $propertyHierarchy = unserialize($propertyHierarchy);
                         fclose($file);
                         if ($propertyHierarchy === FALSE) {
                             $this->ws->conneg->setStatus(500);
                             $this->ws->conneg->setStatusMsg("Internal Error");
                             $this->ws->conneg->setError($this->ws->errorMessenger->_310->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_310->name, $this->ws->errorMessenger->_310->description, "", $this->ws->errorMessenger->_310->level);
                             return;
                         }
                         // When a property appears in this array, it means that it is already
                         // used in the Solr document we are creating
                         $usedSingleValuedProperties = array();
                         // Get properties with the type of the object
                         foreach ($resourceIndex[$subject] as $predicate => $values) {
                             if (array_search($predicate, $labelProperties) === FALSE && array_search($predicate, $descriptionProperties) === FALSE && $predicate != Namespaces::$iron . "prefURL" && $predicate != Namespaces::$geo . "long" && $predicate != Namespaces::$geo . "lat" && $predicate != Namespaces::$geo . "alt" && $predicate != Namespaces::$sco . "polygonCoordinates" && $predicate != Namespaces::$sco . "polylineCoordinates") {
                                 foreach ($values as $value) {
                                     if ($value["type"] == "literal") {
                                         $lang = "";
                                         if (isset($value["lang"])) {
                                             if (array_search($value["lang"], $this->ws->supportedLanguages) !== FALSE) {
                                                 // The language used for this string is supported by the system, so we index it in
                                                 // the good place
                                                 $lang = $value["lang"];
                                             } else {
                                                 // The language used for this string is not supported by the system, so we
                                                 // index it in the default language
                                                 $lang = $this->ws->supportedLanguages[0];
                                             }
                                         } else {
                                             // The language is not defined for this string, so we simply consider that it uses
                                             // the default language supported by the structWSF instance
                                             $lang = $this->ws->supportedLanguages[0];
                                         }
                                         // Detect if the field currently exists in the fields index
                                         if (!$newFields && array_search(urlencode($predicate) . "_attr_" . $lang, $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_date", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_int", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_float", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_" . $lang . "_single_valued", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_date_single_valued", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_int_single_valued", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_float_single_valued", $indexedFields) === FALSE) {
                                             $newFields = TRUE;
                                         }
                                         // Check the datatype of the datatype property
                                         $property = $propertyHierarchy->getProperty($predicate);
                                         if (is_array($property->range) && array_search("http://www.w3.org/2001/XMLSchema#dateTime", $property->range) !== FALSE && $this->safeDate($value["value"]) != "") {
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_date_single_valued\">" . $this->ws->xmlEncode($this->safeDate($value["value"])) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_date\">" . $this->ws->xmlEncode($this->safeDate($value["value"])) . "</field>";
                                             }
                                         } elseif (is_array($property->range) && array_search("http://www.w3.org/2001/XMLSchema#int", $property->range) !== FALSE || is_array($property->range) && array_search("http://www.w3.org/2001/XMLSchema#integer", $property->range) !== FALSE) {
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_int_single_valued\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_int\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                             }
                                         } elseif (is_array($property->range) && array_search("http://www.w3.org/2001/XMLSchema#float", $property->range) !== FALSE) {
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_float_single_valued\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_float\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                             }
                                         } else {
                                             // By default, the datatype used is a literal/string
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_" . $lang . "_single_valued\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_" . $lang . "\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                             }
                                         }
                                         $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode($predicate) . "</field>";
                                         $add .= "<field name=\"" . urlencode($predicate) . "_attr_facets\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                         /* 
                                            Check if there is a reification statement for that triple. If there is one, we index it in 
                                            the index as:
                                            <property> <text>
                                            Note: Eventually we could want to update the Solr index to include a new "reifiedText" field.
                                         */
                                         foreach ($statementsUri as $statementUri) {
                                             if ($resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"][0]["value"] == $subject && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"][0]["value"] == $predicate && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#object"][0]["value"] == $value["value"]) {
                                                 foreach ($resourceIndex[$statementUri] as $reiPredicate => $reiValues) {
                                                     if ($reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#subject" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#object") {
                                                         foreach ($reiValues as $reiValue) {
                                                             $reiLang = "";
                                                             if (isset($reiValue["lang"])) {
                                                                 if (array_search($reiValue["lang"], $this->ws->supportedLanguages) !== FALSE) {
                                                                     // The language used for this string is supported by the system, so we index it in
                                                                     // the good place
                                                                     $reiLang = $reiValue["lang"];
                                                                 } else {
                                                                     // The language used for this string is not supported by the system, so we
                                                                     // index it in the default language
                                                                     $reiLang = $this->ws->supportedLanguages[0];
                                                                 }
                                                             } else {
                                                                 // The language is not defined for this string, so we simply consider that it uses
                                                                 // the default language supported by the structWSF instance
                                                                 $reiLang = $this->ws->supportedLanguages[0];
                                                             }
                                                             if ($reiValue["type"] == "literal") {
                                                                 // Attribute used to reify information to a statement.
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_attr\">" . $this->ws->xmlEncode($predicate) . "</field>";
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_obj\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_value_" . $reiLang . "\">" . $this->ws->xmlEncode($reiValue["value"]) . "</field>";
                                                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode($reiPredicate) . "</field>";
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     } elseif ($value["type"] == "uri") {
                                         // Set default language
                                         $lang = $this->ws->supportedLanguages[0];
                                         // Detect if the field currently exists in the fields index
                                         if (!$newFields && array_search(urlencode($predicate) . "_attr_obj_uri", $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_obj_" . $lang, $indexedFields) === FALSE && array_search(urlencode($predicate) . "_attr_obj_" . $lang . "_single_valued", $indexedFields) === FALSE) {
                                             $newFields = TRUE;
                                         }
                                         // If it is an object property, we want to bind labels of the resource referenced by that
                                         // object property to the current resource. That way, if we have "paul" -- know --> "bob", and the
                                         // user send a seach query for "bob", then "paul" will be returned as well.
                                         $query = $this->ws->db->build_sparql_query("select ?p ?o where {<" . $value["value"] . "> ?p ?o.}", array('p', 'o'), FALSE);
                                         $resultset3 = $this->ws->db->query($query);
                                         $subjectTriples = array();
                                         while (odbc_fetch_row($resultset3)) {
                                             $p = odbc_result($resultset3, 1);
                                             $o = $this->ws->db->odbc_getPossibleLongResult($resultset3, 2);
                                             if (!isset($subjectTriples[$p])) {
                                                 $subjectTriples[$p] = array();
                                             }
                                             array_push($subjectTriples[$p], $o);
                                         }
                                         unset($resultset3);
                                         // We allign all label properties values in a single string so that we can search over all of them.
                                         $labels = "";
                                         foreach ($labelProperties as $property) {
                                             if (isset($subjectTriples[$property])) {
                                                 $labels .= $subjectTriples[$property][0] . " ";
                                             }
                                         }
                                         $property = $propertyHierarchy->getProperty($predicate);
                                         if ($labels != "") {
                                             $labels = trim($labels);
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_" . $lang . "_single_valued\">" . $this->ws->xmlEncode($labels) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_" . $lang . "\">" . $this->ws->xmlEncode($labels) . "</field>";
                                             }
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_uri\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                             $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode($predicate) . "</field>";
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_facets\">" . $this->ws->xmlEncode($labels) . "</field>";
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_uri_label_facets\">" . $this->ws->xmlEncode($value["value"]) . '::' . $this->ws->xmlEncode($labels) . "</field>";
                                         } else {
                                             // If no label is found, we may want to manipulate the ending of the URI to create
                                             // a "temporary" pref label for that object, and then to index it as a search string.
                                             $pos = strripos($value["value"], "#");
                                             if ($pos !== FALSE) {
                                                 $temporaryLabel = substr($value["value"], $pos + 1);
                                             } else {
                                                 $pos = strripos($value["value"], "/");
                                                 if ($pos !== FALSE) {
                                                     $temporaryLabel = substr($value["value"], $pos + 1);
                                                 }
                                             }
                                             // Check if the property is defined as a cardinality of maximum 1
                                             // If it doesn't we consider it a multi-valued field, otherwise
                                             // we use the single-valued version of the field.
                                             if ($property->cardinality == 1 || $property->maxCardinality == 1) {
                                                 if (array_search($predicate, $usedSingleValuedProperties) === FALSE) {
                                                     $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_" . $lang . "_single_valued\">" . $this->ws->xmlEncode($temporaryLabel) . "</field>";
                                                     $usedSingleValuedProperties[] = $predicate;
                                                 }
                                             } else {
                                                 $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_" . $lang . "\">" . $this->ws->xmlEncode($temporaryLabel) . "</field>";
                                             }
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_uri\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                             $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode($predicate) . "</field>";
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_facets\">" . $this->ws->xmlEncode($temporaryLabel) . "</field>";
                                             $add .= "<field name=\"" . urlencode($predicate) . "_attr_uri_label_facets\">" . $this->ws->xmlEncode($value["value"]) . '::' . $this->ws->xmlEncode($temporaryLabel) . "</field>";
                                         }
                                         /* 
                                           Check if there is a reification statement for that triple. If there is one, we index it in the 
                                           index as:
                                           <property> <text>
                                           Note: Eventually we could want to update the Solr index to include a new "reifiedText" field.
                                         */
                                         $statementAdded = FALSE;
                                         foreach ($statementsUri as $statementUri) {
                                             if ($resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"][0]["value"] == $subject && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"][0]["value"] == $predicate && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#object"][0]["value"] == $value["value"]) {
                                                 foreach ($resourceIndex[$statementUri] as $reiPredicate => $reiValues) {
                                                     if ($reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#subject" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate" && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#object") {
                                                         foreach ($reiValues as $reiValue) {
                                                             if ($reiValue["type"] == "literal") {
                                                                 $reiLang = "";
                                                                 if (isset($reiValue["lang"])) {
                                                                     if (array_search($reiValue["lang"], $this->ws->supportedLanguages) !== FALSE) {
                                                                         // The language used for this string is supported by the system, so we index it in
                                                                         // the good place
                                                                         $reiLang = $reiValue["lang"];
                                                                     } else {
                                                                         // The language used for this string is not supported by the system, so we
                                                                         // index it in the default language
                                                                         $reiLang = $this->ws->supportedLanguages[0];
                                                                     }
                                                                 } else {
                                                                     // The language is not defined for this string, so we simply consider that it uses
                                                                     // the default language supported by the structWSF instance
                                                                     $reiLang = $this->ws->supportedLanguages[0];
                                                                 }
                                                                 // Attribute used to reify information to a statement.
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_attr\">" . $this->ws->xmlEncode($predicate) . "</field>";
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_obj\">" . $this->ws->xmlEncode($value["value"]) . "</field>";
                                                                 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_value_" . $reiLang . "\">" . $this->ws->xmlEncode($reiValue["value"]) . "</field>";
                                                                 $add .= "<field name=\"attribute\">" . $this->ws->xmlEncode($reiPredicate) . "</field>";
                                                                 $statementAdded = TRUE;
                                                                 break;
                                                             }
                                                         }
                                                     }
                                                     if ($statementAdded) {
                                                         break;
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                         // Get all types by inference
                         $inferredTypes = array();
                         foreach ($types as $type) {
                             $superClasses = $classHierarchy->getSuperClasses($type);
                             // Add the type to make the closure of the set of inferred types
                             array_push($inferredTypes, $type);
                             foreach ($superClasses as $sc) {
                                 if (array_search($sc->name, $inferredTypes) === FALSE) {
                                     array_push($inferredTypes, $sc->name);
                                 }
                             }
                         }
                         foreach ($inferredTypes as $sc) {
                             $add .= "<field name=\"inferred_type\">" . $this->ws->xmlEncode($sc) . "</field>";
                         }
                         $add .= "</doc></add>";
                         if (!$solr->update($add)) {
                             $this->ws->conneg->setStatus(500);
                             $this->ws->conneg->setStatusMsg("Internal Error");
                             $this->ws->conneg->setError($this->ws->errorMessenger->_303->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_303->name, $this->ws->errorMessenger->_303->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_303->level);
                             return;
                         }
                     }
                     if ($this->ws->solr_auto_commit === FALSE) {
                         if (!$solr->commit()) {
                             $this->ws->conneg->setStatus(500);
                             $this->ws->conneg->setStatusMsg("Internal Error");
                             $this->ws->conneg->setError($this->ws->errorMessenger->_304->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_304->name, $this->ws->errorMessenger->_304->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_304->level);
                             return;
                         }
                     }
                     // Update the fields index if a new field as been detected.
                     if ($newFields) {
                         $solr->updateFieldsIndex();
                     }
                 }
                 /*        
                         // Optimisation can be time consuming "on-the-fly" (which decrease user's experience)
                         if(!$solr->optimize())
                         {
                           $this->ws->conneg->setStatus(500);
                           $this->ws->conneg->setStatusMsg("Internal Error");
                           $this->ws->conneg->setStatusMsgExt("Error #crud-create-106");
                           return;          
                         }
                 */
             }
         }
     }
 }
 public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $solr = new Solr($this->ws->wsf_solr_core, $this->ws->solr_host, $this->ws->solr_port, $this->ws->fields_index_folder);
         $solrQuery = "";
         // Get all datasets accessible to that user
         $accessibleDatasets = array();
         $ws_al = new AuthLister("access_user", "", $this->ws->registered_ip, $this->ws->wsf_local_ip, "none");
         $ws_al->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
         $ws_al->process();
         $xml = new ProcessorXML();
         $xml->loadXML($ws_al->pipeline_getResultset());
         $accesses = $xml->getSubjectsByType("wsf:Access");
         foreach ($accesses as $access) {
             $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess");
             $objects = $xml->getObjects($predicates->item(0));
             $datasetUri = $xml->getURI($objects->item(0));
             $predicates = $xml->getPredicatesByType($access, "wsf:read");
             $objects = $xml->getObjects($predicates->item(0));
             $read = $xml->getContent($objects->item(0));
             if (strtolower($read) == "true" && array_search($datasetUri, $accessibleDatasets) === FALSE) {
                 array_push($accessibleDatasets, $datasetUri);
             }
         }
         unset($ws_al);
         /*
           if registered_ip != requester_ip, this means that the query is sent by a registered system
           on the behalf of someone else. In this case, we want to make sure that that system 
           (the one that send the actual query) has access to the same datasets. Otherwise, it means that
           it tries to personificate that registered_ip user.
         */
         if ($this->ws->registered_ip != $this->ws->requester_ip) {
             // Get all datasets accessible to that system
             $accessibleDatasetsSystem = array();
             $ws_al = new AuthLister("access_user", "", $this->ws->requester_ip, $this->ws->wsf_local_ip, "none");
             $ws_al->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
             $ws_al->process();
             $xml = new ProcessorXML();
             $xml->loadXML($ws_al->pipeline_getResultset());
             $accesses = $xml->getSubjectsByType("wsf:Access");
             foreach ($accesses as $access) {
                 $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess");
                 $objects = $xml->getObjects($predicates->item(0));
                 $datasetUri = $xml->getURI($objects->item(0));
                 $predicates = $xml->getPredicatesByType($access, "wsf:read");
                 $objects = $xml->getObjects($predicates->item(0));
                 $read = $xml->getContent($objects->item(0));
                 if (strtolower($read) == "true") {
                     array_push($accessibleDatasetsSystem, $datasetUri);
                 }
             }
             unset($ws_al);
             /*
               Finally we use the intersection of the two set of dataset URIs as the list of accessible
               datasets to include for the query.
             */
             $accessibleDatasets = array_intersect($accessibleDatasets, $accessibleDatasetsSystem);
         }
         if (count($accessibleDatasets) <= 0) {
             $this->ws->conneg->setStatus(400);
             $this->ws->conneg->setStatusMsg("Bad Request");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_300->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_300->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_300->name, $this->ws->errorMessenger->_300->description, "", $this->ws->errorMessenger->_300->level);
             return;
         }
         $queryParam = "*:*";
         if ($this->ws->query != "") {
             $queryParam = urlencode($this->ws->query);
         }
         $distanceQueryRevelencyBooster = "";
         if ($this->ws->geoEnabled && isset($this->ws->resultsLocationAggregator[0]) && isset($this->ws->resultsLocationAggregator[1]) && ($this->ws->distanceFilter || $this->ws->rangeFilter)) {
             // Here, "^0" is added to zero-out the boost (revelency) value of the keyword
             // in this query, we simply want to aggregate the results related to their
             // distance of the center point.
             //$distanceQueryRevelencyBooster = '^0 AND _val_:"recip(dist(2, lat, long, '.$this->ws->resultsLocationAggregator[0].', '.$this->ws->resultsLocationAggregator[1].'), 1, 1, 0)"^100';
             $distanceQueryRevelencyBooster = '^0 AND _val_:"recip(geodist(geohash, ' . $this->ws->resultsLocationAggregator[0] . ', ' . $this->ws->resultsLocationAggregator[1] . '), 1, 1, 0)"^100';
         }
         $boostingRules = "";
         // Types boosting rules
         if ($this->ws->typesBoost != "") {
             $boostRules = explode(";", $this->ws->typesBoost);
             foreach ($boostRules as $key => $rule) {
                 $boost = explode("^", $rule);
                 $type = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $boostingRules .= '&bq=type:"' . urlencode($type) . '"^' . $modifier;
                 if (strtolower($this->ws->inference) == "on") {
                     $boostingRules .= '&bq=inferred_type:"' . urlencode($type) . '"^' . $modifier;
                 }
             }
             $insertOR = TRUE;
         }
         // Datasets boosting rules
         if ($this->ws->datasetsBoost != "") {
             $boostRules = explode(";", $this->ws->datasetsBoost);
             foreach ($boostRules as $key => $rule) {
                 $boost = explode("^", $rule);
                 $dataset = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $boostingRules .= '&bq=dataset:"' . urlencode($dataset) . '"^' . $modifier;
             }
             $insertOR = TRUE;
         }
         // Attributes & Attributes/values boosting rules
         if ($this->ws->attributesBoost != "") {
             $boostRules = explode(";", $this->ws->attributesBoost);
             foreach ($boostRules as $key => $rule) {
                 $isAttributeValue = FALSE;
                 if (strpos($rule, '::') !== FALSE) {
                     $isAttributeValue = TRUE;
                 }
                 $boost = explode("^", $rule);
                 $attribute = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 if ($isAttributeValue) {
                     $attribute = explode("::", $attribute);
                     $attributeValue = $attribute[1];
                     $attribute = $attribute[0];
                     $indexedFields = array();
                     if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                         $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                     }
                     // Fix the reference to some of the core attributes
                     $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                     // If it is not a core attribute, check if we have to make that attribute
                     // single-valued. We check that by checking if a single_valued version
                     // of that field is currently used in the Solr index.
                     $singleValuedDesignator = "";
                     if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     $attributeFound = FALSE;
                     // Get the Solr field ID for this attribute
                     if (!$isCoreAttribute) {
                         // Check if it is an object property, and check if the pattern of this object property
                         // is using URIs as values
                         $valuesAsURI = FALSE;
                         if (stripos($attribute, "[uri]") !== FALSE) {
                             $valuesAsURI = TRUE;
                             $attribute = str_replace("[uri]", "", $attribute);
                         }
                         $attribute = urlencode($attribute);
                         if (array_search($attribute . "_attr_date" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_date" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_int" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_int" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_float" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_float" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                             $attribute = urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             // Check if the value of that filter is a URI or not.
                             if ($valuesAsURI) {
                                 $attribute = urlencode($attribute) . "_attr_obj_uri";
                             } else {
                                 $attribute = urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator;
                             }
                         }
                     }
                     $boostingRules .= '&bq=' . $attribute . ':"' . urlencode($attributeValue) . '"^' . $modifier;
                 } else {
                     $boostingRules .= '&bq=attribute:"' . urlencode($attribute) . '"^' . $modifier;
                 }
             }
         }
         // Attributes phrases boosting rules
         if ($this->ws->attributesPhraseBoost != "") {
             $boostRules = explode(";", $this->ws->attributesPhraseBoost);
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             foreach ($boostRules as $key => $rule) {
                 if ($rule == '') {
                     continue;
                 }
                 $boost = explode("^", $rule);
                 $attribute = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute) {
                     if (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     if (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                         $attribute = str_replace($attribute, urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator, $attribute);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = str_replace($attribute . ":", urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":", $attribute);
                         $attributeFound = TRUE;
                     }
                 }
                 $boostingRules .= '&pf=' . urlencode($attribute) . '^' . $modifier;
             }
             $boostingRules .= '&qs=' . $this->ws->phraseBoostDistance;
         }
         $restrictionRules = '';
         // Define properties restricted for search and their boost
         if (!empty($this->ws->searchRestrictions)) {
             $restrictionRules .= '&qf=';
             $restrictions = explode(';', $this->ws->searchRestrictions);
             foreach ($restrictions as $restriction) {
                 if (empty($restriction)) {
                     continue;
                 }
                 $modifier = 1;
                 $attribute = $restriction;
                 if (strpos($restriction, '^')) {
                     $res = explode('^', $restriction);
                     $modifier = $res[1];
                     $attribute = $res[0];
                 }
                 $indexedFields = array();
                 if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                     $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                 }
                 // Fix the reference to some of the core attributes
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                 // If it is not a core attribute, check if we have to make that attribute
                 // single-valued. We check that by checking if a single_valued version
                 // of that field is currently used in the Solr index.
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                     $singleValuedDesignator = "_single_valued";
                 }
                 $attributeFound = FALSE;
                 // Get the Solr field ID for this attribute
                 if (!$isCoreAttribute) {
                     $attribute = urlencode($attribute);
                     /*
                      @NOTE: here we can only include fields that uses the "solr.StopFilterFactory" setting in their
                             defined workflow. Otherwise, if a stopword is used in the search query, 0 results
                             will always be returned with the eDisMax query parser.
                     */
                     if (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator;
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator;
                         $attributeFound = TRUE;
                     }
                 } else {
                     $attributeFound = TRUE;
                 }
                 if ($attributeFound) {
                     $restrictionRules .= $attribute . '^' . $modifier . ' ';
                 }
             }
         }
         $restrictionRules = rtrim($restrictionRules);
         $solrQuery = "q=" . $queryParam . $distanceQueryRevelencyBooster . $boostingRules . $restrictionRules . "&start=" . $this->ws->page . "&rows=" . $this->ws->items . (strtolower($this->ws->includeAggregates) == "true" ? "&facet=true" . "&facet.sort=count" . "&facet.limit=-1" . "&facet.field=type" . "&facet.field=attribute" . (strtolower($this->ws->inference) == "on" ? "&facet.field=inferred_type" : "") . "&facet.field=dataset&facet.mincount=1" : "");
         if (strtolower($this->ws->datasets) == "all") {
             $datasetList = "";
             foreach ($accessibleDatasets as $key => $dataset) {
                 if ($key == 0) {
                     $solrQuery .= "&fq=dataset:%22" . urlencode($dataset) . "%22";
                 } else {
                     $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22";
                 }
             }
         } else {
             $datasets = explode(";", $this->ws->datasets);
             $solrQuery .= "&fq=dataset:%22%22";
             foreach ($datasets as $dataset) {
                 // Check if the dataset is accessible to the user
                 if (array_search($dataset, $accessibleDatasets) !== FALSE) {
                     // Decoding potentially encoded ";" characters
                     $dataset = str_replace(array("%3B", "%3b"), ";", $dataset);
                     $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22";
                 }
             }
         }
         if ($this->ws->types != "all") {
             // Lets include the information to facet per type.
             $types = explode(";", $this->ws->types);
             $nbProcessed = 0;
             foreach ($types as $type) {
                 // Decoding potentially encoded ";" characters
                 $type = str_replace(array("%3B", "%3b"), ";", $type);
                 if ($nbProcessed == 0) {
                     $solrQuery .= "&fq=type:%22" . urlencode($type) . "%22";
                 } else {
                     $solrQuery .= " OR type:%22" . urlencode($type) . "%22";
                 }
                 $nbProcessed++;
                 if (strtolower($this->ws->inference) == "on") {
                     $solrQuery .= " OR inferred_type:%22" . urlencode($type) . "%22";
                 }
             }
         }
         if ($this->ws->extendedFilters != "") {
             // Get the fields (attributes) from the extended attributes query
             preg_match_all("/([#%\\.A-Za-z0-9_\\-\\[\\]]+):[\\(\"#%\\.A-Za-z0-9_\\-\\+*]+/Uim", $this->ws->extendedFilters, $matches);
             $attributes = $matches[1];
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             $attributes = array_unique($attributes);
             foreach ($attributes as $attribute) {
                 $attribute = urldecode($attribute);
                 if ($attribute == "dataset") {
                     // Make sure the user has access to this dataset
                     // Get all the dataset values referenced in the extended filters
                     $usedDatasets = array();
                     preg_match_all("/dataset:[\"(](.*)[\")]/Uim", $this->ws->extendedFilters, $matches);
                     $usedDatasets = array_merge($usedDatasets, $matches[1]);
                     preg_match_all("/dataset:([^\"()]*)[\\s\$)]+/Uim", $this->ws->extendedFilters, $matches);
                     $usedDatasets = array_merge($usedDatasets, $matches[1]);
                     $usedDatasets = array_unique($usedDatasets);
                     // Make sure that all defined dataset extended filters are accessible to the requester
                     foreach ($usedDatasets as $key => $usedDataset) {
                         // Unescape values (remove "\" from the Solr query)
                         $usedDataset = str_replace('\\', '', $usedDataset);
                         if (array_search($usedDataset, $accessibleDatasets) === FALSE) {
                             $this->ws->conneg->setStatus(400);
                             $this->ws->conneg->setStatusMsg("Bad Request");
                             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_309->name);
                             $this->ws->conneg->setError($this->ws->errorMessenger->_309->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_309->name, $this->ws->errorMessenger->_309->description, "Unaccessible dataset: " . $usedDataset, $this->ws->errorMessenger->_309->level);
                             return;
                         }
                     }
                 }
                 // Fix the reference to some of the core attributes
                 $coreAttribute = "";
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $coreAttribute);
                 // If it is not a core attribute, check if we have to make that attribute
                 // single-valued. We check that by checking if a single_valued version
                 // of that field is currently used in the Solr index.
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                     $singleValuedDesignator = "_single_valued";
                 }
                 $attributeFound = FALSE;
                 // Get the Solr field ID for this attribute
                 if ($isCoreAttribute) {
                     $attribute = urlencode($attribute);
                     $this->ws->extendedFilters = str_replace($attribute, $coreAttribute, $this->ws->extendedFilters);
                     $attributeFound = TRUE;
                 } else {
                     // Check if it is an object property, and check if the pattern of this object property
                     // is using URIs as values
                     $valuesAsURI = FALSE;
                     if (stripos($attribute, "[uri]") !== FALSE) {
                         $valuesAsURI = TRUE;
                         $attribute = str_replace("[uri]", "", $attribute);
                     }
                     $attribute = urlencode($attribute);
                     if (array_search($attribute . "_attr_date" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_date" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_int" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_int" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_float" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_float" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         // Check if the value of that filter is a URI or not.
                         if ($valuesAsURI) {
                             $this->ws->extendedFilters = str_replace($attribute . "[uri]:", urlencode($attribute) . "_attr_obj_uri:", $this->ws->extendedFilters);
                         } else {
                             $this->ws->extendedFilters = str_replace($attribute . ":", urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":", $this->ws->extendedFilters);
                         }
                         $attributeFound = TRUE;
                     }
                 }
                 if ($attributeFound === FALSE) {
                     $this->ws->conneg->setStatus(400);
                     $this->ws->conneg->setStatusMsg("Bad Request");
                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_310->name);
                     $this->ws->conneg->setError($this->ws->errorMessenger->_310->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_310->name, $this->ws->errorMessenger->_310->description, "Undefined filter: " . urldecode($attribute), $this->ws->errorMessenger->_310->level);
                     return;
                 }
             }
             $solrQuery .= "&fq=" . $this->ws->extendedFilters;
         }
         if ($this->ws->attributes != "all") {
             // Lets include the information to facet per type.
             $attributes = explode(";", $this->ws->attributes);
             $nbProcessed = 0;
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             foreach ($attributes as $attribute) {
                 $attributeValue = explode("::", $attribute);
                 $attribute = urldecode($attributeValue[0]);
                 // Skip possible "dataset" field request. This is handled bia the "dataset" parameter
                 // of this web service endpoint.
                 if ($attribute == "dataset") {
                     continue;
                 }
                 if (isset($attributeValue[1]) && $attributeValue[1] != "") {
                     // Fix the reference to some of the core attributes
                     $coreAttr = $this->isCoreAttribute($attribute, $attribute);
                     // Special handling for some core attributes
                     switch (urldecode($attributeValue[0])) {
                         case "prefLabel":
                         case Namespaces::$iron . "prefLabel":
                             // Check if we are performing an autocompletion task on the pref label
                             $label = urldecode($attributeValue[1]);
                             if (substr($label, strlen($label) - 2) == "**") {
                                 $attribute = "prefLabelAutocompletion_" . $this->ws->lang;
                                 $attributeValue[1] = urlencode(strtolower(str_replace(" ", "\\ ", substr($label, 0, strlen($label) - 1))));
                             }
                             break;
                         case "lat":
                         case Namespaces::$geo . "lat":
                             if (!is_numeric(urldecode($attributeValue[1]))) {
                                 // If the value is not numeric, we skip that attribute/value.
                                 // Otherwise an exception will be raised by Solr.
                                 continue;
                             }
                             break;
                         case "long":
                         case Namespaces::$geo . "long":
                             if (!is_numeric(urldecode($attributeValue[1]))) {
                                 // If the value is not numeric, we skip that attribute/value.
                                 // Otherwise an exception will be raised by Solr.
                                 continue;
                             }
                             break;
                     }
                     // A filtering value as been defined for this attribute.
                     $val = urldecode($attributeValue[1]);
                     // If it is not a core attribute, check if we have to make that attribute
                     // single-valued. We check that by checking if a single_valued version
                     // of that field is currently used in the Solr index.
                     $singleValuedDesignator = "";
                     if (!$coreAttr && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     if ($nbProcessed == 0) {
                         if ($coreAttr) {
                             switch ($attribute) {
                                 case "type":
                                     if (strtolower($this->ws->inference) == "on") {
                                         $solrQuery .= "&fq=((type:" . urlencode($this->escapeSolrValue($val)) . ") OR (inferred_type:" . urlencode($this->escapeSolrValue($val)) . "))";
                                     } else {
                                         $solrQuery .= "&fq=(type:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     }
                                     break;
                                 case "located_in":
                                     $solrQuery .= "&fq=(located_in:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     break;
                                 default:
                                     $solrQuery .= "&fq=(" . $attribute . ":" . urlencode($this->arrangeSolrValue($val)) . ")";
                                     break;
                             }
                         } else {
                             $solrQuery .= "&fq=(";
                         }
                     } else {
                         if ($coreAttr) {
                             switch ($attribute) {
                                 case "type":
                                     if (strtolower($this->ws->inference) == "on") {
                                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " ((type:" . urlencode($this->escapeSolrValue($val)) . ") OR (inferred_type:" . urlencode($this->escapeSolrValue($val)) . "))";
                                     } else {
                                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (type:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     }
                                     break;
                                 case "located_in":
                                     $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (located_in:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     break;
                                 default:
                                     $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (" . $attribute . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                                     break;
                             }
                         } else {
                             if (substr($solrQuery, strlen($solrQuery) - 3) != "fq=") {
                                 $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (";
                             } else {
                                 $solrQuery .= "(";
                             }
                         }
                     }
                     $addOR = FALSE;
                     $empty = TRUE;
                     // We have to detect if the fields are existing in Solr, otherwise Solr will throw
                     // "undefined fields" errors, and there is no way to ignore them and process
                     // the query anyway.
                     if (!$coreAttr && array_search(urlencode($attribute), $indexedFields) !== FALSE) {
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_" . $this->ws->lang . $singleValuedDesignator . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_int" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         if (is_numeric($val)) {
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_int" . $singleValuedDesignator . ":" . $val . ")";
                         } else {
                             // Extract the FROM and TO numbers range
                             $numbers = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($numbers[0] != "*") {
                                 if (!is_numeric($numbers[0])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             if ($numbers[1] != "*") {
                                 if (!is_numeric($numbers[1])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_int" . $singleValuedDesignator . ":" . urlencode("[" . $numbers[0] . " TO " . $numbers[1] . "]") . ")";
                         }
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_float" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         if (is_numeric($val)) {
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_float" . $singleValuedDesignator . ":" . $val . ")";
                         } else {
                             // Extract the FROM and TO numbers range
                             $numbers = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($numbers[0] != "*") {
                                 if (!is_numeric($numbers[0])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             if ($numbers[1] != "*") {
                                 if (!is_numeric($numbers[1])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_float" . $singleValuedDesignator . ":" . urlencode("[" . $numbers[0] . " TO " . $numbers[1] . "]") . ")";
                         }
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_date" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $dateFrom = "";
                         $dateTo = "NOW";
                         // Check if it is a range query
                         if (substr($val, 0, 1) == "[" && substr($val, strlen($val) - 1, 1) == "]") {
                             // Extract the FROM and TO dates range
                             $dates = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($dates[0] != "*") {
                                 $dateFrom = $this->safeDate($dates[0]);
                                 if ($dateFrom === FALSE) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                     return;
                                 }
                             }
                             if ($dates[1] != "*") {
                                 $dateTo = $this->safeDate($dates[1]);
                                 if ($dateTo === FALSE) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                     return;
                                 }
                             }
                         } else {
                             // If no range is defined, we consider the input date to be the initial date to use
                             // until now.
                             $dateFrom = $this->safeDate($val);
                             if ($dateFrom === FALSE) {
                                 $this->ws->conneg->setStatus(400);
                                 $this->ws->conneg->setStatusMsg("Bad Request");
                                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                 $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                 return;
                             }
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_date" . $singleValuedDesignator . ":" . urlencode("[" . $dateFrom . " TO " . $dateTo) . "]" . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":" . urlencode($this->escapeSolrValue($val)) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_obj_uri"), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_obj_uri:" . urlencode($this->escapeURIValue($val)) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if ($nbProcessed == 0) {
                         if (!$coreAttr) {
                             if ($empty) {
                                 $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 1);
                             } else {
                                 $solrQuery .= ")";
                             }
                         }
                     } else {
                         if (!$coreAttr) {
                             if (substr($solrQuery, strlen($solrQuery) - 4) != "fq=(") {
                                 if ($empty) {
                                     $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 5);
                                 } else {
                                     $solrQuery .= ")";
                                 }
                             } else {
                                 $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 1);
                             }
                         }
                     }
                 } else {
                     if ($nbProcessed == 0) {
                         $solrQuery .= "&fq=(attribute:%22" . urlencode($attribute) . "%22)";
                     } else {
                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (attribute:%22" . urlencode($attribute) . "%22)";
                     }
                 }
                 $nbProcessed++;
             }
         }
         // Check if this query is geo-enabled and if a distance-filter is requested
         if ($this->ws->geoEnabled && $this->ws->distanceFilter != "") {
             /*
               $params[0] == latitude
               $params[1] == longitude
               $params[2] == distance
               $params[3] == (0) distance in kilometers, (1) distance in miles
             */
             $params = explode(";", $this->ws->distanceFilter);
             $earthRadius = 6371;
             if ($params[3] == 1) {
                 $earthRadius = 3963.205;
             }
             $solrQuery .= "&fq={!frange l=0 u=" . $params[2] . "}hsin(" . $params[0] . "," . $params[1] . " , lat_rad, long_rad, " . $earthRadius . ")";
         }
         // Check if this query is geo-enabled and if a range-filter is requested
         if ($this->ws->geoEnabled && $this->ws->rangeFilter != "") {
             /*
               $params[0] == latitude top-left
               $params[1] == longitude top-left
               $params[2] == latitude bottom-right
               $params[3] == longitude bottom-right
             */
             $params = explode(";", $this->ws->rangeFilter);
             // Make sure the ranges are respected according to the way the cartesian coordinate
             // system works.
             $p1 = $params[0];
             $p2 = $params[2];
             $p3 = $params[1];
             $p4 = $params[3];
             if ($params[0] > $params[2]) {
                 $p1 = $params[2];
                 $p2 = $params[0];
             }
             if ($params[1] > $params[3]) {
                 $p3 = $params[3];
                 $p4 = $params[1];
             }
             $solrQuery .= "&fq=lat:[" . $p1 . " TO " . $p2 . "]&fq=long:[" . $p3 . " TO " . $p4 . "]";
         }
         // Add the attribute/value aggregates if needed
         if (count($this->ws->aggregateAttributes) > 0 && strtolower($this->ws->includeAggregates) == "true") {
             foreach ($this->ws->aggregateAttributes as $attribute) {
                 $solrQuery .= "&facet.field=" . urlencode(urlencode($attribute));
                 $solrQuery .= "&f." . urlencode(urlencode($attribute)) . ".facet.limit=" . $this->ws->aggregateAttributesNb;
             }
         }
         // Only return these fields in the resultset
         if (count($this->ws->includeAttributesList) > 0) {
             if (strtolower($this->ws->includeAttributesList[0]) == "none") {
                 $solrQuery .= "&fl=";
                 $solrQuery .= "uri ";
                 $solrQuery .= "type ";
                 $solrQuery .= "inferred_type ";
                 $solrQuery .= "dataset ";
                 $solrQuery .= "prefLabelAutocompletion_" . $this->ws->lang . "";
             } else {
                 $solrQuery .= "&fl=";
                 foreach ($this->ws->includeAttributesList as $atl) {
                     if ($atl != "none") {
                         $isCoreAttribute = $this->isCoreAttribute($atl, $atl);
                         if (!$isCoreAttribute) {
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_" . $this->ws->lang . " ";
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_obj_" . $this->ws->lang . " ";
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_obj_uri ";
                         } else {
                             $solrQuery .= $atl . " ";
                         }
                     }
                 }
                 // Also add the core attributes to the mixte
                 $solrQuery .= "uri ";
                 $solrQuery .= "type ";
                 $solrQuery .= "inferred_type ";
                 $solrQuery .= "dataset ";
                 $solrQuery .= "prefLabelAutocompletion_" . $this->ws->lang . "";
             }
         }
         // Remove possible left-over introduced by the procedure above for some rare usecases.
         $solrQuery = str_replace("fq= OR ", "fq=", $solrQuery);
         $solrQuery = str_replace("fq= AND ", "fq=", $solrQuery);
         // Set the default field of the search
         $solrQuery .= "&df=all_text_" . $this->ws->lang;
         // The the sorting parameter
         if (count($this->ws->sort) > 0) {
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                 $solrQuery .= "&sort=";
                 foreach ($this->ws->sort as $sortProperty => $order) {
                     $lSortProperty = strtolower($sortProperty);
                     if ($lSortProperty == "preflabel") {
                         $sortProperty = "prefLabelAutocompletion_" . $this->ws->lang;
                     } else {
                         if ($lSortProperty == "type") {
                             $sortProperty = "type_single_valued";
                         } else {
                             if ($lSortProperty != "uri" && $lSortProperty != "dataset" && $lSortProperty != "score") {
                                 $uSortProperty = urlencode($sortProperty);
                                 if (array_search($uSortProperty . "_attr_date_single_valued", $indexedFields) !== FALSE) {
                                     $sortProperty = urlencode($uSortProperty) . "_attr_date_single_valued";
                                 } else {
                                     if (array_search($uSortProperty . "_attr_float_single_valued", $indexedFields) !== FALSE) {
                                         $sortProperty = urlencode($uSortProperty) . "_attr_float_single_valued";
                                     } else {
                                         if (array_search($uSortProperty . "_attr_int_single_valued", $indexedFields) !== FALSE) {
                                             $sortProperty = urlencode($uSortProperty) . "_attr_int_single_valued";
                                         } else {
                                             if (array_search($uSortProperty . "_attr_obj_" . $this->ws->lang . "_single_valued", $indexedFields) !== FALSE) {
                                                 $sortProperty = urlencode($uSortProperty) . "_attr_obj_" . $this->ws->lang . "_single_valued";
                                             } else {
                                                 if (array_search($uSortProperty . "_attr_" . $this->ws->lang . "_single_valued", $indexedFields) !== FALSE) {
                                                     $sortProperty = urlencode($uSortProperty) . "_attr_" . $this->ws->lang . "_single_valued";
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     $solrQuery .= $sortProperty . " " . $order . ",";
                 }
                 $solrQuery = rtrim($solrQuery, ",");
             }
         }
         if (!empty($this->ws->includeScores)) {
             $solrQuery .= '&fl=' . urlencode('* score');
         }
         // Specify the default search operator
         if ($this->ws->defaultOperator != 'and') {
             if (strpos($this->ws->defaultOperator, '::') !== FALSE) {
                 $orOp = explode('::', $this->ws->defaultOperator .= '&q.op=AND');
                 if ($orOp[0] == 'or') {
                     $solrQuery .= '&q.op=OR';
                     $solrQuery .= '&mm=' . $orOp[1];
                 }
             } else {
                 if ($this->ws->defaultOperator == 'or') {
                     $solrQuery .= '&q.op=OR';
                 }
             }
         } else {
             $solrQuery .= '&q.op=AND';
         }
         // Check if we enable the spellchecker
         if ($this->ws->spellcheck === TRUE) {
             $solrQuery .= '&spellcheck=true';
         }
         // Specifies that the query parser is eDisMax
         $solrQuery .= '&defType=edismax';
         $resultset = $solr->select($solrQuery);
         if ($resultset === FALSE) {
             $this->ws->conneg->setStatus(400);
             $this->ws->conneg->setStatusMsg("Bad Request");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_311->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_311->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_311->name, $this->ws->errorMessenger->_311->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_311->level);
             return;
         }
         // Create the internal representation of the resultset.
         $domResultset = new DomDocument("1.0", "utf-8");
         $domResultset->loadXML($resultset);
         $xpath = new DOMXPath($domResultset);
         // Get the number of results
         $founds = $xpath->query("*[@numFound]");
         foreach ($founds as $found) {
             $nbResources = $found->attributes->getNamedItem("numFound")->nodeValue;
             break;
         }
         // If no results are returned, check if spellchecking was enabled, if it was then
         // try to get the spell suggestions & the the collation
         if ($nbResources <= 0 && $this->ws->spellcheck === TRUE) {
             // Try to get the collation
             $collation = $xpath->query("//*/lst[@name='suggestions']//str[@name='collation']");
             if ($collation->length > 0) {
                 $collation = $collation->item(0)->nodeValue;
             }
             $subject = new Subject($this->ws->uri . "suggestions/" . md5(microtime()));
             $subject->setType(Namespaces::$wsf . "SpellSuggestion");
             $subject->setDataAttribute(Namespaces::$wsf . "collation", $collation);
             $this->ws->rset->addSubject($subject);
             // Try to get the suggested terms
             $suggestedWords = $xpath->query("//*/lst[@name='suggestions']/lst");
             foreach ($suggestedWords as $sw) {
                 $misspelledWord = $sw->getAttribute('name');
                 $suggestion = $xpath->query("arr[@name='suggestion']/lst", $sw);
                 foreach ($suggestion as $word_frequency) {
                     $word = $word_frequency->getElementsByTagName('str')->item(0)->nodeValue;
                     $frequency = $word_frequency->getElementsByTagName('int')->item(0)->nodeValue;
                     $subject = new Subject($this->ws->uri . "suggestions/" . md5(microtime()));
                     $subject->setType(Namespaces::$wsf . "SpellSuggestion");
                     $subject->setDataAttribute(Namespaces::$wsf . "misspelledWord", $misspelledWord);
                     $subject->setDataAttribute(Namespaces::$wsf . "suggestion", $word);
                     $subject->setDataAttribute(Namespaces::$wsf . "frequency", $frequency);
                     $this->ws->rset->addSubject($subject);
                 }
             }
         }
         // Get all the "type" facets with their counts
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='type']/int");
         // Set types aggregates
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "type");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set types aggregates for inferred types
         if (strtolower($this->ws->inference) == "on") {
             // Get all the "inferred_type" facets with their counts
             $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='inferred_type']/int");
             // Get types counts
             foreach ($founds as $found) {
                 $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
                 $subject->setType(Namespaces::$aggr . "Aggregate");
                 $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "type");
                 $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
                 $this->ws->rset->addSubject($subject);
             }
         }
         // Set the dataset aggregates
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='dataset']/int");
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$void . "Dataset");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set the attributes aggregates
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='attribute']/int");
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "Property");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set all the attributes/values aggregates
         foreach ($this->ws->aggregateAttributes as $attribute) {
             $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='" . urlencode($attribute) . "']/int");
             foreach ($founds as $found) {
                 $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
                 $subject->setType(Namespaces::$aggr . "Aggregate");
                 $subject->setObjectAttribute(Namespaces::$aggr . "property", str_replace(array("_attr_uri_label_facets", "_attr_facets", "_attr_obj_uri"), "", urldecode($attribute)));
                 if ($this->ws->aggregateAttributesObjectType == "uri") {
                     $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 } elseif ($this->ws->aggregateAttributesObjectType == "literal") {
                     $subject->setDataAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 } elseif ($this->ws->aggregateAttributesObjectType == "uriliteral") {
                     $values = explode("::", $found->attributes->getNamedItem("name")->nodeValue);
                     $subject->setObjectAttribute(Namespaces::$aggr . "object", $values[0]);
                     $subject->setDataAttribute(Namespaces::$aggr . "object", $values[1]);
                 }
                 $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
                 $this->ws->rset->addSubject($subject);
             }
         }
         // Set all the results
         $resultsDom = $xpath->query("//doc");
         foreach ($resultsDom as $result) {
             // get URI
             $resultURI = $xpath->query("str[@name='uri']", $result);
             $uri = "";
             if ($resultURI->length > 0) {
                 $uri = $resultURI->item(0)->nodeValue;
             } else {
                 continue;
             }
             $subject = new Subject($uri);
             // get Dataset URI
             $resultDatasetURI = $xpath->query("str[@name='dataset']", $result);
             if ($resultDatasetURI->length > 0) {
                 $subject->setObjectAttribute(Namespaces::$dcterms . "isPartOf", $resultDatasetURI->item(0)->nodeValue);
             }
             // get records preferred label
             $resultPrefLabelURI = $xpath->query("str[@name='prefLabel_" . $this->ws->lang . "']", $result);
             if ($resultPrefLabelURI->length > 0) {
                 $subject->setPrefLabel($resultPrefLabelURI->item(0)->nodeValue);
             }
             // get records aternative labels
             $resultAltLabelURI = $xpath->query("arr[@name='altLabel_" . $this->ws->lang . "']/str", $result);
             for ($i = 0; $i < $resultAltLabelURI->length; ++$i) {
                 $subject->setAltLabel($resultAltLabelURI->item($i)->nodeValue);
             }
             // Get possible Lat/Long and shapes descriptions
             // First check if there is a polygonCoordinates pr a polylineCoordinates attribute for that record
             // If there is one, then we simply ignore the lat/long coordinates since they come from these
             // attributes and that we don't want to duplicate that information.
             $skipLatLong = FALSE;
             $resultPolygonCoordinates = $xpath->query("arr[@name='polygonCoordinates']/str", $result);
             if ($resultPolygonCoordinates->length > 0) {
                 foreach ($resultPolygonCoordinates as $value) {
                     $subject->setDataAttribute(Namespaces::$sco . "polygonCoordinates", $value->nodeValue);
                 }
                 $skipLatLong = TRUE;
             }
             $resultPolylineCoordinates = $xpath->query("arr[@name='polylineCoordinates']/str", $result);
             if ($resultPolylineCoordinates->length > 0) {
                 foreach ($resultPolylineCoordinates as $value) {
                     $subject->setDataAttribute(Namespaces::$sco . "polylineCoordinates", $value->nodeValue);
                 }
                 $skipLatLong = TRUE;
             }
             if (!$skipLatLong) {
                 $resultDescriptionLat = $xpath->query("arr[@name='lat']/double", $result);
                 if ($resultDescriptionLat->length > 0) {
                     $subject->setDataAttribute(Namespaces::$geo . "lat", $resultDescriptionLat->item(0)->nodeValue);
                 }
                 $resultDescriptionLong = $xpath->query("arr[@name='long']/double", $result);
                 if ($resultDescriptionLong->length > 0) {
                     $subject->setDataAttribute(Namespaces::$geo . "long", $resultDescriptionLong->item(0)->nodeValue);
                 }
             }
             // Set possible score
             if (!empty($this->ws->includeScores)) {
                 $score = $xpath->query("float[@name='score']", $result);
                 if ($score->length > 0) {
                     $subject->setDataAttribute(Namespaces::$wsf . "score", $score->item(0)->nodeValue);
                 }
             }
             // get possible locatedIn URI(s)
             $resultLocatedIn = $xpath->query("arr[@name='located_in']/str", $result);
             if ($resultLocatedIn->length > 0) {
                 $subject->setObjectAttribute(Namespaces::$geoname . "locatedIn", $resultLocatedIn->item(0)->nodeValue);
             }
             // get records description
             $resultDescriptionURI = $xpath->query("arr[@name='description_" . $this->ws->lang . "']/str", $result);
             if ($resultDescriptionURI->length > 0) {
                 $subject->setDescription($resultDescriptionURI->item(0)->nodeValue);
             }
             // Get all dynamic fields attributes that are multi-valued
             $resultProperties = $xpath->query("arr", $result);
             $objectPropertyLabels = array();
             $objectPropertyUris = array();
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 // Exclude the attributes that have to be ignored by the Search endpoint
                 // when creating the new resultset.
                 if (array_search($attributeURI, $this->ws->searchExcludedAttributes) !== FALSE) {
                     continue;
                 }
                 if ($attributeURI == Namespaces::$rdf . "type") {
                     continue;
                 }
                 switch ($attributeType) {
                     case "_attr_" . $this->ws->lang:
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue);
                         }
                         break;
                     case "_attr_date":
                         $values = $property->getElementsByTagName("date");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$date);
                         }
                         break;
                     case "_attr_int":
                         $values = $property->getElementsByTagName("int");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$int);
                         }
                         break;
                     case "_attr_float":
                         $values = $property->getElementsByTagName("float");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$float);
                         }
                         break;
                     case "_attr_obj_" . $this->ws->lang:
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             if (!is_array($objectPropertyLabels[$attributeURI])) {
                                 $objectPropertyLabels[$attributeURI] = array();
                             }
                             array_push($objectPropertyLabels[$attributeURI], $value->nodeValue);
                         }
                         break;
                     case "_attr_obj_uri":
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             if (!is_array($objectPropertyUris[$attributeURI])) {
                                 $objectPropertyUris[$attributeURI] = array();
                             }
                             array_push($objectPropertyUris[$attributeURI], $value->nodeValue);
                         }
                         break;
                     case "_reify_attr":
                     case "_reify_attr_obj":
                     case "_reify_obj":
                     case "_reify_value_" . $this->ws->lang:
                         // @todo Implement reification in Search result. This means that reified statements should appears in the resultsets.
                         break;
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a string
             $resultProperties = $xpath->query("str", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_" . $this->ws->lang . "_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a date
             $resultProperties = $xpath->query("date", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_date_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$date);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a integer
             $resultProperties = $xpath->query("int", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_int_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$int);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a float
             $resultProperties = $xpath->query("float", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_float_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$float);
                 }
             }
             foreach ($objectPropertyUris as $attributeUri => $objectUris) {
                 foreach ($objectUris as $key => $objectUri) {
                     if (isset($objectPropertyLabels[$attributeUri][$key])) {
                         $subject->setObjectAttribute($attributeUri, $objectUri, array(Namespaces::$wsf . "objectLabel" => array($label = $objectPropertyLabels[$attributeUri][$key])));
                     } else {
                         $subject->setObjectAttribute($attributeUri, $objectUri);
                     }
                 }
             }
             unset($objectPropertyUris);
             unset($objectPropertyLabels);
             // Get the types of the resource.
             $resultTypes = $xpath->query("arr[@name='type']/str", $result);
             for ($i = 0; $i < $resultTypes->length; ++$i) {
                 if ($resultTypes->item($i)->nodeValue != "-") {
                     $subject->setType($resultTypes->item($i)->nodeValue);
                 }
             }
             $this->ws->rset->addSubject($subject, $resultDatasetURI->item(0)->nodeValue);
         }
     }
 }