/** Serialize the converted UCB Memorial Data content into different serialization formats
 
       @return returns the serialized content
     
       @author Frederick Giasson, Structured Dynamics LLC.
   */
 public function pipeline_serialize()
 {
     $rdf_part = "";
     switch ($this->conneg->getMime()) {
         case "application/iron+json":
             $irJSON = "{\n";
             $xml = new ProcessorXML();
             $xml->loadXML($this->pipeline_getResultset());
             $subjects = $xml->getSubjects();
             $datasetJson = "    \"dataset\": {\n";
             $instanceRecordsJson = "    \"recordList\": [ \n";
             // The first thing we have to check is if a linkage schema is available for this dataset.
             // If it is not, then we simply use the RDF properties and values to populate the IRON+JSON file.
             $accesses = $xml->getSubjectsByType("http://rdfs.org/ns/void#Dataset");
             $ls = array();
             $linkageSchemas = array();
             foreach ($accesses as $access) {
                 // We check if there is a link to a linkage schema
                 $predicates = $xml->getPredicatesByType($access, "http://purl.org/ontology/iron#linkage");
                 if ($predicates->length > 0) {
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         $linkageSchemaUrl = $xml->getContent($objects->item(0));
                         if (substr($linkageSchemaUrl, 0, 7) == "http://") {
                             $ch = curl_init();
                             curl_setopt($ch, CURLOPT_URL, $linkageSchemaUrl);
                             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
                             $data = curl_exec($ch);
                             $data = trim($data);
                             if (!curl_errno($ch) && $data != "") {
                                 $parsedContent = json_decode($data);
                                 array_push($ls, $parsedContent);
                             }
                             curl_close($ch);
                         }
                     }
                 } else {
                     // If no link, we create a inline schema.
                 }
                 // We check if there is a link to a structure schema
                 // If no link, we create an inline schema.
             }
             // Now populate the linkage schema object.
             foreach ($ls as $linkageSchema) {
                 $linkageSchema = $linkageSchema->linkage;
                 $tempSchema = new LinkageSchema();
                 // Set version
                 $tempSchema->setVersion($linkageSchema->version);
                 // Set linkedType
                 $tempSchema->setLinkedType($linkageSchema->linkedType);
                 // Set prefixes
                 if (isset($linkageSchema->prefixList)) {
                     foreach ($linkageSchema->prefixList as $prefix => $uri) {
                         $tempSchema->setPrefix($prefix, $uri);
                     }
                 }
                 // Set propertieslinkageSchemas
                 if (isset($linkageSchema->attributeList)) {
                     foreach ($linkageSchema->attributeList as $property => $values) {
                         $tempSchema->setPropertyX($property, $values->mapTo, $error);
                     }
                 }
                 // Set types
                 if (isset($linkageSchema->typeList)) {
                     foreach ($linkageSchema->typeList as $type => $values) {
                         $adds = array();
                         if (isset($values->add)) {
                             foreach ($values->add as $key => $value) {
                                 $adds[$key] = $value;
                             }
                         }
                         $error = "";
                         $tempSchema->setTypeX($type, $values->mapTo, $adds, $error);
                     }
                 }
                 array_push($linkageSchemas, $tempSchema);
             }
             // Check if a linkage schema of the same linkageType exists. If it exists, we merge them together.
             // Merging rules:
             // (1) if a type already exists, the type of the first schema will be used
             // (2) if an attribute already exists, the attribute of the first schema will be used.
             $merged = FALSE;
             $mergedSchemas = array();
             foreach ($linkageSchemas as $linkageSchema) {
                 $merged = FALSE;
                 // Check if this linkageType has already been merged
                 foreach ($mergedSchemas as $ms) {
                     if ($ms->linkageType == $linkageSchema->linkageType) {
                         // Merge schemas
                         // merge prefixes
                         if (isset($linkageSchema->prefixes)) {
                             foreach ($linkageSchema->prefixes as $prefix => $uri) {
                                 if (!isset($ms->prefixes[$prefix])) {
                                     $ms->prefixes[$prefix] = $uri;
                                 }
                             }
                         }
                         // merge types
                         if (isset($linkageSchema->typeX)) {
                             foreach ($linkageSchema->typeX as $type => $typeObject) {
                                 if (!isset($ms->typeX[$type])) {
                                     $ms->typeX[$type] = $typeObject;
                                 }
                             }
                         }
                         // merge attributes
                         if (isset($linkageSchema->propertyX)) {
                             foreach ($linkageSchema->propertyX as $attribute => $attributeObject) {
                                 if (!isset($ms->propertyX[$attribute])) {
                                     $ms->propertyX[$attribute] = $attributeObject;
                                 }
                             }
                         }
                         $merged = TRUE;
                         break;
                     }
                 }
                 if (!$merged) {
                     array_push($mergedSchemas, $linkageSchema);
                 }
             }
             $linkageSchemas = $mergedSchemas;
             // Now lets create the IRON+JSON serialization for dataset description and instance records descriptions.
             // Get the base (dataset) ID
             $datasetID = "";
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectType = $xml->getType($subject, FALSE);
                 if ($subjectType == "http://rdfs.org/ns/void#Dataset") {
                     $datasetID = $subjectURI;
                 }
             }
             $linkageSchemaLinks = array();
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectType = $xml->getType($subject, FALSE);
                 if ($subjectType == "http://rdfs.org/ns/void#Dataset") {
                     $datasetJson .= "        \"id\": \"{$datasetID}\",\n";
                     $predicates = $xml->getPredicates($subject);
                     $processingPredicateNum = 1;
                     $predicateType = "";
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         foreach ($objects as $object) {
                             if ($predicateType != $xml->getType($predicate, FALSE)) {
                                 $predicateType = $xml->getType($predicate, FALSE);
                                 $processingPredicateNum = 1;
                             } else {
                                 $processingPredicateNum++;
                             }
                             $objectContent = $xml->getContent($object);
                             $predicateName = "";
                             // Check for a linked property.
                             foreach ($linkageSchemas as $linkageSchema) {
                                 if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                                     foreach ($linkageSchema->propertyX as $property => $value) {
                                         if ($value[0]["mapTo"] == $predicateType) {
                                             $predicateName = $property;
                                         }
                                     }
                                 }
                             }
                             if ($predicateName == "") {
                                 /** @todo: custom linkage file */
                                 // If we still dont have a reference to a property name, we use the end of the RDF generated one.
                                 $predicateName = str_replace($this->wsf_graph . "ontology/properties/", "", $predicateType);
                                 $this->splitUri($predicateType, $base, $ext);
                                 $this->customLinkageSchema->setPropertyX($ext, $predicateType, $error);
                                 $predicateName = $ext;
                             }
                             if ($predicateName != "") {
                                 if ($this->nbPredicates($subject, $xml, $predicateType) > 1 && $processingPredicateNum == 1) {
                                     if ($predicateName != "linkage") {
                                         $datasetJson .= "        \"{$predicateName}\": [";
                                     }
                                 }
                                 if ($xml->getURI($object) == "") {
                                     $objectValue = $xml->getContent($object);
                                     if ($objects->length == 1) {
                                         if ($predicateName == "linkage") {
                                             //                          $datasetJson .= "        \"$predicateName\": [\"".$this->jsonEscape($objectValue)."\"],\n";
                                             array_push($linkageSchemaLinks, $objectValue);
                                         } else {
                                             $datasetJson .= "        \"{$predicateName}\": \"" . $this->jsonEscape($objectValue) . "\",\n";
                                         }
                                     } else {
                                         $datasetJson .= "        \"" . $this->jsonEscape($objectValue) . "\",";
                                     }
                                 } else {
                                     $objectURI = $xml->getURI($object);
                                     $datasetJson .= "        \"{$predicateName}\": {\n";
                                     if (stripos($objectURI, "/irs/") === FALSE) {
                                         $nbReplaced = 0;
                                         $ref = str_replace($datasetID, "@", $objectURI, $nbReplaced);
                                         if ($nbReplaced > 0) {
                                             $datasetJson .= "            \"ref\": \"" . $this->jsonEscape($ref) . "\",\n";
                                         } else {
                                             $datasetJson .= "            \"ref\": \"" . $this->jsonEscape("@@" . $objectURI) . "\",\n";
                                         }
                                     }
                                     $reifies = $xml->getReificationStatements($object);
                                     foreach ($reifies as $reify) {
                                         $v = $xml->getValue($reify);
                                         $t = $xml->getType($reify, FALSE);
                                         $predicateName = "";
                                         // Check for a linked property
                                         foreach ($linkageSchemas as $linkageSchema) {
                                             if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                                                 foreach ($linkageSchema->propertyX as $property => $value) {
                                                     if ($value[0]["mapTo"] == $t) {
                                                         $predicateName = $property;
                                                     }
                                                 }
                                             }
                                         }
                                         if ($predicateName == "") {
                                             /** @todo: custom linkage file */
                                             // If we still dont have a reference to a property name, we use the end of the RDF generated one.
                                             $predicateName = str_replace($this->wsf_graph . "ontology/properties/", "", $t);
                                             $this->splitUri($t, $base, $ext);
                                             $this->customLinkageSchema->setPropertyX($ext, $t, $error);
                                             $predicateName = $ext;
                                         }
                                         $datasetJson .= "            \"" . $predicateName . "\": \"" . $this->jsonEscape($v) . "\",\n";
                                     }
                                     $datasetJson = substr($datasetJson, 0, strlen($datasetJson) - 2) . "\n";
                                     $datasetJson .= "        },\n";
                                 }
                             }
                         }
                         if ($this->nbPredicates($subject, $xml, $predicateType) > 1 && $processingPredicateNum == $this->nbPredicates($subject, $xml, $predicateType)) {
                             if ($predicateName != "linkage") {
                                 $datasetJson = substr($datasetJson, 0, strlen($datasetJson) - 2);
                                 $datasetJson .= " ],\n";
                             }
                         }
                     }
                     $datasetJson = substr($datasetJson, 0, strlen($datasetJson) - 2) . "\n";
                 } else {
                     $instanceRecordsJson .= "        {\n";
                     $instanceRecordsJson .= "            \"id\": \"" . str_replace($datasetID, "", $subjectURI) . "\",\n";
                     // Get the type
                     $typeName = $subjectType;
                     $break = FALSE;
                     foreach ($linkageSchemas as $linkageSchema) {
                         if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                             foreach ($linkageSchema->typeX as $type => $value) {
                                 if ($value[0]["mapTo"] == $subjectType) {
                                     $typeName = $type;
                                     $break = TRUE;
                                     break;
                                 }
                             }
                             if ($break) {
                                 break;
                             }
                         }
                     }
                     // If there is no linked type for this type, we use the end of the automatically RDF type generated.
                     if ($break === FALSE) {
                         /** @todo: custom linkage file */
                         //$typeName = str_replace($this->wsf_graph."ontology/types/", "", $typeName);
                         $this->splitUri($typeName, $base, $ext);
                         $this->customLinkageSchema->setTypeX($ext, $typeName, array(), $error);
                         $typeName = $ext;
                     }
                     if ($this->nbPredicates($subject, $xml, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") >= 1) {
                         $instanceRecordsJson .= "            \"type\": [ \n";
                         $predicates = $xml->getPredicates($subject);
                         foreach ($predicates as $predicate) {
                             $pt = $xml->getType($predicate, FALSE);
                             if ($pt == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") {
                                 $objects = $xml->getObjects($predicate);
                                 $objectValue = $xml->getURI($objects->item(0));
                                 // Get the type
                                 $break = FALSE;
                                 foreach ($linkageSchemas as $linkageSchema) {
                                     if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                                         foreach ($linkageSchema->typeX as $type => $value) {
                                             if ($value[0]["mapTo"] == $objectValue) {
                                                 $objectValue = $type;
                                                 $break = TRUE;
                                                 break;
                                             }
                                         }
                                         if ($break) {
                                             break;
                                         }
                                     }
                                 }
                                 // If there is no linked type for this type, we use the end of the automatically RDF type generated.
                                 if ($break === FALSE) {
                                     /** @todo: custom linkage file */
                                     $objectValue = str_replace($this->wsf_graph . "ontology/types/", "", $objectValue);
                                     $this->splitUri($objectValue, $base, $ext);
                                     $this->customLinkageSchema->setTypeX($ext, $objectValue, array(), $error);
                                     $objectValue = $ext;
                                 }
                                 $instanceRecordsJson .= "                \"" . $objectValue . "\", \n";
                             }
                         }
                         $instanceRecordsJson .= "                \"" . $typeName . "\" ],\n";
                     } else {
                         $instanceRecordsJson .= "            \"type\": \"" . $typeName . "\",\n";
                     }
                     $predicates = $xml->getPredicates($subject);
                     $processingPredicateNum = 1;
                     $predicateType = "";
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         foreach ($objects as $object) {
                             $objectType = $xml->getType($object);
                             if ($predicateType != $xml->getType($predicate, FALSE)) {
                                 $predicateType = $xml->getType($predicate, FALSE);
                                 $processingPredicateNum = 1;
                             } else {
                                 $processingPredicateNum++;
                             }
                             if ($predicateType == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") {
                                 continue;
                             }
                             $objectContent = $xml->getContent($object);
                             $predicateName = "";
                             // Check for a linked property.
                             foreach ($linkageSchemas as $linkageSchema) {
                                 if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                                     foreach ($linkageSchema->propertyX as $property => $value) {
                                         if ($value[0]["mapTo"] == $predicateType) {
                                             $predicateName = $property;
                                         }
                                     }
                                 }
                             }
                             if ($predicateName == "") {
                                 /** @todo: custom linkage file */
                                 // If we still dont have a reference to a property name, we use the end of the RDF generated one.
                                 $predicateName = str_replace($this->wsf_graph . "ontology/properties/", "", $predicateType);
                                 $this->splitUri($predicateType, $base, $ext);
                                 $this->customLinkageSchema->setPropertyX($ext, $predicateType, $error);
                                 $predicateName = $ext;
                             }
                             if ($this->nbPredicates($subject, $xml, $predicateType) > 1 && $processingPredicateNum == 1) {
                                 $instanceRecordsJson .= "            \"{$predicateName}\": [\n";
                             }
                             if ($xml->getURI($object) == "") {
                                 $objectValue = $xml->getContent($object);
                                 if ($this->nbPredicates($subject, $xml, $predicateType) == 1) {
                                     $instanceRecordsJson .= "            \"{$predicateName}\": \"" . $this->jsonEscape($objectValue) . "\",\n";
                                 } else {
                                     $instanceRecordsJson .= "            \"" . $this->jsonEscape($objectValue) . "\",\n";
                                 }
                             } else {
                                 $objectURI = $xml->getURI($object);
                                 if ($this->nbPredicates($subject, $xml, $predicateType) > 1) {
                                     $instanceRecordsJson .= "            {\n";
                                 } else {
                                     $instanceRecordsJson .= "            \"{$predicateName}\": {\n";
                                 }
                                 if (stripos($objectURI, "/irs/") === FALSE) {
                                     $nbReplaced = 0;
                                     $ref = str_replace($datasetID, "@", $objectURI, $nbReplaced);
                                     if ($nbReplaced > 0) {
                                         $instanceRecordsJson .= "            \"ref\": \"" . $this->jsonEscape($ref) . "\",\n";
                                     } else {
                                         $instanceRecordsJson .= "            \"ref\": \"" . $this->jsonEscape("@@" . $objectURI) . "\",\n";
                                     }
                                 }
                                 $reifies = $xml->getReificationStatements($object);
                                 foreach ($reifies as $reify) {
                                     $v = $xml->getValue($reify);
                                     $t = $xml->getType($reify, FALSE);
                                     $predicateName = "";
                                     // Check for a linked property
                                     foreach ($linkageSchemas as $linkageSchema) {
                                         if (strtolower($linkageSchema->linkedType) == "application/rdf+xml") {
                                             foreach ($linkageSchema->propertyX as $property => $value) {
                                                 if ($value[0]["mapTo"] == $t) {
                                                     $predicateName = $property;
                                                 }
                                             }
                                         }
                                     }
                                     if ($predicateName == "") {
                                         /** @todo: custom linkage file */
                                         // If we still dont have a reference to a property name, we use the end of the RDF generated one.
                                         $predicateName = str_replace($this->wsf_graph . "ontology/properties/", "", $t);
                                         $this->splitUri($t, $base, $ext);
                                         $this->customLinkageSchema->setPropertyX($ext, $t, $error);
                                         $predicateName = $ext;
                                     }
                                     $instanceRecordsJson .= "                \"" . $predicateName . "\": \"" . $this->jsonEscape($v) . "\",\n";
                                 }
                                 $instanceRecordsJson = rtrim(rtrim($instanceRecordsJson, "\n"), ",") . "\n";
                                 $instanceRecordsJson .= "            },\n";
                             }
                         }
                         if ($this->nbPredicates($subject, $xml, $predicateType) > 1 && $processingPredicateNum == $this->nbPredicates($subject, $xml, $predicateType)) {
                             $instanceRecordsJson = substr($instanceRecordsJson, 0, strlen($instanceRecordsJson) - 2);
                             $instanceRecordsJson .= "     ],\n";
                         }
                     }
                     $instanceRecordsJson = substr($instanceRecordsJson, 0, strlen($instanceRecordsJson) - 2) . "\n";
                     $instanceRecordsJson .= "        },\n";
                 }
             }
             $instanceRecordsJson = substr($instanceRecordsJson, 0, strlen($instanceRecordsJson) - 2) . "\n";
             $instanceRecordsJson .= "        ]\n";
             $datasetJson .= "    },\n";
             $irJSON .= $datasetJson . $instanceRecordsJson;
             $irJSON .= "}";
             // Inject the custom linakge schema in the dataset description.
             if (($pos = stripos($irJSON, '"dataset"')) !== FALSE) {
                 $irJSONLinkageSchema = "";
                 if (count($this->customLinkageSchema->prefixes) > 0 || count($this->customLinkageSchema->predicateX) > 0 || count($this->customLinkageSchema->typeX) > 0) {
                     $irJSONLinkageSchema .= $this->customLinkageSchema->generateJsonSerialization() . ",";
                 }
                 foreach ($linkageSchemaLinks as $lsl) {
                     $irJSONLinkageSchema .= "\"{$lsl}\",";
                 }
                 if ($irJSONLinkageSchema != "") {
                     $posStart = strpos($irJSON, "{", $pos);
                     $endIrJsonFile = substr($irJSON, $posStart + 1, strlen($irJSON) - $posStart);
                     $irJSON = substr($irJSON, 0, $posStart + 1) . "\n        \"linkage\": [\n";
                     $irJSON .= $irJSONLinkageSchema;
                     $irJSON = rtrim($irJSON, ",");
                     $irJSON .= "],\n";
                     $irJSON .= $endIrJsonFile;
                 }
             }
             /*
             if(($pos = stripos($irJSON, '"linkage"')) !== FALSE)
             {
               $posStart = strpos($irJSON, "[", $pos);
               $irJSON = substr($irJSON, 0, $posStart + 1).$this->customLinkageSchema->generateJsonSerialization().",\n".substr($irJSON, $posStart + 1, strlen($irJSON) - $posStart);
             }
             else
             {
               // no linakgeSchema property found. Lets create one.
               if(($pos = stripos($irJSON, "dataset")) !== FALSE)
               {
                 $posStart = strpos($irJSON, "{", $pos);
                 $irJSON = substr($irJSON, 0, $posStart + 1)."\n        \"linkage\": [\n".$this->customLinkageSchema->generateJsonSerialization()."        ],\n".substr($irJSON, $posStart + 1, strlen($irJSON) - $posStart);
               }
             }
             */
             return $this->jsonRemoveTrailingCommas($irJSON);
             break;
         case "text/tsv":
         case "text/csv":
             $tsv = "";
             $xml = new ProcessorXML();
             $xml->loadXML($this->pipeline_getResultset());
             $subjects = $xml->getSubjects();
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectType = $xml->getType($subject, FALSE);
                 if ($subjectType != "http://rdfs.org/ns/void#Dataset" || $this->include_dataset_description == "true") {
                     $tsv .= str_replace($this->delimiter, urlencode($this->delimiter), $subjectURI) . $this->delimiter . "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" . $this->delimiter . str_replace($this->delimiter, urlencode($this->delimiter), $subjectType) . "\n";
                     $predicates = $xml->getPredicates($subject);
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         foreach ($objects as $object) {
                             $objectType = $xml->getType($object);
                             $predicateType = $xml->getType($predicate, FALSE);
                             $objectContent = $xml->getContent($object);
                             if ($xml->getURI($object) == "") {
                                 $objectValue = $xml->getContent($object);
                                 $tsv .= str_replace($this->delimiter, urlencode($this->delimiter), $subjectURI) . $this->delimiter . str_replace($this->delimiter, urlencode($this->delimiter), $predicateType) . $this->delimiter . str_replace($this->delimiter, urlencode($this->delimiter), $objectValue) . "\n";
                             } else {
                                 $objectURI = $xml->getURI($object);
                                 $tsv .= str_replace($this->delimiter, urlencode($this->delimiter), $subjectURI) . $this->delimiter . str_replace($this->delimiter, urlencode($this->delimiter), $predicateType) . $this->delimiter . str_replace($this->delimiter, urlencode($this->delimiter), $objectURI) . "\n";
                             }
                         }
                     }
                 }
             }
             return $tsv;
             break;
         case "application/rdf+n3":
             $xml = new ProcessorXML();
             $xml->loadXML($this->pipeline_getResultset());
             $subjects = $xml->getSubjects();
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectType = $xml->getType($subject, FALSE);
                 if ($subjectType != "http://rdfs.org/ns/void#Dataset" || $this->include_dataset_description == "true") {
                     $rdf_part .= "\n    <{$subjectURI}> a <{$subjectType}> ;\n";
                     $predicates = $xml->getPredicates($subject);
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         foreach ($objects as $object) {
                             $objectType = $xml->getType($object);
                             $predicateType = $xml->getType($predicate, FALSE);
                             $objectContent = $xml->getContent($object);
                             if ($xml->getURI($object) == "") {
                                 $objectValue = $xml->getContent($object);
                                 $rdf_part .= "        <{$predicateType}> \"\"\"" . str_replace(array("\\"), "\\\\", $objectValue) . "\"\"\" ;\n";
                             } else {
                                 $objectURI = $xml->getURI($object);
                                 $rdf_part .= "        <{$predicateType}> <{$objectURI}> ;\n";
                             }
                         }
                     }
                     if (strlen($rdf_part) > 0) {
                         $rdf_part = substr($rdf_part, 0, strlen($rdf_part) - 2) . ".\n";
                     }
                 }
             }
             return $rdf_part;
             break;
         case "application/rdf+xml":
             $xml = new ProcessorXML();
             $xml->loadXML($this->pipeline_getResultset());
             $subjects = $xml->getSubjects();
             $this->namespaces = array("http://www.w3.org/2002/07/owl#" => "owl", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" => "rdf", "http://www.w3.org/2000/01/rdf-schema#" => "rdfs", "http://purl.org/ontology/iron#" => "iron");
             $nsId = 0;
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectType = $xml->getType($subject, FALSE);
                 if ($subjectType != "http://rdfs.org/ns/void#Dataset" || $this->include_dataset_description == "true") {
                     $ns = $this->getNamespace($subjectType);
                     $stNs = $ns[0];
                     $stExtension = $ns[1];
                     if (!isset($this->namespaces[$stNs])) {
                         // Make sure the ID is not already existing. Increase the counter if it is the case.
                         while (array_search("ns" . $nsId, $this->namespaces) !== FALSE) {
                             $nsId++;
                         }
                         $this->namespaces[$stNs] = "ns" . $nsId;
                         $nsId++;
                     }
                     $rdf_part .= "\n    <" . $this->namespaces[$stNs] . ":" . $stExtension . " rdf:about=\"" . $this->xmlEncode($subjectURI) . "\">\n";
                     $predicates = $xml->getPredicates($subject);
                     foreach ($predicates as $predicate) {
                         $objects = $xml->getObjects($predicate);
                         foreach ($objects as $object) {
                             $objectType = $xml->getType($object);
                             $predicateType = $xml->getType($predicate, FALSE);
                             if ($xml->getURI($object) == "") {
                                 $objectValue = $xml->getContent($object);
                                 $ns = $this->getNamespace($predicateType);
                                 $ptNs = $ns[0];
                                 $ptExtension = $ns[1];
                                 if (!isset($this->namespaces[$ptNs])) {
                                     // Make sure the ID is not already existing. Increase the counter if it is the case.
                                     while (array_search("ns" . $nsId, $this->namespaces) !== FALSE) {
                                         $nsId++;
                                     }
                                     $this->namespaces[$ptNs] = "ns" . $nsId;
                                     $nsId++;
                                 }
                                 $rdf_part .= "        <" . $this->namespaces[$ptNs] . ":" . $ptExtension . ">" . $this->xmlEncode($objectValue) . "</" . $this->namespaces[$ptNs] . ":" . $ptExtension . ">\n";
                             } else {
                                 $objectURI = $xml->getURI($object);
                                 $ns = $this->getNamespace($predicateType);
                                 $ptNs = $ns[0];
                                 $ptExtension = $ns[1];
                                 if (!isset($this->namespaces[$ptNs])) {
                                     // Make sure the ID is not already existing. Increase the counter if it is the case.
                                     while (array_search("ns" . $nsId, $this->namespaces) !== FALSE) {
                                         $nsId++;
                                     }
                                     $this->namespaces[$ptNs] = "ns" . $nsId;
                                     $nsId++;
                                 }
                                 $rdf_part .= "        <" . $this->namespaces[$ptNs] . ":" . $ptExtension . " rdf:resource=\"" . $this->xmlEncode($objectURI) . "\" />\n";
                             }
                         }
                     }
                     $rdf_part .= "    </" . $this->namespaces[$stNs] . ":" . $stExtension . ">\n";
                 }
             }
             return $rdf_part;
             break;
     }
 }
