From a410b2f1fe3f6c35b79cd6f76836f1943645faed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Euzenat?= <Jerome.Euzenat@inria.fr>
Date: Wed, 3 Jun 2015 11:22:38 +0000
Subject: [PATCH] - finished fully working SPARQL generator for link keys

---
 html/relnotes.html                            |   3 +-
 .../renderer/GraphPatternRendererVisitor.java | 177 +++++++++---------
 .../SPARQLLinkkerRendererVisitor.java         |  32 ++--
 3 files changed, 110 insertions(+), 102 deletions(-)

diff --git a/html/relnotes.html b/html/relnotes.html
index 167c8e68..0aba8a13 100644
--- a/html/relnotes.html
+++ b/html/relnotes.html
@@ -71,6 +71,7 @@ with a warning:
 <p><ul compact="1">
 <li>Added interface <tt>AlignmentRepairer</tt> (api)</tt>
 <li>Added some more SPARQL renderers (impl)</li>
+<li>Added <tt>SPARQLLinkkerRendererVisitor</tt> generating SPARQL from link keys(impl)</li>
 <li>Fixed a bug in pull aggregation (impl)</li>
 <li>Improved error reporting (err500) when ontology is unknown (serv)</li>
 <li>Implemented <tt>AbstractRepairer</tt> (impl)</tt>
@@ -91,7 +92,7 @@ with a warning:
 <li>Fixed several bugs in <tt>GraphPatternRendererVisitor</tt> (impl)</li>
 <li>Fixed a bug in server updating (impl)</li>
 <li>Fixed the compareTo implementation in <tt>BasicCell</tt> (impl)</li>
-<li>Implemented linkkeys in EDOAL (edoal)</li>
+<li>Implemented link keys in EDOAL (edoal)</li>
 <li>Implemented (fully) extension parsing in RDFParser (parser)</li>
 <li>Reorganised AlignmentServices into transport (HTTP) and service (HTML/Web service) (serv)</li>
 <li>Enabled query translation in interface and web service (serv)</li>
diff --git a/src/fr/inrialpes/exmo/align/impl/renderer/GraphPatternRendererVisitor.java b/src/fr/inrialpes/exmo/align/impl/renderer/GraphPatternRendererVisitor.java
index 2baf6c19..aa47ba4c 100644
--- a/src/fr/inrialpes/exmo/align/impl/renderer/GraphPatternRendererVisitor.java
+++ b/src/fr/inrialpes/exmo/align/impl/renderer/GraphPatternRendererVisitor.java
@@ -65,6 +65,7 @@ import fr.inrialpes.exmo.align.impl.edoal.RelationDomainRestriction;
 import fr.inrialpes.exmo.align.impl.edoal.RelationId;
 import fr.inrialpes.exmo.align.impl.edoal.Transformation;
 import fr.inrialpes.exmo.align.impl.edoal.Value;
+import fr.inrialpes.exmo.align.impl.edoal.ValueExpression;
 import fr.inrialpes.exmo.align.parser.SyntaxElement.Constructor;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -197,14 +198,15 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         return listBGP;
     }
 
