/* * $Id$ * * Copyright (C) INRIA, 2012-2014 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package fr.inrialpes.exmo.align.impl.renderer; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.semanticweb.owl.align.Alignment; import org.semanticweb.owl.align.AlignmentException; import org.semanticweb.owl.align.Cell; import fr.inrialpes.exmo.align.impl.edoal.Expression; import fr.inrialpes.exmo.align.impl.edoal.Apply; import fr.inrialpes.exmo.align.impl.edoal.ClassConstruction; import fr.inrialpes.exmo.align.impl.edoal.ClassDomainRestriction; import fr.inrialpes.exmo.align.impl.edoal.ClassExpression; import fr.inrialpes.exmo.align.impl.edoal.ClassId; import fr.inrialpes.exmo.align.impl.edoal.ClassOccurenceRestriction; import fr.inrialpes.exmo.align.impl.edoal.ClassTypeRestriction; import fr.inrialpes.exmo.align.impl.edoal.ClassValueRestriction; import fr.inrialpes.exmo.align.impl.edoal.Comparator; import fr.inrialpes.exmo.align.impl.edoal.Datatype; import fr.inrialpes.exmo.align.impl.edoal.EDOALVisitor; import fr.inrialpes.exmo.align.impl.edoal.InstanceExpression; import fr.inrialpes.exmo.align.impl.edoal.InstanceId; import fr.inrialpes.exmo.align.impl.edoal.PathExpression; import fr.inrialpes.exmo.align.impl.edoal.PropertyConstruction; import fr.inrialpes.exmo.align.impl.edoal.PropertyDomainRestriction; import fr.inrialpes.exmo.align.impl.edoal.PropertyId; import fr.inrialpes.exmo.align.impl.edoal.PropertyTypeRestriction; import fr.inrialpes.exmo.align.impl.edoal.PropertyValueRestriction; import fr.inrialpes.exmo.align.impl.edoal.RelationCoDomainRestriction; import fr.inrialpes.exmo.align.impl.edoal.RelationConstruction; 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; /** * Translate correspondences into Graph Patterns * */ // JE: create a string... problem with increment. public abstract class GraphPatternRendererVisitor extends IndentedRendererVisitor implements EDOALVisitor { final static Logger logger = LoggerFactory.getLogger( GraphPatternRendererVisitor.class ); Alignment alignment = null; Cell cell = null; Hashtable<String,String> nslist = null; protected boolean ignoreerrors = false; protected static boolean blanks = false; protected boolean weakens = false; protected boolean corese = false; private boolean inClassRestriction = false; private Object valueRestriction = null; private boolean flagRestriction; private String instance = null; private String value = ""; private String uriType = null; private String datatype = ""; private Constructor op = null; private Integer nbCardinality = null; private String opOccurence = ""; private static int numberNs; private static int number = 1; private static String sub = ""; protected String obj = ""; private String strBGP = ""; protected List<String> listBGP = null; private Set<String> subjectsRestriction = null;; private Set<String> objectsRestriction = null; protected Hashtable<String,String> prefixList = null; protected static int count = 1; public GraphPatternRendererVisitor( PrintWriter writer ){ super( writer ); listBGP = new ArrayList<String>(); subjectsRestriction = new HashSet<String>(); objectsRestriction = new HashSet<String>(); prefixList = new Hashtable<String,String>(); prefixList.put( "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf" ); } public void initStructure() { count = 1; strBGP = ""; listBGP.clear(); objectsRestriction.clear(); flagRestriction = false; } public void resetVariables( Expression expr, String s, String o ) throws AlignmentException { if ( expr instanceof ClassExpression ) { resetVariables( (ClassExpression)expr, s, o ); } else if ( expr instanceof PathExpression ) { resetVariables( (PathExpression)expr, s, o ); } else if ( expr instanceof InstanceExpression ) { resetVariables( (InstanceExpression)expr, s, o ); } else { throw new AlignmentException( "Cannot render as query : "+expr ); } } public void resetVariables( ClassExpression expr, String s, String o ) { initStructure(); resetVariables( "?" + s, createVarName() ); } public void resetVariables( PathExpression expr, String s, String o ) { initStructure(); resetVariables( "?" + s, "?" + o); } public void resetVariables( InstanceExpression expr, String s, String o ) { initStructure(); resetVariables( "?" + s, createVarName() ); } public void resetVariables( String s, String o ) { sub = s; obj = o; } // JE2014: Why do we only create variables for obj? private String createVarName() { if ( blanks ) { obj = "_:o" + ++count; } else { obj = "?o" + ++count; } return obj; } public String getGP(){ return strBGP; } public List<String> getBGP() { return listBGP; } public String registerPrefix( URI u ) { String prefix = getPrefixDomain( u ); String tag = getPrefixName( u ); String shortCut=getOrGenerateNSPrefix( prefix ); return shortCut+":"+tag; } public String getPrefixDomain( URI u ) { String str = u.toString(); int index; if ( str.contains("#") ) index = str.lastIndexOf("#"); else index = str.lastIndexOf("/"); return str.substring(0, index+1); } public String getPrefixName( URI u ) { String str = u.toString(); int index; if ( str.contains("#") ) index = str.lastIndexOf("#"); else index = str.lastIndexOf("/"); return str.substring( index+1 ); } public String getOrGenerateNSPrefix(String namespace){ if (namespace.length()==0) return ""; String ns = prefixList.get(namespace); if (ns==null) { prefixList.put(namespace, ns="ns"+numberNs++); } return ns; } public void createQueryFile( String dir, String query ) { BufferedWriter out = null; try { FileWriter writer = new FileWriter( dir+"query"+number +".rq" ); out = new BufferedWriter( writer ); number++; out.write( query ); if ( out != null ) // there was at least one file out.close(); } catch(IOException ioe) { logger.debug( "IGNORED Exception", ioe ); } } protected String createPrefixList() { String result = ""; for ( String k : prefixList.keySet() ) { result += "PREFIX "+prefixList.get(k)+":<"+k+">"+NL; } return result; } public void visit( final ClassId e ) throws AlignmentException { if ( e.getURI() != null ) { String id = registerPrefix( e.getURI() ); if ( !subjectsRestriction.isEmpty() ) { Iterator<String> listSub = subjectsRestriction.iterator(); while ( listSub.hasNext() ) { String str = listSub.next(); strBGP += str + " rdf:type " + id + " ." + NL; } subjectsRestriction.clear(); } else { strBGP += sub + " rdf:type " + id + " ." + NL; } } } public void visit( final ClassConstruction e ) throws AlignmentException { op = e.getOperator(); if (op == Constructor.OR) { int size = e.getComponents().size(); for ( final ClassExpression ce : e.getComponents() ) { strBGP += "{" + NL; ce.accept( this ); size--; if( size != 0 ) { strBGP += "}" + " UNION " + NL; } else { strBGP += "}" + NL; } } } else if ( op == Constructor.NOT ) { strBGP += "FILTER (NOT EXISTS {" + NL; for ( final ClassExpression ce : e.getComponents() ) { ce.accept( this ); } strBGP += "})" + NL; } else { for ( final ClassExpression ce : e.getComponents() ) { ce.accept( this ); if ( weakens && !strBGP.equals("") ) { listBGP.add( strBGP ); strBGP = ""; } } } } public void visit( final ClassValueRestriction c ) throws AlignmentException { String str = ""; instance = ""; value = ""; flagRestriction = true; c.getValue().accept( this ); flagRestriction = false; 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 ClassTypeRestriction c ) throws AlignmentException { String str = ""; datatype = ""; inClassRestriction = true; flagRestriction = true; c.getRestrictionPath().accept( this ); flagRestriction = false; if ( !objectsRestriction.isEmpty() ) { Iterator<String> listObj = objectsRestriction.iterator(); int size = objectsRestriction.size(); if ( size > 0 ) { str = "FILTER (datatype(" + listObj.next() + ") = "; visit( c.getType() ); str += "xsd:" + datatype; } while ( listObj.hasNext() ) { str += " && datatype(" + listObj.next() + ") = "; visit( c.getType() ); str += "xsd:" + datatype; } str += ")" + NL; strBGP += str; } objectsRestriction.clear(); inClassRestriction = false; } public void visit( final ClassDomainRestriction c ) throws AlignmentException { inClassRestriction = true; flagRestriction = true; c.getRestrictionPath().accept( this ); flagRestriction = false; Iterator<String> listObj = objectsRestriction.iterator(); while ( listObj.hasNext() ) { subjectsRestriction.add(listObj.next()); } c.getDomain().accept( this ); objectsRestriction.clear(); inClassRestriction = false; } 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 = "<"; } flagRestriction = true; c.getRestrictionPath().accept( this ); flagRestriction = false; if ( !objectsRestriction.isEmpty() ) { Iterator<String> listObj = objectsRestriction.iterator(); if (op == Constructor.COMP) { String tmp = ""; while ( listObj.hasNext() ) tmp = listObj.next(); str += "FILTER(COUNT(" + tmp + ")" + opOccurence + nbCardinality + ")" +NL; } else { while ( listObj.hasNext() ) { str += "FILTER(COUNT(" + listObj.next() + ")" + opOccurence + nbCardinality + ")" +NL; } } strBGP += str; } nbCardinality = null; opOccurence = ""; inClassRestriction = false; } public void visit( final PropertyId e ) throws AlignmentException { if ( e.getURI() != null ) { String id = registerPrefix( e.getURI() ); String temp = obj; if( valueRestriction != null && !inClassRestriction && op != Constructor.COMP && flagRestriction ) obj = "\"" + valueRestriction.toString() + "\""; if ( flagRestriction && inClassRestriction ) objectsRestriction.add( obj ); // createVarName(); //JE2014! strBGP += sub + " " + id + " " + obj + " ." +NL; obj = temp; } } public void visit( final PropertyConstruction e ) throws AlignmentException { op = e.getOperator(); if ( op == Constructor.OR ){ if ( valueRestriction != null && !inClassRestriction ) obj = "\"" + valueRestriction.toString() + "\""; int size = e.getComponents().size(); for ( final PathExpression re : e.getComponents() ) { strBGP += "{" +NL; re.accept( this ); size--; if( size != 0 ){ strBGP += "}" + " UNION " + NL; } else { strBGP += "}" +NL; } } objectsRestriction.add( obj ); } else if ( op == Constructor.NOT ) { strBGP += "FILTER (NOT EXISTS {" + NL; for ( final PathExpression re : e.getComponents() ) { re.accept( this ); } strBGP += "})" + NL; } else if ( op == Constructor.COMP ){ String tempSub = sub; //if ( blanks && this.getClass() == SPARQLConstructRendererVisitor.class ) { // obj = "_:o" + ++count; //} String tempObj = obj; int size = e.getComponents().size(); for ( final PathExpression re : e.getComponents() ) { size--; // next object if ( size == 0 ) { // last step if ( valueRestriction != null && !inClassRestriction ) { obj = "\"" + valueRestriction.toString() + "\""; } else { obj = tempObj; } // otherwise, generating intermediate variables... } else if ( blanks && this.getClass() == SPARQLConstructRendererVisitor.class ) { obj = "_:o" + ++count; } else { obj = "?o" + ++count; } // sub = last obj; obj = obj if last, var or blank otherwise re.accept( this ); // p sub = obj; // sub <= last object } objectsRestriction.add( obj ); obj = tempObj; sub = tempSub; } else { if ( valueRestriction != null && !inClassRestriction ) obj = "\"" + valueRestriction.toString() + "\""; int size = e.getComponents().size(); for ( final PathExpression re : e.getComponents() ) { re.accept( this ); size--; objectsRestriction.add( obj ); if( size != 0 && valueRestriction == null ){ //createVarName(); obj = "?o" + ++count; } if ( weakens && !strBGP.equals("") && !inClassRestriction ) { listBGP.add( strBGP ); strBGP = ""; } } } obj = "?o" + ++count; } public void visit( final PropertyValueRestriction c ) throws AlignmentException { String str = ""; value = ""; uriType = ""; flagRestriction = true; c.getValue().accept( this ); flagRestriction = false; if ( c.getComparator().getURI().equals( Comparator.EQUAL.getURI() ) ) { str = "FILTER (xsd:" + uriType + "(" + obj + ") = "; } else if ( c.getComparator().getURI().equals( Comparator.GREATER.getURI() ) ) { str = "FILTER (xsd:" + uriType + "(" + obj + ") > "; } else { str = "FILTER (xsd:" + uriType + "(" + obj + ") < "; } str += "\"" + value + "\")" + NL; strBGP += str; value = ""; uriType = ""; } public void visit( final PropertyDomainRestriction c ) throws AlignmentException { flagRestriction = true; c.getDomain().accept( this ); flagRestriction = false; } public void visit( final PropertyTypeRestriction c ) throws AlignmentException { String str = ""; if ( !objectsRestriction.isEmpty() ) { Iterator<String> listObj = objectsRestriction.iterator(); int size = objectsRestriction.size(); if ( size > 0 ) { str = "FILTER (datatype(" + listObj.next() + ") = "; visit( c.getType() ); str += "xsd:" + datatype; } while ( listObj.hasNext() ) { str += " && datatype(" + listObj.next() + ") = "; visit( c.getType() ); str += "xsd:" + datatype; } str += ")" + NL; strBGP += str; } objectsRestriction.clear(); } public void visit( final RelationId e ) throws AlignmentException { if ( e.getURI() != null ) { String id = registerPrefix( e.getURI() ); strBGP += sub + " " + id + ""; if ( op == Constructor.TRANSITIVE && flagRestriction ) { strBGP += "*"; } if ( valueRestriction != null && !inClassRestriction && op != Constructor.COMP && flagRestriction ) obj = valueRestriction.toString(); if ( flagRestriction && inClassRestriction && op != Constructor.COMP ) objectsRestriction.add(obj); strBGP += " " + obj + " ." + NL; } } public void visit( final RelationConstruction e ) throws AlignmentException { op = e.getOperator(); if ( op == Constructor.OR ) { int size = e.getComponents().size(); if ( valueRestriction != null && !inClassRestriction ) obj = valueRestriction.toString(); String temp = obj; for ( final PathExpression re : e.getComponents() ) { strBGP += "{" + NL; re.accept( this ); obj = temp; size--; if ( size != 0 ) { strBGP += "}" + "UNION " + NL; } else { strBGP += "}" + NL; } } objectsRestriction.add( obj ); } else if ( op == Constructor.AND ) { if ( valueRestriction != null && !inClassRestriction ) obj = valueRestriction.toString(); String temp = obj; for ( final PathExpression re : e.getComponents() ) { re.accept( this ); obj = temp; } objectsRestriction.add( obj ); } else if ( op == Constructor.NOT ) { strBGP += "FILTER (NOT EXISTS {" + NL; for ( final PathExpression re : e.getComponents() ) { re.accept( this ); } strBGP += "})" + NL; } else if ( op == Constructor.COMP ) { int size = e.getComponents().size(); String temp = sub; //if ( blanks && this.getClass() == SPARQLConstructRendererVisitor.class ) { //obj = "_:o" + ++count; createVarName(); //} for ( final PathExpression re : e.getComponents() ) { re.accept( this ); size--; if( size != 0 ) { sub = obj; if ( size == 1 && valueRestriction != null && !inClassRestriction ) { obj = valueRestriction.toString(); } else { if ( this.getClass() == SPARQLConstructRendererVisitor.class ) { createVarName(); } objectsRestriction.add( obj ); } } } sub = temp; } else if ( op == Constructor.INVERSE ) { String tempSub = sub; for ( final PathExpression re : e.getComponents() ) { String temp = sub; sub = obj; obj = temp; re.accept( this ); sub = tempSub; } } else if ( op == Constructor.SYMMETRIC ) { String tempSub = sub; for ( final PathExpression re : e.getComponents() ) { strBGP += "{" + NL; re.accept( this ); objectsRestriction.add( obj ); String temp = sub; sub = obj; obj = temp; strBGP += "} UNION {" + NL; re.accept( this ); objectsRestriction.add( obj ); strBGP +="}" + NL; } sub = tempSub; } else if (op == Constructor.TRANSITIVE){ for ( final PathExpression re : e.getComponents() ) { flagRestriction = true; re.accept( this ); flagRestriction = false; } } else if ( op == Constructor.REFLEXIVE ) { for ( final PathExpression re : e.getComponents() ) { strBGP += "{" + NL; re.accept( this ); strBGP += "} UNION {" + NL + "FILTER(" + sub + "=" + obj + ")" + NL + "}"; } } else { // JE2014: THIS IS SUPPOSED TO BE A AND! if ( valueRestriction != null && !inClassRestriction ) obj = valueRestriction.toString(); for ( final PathExpression re : e.getComponents() ) { re.accept( this ); objectsRestriction.add( obj ); if ( weakens && !strBGP.equals("") && !inClassRestriction ) { listBGP.add( strBGP ); strBGP = ""; } } } //obj = "?o" + ++count; } public void visit(final RelationCoDomainRestriction c) throws AlignmentException { String stemp = sub; sub = obj; flagRestriction = true; c.getCoDomain().accept( this ); flagRestriction = false; sub = stemp; } public void visit(final RelationDomainRestriction c) throws AlignmentException { flagRestriction = true; c.getDomain().accept( this ); flagRestriction = false; } public void visit( final InstanceId e ) throws AlignmentException { if ( e.getURI() != null ) { String id = registerPrefix( e.getURI() ); if ( flagRestriction ) instance = id; else strBGP += id + " ?p ?o1 ." +NL; } } public void visit( final Value e ) throws AlignmentException { if (e.getType() != null) { String str = e.getType().toString(); int index; if ( str.contains("#") ) index = str.lastIndexOf("#"); else index = str.lastIndexOf("/"); uriType = str.substring( index+1 ); } value = e.getValue(); if ( uriType != null && uriType.equals("") ) { uriType = "string"; } } public void visit( final Apply e ) throws AlignmentException {} public void visit( final Transformation transf ) throws AlignmentException {} public void visit( final Datatype e ) throws AlignmentException { int index; if ( e.getType().contains("#") ) index = e.getType().lastIndexOf("#"); else index = e.getType().lastIndexOf("/"); datatype = e.getType().substring( index+1 ); } }