Пример #2
0
 /** Validate a query to this web service
 
       @return TRUE if valid; FALSE otherwise
     
       @note This function is not used by the authentication validator web service
     
       @author Frederick Giasson, Structured Dynamics LLC.
   */
 public function validateQuery()
 {
     if (array_search($this->lang, $this->supportedLanguages) === FALSE && $this->lang != "") {
         $this->conneg->setStatus(400);
         $this->conneg->setStatusMsg("Bad Request");
         $this->conneg->setStatusMsgExt($this->errorMessenger->_308->name);
         $this->conneg->setError($this->errorMessenger->_308->id, $this->errorMessenger->ws, $this->errorMessenger->_308->name, $this->errorMessenger->_308->description, "", $this->errorMessenger->_308->level);
         return;
     }
     /*
      Check if dataset(s) URI(s) have been defined for this request. If not, then we query the
      AuthLister web service endpoint to get the list of datasets accessible by this user to see
      if the URI he wants to read is defined in one of these accessible dataset. 
     */
     if ($this->globalDataset === TRUE) {
         $ws_al = new AuthLister("access_user", "", $this->registered_ip, $this->wsf_local_ip, "none");
         $ws_al->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
         $ws_al->process();
         $xml = new ProcessorXML();
         $xml->loadXML($ws_al->pipeline_getResultset());
         $accesses = $xml->getSubjectsByType("wsf:Access");
         $accessibleDatasets = array();
         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") {
                 $this->dataset .= "{$datasetUri};";
                 array_push($accessibleDatasets, $datasetUri);
             }
         }
         if (count($accessibleDatasets) <= 0) {
             $this->conneg->setStatus(400);
             $this->conneg->setStatusMsg("Bad Request");
             $this->conneg->setStatusMsgExt($this->errorMessenger->_202->name);
             $this->conneg->setError($this->errorMessenger->_202->id, $this->errorMessenger->ws, $this->errorMessenger->_202->name, $this->errorMessenger->_202->description, "", $this->errorMessenger->_202->level);
             return;
         }
         unset($ws_al);
         $this->dataset = rtrim($this->dataset, ";");
     } else {
         $datasets = explode(";", $this->dataset);
         $datasets = array_unique($datasets);
         // Validate for each requested records of each dataset
         foreach ($datasets as $dataset) {
             // Validation of the "requester_ip" to make sure the system that is sending the query as the rights.
             $ws_av = new AuthValidator($this->requester_ip, $dataset, $this->uri);
             $ws_av->pipeline_conneg("text/xml", $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
             $ws_av->process();
             if ($ws_av->pipeline_getResponseHeaderStatus() != 200) {
                 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus());
                 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg());
                 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt());
                 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level);
                 return;
             }
             unset($ws_av);
             // Validation of the "registered_ip" to make sure the user of this system has the rights
             $ws_av = new AuthValidator($this->registered_ip, $dataset, $this->uri);
             $ws_av->pipeline_conneg("text/xml", $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
             $ws_av->process();
             if ($ws_av->pipeline_getResponseHeaderStatus() != 200) {
                 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus());
                 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg());
                 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt());
                 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level);
                 return;
             }
         }
     }
 }
 /** Serialize the converted UCB Memorial Data content into different serialization formats
 
       @return returns the serialized content
     
       @author Frederick Giasson, Structured Dynamics LLC.
   */
 public function pipeline_serialize()
 {
     $rdf_part = "";
     switch ($this->conneg->getMime()) {
         case "text/xml":
             return $this->pipeline_getResultset();
             break;
         case "application/rdf+n3":
             $dataset = $this->parser->getDataset();
             $datasetID = "";
             if (isset($dataset["&id"][0]["value"])) {
                 $datasetID = $dataset["&id"][0]["value"];
             }
             return $this->parser->getRdfN3($datasetID, $datasetID);
             break;
         case "application/iron+csv":
             $commON = "";
             $xml = new ProcessorXML();
             $xml->loadXML($this->pipeline_getResultset());
             $subjects = $xml->getSubjects();
             $commON .= "&&recordList\n";
             $prefixes = array();
             // Get the complete list of all the attributes used in this resultset.
             $attributes = array();
             foreach ($subjects as $subject) {
                 $predicates = $xml->getPredicates($subject);
                 foreach ($predicates as $predicate) {
                     $attributeURI = $xml->getType($predicate, FALSE);
                     if (!isset($attributes[$attributeURI])) {
                         $prefix = "";
                         $baseUri = "";
                         if (($pos = strripos($attributeURI, "#")) !== FALSE) {
                             $baseUri = substr($attributeURI, 0, $pos + 1);
                             if (isset($prefixes[$baseUri])) {
                                 $prefix = $prefixes[$baseUri];
                             } else {
                                 $prefix = "ns" . count($prefixes);
                             }
                         } elseif (($pos = strripos($attributeURI, "/")) !== FALSE) {
                             $baseUri = substr($attributeURI, 0, $pos + 1);
                             if (isset($prefixes[$baseUri])) {
                                 $prefix = $prefixes[$baseUri];
                             } else {
                                 $prefix = "ns" . count($prefixes);
                             }
                         }
                         if ($prefix != "" && $baseUri != "") {
                             $prefixes[$baseUri] = $prefix;
                             $attributes[$attributeURI] = str_replace($baseUri, $prefix . "_", $attributeURI);
                         } else {
                             $attributes[$attributeURI] = $attributeUri;
                         }
                     }
                 }
             }
             // Get the complete list of all the types used in this resultset.
             $types = array();
             foreach ($subjects as $subject) {
                 $typeURI = $xml->getType($subject, FALSE);
                 if ($typeURI == "http://rdfs.org/ns/void#Dataset") {
                     continue;
                 }
                 if (!isset($types[$typeURI])) {
                     $prefix = "";
                     $baseUri = "";
                     if (($pos = strripos($typeURI, "#")) !== FALSE) {
                         $baseUri = substr($typeURI, 0, $pos + 1);
                         if (isset($prefixes[$baseUri])) {
                             $prefix = $prefixes[$baseUri];
                         } else {
                             $prefix = "ns" . count($prefixes);
                         }
                     } elseif (($pos = strripos($typeURI, "/")) !== FALSE) {
                         $baseUri = substr($typeURI, 0, $pos + 1);
                         if (isset($prefixes[$baseUri])) {
                             $prefix = $prefixes[$baseUri];
                         } else {
                             $prefix = "ns" . count($prefixes);
                         }
                     }
                     if ($prefix != "" && $baseUri != "") {
                         $prefixes[$baseUri] = $prefix;
                         $types[$typeURI] = str_replace($baseUri, $prefix . "_", $typeURI);
                     } else {
                         $types[$typeURI] = $typeURI;
                     }
                 }
             }
             // Now create the complete list of attributes of this resultset
             $commON .= "&id,&type,";
             foreach ($attributes as $attributeURI => $attributePrefixed) {
                 $commON .= "&" . str_replace(':', '_', $attributePrefixed) . ",";
             }
             $commON = trim($commON, ",") . "\n";
             // Now populate the commON file with all the records
             foreach ($subjects as $subject) {
                 $subjectURI = $xml->getURI($subject);
                 $subjectTypeURI = $xml->getType($subject, FALSE);
                 if ($subjectTypeURI == "http://rdfs.org/ns/void#Dataset") {
                     continue;
                 }
                 $commON .= $subjectURI . ",";
                 if (($pos = strripos($subjectTypeURI, "#")) !== FALSE) {
                     $baseUri = substr($subjectTypeURI, 0, $pos + 1);
                 } elseif (($pos = strripos($subjectTypeURI, "/")) !== FALSE) {
                     $baseUri = substr($subjectTypeURI, 0, $pos + 1);
                 }
                 $commON .= str_replace(":", "_", str_replace($baseUri, $prefixes[$baseUri] . ":", $subjectTypeURI)) . ",";
                 foreach ($attributes as $attributeURI => $attributePrefix) {
                     $values = $xml->getPredicatesByType($subject, $attributeURI);
                     if ($values->length > 0) {
                         $commON .= '"';
                         foreach ($values as $element) {
                             $objects = $xml->getObjects($element);
                             foreach ($objects as $object) {
                                 if ($xml->getURI($object) == "") {
                                     $objectValue = $xml->getContent($object);
                                     $commON .= $this->escapeCSV($objectValue) . '||';
                                 } else {
                                     $objectURI = $xml->getURI($object);
                                     $prefix = "";
                                     $baseUri = "";
                                     if (($pos = strripos($objectURI, "#")) !== FALSE) {
                                         $baseUri = substr($objectURI, 0, $pos + 1);
                                         if (isset($prefixes[$baseUri])) {
                                             $prefix = $prefixes[$baseUri];
                                         } else {
                                             $prefix = "ns" . count($prefixes);
                                         }
                                     } elseif (($pos = strripos($objectURI, "/")) !== FALSE) {
                                         $baseUri = substr($objectURI, 0, $pos + 1);
                                         if (isset($prefixes[$baseUri])) {
                                             $prefix = $prefixes[$baseUri];
                                         } else {
                                             $prefix = "ns" . count($prefixes);
                                         }
                                     }
                                     if ($prefix != "" && $baseUri != "") {
                                         $prefixes[$baseUri] = $prefix;
                                         $commON .= $this->escapeCSV("@@" . str_replace($baseUri, $prefix . ":", $objectURI)) . '||';
                                     } else {
                                         $commON .= $this->escapeCSV("@@" . $objectURI) . '||';
                                     }
                                 }
                             }
                         }
                         $commON = substr($commON, 0, strlen($commON) - 2);
                         $commON .= '",';
                     } else {
                         $commON .= ",";
                     }
                 }
                 $commON = trim($commON, ",") . "\n";
             }
             $commON .= "\n";
             $commON .= "&&linkage\n";
             $commON .= "&version,&linkageType\n";
             $commON .= "1,application/rdf+xml\n";
             $commON .= "\n";
             $commON .= "&prefixList,&mapTo\n";
             foreach ($prefixes as $baseUri => $prefix) {
                 $commON .= $prefix . "," . $baseUri . "\n";
             }
             $commON .= "\n";
             $commON .= "&attributeList,&mapTo\n";
             foreach ($attributes as $uri => $attr) {
                 $commON .= $attr . "," . $uri . "\n";
             }
             $commON .= "\n";
             $commON .= "&typeList,&mapTo\n";
             foreach ($types as $uri => $type) {
                 $commON .= $type . "," . $uri . "\n";
             }
             return $commON;
     }
 }
 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);
         }
     }
 }