-    public String registerPrefix(URI u) {
-        String prefix = getPrefixDomain(u);
-        String tag = getPrefixName(u);
-        String shortCut = getOrGenerateNSPrefix(prefix);
-        return shortCut + ":" + tag;
+    public String registerPrefix( URI u ) {
+        String str = u.toString();
+        int index;
+        if ( str.contains("#") ) index = str.lastIndexOf("#");
+        else index = str.lastIndexOf("/");
+	return getOrGenerateNSPrefix(str.substring(0, index + 1)) + ":" + str.substring(index + 1);
     }
 
-    public String getPrefixDomain(URI u) {
+    public String getPrefixDomain( URI u ) {
         String str = u.toString();
         int index;
         if (str.contains("#")) {
@@ -215,7 +217,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         return str.substring(0, index + 1);
     }
 
-    public String getPrefixName(URI u) {
+    public String getPrefixName(URI u) { // Would better be suffix
         String str = u.toString();
         int index;
         if (str.contains("#")) {
@@ -226,13 +228,11 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         return str.substring(index + 1);
     }
 
-    public String getOrGenerateNSPrefix(String namespace) {
-        if (namespace.length() == 0) {
-            return "";
-        }
-        String ns = prefixList.get(namespace);
+    public String getOrGenerateNSPrefix( String namespace ) {
+        if ( namespace.length() == 0 ) return "";
+        String ns = prefixList.get( namespace );
         if (ns == null) {
-            prefixList.put(namespace, ns = "ns" + numberNs++);
+            prefixList.put( namespace, ns = "ns" + numberNs++ );
         }
         return ns;
     }
@@ -315,7 +315,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         }
     }
 
-    public void visit(final ClassConstruction e) throws AlignmentException {
+    public void visit( final ClassConstruction e ) throws AlignmentException {
         op = e.getOperator();
         if (op == Constructor.OR) {
             int size = e.getComponents().size();
@@ -330,7 +330,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
                 }
             }
         } else if (op == Constructor.NOT) {
-            strBGP += "FILTER (NOT EXISTS {" + NL;
+            strBGP += "FILTER (NOT EXISTS {";
             for (final ClassExpression ce : e.getComponents()) {
                 ce.accept(this);
             }
@@ -346,54 +346,61 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         }
     }
 
-    public void visit(final ClassValueRestriction c) throws AlignmentException {
-        String str = "";
-        instance = "";
+    private String valueToCompare( ValueExpression val, String var ) throws AlignmentException {
         value = "";
+        uriType = "";
         flagRestriction = true;
-        c.getValue().accept(this);
+        val.accept(this);
         flagRestriction = false;
+	return "xsd:"+uriType+"( "+var+" )";
+    }
 
-        if (!instance.equals("")) {
-            valueRestriction = instance;
-        } else if (!value.equals("")) {
-            valueRestriction = value;
-        }
-
-        if (c.getComparator().getURI().equals(Comparator.GREATER.getURI())) {
-            opOccurence = ">";
-            inClassRestriction = true;
-        }
-        if (c.getComparator().getURI().equals(Comparator.LOWER.getURI())) {
-            opOccurence = "<";
-            inClassRestriction = true;
-        }
-        flagRestriction = true;
-        c.getRestrictionPath().accept(this);
-        flagRestriction = false;
-        String temp = obj;
-        if (inClassRestriction && !objectsRestriction.isEmpty()) {
-            Iterator<String> listObj = objectsRestriction.iterator();
-            if (op == Constructor.COMP) {
-                String tmp = "";
-                while (listObj.hasNext()) {
-                    tmp = listObj.next();
-                }
-                str = "FILTER (" + tmp + opOccurence + valueRestriction + ")" + NL;
-            } else {
-                while (listObj.hasNext()) {
-                    str += "FILTER (" + listObj.next() + opOccurence + valueRestriction + ")" + NL;
-                }
-            }
-            strBGP += str;
-        }
-        valueRestriction = null;
-        inClassRestriction = false;
-        obj = temp;
-        if (op == Constructor.AND) {
-            createVarName();
-        }
+    public void visit(final ClassValueRestriction c) throws AlignmentException {
+	String str = "";
+	instance = "";
+	value = "";
+	flagRestriction = true;
+	c.getValue().accept(this);
+	flagRestriction = false;
+	//String xxxx = valueToCompare( c.getValue() );
+	
+	if (!instance.equals("")) {
+	    valueRestriction = instance;
+	} else if (!value.equals("")) {
+	    valueRestriction = value;
+	}
+	
+	opOccurence = c.getComparator().getSPARQLComparator();
+	inClassRestriction = true;
+
+	flagRestriction = true;
+	c.getRestrictionPath().accept(this);
+	flagRestriction = false;
+
+	String temp = obj;
+	if (inClassRestriction && !objectsRestriction.isEmpty()) {
+	    Iterator<String> listObj = objectsRestriction.iterator();
+	    if (op == Constructor.COMP) {
+		String tmp = "";
+		while (listObj.hasNext()) {
+		    tmp = listObj.next();
+		}
+		str = "FILTER (" + tmp + opOccurence + valueRestriction + ")" + NL;
+	    } else {
+		while (listObj.hasNext()) {
+		    str += "FILTER (" + listObj.next() + opOccurence + valueRestriction + ")" + NL;
+		}
+	    }
+	    strBGP += str;
+	}
+	obj = temp;
+	valueRestriction = null;
+	inClassRestriction = false;
+	if (op == Constructor.AND) {
+	    createVarName();
+	}
     }
+    
 
     public void visit(final ClassTypeRestriction c) throws AlignmentException {
         String str = "";
@@ -440,32 +447,22 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
     public void visit(final ClassOccurenceRestriction c) throws AlignmentException {
         String str = "";
         inClassRestriction = true;
-        if (c.getComparator().getURI().equals(Comparator.EQUAL.getURI())) {
-            nbCardinality = c.getOccurence();
-            opOccurence = "=";
-        }
-        if (c.getComparator().getURI().equals(Comparator.GREATER.getURI())) {
-            nbCardinality = c.getOccurence();
-            opOccurence = ">";
-        }
-        if (c.getComparator().getURI().equals(Comparator.LOWER.getURI())) {
-            nbCardinality = c.getOccurence();
-            opOccurence = "<";
-        }
+	opOccurence = c.getComparator().getSPARQLComparator();
+	nbCardinality = c.getOccurence();
         flagRestriction = true;
         c.getRestrictionPath().accept(this);
         flagRestriction = false;
         if (!objectsRestriction.isEmpty()) {
             Iterator<String> listObj = objectsRestriction.iterator();
-            if (op == Constructor.COMP) {
+            if ( op == Constructor.COMP ) {
                 String tmp = "";
                 while (listObj.hasNext()) {
                     tmp = listObj.next();
                 }
-                str += "FILTER(COUNT(" + tmp + ")" + opOccurence + nbCardinality + ")" + NL;
+                str += "FILTER( COUNT(" + tmp + ") " + opOccurence + " " + nbCardinality + ")" + NL;
             } else {
                 while (listObj.hasNext()) {
-                    str += "FILTER(COUNT(" + listObj.next() + ")" + opOccurence + nbCardinality + ")" + NL;
+                    str += "FILTER( COUNT(" + listObj.next() + ") " + opOccurence + " " + nbCardinality + ")" + NL;
                 }
             }
 
@@ -517,12 +514,12 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
             }
             strBGP += "})" + NL;
         } else if (op == Constructor.COMP) {
+            int size = e.getComponents().size();
             String tempSub = sub;
-            //if ( blanks && this.getClass() == SPARQLConstructRendererVisitor.class ) {
+            //if ( blanks && ( this.getClass() == SPARQLConstructRendererVisitor.class || this.getClass() == SPARQLLinkkerRendererVisitor.class ) ) {
             //	obj = "_:o" + ++count;
             //}
             String tempObj = obj;
-            int size = e.getComponents().size();
             for (final PathExpression re : e.getComponents()) {
                 size--;
                 // next object 
@@ -532,7 +529,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
                     } else {
                         obj = tempObj;
                     } // otherwise, generating intermediate variables...
-                } else if (blanks && this.getClass() == SPARQLConstructRendererVisitor.class) {
+                } else if (blanks && (this.getClass() == SPARQLConstructRendererVisitor.class || this.getClass() == SPARQLLinkkerRendererVisitor.class )) {
                     obj = "_:o" + ++varsIndexcount;
                 } else {
                     obj = "?o" + ++varsIndexcount;
@@ -568,19 +565,18 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
 
     public void visit( final PropertyValueRestriction c ) throws AlignmentException {
         String str = "";
-        value = "";
-        uriType = "";
-        flagRestriction = true;
-        c.getValue().accept(this);
-        flagRestriction = false;
+	String val = valueToCompare( c.getValue(), obj );
+	/*
         if (c.getComparator().getURI().equals(Comparator.EQUAL.getURI())) {
-            str = "FILTER (xsd:" + uriType + "(" + obj + ") = ";
+            str = "FILTER (" + val + " = ";
         } else if (c.getComparator().getURI().equals(Comparator.GREATER.getURI())) {
-            str = "FILTER (xsd:" + uriType + "(" + obj + ") > ";
+            str = "FILTER (" + val + " > ";
         } else {
-            str = "FILTER (xsd:" + uriType + "(" + obj + ") < ";
+            str = "FILTER (" + val + " < ";
         }
         str += "\"" + value + "\")" + NL;
+	*/
+	str = "FILTER (" + val + " " + c.getComparator().getSPARQLComparator() + " \"" + value + "\")" + NL;
 
         strBGP += str;
         value = "";
@@ -670,7 +666,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         } else if (op == Constructor.COMP) {
             int size = e.getComponents().size();
             String temp = sub;
-            //if ( blanks && this.getClass() == SPARQLConstructRendererVisitor.class ) {
+            //if ( blanks && (this.getClass() == SPARQLConstructRendererVisitor.class || this.getClass() == SPARQLLinkkerRendererVisitor.class ) ) {
             //obj = "_:o" + ++count;
             createVarName();
             //}
@@ -682,7 +678,7 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
                     if (size == 1 && valueRestriction != null && !inClassRestriction) {
                         obj = valueRestriction.toString();
                     } else {
-                        if (this.getClass() == SPARQLConstructRendererVisitor.class || this.getClass() == SPARQLSelectRendererVisitor.class) {
+                        if (this.getClass() == SPARQLConstructRendererVisitor.class || this.getClass() == SPARQLSelectRendererVisitor.class || this.getClass() == SPARQLLinkkerRendererVisitor.class ) {
                             createVarName();
                         }
                         objectsRestriction.add(obj);
@@ -757,10 +753,10 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
         flagRestriction = false;
     }
 
-    public void visit(final InstanceId e) throws AlignmentException {
+    public void visit( final InstanceId e ) throws AlignmentException {
         if (e.getURI() != null) {
-            String id = registerPrefix(e.getURI());
-            if (flagRestriction) {
+            String id = registerPrefix( e.getURI() );
+            if ( flagRestriction ) {
                 instance = id;
             } else {
                 strBGP += id + " ?p ?o1 ." + NL;
@@ -770,7 +766,8 @@ public abstract class GraphPatternRendererVisitor extends IndentedRendererVisito
 
     public void visit( final Value e ) throws AlignmentException {
         value = e.getValue();
-        if ( e.getType() != null ) uriType = decodeDatatype( e.getType().toString() );
+	if ( e.getType() != null ) uriType = registerPrefix( e.getType() );
+        //if ( e.getType() != null ) uriType = decodeDatatype( e.getType().toString() );
 	// JE2015: Not sure that this is really useful
         //if ( uriType != null && uriType.equals("") ) uriType = "xsd:string";
     }
diff --git a/src/fr/inrialpes/exmo/align/impl/renderer/SPARQLLinkkerRendererVisitor.java b/src/fr/inrialpes/exmo/align/impl/renderer/SPARQLLinkkerRendererVisitor.java
index 5ad1512f..f6d07b31 100644
--- a/src/fr/inrialpes/exmo/align/impl/renderer/SPARQLLinkkerRendererVisitor.java
+++ b/src/fr/inrialpes/exmo/align/impl/renderer/SPARQLLinkkerRendererVisitor.java
@@ -249,29 +249,39 @@ public class SPARQLLinkkerRendererVisitor extends GraphPatternRendererVisitor im
         }
     }
 
+    /**
+     * Generate the constraint corresponding to:
+     * MINUS SELECT ?x ?y WHERE { ?x pj ?wj . FILTER NOT EXISTS { ?y qj ?wj . } }
+     * MINUS SELECT ?x ?y WHERE { ?y qj ?wj . FILTER NOT EXISTS { ?x pj ?wj . } }
+     */
     public void visit( final LinkkeyEquals linkkeyEquals ) throws AlignmentException {
-	String extravar1 = "x";
-	String extravar2 = "y";
-	initStructure(); //strBGP = ""; // congrats!
-	resetVariables( "?x", "?o" );
+	// In the semantics of EQ-Linkkeys, the intersection must not be empty...
+	processInLinkKey( linkkeyEquals );
+	String extravar1 = createVarName();
+	String extravar2 = createVarName();
+	initStructure(); //strBGP = ""; // congrats! Unsure
+	String o1 = createVarName();
+	resetVariables( extravar1, o1 );
 	linkkeyEquals.getExpression1().accept( this );
 	String temp = obj;
         String GP1 = wrapInNamedGraph( onto1NamedGraph, getGP() );
         // == resetS2( lkvar2 );
 	initStructure(); //strBGP = ""; // congrats!
-	resetVariables( "?y", "?o" );
+	resetVariables( extravar2, o1 );
 	obj = temp;
 	linkkeyEquals.getExpression2().accept( this );
         String GP2 = wrapInNamedGraph( onto2NamedGraph, getGP() );
-	lkpattern += "MINUS SELECT ?x ?y WHERE { " + GP1 + " FILTER NOT EXISTS { " + GP2 + " } }";
-	lkpattern += "MINUS SELECT ?x ?y WHERE { " + GP2 + " FILTER NOT EXISTS { " + GP1 + " } }";
-	//MINUS SELECT ?x ?y WHERE { ?x pj ?wj . FILTER NOT EXISTS { ?y qj ?wj . } }
-	//MINUS SELECT ?x ?y WHERE { ?y qj ?wj . FILTER NOT EXISTS { ?x pj ?wj . } }
+	lkpattern += "MINUS { SELECT "+extravar1+" "+extravar2+" WHERE { " + GP1 + " FILTER NOT EXISTS { " + GP2 + " } } }"+NL;
+	lkpattern += "MINUS { SELECT "+extravar1+" "+extravar2+" WHERE { " + GP2 + " FILTER NOT EXISTS { " + GP1 + " } } }"+NL;
    }
 
+    public void visit( final LinkkeyIntersects linkkeyIntersects ) throws AlignmentException {
+	processInLinkKey( linkkeyIntersects );
+    }
+
     // JE: I do not understand where the common variables are created... (by default obj is preserved)
     // JE: Is the GP reset??? The answer is no. Hence init...
-    public void visit( final LinkkeyIntersects linkkeyIntersects ) throws AlignmentException {
+    public void processInLinkKey( final LinkkeyBinding linkkeyIntersects ) throws AlignmentException {
 	//?x p'i ?zi . ?y q'i ?zi .
 	//= lkpattern += NL + lkvar1 + "p" + "newvar" + " . " + NL + lkvar2 + "q" + "samenewvar" + " . ";
         // == resetS1( lkvar1 );
@@ -288,7 +298,7 @@ public class SPARQLLinkkerRendererVisitor extends GraphPatternRendererVisitor im
 	resetVariables( lkvar2, o2 );
 	linkkeyIntersects.getExpression2().accept( this );
         lkpattern += wrapInNamedGraph( onto2NamedGraph, getGP() );
-	lkpattern += "FILTER( lcase(str("+o1+")) = lcase(str("+o2+")) ) ";
+	lkpattern += "FILTER( lcase(str("+o1+")) = lcase(str("+o2+")) ) "+NL;
     }
 
     protected String wrapInNamedGraph( String namedGraph, String stuff ) {
-- 
GitLab