Karima Rafes has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/178065

Change subject: Fix hyperlink for HTML and update lib
......................................................................

Fix hyperlink for HTML and update lib

Change-Id: I8d2f198d9a2e0ad436f3d005f925750a1ee422b0
---
M LinkedWiki.php
A lib/SPARQL/ConversionMimetype.php
M lib/SPARQL/Curl.php
M lib/SPARQL/Endpoint.php
M lib/SPARQL/ParserCSV.php
M lib/SPARQL/ParserSparqlResult.php
M lib/SPARQL/ParserTurtle.php
M lib/SPARQL/README.md
A lib/SPARQL/ToolsBlankNode.php
A lib/SPARQL/ToolsConvert.php
M lib/SPARQL/composer.json
M lib/SPARQL/query
M test/sparqlbasic.feature
M test/table2CSV.feature
M test/tests.sh
15 files changed, 1,111 insertions(+), 185 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/LinkedWiki 
refs/changes/65/178065/1

diff --git a/LinkedWiki.php b/LinkedWiki.php
index 456bab6..cd44a47 100644
--- a/LinkedWiki.php
+++ b/LinkedWiki.php
@@ -563,7 +563,7 @@
                      $str .= "<td>";
 
                        if($row[$variable." type"] == "uri" ){
-                               $str .=  
efSparqlParserFunction_uri2Link($row[$variable]) ;
+                               $str .= "<a 
href='".$row[$variable]."'>".$row[$variable]."</a>" ;
                        }else{
                                $str .= $row[$variable] ;
                        }
diff --git a/lib/SPARQL/ConversionMimetype.php 
b/lib/SPARQL/ConversionMimetype.php
new file mode 100644
index 0000000..84ec1d2
--- /dev/null
+++ b/lib/SPARQL/ConversionMimetype.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @git g...@github.com:BorderCloud/SPARQL.git
+ * @author Karima Rafes <karima.ra...@bordercloud.com>
+ * @license http://creativecommons.org/licenses/by-sa/4.0/
+*/
+
+class ConversionMimetype {
+
+    private static $_mimetypeToShortname;
+    private static $_filenameExtensionToMimetype;
+    
+    private static function init()
+    {
+       $_mimetypeToShortname = array();
+       $_filenameExtensionToMimetype = array();
+       self::add('rdf','rdf', 'application/rdf+xml');
+       self::add('nt','text', 'text/plain');
+       self::add('csv','csv', 'text/csv; charset=utf-8');
+       self::add('','csv', 'text/csv');
+       self::add('tsv','tsv', 'text/tab-separated-values; charset=utf-8');
+       self::add('','tsv', 'text/tab-separated-values');
+       self::add('ttl','ttl', 'text/turtle');
+       self::add('srx','xml', 'application/sparql-results+xml');
+       self::add('srj','json', 'application/sparql-results+json');
+    }
+
+    private static function add($extension, $shortname, $mimetype)
+    {
+        self::$_mimetypeToShortname[$mimetype] = $shortname;
+        
+        if(!EMPTY($extension))
+         self::$_filenameExtensionToMimetype[$extension] = $mimetype;
+    }
+
+    public static function getMimetypeOfFilenameExtensions($extension)
+    {
+       if (self::$_filenameExtensionToMimetype == null)
+         self::init();
+         
+       if (array_key_exists($extension, self::$_filenameExtensionToMimetype)) {
+         return self::$_filenameExtensionToMimetype[$extension];
+       }else{
+         return NULL;
+       }
+    }
+
+    public static function getShortnameOfMimetype($mimetype)
+    {
+       if (self::$_mimetypeToShortname == null)
+         self::init();
+         
+       if (array_key_exists($mimetype, self::$_mimetypeToShortname)) {
+         return self::$_mimetypeToShortname[$mimetype];
+       }else{
+         return NULL;
+       }
+    }
+}
\ No newline at end of file
diff --git a/lib/SPARQL/Curl.php b/lib/SPARQL/Curl.php
index bca705d..9c50cd4 100644
--- a/lib/SPARQL/Curl.php
+++ b/lib/SPARQL/Curl.php
@@ -12,21 +12,21 @@
         * @access private
         * @var resource
         */
-       public $ch ;
+       var $ch ;
 
        /**
         * set debug to true in order to get usefull output
         * @access private
         * @var string
         */
-       public $debug = false;
+       var $debug = false;
 
        /**
         * Contain last error message if error occured
         * @access private
         * @var string
         */
-       public $error_msg;
+       var $error_msg;
        
        /**
         * Curl_HTTP_Client constructor
@@ -63,7 +63,12 @@
         */
        function set_credentials($username,$password)
        {
-               curl_setopt($this->ch, CURLOPT_USERPWD, "$username:$password");
+
+               curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
+               curl_setopt($this->ch, CURLOPT_USERPWD, 
$username.":".$password);
+               curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+               curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false);
+               curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
        }
 
        /**
@@ -117,7 +122,7 @@
         * @return string data
         * @access public
     */
-       function send_post_data($url, $postdata, $arrayHeader=null, $ip=null, 
$timeout=10)
+       function send_post_data($url, $postdata, $arrayHeader=null, $ip=null, 
$timeout=600)
        {
                //set various curl options first
                if($this->debug)
diff --git a/lib/SPARQL/Endpoint.php b/lib/SPARQL/Endpoint.php
index b4f5aac..8d4b5bb 100644
--- a/lib/SPARQL/Endpoint.php
+++ b/lib/SPARQL/Endpoint.php
@@ -7,7 +7,10 @@
 require_once("Curl.php");
 require_once("Net.php");
 require_once("Base.php");
+require_once("ToolsConvert.php");
+require_once("ToolsBlankNode.php");
 require_once("ParserSparqlResult.php");
+//require_once("ConversionMimetype.php");
 
 /**
  * Sparql HTTP Client for SPARQL1.1's Endpoint
@@ -224,6 +227,10 @@
         */
        private $_nameParameterQueryWrite;
        
+
+       private $_login;
+       private $_password;
+       
        /** For Arc2 **/
 //     private $_arc2_RemoteStore;
 //     private $_arc2_Reader;
@@ -360,6 +367,42 @@
        public function getNameParameterQueryRead() {
                return $this->_nameparameterQueryRead;
        }
+
+       /**
+        * Set the server login
+        * @param string $login : server login
+        * @access public
+        */
+       public function setLogin($login) {
+               $this->_login = $login;
+       }
+       
+       /**
+        * Get the server login
+        * @return string $login : server login
+        * @access public
+        */
+       public function getLogin() {
+               return $this->_login;
+       }
+       
+       /**
+        * Set the server password
+        * @param string $password : server password
+        * @access public
+        */
+       public function setPassword($password) {
+               $this->_password = $password;
+       }
+       
+       /**
+        * Get the server login
+        * @return string $password : server password
+        * @access public
+        */
+       public function getPassword() {
+               return $this->_password;
+       }
        
        /**
         * Check if the server is up.
@@ -452,7 +495,9 @@
                        $response = $client->send_post_data($sUri,$data);
                }else{
                        $data = array($this->_nameParameterQueryRead =>   
$query,
+                       //"output" => 
ConversionMimetype::getShortnameOfMimetype($typeOutput), //possible fix for 
4store/fuseki..
                        "Accept" => $typeOutput); //fix for sesame
+                       //print_r($data);
                        $response = 
$client->send_post_data($sUri,$data,array('Accept: '.$typeOutput));
                }               
 
@@ -462,7 +507,7 @@
        
                if($code < 200 || $code >= 300)
                {
-                       $error = 
$this->errorLog($query,$data,$sUri,$code,$response);
+                       $error = 
$this->errorLog($query,$data,$sUri,$code,$response. $client->get_error_msg() );
                        $this->addError($error);
                        return false;
                }
@@ -490,6 +535,7 @@
                                $response = 
$client->send_post_data($sUri,$data);
                        }else{
                                $data = array($this->_nameParameterQueryWrite 
=>   $query,
+                               //"output" => 
ConversionMimetype::getShortnameOfMimetype($typeOutput), //possible fix for 
4store/fuseki...
                                "Accept" => $typeOutput); //fix for sesame
                                $response = 
$client->send_post_data($sUri,$data,array('Accept: '.$typeOutput));
                        }               
@@ -565,10 +611,13 @@
         * @access private
         */
        private function initCurl(){
-               $objCurl = new Curl();
+               $objCurl = new Curl();//$this->_debug
                if($this->_proxy_host != null && $this->_proxy_port != null){
                        
$objCurl->set_proxy($this->_proxy_host.":".$this->_proxy_port); 
                }
+               if($this->_login != null && $this->_password != null){
+                       
$objCurl->set_credentials($this->_login,$this->_password);
+               }
                return $objCurl;
        }
 }
diff --git a/lib/SPARQL/ParserCSV.php b/lib/SPARQL/ParserCSV.php
index 686923b..3409fca 100644
--- a/lib/SPARQL/ParserCSV.php
+++ b/lib/SPARQL/ParserCSV.php
@@ -7,7 +7,8 @@
 
 class ParserCSV {
 
-       function csv_to_array($csv, $delimiter = ',', $enclosure = '"', $escape 
= '\\', $terminator = "\n") { 
+       function csv_to_array($csv, $delimiter = ',', $enclosure = '\'', 
$escape = '\\', $terminator = "\n") { 
+       
                $r = array();
                //$string = utf8_encode($csv);
                //echo mb_detect_encoding($names);
@@ -19,13 +20,21 @@
                foreach ($rows as $row) { 
                        if (trim($row)) { 
                                $values 
=str_getcsv($row,$delimiter,$enclosure,$escape) ;  
+                               
                                if (!$values) $values = array_fill(0,$nc,null); 
                                
                                $tabTemp = array();                             
                                //array_combine($names,$values);
                                foreach($names as $key=>$nameCol){ 
                                        if(isset($values[$key])){
-                                               $tabTemp[$nameCol] = 
$values[$key]; 
+                                       
+                                           $value = $values[$key]; 
+                                           if 
(ToolsConvert::isTrueFloat($value)) {
+                                               $value = floatval($value);
+                                           } elseif (is_int($value)) {
+                                               $value = intval($value);
+                                           }
+                                           $tabTemp[$nameCol] = $value; 
                                        }else{                                  
        
                                                $tabTemp[$nameCol] = NULL; 
                                        }
@@ -76,4 +85,120 @@
                usort($result, 'ParserCSV::mySortAllColumn');
                return $result;
        }
+       
+      public static function compare($rs1,$rs2,$ordered=false,$distinct=false) 
{
+       $difference=array();
+       //A/ Check the variables lists in the header are the same.
+       if(count($rs1) ==0 && count($rs2) ==0){
+           return $difference; //return true ;
+       }elseif (count($rs1[0]) != count($rs2[0])) {
+            $difference[1]="Nb columns :".count($rows1);
+            $difference[2]="Nb columns :".count($rows2);
+            return $difference; //return false ;
+        }
+
+
+      //Check if there are blanknodes//////////////////////
+       //ref : http://blog.datagraph.org/2010/03/rdf-isomorphism
+       
+  // 1.Compare graph sizes and all statements without blank nodes. If they do 
not match, fail.
+  //1.1 remove blank nodes      
+      $clone1WithoutBlanknodes = NULL;
+      $clone2WithoutBlanknodes = NULL;
+      if($distinct){
+       $clone1WithoutBlanknodes = $rs1;
+        $clone2WithoutBlanknodes = $rs2;
+      }else{
+       $clone1WithoutBlanknodes = ToolsBlankNode::removeDuplicate($rs1);
+       $clone2WithoutBlanknodes = ToolsBlankNode::removeDuplicate($rs2);
+      } 
+     
+      $bnodesInRs1=array();
+      $bnodesInRs2=array();
+      $patternBlankNode = '/^_:/';
+
+      // echo "AVANT";
+         //  print_r($clone1);
+         //  print_r($clone2);
+       foreach ($clone1WithoutBlanknodes as &$row) {
+         foreach ($row as $key=>&$value) {
+             if (preg_match($patternBlankNode, $value)) {
+                 $bnodesInRs1[] = $value ;
+                 $value = "BLANKNODE";//remove
+             }
+           }
+       }
+       foreach ($clone2WithoutBlanknodes as &$row) {
+         foreach ($row as $key=>&$value) {
+             if (preg_match($patternBlankNode, $value)) {
+                 $bnodesInRs2[] = $value ;
+                 $value = "BLANKNODE";//remove
+             }
+           }
+       }
+
+          // print_r($clone1WithoutBlanknodes);
+           //print_r($clone2WithoutBlanknodes);
+           //exit();
+        //1.2 compare
+       if($ordered){
+               $difference =  ToolsBlankNode::array_diff_assoc_recursive( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes);
+       }else{
+               $difference =  ToolsBlankNode::array_diff_assoc_unordered( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes) ;
+       }
+
+      //Check if there are blank nodes
+       if((count($bnodesInRs1) == 0 && count($bnodesInRs2) == 0 )  || 
count($difference) != 0)
+           return $difference;
+
+      //With blank nodes
+         $bnodesInRs1=array_values(array_unique($bnodesInRs1));
+         $bnodesInRs2=array_values(array_unique($bnodesInRs2));
+         if(count($bnodesInRs1) != count($bnodesInRs2)) {
+             $difference[1]="Nb bnode :".count($bnodesInRs1);
+             $difference[2]="Nb bnode :".count($bnodesInRs2);
+             return $difference; //return false ;
+         }
+
+//       echo "BLANKNODE\n";     
+//       print_r($bnodesInRs1);
+//       print_r($bnodesInRs2);
+         
+       $clone1 = $rs1;
+//         print_r($clone1);
+       
+       // 2.Repeat, for each graph:
+       $arrayPermutationsBnode = ToolsBlankNode::AllPermutations($bnodesInRs2);
+         //echo "PERMUTATION\n";
+         //print_r($arrayPermutationsBnode );      
+         //exit();
+         foreach ( $arrayPermutationsBnode as $permute) {
+//               print_r($permute);
+           $clone2 = $rs2;
+           foreach ( $clone2 as $key=>&$row) {
+             $arrayVariableTypeBnode = array_keys( $row , "bnode") ;
+             foreach ($arrayVariableTypeBnode as $variableTypeBnode) {
+                   $variableArray = split(" ",$variableTypeBnode);
+                   $variable=$variableArray[0];
+
+                   $row[$variable] = $bnodesInRs1[array_search($row[$variable] 
,$permute)];
+               }
+           }
+
+//           print_r($clone2);
+          
+           if($ordered){
+                   $difference =  ToolsBlankNode::array_diff_assoc_recursive( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes);
+           }else{
+                   $difference =  ToolsBlankNode::array_diff_assoc_unordered( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes) ;
+           }
+           if(count($difference) == 0){
+                 return $difference; //true
+           }
+       }
+
+       return $difference;
+    }
+
+
 } 
diff --git a/lib/SPARQL/ParserSparqlResult.php 
b/lib/SPARQL/ParserSparqlResult.php
index f03702d..1247797 100644
--- a/lib/SPARQL/ParserSparqlResult.php
+++ b/lib/SPARQL/ParserSparqlResult.php
@@ -63,86 +63,258 @@
    //callback for the end of each element
    function endElement($parser_object, $elementname) {
        if($elementname == "binding"){
-                       
if(!isset($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 type"]))
-                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
type"]=NULL;
-                               
-                       
if($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
type"] == "uri"){
-                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
trim($this->_value);
-                       
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 type"] == "literal"){
-                               $value = trim($this->_value);
-                               if(array_key_exists($this->_cellCurrent." 
datatype",$this->_result['result']['rows'][$this->_rowCurrent])){
-                                       
if($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
datatype"] == "http://www.w3.org/2001/XMLSchema#double"; ||
-                                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
datatype"] == "http://www.w3.org/2001/XMLSchema#decimal"; 
-                                               ){
-                                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
floatval($value);
-                                       
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 datatype"] == "http://www.w3.org/2001/XMLSchema#integer";
-                                               ){
-                                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
intval($value);
-                                       
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 datatype"] == "http://www.w3.org/2001/XMLSchema#boolean";
-                                               ){
-                                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$value === "true" ? true : false;
-                                       }else{                                  
        
-                                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$value;
-                                       }
-                               }else{
+       
+               if(strlen(trim($this->_value)) == 0)
+                   return;
+               
+               
if(!isset($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 type"]))
+                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
type"]=NULL;
+                       
+               
if($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
type"] == "uri"){
+                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
trim($this->_value);
+               
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 type"] == "bnode"){
+                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
trim($this->_value);
+               
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 type"] == "literal"){
+                       $value = trim($this->_value);
+                       if(array_key_exists($this->_cellCurrent." 
datatype",$this->_result['result']['rows'][$this->_rowCurrent])){
+                               
if($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
datatype"] == "http://www.w3.org/2001/XMLSchema#double"; ||
+                                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent." 
datatype"] == "http://www.w3.org/2001/XMLSchema#decimal"; 
+                                       ){
+                                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
floatval($value);
+                               
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 datatype"] == "http://www.w3.org/2001/XMLSchema#integer";
+                                       ){
+                                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
intval($value);
+                               
}elseif($this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent."
 datatype"] == "http://www.w3.org/2001/XMLSchema#boolean";
+                                       ){
+                                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$value === "true" ? true : false;
+                               }else{                                          
                                        
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$value;
                                }
                        }else{
-                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$this->_value;
+                               
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$value;
                        }
-                       $this->_cellCurrent = null;
-                       $this->_value = "";
-               }
-   }
-
-   //callback for the content within an element
-   function contentHandler($parser_object,$data)
-   {
-               if($this->_cellCurrent != null){
-                  //   echo "DATA". $data." - ".$this->_cellCurrent."\n";
-                       $this->_value .= $data;
-               }
-   }
-   
-       function sortResult($array){
-               $result = $array;                               
-               if(isset($result['result']['rows']))
-                       usort($result['result']['rows'], 
'ParserSparqlResult::mySortResult');
-               return $result;         
-       }
-       
-       function mySortResult($row1, $row2){    
-               $result = 0;
-               $countTab = 0;
-               if( count($row1) > count($row2)){
-                       $countTab = count($row1);
                }else{
-                       $countTab = count($row2);
+                       
$this->_result['result']['rows'][$this->_rowCurrent][$this->_cellCurrent] = 
$this->_value;
                }
-               
-               for($i=0; $i < $countTab; $i++){
-                       if((!isset($row1[$i])) || (!isset($row2[$i]))){
-                               if(isset($row1[$i]) && 
isset($row2[$i])){//impossible in theory
-                                       $result =  0;
-                                       break;
-                               }elseif(!isset($row1[$i])){
-                                       $result =  -1;
-                                       break;
-                               }elseif(!isset($row2[$i])){
-                                       $result =  1;
-                                       break;
-                               }
-                       }
-                       else if($row1[$i] < $row2[$i]){
-                               $result =  1;
-                               break;
-                       }
-                       else if($row1[$i] < $row2[$i]){
-                               $result =  -1;
-                               break;
-                       }
-               }
-               return $result;
+               $this->_cellCurrent = null;
+               $this->_value = "";
+         }
+    }
+
+    //callback for the content within an element
+    function contentHandler($parser_object,$data)
+    {
+                 if($this->_cellCurrent != null){
+                   //  echo "DATA". $data." - ".$this->_cellCurrent."\n";
+                         $this->_value .= $data;
+                 }
+    }
+   
+    function sortResult($array){
+           $result = $array;                           
+           if(isset($result['result']['rows']))
+                   usort($result['result']['rows'], 
'ParserSparqlResult::mySortResult');
+           return $result;             
+    }
+    
+    function mySortResult($row1, $row2){       
+           $result = 0;
+           $countTab = 0;
+           if( count($row1) > count($row2)){
+                   $countTab = count($row1);
+           }else{
+                   $countTab = count($row2);
+           }
+           
+           for($i=0; $i < $countTab; $i++){
+                   if((!isset($row1[$i])) || (!isset($row2[$i]))){
+                           if(isset($row1[$i]) && 
isset($row2[$i])){//impossible in theory
+                                   $result =  0;
+                                   break;
+                           }elseif(!isset($row1[$i])){
+                                   $result =  -1;
+                                   break;
+                           }elseif(!isset($row2[$i])){
+                                   $result =  1;
+                                   break;
+                           }
+                   }
+                   else if($row1[$i] < $row2[$i]){
+                           $result =  1;
+                           break;
+                   }
+                   else if($row1[$i] < $row2[$i]){
+                           $result =  -1;
+                           break;
+                   }
+           }
+           return $result;
+    }
+    
+    public static function compare($rs1,$rs2,$ordered=false,$distinct=false) {
+      $difference=array();
+      //A/ Check the variables lists in the header are the same.
+      if(! isset($rs1['result']['variables']) && ! 
isset($rs2['result']['variables'])){
+          return $difference; //return true ;
+      }elseif (! isset($rs1['result']['variables']) || ! 
isset($rs2['result']['variables']) ) {
+          $difference[1]=$rs1['result']['variables'];
+          $difference[2]=$rs2['result']['variables'];
+          return $difference; //return false ;
+      }
+
+     //Check if there are blanknodes//////////////////////
+      //ref : http://blog.datagraph.org/2010/03/rdf-isomorphism
+      
+// 1.Compare graph sizes and all statements without blank nodes. If they do 
not match, fail.
+//1.1 remove blank nodes
+      $clone1WithoutBlanknodes = NULL;
+      $clone2WithoutBlanknodes = NULL;
+      if($distinct){
+       $clone1WithoutBlanknodes = $rs1['result']['rows'];
+        $clone2WithoutBlanknodes = $rs2['result']['rows'];
+      }else{
+       $clone1WithoutBlanknodes = 
ToolsBlankNode::removeDuplicate($rs1['result']['rows']);
+       $clone2WithoutBlanknodes = 
ToolsBlankNode::removeDuplicate($rs2['result']['rows']);
+      } 
+     
+     $bnodesInRs1=array();
+     $bnodesInRs2=array();
+
+     // echo "AVANT";
+        //  print_r($clone1);
+        //  print_r($clone2);
+      foreach ($clone1WithoutBlanknodes as $key=>&$row) {
+         $arrayVariableTypeBnode = array_keys( $row , "bnode") ;
+         foreach ($arrayVariableTypeBnode as $variableTypeBnode) {
+                $variableArray = split(" ",$variableTypeBnode);
+                $variable=$variableArray[0];
+                $bnodesInRs1[] = $row[$variable] ;
+               $row[$variable] = "BLANKNODE";//remove
+          }
+      }
+      foreach ( $clone2WithoutBlanknodes as $key=>&$row) {
+         $arrayVariableTypeBnode = array_keys( $row , "bnode") ;
+         foreach ($arrayVariableTypeBnode as $variableTypeBnode) {
+                $variableArray = split(" ",$variableTypeBnode);
+                $variable=$variableArray[0];
+               $bnodesInRs2[] = $row[$variable] ;
+               $row[$variable] = "BLANKNODE";//remove
+          }
+      }
+
+          //print_r($clone1WithoutBlanknodes);
+          //print_r($clone2WithoutBlanknodes);
+//1.2 compare
+       if($ordered){
+               $difference =  ToolsBlankNode::array_diff_assoc_recursive( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes);
+       }else{
+               $difference =  ToolsBlankNode::array_diff_assoc_unordered( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes) ;
        }
-       
-}
\ No newline at end of file
+
+      //Check if there are blank nodes
+      if((count($bnodesInRs1) == 0 && count($bnodesInRs2) == 0 )  || 
count($difference) != 0)
+          return $difference;
+
+      //With blank nodes
+        $bnodesInRs1=array_values(array_unique($bnodesInRs1));
+        $bnodesInRs2=array_values(array_unique($bnodesInRs2));
+        if(count($bnodesInRs1) != count($bnodesInRs2)) {
+            $difference[1]="Nb bnode :".count($bnodesInRs1);
+            $difference[2]="Nb bnode :".count($bnodesInRs2);
+            return $difference; //return false ;
+        }
+
+//     echo "BLANKNODE\n";     
+//     print_r($bnodesInRs1);
+//     print_r($bnodesInRs2);
+       $clone1 = $rs1['result']['rows'];
+       //    print_r($clone1);
+       //$clone2 = $rs2['result']['rows'];
+       // 2.Repeat, for each graph:
+       $arrayPermutationsBnode = ToolsBlankNode::AllPermutations($bnodesInRs2);
+       //echo "PERMUTATION\n";
+       //print_r($arrayPermutationsBnode );      
+       // exit();
+       foreach ( $arrayPermutationsBnode as $permute) {
+           $clone2 = $rs2['result']['rows'];
+
+         //print_r($clone2);
+         foreach ( $clone2 as $key=>&$row) {
+           $arrayVariableTypeBnode = array_keys( $row , "bnode") ;
+           foreach ($arrayVariableTypeBnode as $variableTypeBnode) {
+                 $variableArray = split(" ",$variableTypeBnode);
+                 $variable=$variableArray[0];
+
+                 $row[$variable] = $bnodesInRs1[array_search($row[$variable] 
,$permute)];
+             }
+         }
+           //print_r($clone2);
+           //$difference =  self::sub_array_diff_assoc_unordered( 
$clone1,$clone2) ;          
+         if($ordered){
+                 $difference =  
ToolsBlankNode::array_diff_assoc_recursive($clone1,$clone2);
+         }else{
+                 $difference =  
ToolsBlankNode::array_diff_assoc_unordered($clone1,$clone2) ;
+         }
+         
+         if(count($difference) == 0){
+               return $difference; //true
+         }
+       }
+
+      return $difference;
+  }
+/*
+    private static function sub_array_diff_assoc_unordered( $rows1,  $rows2) {
+        $difference=array();
+
+        //B/ Check the result set have the same number of rows.
+        if(count($rows1) != count($rows2)) {
+            $difference[1]="Nb rows :".count($rows1);
+            $difference[2]="Nb rows :".count($rows2);
+            return $difference; //return false ;
+        }
+
+        //C/ Pick a row from the test results, scan the expected results
+        //   to find a row with same variable/value bindings, and remove
+        //   from the expected results. If all test rows, match then
+        //   (because of B) the result sets have the same rows.
+        //   
+        //return equivalent(convert(rs1), convert(rs2), new 
BNodeIso(NodeUtils.sameValue)) ;
+        $clone1 = $rows1;
+        $clone2 = $rows2;
+
+        // echo "AVANT";
+          //  print_r($clone1);
+          //  print_r($clone2);
+        foreach ($rows1 as $key1=>&$value1) {
+            $tmpclone2 = $clone2;
+              foreach ($tmpclone2 as $key2=>&$value2) {
+
+                //echo "-------------";
+                //print_r($value1);
+                //print_r($value2);
+                if(count(array_diff_assoc($value1,$value2)) == 0 &&
+                    count(array_diff_assoc($value2,$value1)) == 0 ){
+                      unset($clone1[$key1]);
+                      unset($clone2[$key2]);
+                      break;
+                }
+              }
+              //echo "-------------APRES";
+              //print_r($clone1);
+              //print_r($clone2);
+        }
+
+        if(count($clone1) != 0 ||
+            count($clone2) != 0 ){
+            $difference[1]=$clone1;
+            $difference[2]=$clone2;
+            $difference[1]=$clone1;
+            $difference[2]=$clone2;
+            return $difference; //return false ;
+        }
+        return $difference;
+      }
+      */
+}
+
diff --git a/lib/SPARQL/ParserTurtle.php b/lib/SPARQL/ParserTurtle.php
index d3c9a7c..e4623e6 100644
--- a/lib/SPARQL/ParserTurtle.php
+++ b/lib/SPARQL/ParserTurtle.php
@@ -7,13 +7,14 @@
 
 class ParserTurtle {
 
-       function turtle_to_array($turtle,$baseGraph){
+       static function turtle_to_array($turtle,$baseGraph,$idMD5 = false){
                $tabResult = array();
                $tabResult["prefix"] = array();
                $tabResult["prefix"]["base"] = $baseGraph;
                $tabResult["triples"] = array();
                
-               
preg_match_all("/((?:(?:\"|').*(?:\"|')(?:\^\^[^\s]*)?|a|<[^\s]*>|[^\s]*:[^\s]+|;|,|@prefix\s*[^\s]*\s*:\s*<[^\s<>]+>|\s*\r?\n?)+\s\.)/i",$turtle,
 $matches, PREG_SET_ORDER);
+               
preg_match_all("/((?:(?:\"|').*(?:\"|')(?:\^\^[^\s]*)?|a|<[^\s]*>|[^\s]*:[^\s]+|;|,|@prefix\s*[^\s]*\s*:\s*<[^\s<>]+>|\s*\r?\n?)+\s?\.)/i",$turtle,
 $matches, PREG_SET_ORDER);
+
                foreach ($matches as $val) {
                //// 
http://answers.semanticweb.com/questions/2025/what-is-the-meaning-of-base-and-prefix-in-turtle-documents
                   
@@ -23,44 +24,61 @@
                                $namePrefix = $valMatches[1] == "" ? "empty" : 
$valMatches[1];
                                $tabResult["prefix"][$namePrefix] = 
$valMatches[2];
                        
}elseif(preg_match("/^\s*(<[^\s]*>|[^\s]*:[^\s]+)\s*(.*)\s*\.$/is", $val[0], 
$valMatches)){
-                                                       $object = 
ParserTurtle::relativeToExplicitURI($valMatches[1],$tabResult["prefix"]) ;
-                                                       
-                                                       
preg_match_all("/\s*(a|<[^\s]*>|[^\s]*:[^\s]+)\s*((?:(?:<[^\s]*>|[^\s]*:[^\s]+|(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')(?:\^\^[^\s]*)?|\s*),?)+\s*);?/is",$valMatches[2],
 $propertyMatches, PREG_SET_ORDER);
-                                                       foreach 
($propertyMatches as $propertyVal) {
-                                                               $property ="";
-                                                               
if($propertyVal[1] == "a"){
-                                                                       
$property = "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"  ;
-                                                               }else{
-                                                                       
$property = 
ParserTurtle::relativeToExplicitURI($propertyVal[1],$tabResult["prefix"]) ;
-                                                               }
-                                                               
preg_match_all("/(<[^\s]*>|[^\s]*:[^\s]+|(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')(?:\^\^[^\s]*)?)\s*,?/is",$propertyVal[2],
 $valueMatches, PREG_SET_ORDER);
-
-                                                               foreach 
($valueMatches as $valueVal) {          
-                                                                       $value 
= ParserTurtle::relativeToExplicitURI($valueVal[1],$tabResult["prefix"]) ;
-                                                                       //echo 
"s=>".$object." p=>".$property." o=>".$value."\n";
-                                                                       
$tabResult["triples"][] = array("s"=>$object,"p"=>$property,"o"=>$value);
-                                                               }
-                                                       }
-                                               }
+                                $object = 
ParserTurtle::relativeToExplicitURI($valMatches[1],$tabResult["prefix"]) ;
+                                
preg_match_all("/\s*(a|<[^\s\,\;]*>|[^\s]*:[^\s\;]+)\s*((?:(?:<[^\s\,\;]*>|[^\s]*:[^\s\;]+|(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')(?:\^\^[^\s\;]*)?|\s*),?)+\s*);?/is",$valMatches[2],
 $propertyMatches, PREG_SET_ORDER);
+                                foreach ($propertyMatches as $propertyVal) {
+                                
+                                        $property ="";
+                                        if($propertyVal[1] == "a"){
+                                                $property = 
"<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>"  ;
+                                        }else{
+                                                $property = 
ParserTurtle::relativeToExplicitURI($propertyVal[1],$tabResult["prefix"]) ;
+                                        }
+                                        
preg_match_all("/(<[^\s\,\;]*>|[^\s]*:[^\s\,]+|(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')(?:\^\^[^\s\,]*)?)\s*,?/is",$propertyVal[2],
 $valueMatches, PREG_SET_ORDER);
+                                        foreach ($valueMatches as $valueVal) { 
        
+                                                $value = 
ParserTurtle::relativeToExplicitURI($valueVal[1],$tabResult["prefix"]) ;
+                                                //echo "s=>".$object." 
p=>".$property." o=>".$value."\n";
+                                                if($idMD5)
+                                                    
$tabResult["triples"][md5($object.$property.$value)] = 
array("s"=>$object,"p"=>$property,"o"=>$value);
+                                                else
+                                                    $tabResult["triples"][] = 
array("s"=>$object,"p"=>$property,"o"=>$value);
+                                        }
+                                }
+                        }
                }
                return $tabResult;
        }
        
-       function relativeToExplicitURI($uri,$prefix){
+       static function relativeToExplicitURI($uri,$prefix){            
                $result = $uri;
-               
                
if(preg_match("/^(\"(?:\\\"|[^\"])*\"|'(?:\\'|[^'])*')(?:\^\^([^\s]*))?$/i",$uri,
 $matches)){//<>
                        if(isset($matches[2])){
-                               $result = 
$matches[1]."^^".ParserTurtle::relativeToExplicitURI($matches[2],$prefix);
+                           $type = 
ParserTurtle::relativeToExplicitURI($matches[2],$prefix);
+                           $value = $matches[1];
+                               if($type == 
"http://www.w3.org/2001/XMLSchema#double"; || 
+                                  $type == 
"http://www.w3.org/2001/XMLSchema#decimal"; ){
+                                       $value = floatval($value);
+                               }elseif($type == 
"http://www.w3.org/2001/XMLSchema#integer";){
+                                       $value = intval($value);
+                               //}elseif($type == 
"http://www.w3.org/2001/XMLSchema#boolean";){
+                               //      $value = $value === "true" ? true : 
false;
+                               }                       
+                               $result = "\"".$value."\"^^".$type;
                        }else{
-                               $result = $matches[1];
+                               $value = $matches[1];
+                               if (ToolsConvert::isTrueFloat($value)) {
+                                   $value = floatval($value);
+                               } elseif (is_int($value)) {
+                                   $value = intval($value);
+                               }
+                               $result = $value; 
                        }
 
                }elseif(preg_match("/^<>$/i",$uri, $matches)){//<>
                        $result = "<".$prefix["base"].">";
                }elseif(preg_match("/^<#([^:]+)>$/i",$uri, $matches)){//<#truc>
                        $result = "<".$prefix["base"].$matches[1].">";
-               }elseif(preg_match("/^<#([^:]+)>$/i",$uri, $matches)){//<truc>
+               }elseif(preg_match("/^<([^:]+)>$/i",$uri, $matches)){//<truc>
                        $len = strlen( $prefix["base"]);
                        $prefixbase = substr( $prefix["base"], 0, strrpos 
($prefix["base"] , "/"));
                        $result = "<".$prefixbase.$matches[1].">";
@@ -68,11 +86,19 @@
                        $result = "<".$prefix["empty"].$matches[1].">";
                }elseif(preg_match("/^([^:_]*):([^><]*)$/i",$uri, 
$matches)){//x:truc
                        $result = "<".$prefix[$matches[1]].$matches[2].">";
+               }else{  
+                   $value = $uri;
+                   if (ToolsConvert::isTrueFloat($value)) {
+                       $value = floatval($value);
+                   } elseif (is_int($value)) {
+                       $value = intval($value);
+                   }
+                   $result = $value; 
                }
                return $result;
        }
        
-       function mySortTriples($itm1, $itm2){
+       static function mySortTriples($itm1, $itm2){
                if($itm1["s"] > $itm2["s"]){
                        return 1;
                }
@@ -100,12 +126,210 @@
                }
        }
        
-       function sortTriples($arrayTurtle){
-               $result = $arrayTurtle;         
-               array_multisort($result["prefix"],SORT_ASC,SORT_STRING);
+    static function sortTriples($arrayTurtle){
+            $result = $arrayTurtle;            
+            array_multisort($result["prefix"],SORT_ASC,SORT_STRING);
+
+            usort($result["triples"], 'ParserTurtle::mySortTriples');  
+
+            return $result;            
+    }  
+        
+    static function getKey($arrayTurtle, $s,$p){
+        $result = null;
+        if(!EMPTY($arrayTurtle)){
+            foreach ($arrayTurtle["triples"] as $key=>$triple) {
+               if("<".$s.">" == $triple["s"] && "<".$p.">" == $triple["p"] ){
+                      $result = $key;
+                      break;
+                }
+            }
+        }
+        return $key;
+    }
+    static function getTriple($arrayTurtle, $s,$p){
+        $result = null;
+        if(!EMPTY($arrayTurtle)){
+            foreach ($arrayTurtle["triples"] as $key=>$triple) {
+               if("<".$s.">" == $triple["s"] && "<".$p.">" == $triple["p"] ){
+                      $result = $triple;
+                      preg_match( 
'@^(?:<tel\:([^<>]+)>|<mailto\:([^<>]+)>|<([^<>]+)>|([^\"<>]+)|\"(.*)\"[^\"]*)$@i',$triple["o"],
 $matches);
+//\<mailto\:([^\<\>])+\>|\<([^\<\>])+\>|                      
+//print_r($triple["o"]);
+                      //print_r($matches);
+                      foreach ($matches as $key=>$match) {
+                        if($key != 0 && ! EMPTY($match)){
+                          $result["value"] = $match;
+                          break;
+                        }
+                      }
+                      break;
+                }
+            }
+        }
+        return $result;
+    }
+    
+    public static function compare($rs1,$rs2,$ordered=false,$distinct=false) {
+      $difference=array();
+      $rs1Triples = NULL;
+      $rs2Triples = NULL;
+      
+      if($distinct){
+       $rs1Triples = $rs1["triples"];
+       $rs2Triples = $rs2["triples"];
+      }else{
+       $rs1Triples = ToolsBlankNode::removeDuplicate($rs1["triples"]);
+       $rs2Triples = ToolsBlankNode::removeDuplicate($rs2["triples"]);
+      }      
+
+      //B/ Check the result set have the same number of rows.
+      if(count($rs1Triples) != count($rs2Triples)) {
+         $difference[1]="Nb rows :".count($rs1Triples);
+         $difference[2]="Nb rows :".count($rs2Triples);
+         return $difference; //return false ;
+      }
+
+     //Check if there are blanknodes//////////////////////
+      //ref : http://blog.datagraph.org/2010/03/rdf-isomorphism
+      
+// 1.Compare graph sizes and all statements without blank nodes. If they do 
not match, fail.
+//1.1 remove blank nodes
+     $clone1WithoutBlanknodes =$rs1Triples;
+     $clone2WithoutBlanknodes = $rs2Triples;
+     $bnodesInRs1=array();
+     $bnodesInRs2=array();
+      $patternBlankNode = '/^_:/';
+
+      // echo "AVANT";
+         //  print_r($clone1);
+         //  print_r($clone2);
+       foreach ($clone1WithoutBlanknodes as &$row) {
+         foreach ($row as $key=>&$value) {
+             if (preg_match($patternBlankNode, $value)) {
+                 $bnodesInRs1[] = $value ;
+                 $value = "BLANKNODE";//remove
+             }
+           }
+       }
+       foreach ($clone2WithoutBlanknodes as &$row) {
+         foreach ($row as $key=>&$value) {
+             if (preg_match($patternBlankNode, $value)) {
+                 $bnodesInRs2[] = $value ;
+                 $value = "BLANKNODE";//remove
+             }
+           }
+       }
+
+          //print_r($clone1WithoutBlanknodes);
+          //print_r($clone2WithoutBlanknodes);
+//1.2 compare
+       if($ordered){
+               $difference =  ToolsBlankNode::array_diff_assoc_recursive( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes);
+       }else{
+               $difference =  ToolsBlankNode::array_diff_assoc_unordered( 
$clone1WithoutBlanknodes, $clone2WithoutBlanknodes) ;
+       }
+
+      //Check if there are blank nodes
+      if((count($bnodesInRs1) == 0 && count($bnodesInRs2) == 0 )  || 
count($difference) != 0) 
+          return $difference;
+
+      //With blank nodes
+        $bnodesInRs1=array_values(array_unique($bnodesInRs1));
+        $bnodesInRs2=array_values(array_unique($bnodesInRs2));
+        if(count($bnodesInRs1) != count($bnodesInRs2)) {
+            $difference[1]="Nb bnode :".count($bnodesInRs1);
+            $difference[2]="Nb bnode :".count($bnodesInRs2);
+            return $difference; //return false ;
+        }
+
+        //echo "BLANKNODE\n";     
+        //print_r($bnodesInRs1);
+        //print_r($bnodesInRs2);
+      $clone1 = $rs1Triples;
+        //    print_r($clone1);      
+      // 2.Repeat, for each graph:
+      $arrayPermutationsBnode = ToolsBlankNode::AllPermutations($bnodesInRs2);
+        //echo "PERMUTATION\n";
+        //print_r($arrayPermutationsBnode );      
+        //exit();
+        foreach ( $arrayPermutationsBnode as $permute) {
+                //print_r($permute);
+         $clone2 = $rs2Triples;
+          foreach ( $clone2 as $key=>&$row) {
+            $arrayVariableTypeBnode = array_keys( $row , "bnode") ;
+            foreach ($arrayVariableTypeBnode as $variableTypeBnode) {
+                  $variableArray = split(" ",$variableTypeBnode);
+                  $variable=$variableArray[0];
+
+                  $row[$variable] = $bnodesInRs1[array_search($row[$variable] 
,$permute)];
+              }
+          }
+
+            //print_r($clone2);
+            //$difference =  self::sub_array_diff_assoc_unordered( 
$clone1,$clone2) ;          
+           if($ordered){
+                   $difference =  
ToolsBlankNode::array_diff_assoc_recursive($clone1,$clone2);
+           }else{
+                   $difference =  
ToolsBlankNode::array_diff_assoc_unordered($clone1,$clone2) ;
+           }
+          if(count($difference) == 0){
+                return $difference; //true
+          }
+      }
+
+      return $difference;
+  }
+ /*   
+   public static function array_diff_assoc_unordered( $rs1,  $rs2) {
+      $difference=array();
+      $rs1Triples = $rs1["triples"];
+      $rs2Triples = $rs2["triples"];
+
+      //B/ Check the result set have the same number of rows.
+      if(count($rs1Triples) != count($rs2Triples)) {
+         $difference[1]="Nb rows :".count($rs1Triples);
+         $difference[2]="Nb rows :".count($rs2Triples);
+         return $difference; //return false ;
+      }
+
+      //C/ Pick a row from the test results, scan the expected results
+      //   to find a row with same variable/value bindings, and remove
+      //   from the expected results. If all test rows, match then
+      //   (because of B) the result sets have the same rows.
+      //   
+      //return equivalent(convert(rs1), convert(rs2), new 
BNodeIso(NodeUtils.sameValue)) ;
+      $clone1 = $rs1Triples;
+      $clone2 = $rs2Triples;
+//       echo "AVANT";
+//       print_r($clone1);
+//       print_r($clone2);
+      foreach ($rs1Triples as $key1=>&$value1) {
+         $tmpclone2 = $clone2;
+           foreach ($tmpclone2 as $key2=>&$value2) {
                
-               usort($result["triples"], 'ParserTurtle::mySortTriples');       
-               
-               return $result;         
-       }       
+//       echo "-------------";
+//         print_r($value1);
+//         print_r($value2);
+             if(count(array_diff_assoc($value1,$value2)) == 0 && 
+                 count(array_diff_assoc($value2,$value1)) == 0 ){
+                   unset($clone1[$key1]);
+                   unset($clone2[$key2]);
+                   break;
+             }
+           }
+//       echo "-------------APRES";
+//         print_r($clone1);
+//         print_r($clone2);
+      }
+
+      if(count($clone1) != 0 || 
+         count($clone2) != 0 ){
+         $difference[1]=$clone1;
+         $difference[2]=$clone2;
+         return $difference; //return false ;
+      }
+
+      return $difference;
+  }*/
 }
diff --git a/lib/SPARQL/README.md b/lib/SPARQL/README.md
index f2ab54d..561b70e 100644
--- a/lib/SPARQL/README.md
+++ b/lib/SPARQL/README.md
@@ -45,8 +45,12 @@
                                         the request http to write.
                                         (by default : update)
     -f,--file=File                      File of the query.
-       -t, --typeOutput=TYPE               Type of response: 
txt,csv,tsv,ttl,srx,srj
-                                        (by default : txt)
+    -t, --typeOutput=TYPE               Type of response: 
table,txt,csv,tsv,ttl,srx,srj
+                                        (by default : table)
+                                                      
+    -l, --login=LOGIN                  Server login
+    -p, --password=PASSWORD            Server password
+    
     -v, --verbose                       Mode verbose
     -d, --debug                         Mode debug
 
@@ -90,7 +94,7 @@
 -f ./example/queryRead1.rq
 ```
 
-### Example with API 
+### Examples
 
 Send a simple query to DBpedia :
 ```php
@@ -98,11 +102,47 @@
 
 require_once('bordercloud/Endpoint.php');
 
-    $endpoint ="http://dbpedia.org/";;
+    $endpoint ="http://dbpedia.org/sparql";;
     $sp_readonly = new Endpoint($endpoint);
  $q = "select *  where {?x ?y ?z.} LIMIT 5";
  $rows = $sp_readonly->query($q, 'rows');
  $err = $sp_readonly->getErrors();
+ if ($err) {
+      print_r($err);
+      throw new Exception(print_r($err,true));
+    }
+
+ foreach($rows["result"]["variables"] as $variable){
+        printf("%-20.20s",$variable);
+        echo '|';
+ }
+ echo "\n";
+
+ foreach ($rows["result"]["rows"] as $row){
+        foreach($rows["result"]["variables"] as $variable){
+                printf("%-20.20s",$row[$variable]);
+        echo '|';
+        }
+        echo "\n";
+ }
+?>
+```
+
+Send a simple query via an endpoint sparql-auth (with OpenLink Virtuoso 
Open-Source Edition) :
+```php
+<?php
+
+require_once('../Endpoint.php');
+
+    $endpoint = "https://example.com/sparql-auth";;
+    $sp_ReadAndWrite = new Endpoint($endpoint,false);
+ 
+    $sp_ReadAndWrite->setLogin("login");
+    $sp_ReadAndWrite->setPassword("password");
+    
+    $q = "select *  where {?x ?y ?z.} LIMIT 5";
+    $rows = $sp_ReadAndWrite->query($q, 'rows');
+    $err = $sp_ReadAndWrite->getErrors();
  if ($err) {
       print_r($err);
       throw new Exception(print_r($err,true));
@@ -132,9 +172,6 @@
 TODO !!
 git clone http://github.com/BorderCloud/SPARQL.git
 
-### Howto TESTS 
-TODO !!
-
 ### Contact 
 
 If you have remarks, questions, or suggestions, please send them to
@@ -142,7 +179,7 @@
 
 ### Release-Notes 
 
-* V0.1.0.0 version SPARQL.Pro lib PHP by Karima Rafes 
<karima.ra...@bordercloud.com>
+* V1.O.0.0 version SPARQL.Pro lib PHP by Karima Rafes 
<karima.ra...@bordercloud.com>
 
 ### license 
 SPARQL.Pro lib PHP (c)2014 by Karima Rafes - BorderCloud
diff --git a/lib/SPARQL/ToolsBlankNode.php b/lib/SPARQL/ToolsBlankNode.php
new file mode 100644
index 0000000..31b5523
--- /dev/null
+++ b/lib/SPARQL/ToolsBlankNode.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * @git g...@github.com:BorderCloud/SPARQL.git
+ * @author Karima Rafes <karima.ra...@bordercloud.com>
+ * @license http://creativecommons.org/licenses/by-sa/4.0/
+*/
+class ToolsBlankNode {
+
+      public static function removeDuplicate($set)
+        {
+         $find = false;
+         $result = array();
+         foreach ($set as $key1=>$value1) {
+           $find = false;
+           foreach ($result as $key2=>$value2) {
+             if(count(array_diff_assoc($value1,$value2)) == 0 ){
+               $find = true;
+               break;
+             }
+           }
+           if(! $find)
+               $result[] = $value1;
+
+         }
+         return $result;
+        }
+        
+      public static function AllPermutations($set)
+        {
+                $solutions=array();
+                $solutions[]=$set;
+                $n=count($set);
+                $p=array_keys($set);
+                $i=1;
+
+                while ($i<$n)
+                {
+                  if ($p[$i]>0){
+                        $p[$i]--;
+                        $j=0;
+                        if ($i%2==1)
+                                $j=$p[$i];
+                        //swap
+                        $tmp=$set[$j];
+                        $set[$j]=$set[$i];
+                        $set[$i]=$tmp;
+                        $i=1;
+                        $solutions[]=$set;
+                   }
+                   elseif ($p[$i]==0){
+                        $p[$i]=$i;
+                        $i++;
+                   }
+                }
+                return $solutions;
+        }
+        
+        
+    public static function array_diff_assoc_unordered( $rows1,  $rows2) {
+        $difference=array();
+
+        //B/ Check the result set have the same number of rows.
+        if(count($rows1) != count($rows2)) {
+            $difference[1]="Nb rows :".count($rows1);
+            $difference[2]="Nb rows :".count($rows2);
+            return $difference; //return false ;
+        }
+
+        //C/ Pick a row from the test results, scan the expected results
+        //   to find a row with same variable/value bindings, and remove
+        //   from the expected results. If all test rows, match then
+        //   (because of B) the result sets have the same rows.
+        //   
+        //return equivalent(convert(rs1), convert(rs2), new 
BNodeIso(NodeUtils.sameValue)) ;
+        $clone1 = $rows1;
+        $clone2 = $rows2;
+
+        // echo "AVANT";
+          //  print_r($clone1);
+          //  print_r($clone2);
+        foreach ($rows1 as $key1=>&$value1) {
+            $tmpclone2 = $clone2;
+              foreach ($tmpclone2 as $key2=>&$value2) {
+
+                //echo "-------------";
+                //print_r($value1);
+                //print_r($value2);
+                if(count(array_diff_assoc($value1,$value2)) == 0 &&
+                    count(array_diff_assoc($value2,$value1)) == 0 ){
+                      unset($clone1[$key1]);
+                      unset($clone2[$key2]);
+                      break;
+                }
+              }
+              //echo "-------------APRES";
+              //print_r($clone1);
+              //print_r($clone2);
+        }
+
+        if(count($clone1) != 0 ||
+            count($clone2) != 0 ){
+            $difference[1]=$clone1;
+            $difference[2]=$clone2;
+            $difference[1]=$clone1;
+            $difference[2]=$clone2;
+            return $difference; //return false ;
+        }
+        return $difference;
+      }
+      
+      public static function array_diff_assoc_recursive($array1, $array2) {
+               $difference=array();
+               foreach($array1 as $key => $value) {
+                       if( is_array($value) ) {
+                               if( !isset($array2[$key]) || 
!is_array($array2[$key]) ) {
+                                 $difference[1][$key] = $value;
+                                 $difference[2][$key] = "Not set";
+                               } else {
+                                       $new_diff = 
self::array_diff_assoc_recursive($value, $array2[$key]);
+                                       if( count($new_diff)>0 ){
+                                           $difference[1][$key] = $new_diff[1];
+                                           $difference[2][$key] = $new_diff[2];
+                                        }
+                               }
+                       } else if( !array_key_exists($key,$array2)) {
+                               $difference[1][$key] = $value;
+                               $difference[2][$key] = "Key doesnt exist";
+                       } else if($array2[$key] !== $value) {
+                               $difference[1][$key] = $value;
+                               $difference[2][$key] = $array2[$key];
+                       }
+               }
+               return $difference;
+       }
+       /*
+       function array_diff_assoc_recursive_with_blanknode($array1, $array2) {
+               $difference=array();
+               $node = array();
+               foreach($array1 as $key => $value) {
+                       if( is_array($value) ) {
+                               if( !isset($array2[$key]) || 
!is_array($array2[$key]) ) {
+                                       $difference[$key] = $value;
+                               } else {
+                                       $new_diff = 
Tools::array_diff_assoc_recursive_with_blanknode($value, $array2[$key]);
+                                       if( !empty($new_diff) )
+                                               $difference[$key] = $new_diff;
+                               }
+                       } else if( !array_key_exists($key,$array2) ) {
+                               $difference[$key] = $value;                     
+                       } else if( $array2[$key] !== $value && 
floatval($array2[$key]) !== floatval($value)) {  
+                               if(isset($value[0]) && $value[0] == 
"_"){//(array_key_exists("type",$array1) && $array1["type"] == "bnode"){
+                                       if(!array_key_exists($value,$node )){
+                                               $node[$value] = $array2[$key];
+                                       }else if($node[$value] !==  
$array2[$key] ){                                                            
+                                               $difference[$key] = $value;
+                                       }
+                               }else{
+                                       $difference[$key] = $value;
+                               }
+                       }
+               }
+               return $difference;
+       }
+       */
+}
\ No newline at end of file
diff --git a/lib/SPARQL/ToolsConvert.php b/lib/SPARQL/ToolsConvert.php
new file mode 100644
index 0000000..6ff57ea
--- /dev/null
+++ b/lib/SPARQL/ToolsConvert.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @git g...@github.com:BorderCloud/SPARQL.git
+ * @author Karima Rafes <karima.ra...@bordercloud.com>
+ * @license http://creativecommons.org/licenses/by-sa/4.0/
+*/
+class ToolsConvert {
+
+      public static function isTrueFloat($val) 
+      { 
+         $pattern = '/^[+-]?(\d*\.\d+([eE]?[+-]?\d+)?|\d+[eE][+-]?\d+)$/'; 
+         //echo 'Val:'. $val."\n";
+         //var_dump(is_float($val) || preg_match($pattern, trim($val)));
+         return (is_float($val) || preg_match($pattern, trim($val))); 
+      } 
+}
\ No newline at end of file
diff --git a/lib/SPARQL/composer.json b/lib/SPARQL/composer.json
index 1648b04..e1ce7ac 100644
--- a/lib/SPARQL/composer.json
+++ b/lib/SPARQL/composer.json
@@ -1,5 +1,23 @@
 {
-       "name": "BorderCloud/SPARQL",
+    "name": "bordercloud/sparql",
+    "type": "library",
+    "description": "Lib PHP very easy for SPARQL 1.1",
+    "keywords": ["SPARQL","RDF"],
+    "homepage": "https://github.com/BorderCloud/SPARQL";,
+    "license": "CC-BY-SA-4.0",
+    "version": "1.0.0",
+    "authors": [
+        {
+            "name": "Karima Rafes",
+            "email": "karima.ra...@bordercloud.com",
+            "homepage": "http://www.bordercloud.com/";,
+            "role": "Developer"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.0"
+    },
+    
     "repositories": [
         {
             "type": "vcs",
@@ -7,7 +25,7 @@
         }
     ],
     "require-dev": {
-           "evert/phpdoc-md" : "0.0.*",
+       "evert/phpdoc-md" : "0.0.*",
         "phpdocumentor/phpdocumentor": "2.*"
     }
 }
diff --git a/lib/SPARQL/query b/lib/SPARQL/query
index 687cf2e..162a2c6 100755
--- a/lib/SPARQL/query
+++ b/lib/SPARQL/query
@@ -28,8 +28,12 @@
                                         the request http to write.
                                         (by default : update)
     -f,--file=File                      File of the query.
-       -t, --typeOutput=TYPE               Type of response: 
txt,csv,tsv,ttl,srx,srj
-                                        (by default : txt)
+    -t, --typeOutput=TYPE               Type of response: 
table,txt,csv,tsv,ttl,srx,srj
+                                        (by default : table)
+                                                      
+    -l, --login=LOGIN                  Server login
+    -p, --password=PASSWORD            Server password
+    
     -v, --verbose                       Mode verbose
     -d, --debug                         Mode debug
 
@@ -86,12 +90,14 @@
 $endpointUpdateOnly = "";
 $nameParameterQuery = "query";
 $nameParameterUpdate = "update";
+$endpointLogin = "";
+$endpointPassword = "";
 
 $modeRead = false;
 $modeWrite = false;
 
 $filename= "";
-$typeOutput="txt";
+$typeOutput="table";
 $type="";
 
 //Client web
@@ -236,18 +242,50 @@
                        break;
                case "-t":
                        if(! array_key_exists($i + 1, $argv)){
-                               echo "ERROR : forget parameter after -f (see 
--help)\n";
+                               echo "ERROR : forget parameter after -t (see 
--help)\n";
                                exit();
                        }
                        $typeOutput = $argv[$i + 1];
                        $i++;
+                       break;
                case "--typeOutput":
                        if(! array_key_exists(1, $param)){      
-                               echo "ERROR : forget parameter after 
--endpointQueryOnly (see --help)\n";
+                               echo "ERROR : forget parameter after 
--typeOutput (see --help)\n";
                                exit();
                        }
                        $typeOutput = $param[1];
-                       break;                  
+                       break;
+               
+               case "-l":
+                       if(! array_key_exists($i + 1, $argv)){  
+                               echo "ERROR : forget parameter after -l (see 
--help)\n";
+                               exit();
+                       }
+                       $endpointLogin = $argv[$i + 1];
+                       $i++;
+                       break;
+               case "--login":                 
+                       if(! array_key_exists(1, $param)){      
+                               echo "ERROR : forget parameter after --login 
(see --help)\n";
+                               exit();
+                       }
+                       $endpointLogin = $param[1];
+                       break;          
+               case "-p":
+                       if(! array_key_exists($i + 1, $argv)){  
+                               echo "ERROR : forget parameter after -p (see 
--help)\n";
+                               exit();
+                       }                       
+                       $endpointPassword = $argv[$i + 1];
+                       $i++;
+                       break;
+               case "--password":                      
+                       if(! array_key_exists(1, $param)){      
+                               echo "ERROR : forget parameter after --password 
(see --help)\n";
+                               exit();
+                       }
+                       $endpointPassword = $param[1];
+                       break;
                default:
                        //echo $usage; exit();
                        echo "ERROR usage ! (".$param[0]."?)";
@@ -278,9 +316,16 @@
        $ENDPOINT->setNameParameterQueryWrite($nameParameterUpdate);
 }
 
+if($endpointLogin != "" && $endpointPassword != ""){
+       $ENDPOINT->setLogin($endpointLogin);
+       $ENDPOINT->setPassword($endpointPassword);
+}
+
+
 switch($typeOutput){
        case "txt":                             
                $type  =  "text/plain";
+               break;
        case "csv":
                $type =  "text/csv; charset=utf-8";
                break;
@@ -290,6 +335,7 @@
        case "ttl":
                $type =  "text/turtle";
                break;
+       case "table":
        case "srx":
                $type = "application/sparql-results+xml";
                break;
@@ -308,6 +354,8 @@
 - Mode verbose         : ".($modeVerbose?"ON":"OFF")."
 - Mode debug           : ".($modeDebug?"ON":"OFF")."
 - Type output           : ".$type."
+- Endpoint login       : ".$ENDPOINT->getLogin()."
+- Endpoint password    : ".$ENDPOINT->getPassword()."
 ";
 }
 
@@ -317,45 +365,50 @@
 
 //queryRead
 /*
-$rows = $ENDPOINT->query( file_get_contents($filename), 'rows');
-$err = $ENDPOINT->getErrors();
 
- if ($err) {
-       echo "ERROR \n";
-       print_r($err,true);
-       exit();
- }
- 
-foreach($rows["result"]["variables"] as $variable){
-       printf("%-20.20s",$variable);
-       echo '|';
-}
-echo "\n";
-
-foreach ($rows["result"]["rows"] as $row){
-       foreach($rows["result"]["variables"] as $variable){
-               printf("%-20.20s",$row[$variable]);
-       echo '|';
-       }
-       echo "\n";
-}
 */
 
-if($modeRead)
-       $response = $ENDPOINT->queryRead( file_get_contents($filename),$type);
-elseif ($modeWrite)    
-       $response = $ENDPOINT->queryUpdate( file_get_contents($filename),$type);
-else{
-       echo "ERROR : forget parameter after -r or -w (see --help)\n";
-       exit();
-}
-       
-$err = $ENDPOINT->getErrors();
 
- if ($err) {
-       echo "ERROR \n";
-       print_r($err,true);
-       exit();
- }
  
- echo $response;
\ No newline at end of file
+if($typeOutput === "table"){
+    $rows = $ENDPOINT->query( file_get_contents($filename), 'rows');
+    $err = $ENDPOINT->getErrors();
+
+    if ($err) {
+           echo "ERROR \n";
+           print_r($err,true);
+           exit();
+    }
+    
+    foreach($rows["result"]["variables"] as $variable){
+           printf("%-20.20s",$variable);
+           echo '|';
+    }
+    echo "\n";
+
+    foreach ($rows["result"]["rows"] as $row){
+           foreach($rows["result"]["variables"] as $variable){
+                   printf("%-20.20s",$row[$variable]);
+           echo '|';
+           }
+           echo "\n";
+    }
+ }else{
+    if($modeRead)
+           $response = $ENDPOINT->queryRead( 
file_get_contents($filename),$type);
+    elseif ($modeWrite)        
+           $response = $ENDPOINT->queryUpdate( 
file_get_contents($filename),$type);
+    else{
+           echo "ERROR : forget parameter after -r or -w (see --help)\n";
+           exit();
+    }
+           
+    $err = $ENDPOINT->getErrors();
+
+    if ($err) {
+           echo "ERROR \n";
+           print_r($err,true);
+           exit();
+    }
+    echo $response;
+ }
\ No newline at end of file
diff --git a/test/sparqlbasic.feature b/test/sparqlbasic.feature
index 406fdfc..4239849 100644
--- a/test/sparqlbasic.feature
+++ b/test/sparqlbasic.feature
@@ -39,7 +39,7 @@
       
 Scenario: Print a empty table with a query SPARQL
     Given I am at page that does not exist
-    And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.100:8181
+    And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.40:8181
     When I click link Create source
       And I enter the wikitext:
         """
@@ -48,7 +48,7 @@
 GRAPH <http://example.com/data> 
 { ?x ?y ?z . } 
 }
-|endpoint=http://192.168.1.100:8181/sparql/
+|endpoint=http://192.168.1.40:8181/sparql/
 }}
         """
       And I click Save page button
@@ -58,8 +58,8 @@
         
 Scenario: Print a table with a query SPARQL
     Given I am at page that does not exist
-    And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.100:8181
-    And I do this SPARQL query in the triplestore http://192.168.1.100:8181:
+    And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.40:8181
+    And I do this SPARQL query in the triplestore http://192.168.1.40:8181:
         """
 PREFIX dc: <http://purl.org/dc/elements/1.1/>
 INSERT DATA
@@ -75,18 +75,18 @@
         """
 {{#sparql:
 PREFIX dc: <http://purl.org/dc/elements/1.1/>
-SELECT ?title ?creator WHERE {
+SELECT ?x ?title ?creator WHERE {
 GRAPH <http://example.com/data> 
 { ?x dc:title ?title ;
      dc:creator ?creator .
 } 
 } ORDER BY  ?title ?creator
-|endpoint=http://192.168.1.100:8181/sparql/
+|endpoint=http://192.168.1.40:8181/sparql/
 }}
         """
       And I click Save page button
     Then newly created page should open
       And LinkedWiki's table should be there:
-        | title | creator |
-        | Book 1 | A.N.Other1 |
-        | Book 2 | A.N.Other2 |
+        | x | title | creator |
+        | http://example/book1 | Book 1 | A.N.Other1 |
+        | http://example/book2 | Book 2 | A.N.Other2 |
\ No newline at end of file
diff --git a/test/table2CSV.feature b/test/table2CSV.feature
index df87e09..7285c93 100644
--- a/test/table2CSV.feature
+++ b/test/table2CSV.feature
@@ -2,8 +2,8 @@
 Feature: table2CSV
   Background:
     Given I am logged in
-      And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.100:8181
-      And I do this SPARQL query in the triplestore http://192.168.1.100:8181:
+      And I has a empty graph http://example.com/data in the triplestore 
http://192.168.1.40:8181
+      And I do this SPARQL query in the triplestore http://192.168.1.40:8181:
         """
 PREFIX dc: <http://purl.org/dc/elements/1.1/>
 INSERT DATA
@@ -29,7 +29,7 @@
      dc:creator ?creator .
 } 
 } ORDER BY  ?title ?creator
-|endpoint=http://192.168.1.100:8181/sparql/
+|endpoint=http://192.168.1.40:8181/sparql/
 }}
         """
       And I click Save page button
diff --git a/test/tests.sh b/test/tests.sh
index 73ebd3d..4428a2b 100755
--- a/test/tests.sh
+++ b/test/tests.sh
@@ -1,3 +1,6 @@
+#vagrant config nfs_shares no
+#vagrant up
+
 export MEDIAWIKI_URL=http://127.0.0.1:8080/wiki/
 
 cp -R * ~/git/browsertests/features/

-- 
To view, visit https://gerrit.wikimedia.org/r/178065
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8d2f198d9a2e0ad436f3d005f925750a1ee422b0
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/LinkedWiki
Gerrit-Branch: master
Gerrit-Owner: Karima Rafes <karima.ra...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to