diff --git a/html/relnotes.html b/html/relnotes.html index 41eb5c2d031d195979dbede193923651d6fe0ba5..bac447dd65b8ec41054eb08dfb316195eb08a3a2 100644 --- a/html/relnotes.html +++ b/html/relnotes.html @@ -76,6 +76,8 @@ with a warning: <p><ul compact="1"> <li><span style="color: red;">Deprecated</span> <tt>BasicAlignment.removeAlignCell()</tt>, use <tt>remCell()</tt> instead (impl)</tt> +<li>Fixed a bug in <tt>QueryMediator</tt> which doubled '#' (serv)</li> +<li>Added a command-line utility for query mediation (cli)</li> <li>Added a guard forbiding to create a <tt>BasicCell</tt> with null objects (impl)</li> </ul></p> diff --git a/src/fr/inrialpes/exmo/align/cli/ParserPrinter.java b/src/fr/inrialpes/exmo/align/cli/ParserPrinter.java index a395bee708eaedf8155ce558bcde985ddfd5019a..6f94d5807df7f73aec76cab767164b1e38444e09 100644 --- a/src/fr/inrialpes/exmo/align/cli/ParserPrinter.java +++ b/src/fr/inrialpes/exmo/align/cli/ParserPrinter.java @@ -20,10 +20,7 @@ package fr.inrialpes.exmo.align.cli; -import java.lang.Integer; import java.lang.Double; -import java.util.Hashtable; -import java.util.List; import java.util.Properties; import java.io.File; @@ -34,8 +31,6 @@ import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.lang.reflect.Constructor; -import org.xml.sax.SAXException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,8 +44,6 @@ import org.semanticweb.owl.align.AlignmentVisitor; import org.semanticweb.owl.align.AlignmentException; import fr.inrialpes.exmo.align.impl.renderer.RDFRendererVisitor; -import fr.inrialpes.exmo.align.impl.ObjectAlignment; -import fr.inrialpes.exmo.align.impl.URIAlignment; import fr.inrialpes.exmo.align.parser.AlignmentParser; /** A really simple utility that loads and alignment and prints it. diff --git a/src/fr/inrialpes/exmo/align/cli/TransformQuery.java b/src/fr/inrialpes/exmo/align/cli/TransformQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..a5d5a870b48c1ecc3ee7724604db5838a383744a --- /dev/null +++ b/src/fr/inrialpes/exmo/align/cli/TransformQuery.java @@ -0,0 +1,150 @@ +/* + * $Id$ + * + * Copyright (C) INRIA, 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.cli; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.PrintWriter; +import java.io.BufferedWriter; +import java.io.BufferedReader; +import java.io.OutputStreamWriter; +import java.io.InputStreamReader; + +import java.lang.reflect.Constructor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.ParseException; + +import org.semanticweb.owl.align.Alignment; +import org.semanticweb.owl.align.AlignmentException; + +import fr.inrialpes.exmo.align.service.QueryMediator; + +/** + * Transform a query according to an alignment + */ + +public class TransformQuery extends CommonCLI { + final static Logger logger = LoggerFactory.getLogger( ParserPrinter.class ); + + public TransformQuery() { + super(); + options.addOption( "e", "echo", false, "Echo the input query" ); + options.addOption( OptionBuilder.withLongOpt( "process" ).hasArg().withDescription( "Process the query against a particular CLASS" ).withArgName("CLASS").create( 'p' ) ); + options.addOption( OptionBuilder.withLongOpt( "process" ).hasArg().withDescription( "get the query from the corresponding FILE" ).withArgName("FILE").create( 'q' ) ); + //options.addOption( OptionBuilder.withLongOpt( "parser" ).hasArg().withDescription( "Use the given CLASS for parsing" ).withArgName("CLASS").create( 'p' ) ); + } + + public static void main(String[] args) { + try { new TransformQuery().run( args ); } + catch (Exception ex) { ex.printStackTrace(); }; + } + + public void run(String[] args) throws Exception { + Alignment al = null; + String alignmentURL = null; + String query = ""; + String result = null; + String processorClass = null; + String queryFile = null; + PrintWriter writer = null; + boolean echo = false; + + try { + CommandLine line = parseCommandLine( args ); + if ( line == null ) return; // --help + + // Here deal with command specific arguments + if ( line.hasOption( 'p' ) ) processorClass = line.getOptionValue( 'p' ); + if ( line.hasOption( 'q' ) ) queryFile = line.getOptionValue( 'q' ); + if ( line.hasOption( 'e' ) ) echo = true; + String[] argList = line.getArgs(); + if ( argList.length > 0 ) { + alignmentURL = argList[0]; + } else { + logger.error("Require the alignement URL"); + usage(); + System.exit(-1); + } + } catch( ParseException exp ) { + logger.error( exp.getMessage() ); + usage(); + System.exit(-1); + } + + try { + + try { + InputStream in = new FileInputStream( queryFile ); + BufferedReader reader = + new BufferedReader(new InputStreamReader(in)); + String line = null; + while ((line = reader.readLine()) != null) { + query += line + "\n"; + } + } catch (IOException x) { + System.err.println(x); + System.exit( -1 ); + //} finally { + } + + if ( echo ) System.out.println( query ); + // Create query processor + QueryMediator qproc = new QueryMediator( alignmentURL ); + result = qproc.rewriteQuery( query ); + + // Set output file + OutputStream stream; + if ( outputfilename == null ) { + stream = System.out; + } else { + stream = new FileOutputStream( outputfilename ); + } + writer = new PrintWriter ( + new BufferedWriter( + new OutputStreamWriter( stream, "UTF-8" )), true); + + // Print + try { + writer.println( result ); + } finally { + writer.flush(); + writer.close(); + } + + } catch (Exception ex) { + logger.debug( "IGNORED Exception", ex ); + } + } + + public void usage() { + usage( "java "+this.getClass().getName()+" [options] alignmentURI query\nTransforms the given query and transforms it according to the alignment" ); + } +} diff --git a/src/fr/inrialpes/exmo/align/service/QueryMediator.java b/src/fr/inrialpes/exmo/align/service/QueryMediator.java index 8fedb1c89a20ac84b12f1d19499ae3d555e03c9c..31bda4273078fb5a055a5dd2fbb3f09a7abf0ef4 100644 --- a/src/fr/inrialpes/exmo/align/service/QueryMediator.java +++ b/src/fr/inrialpes/exmo/align/service/QueryMediator.java @@ -144,7 +144,6 @@ public class QueryMediator implements QueryProcessor { /** * @param aQuery -- query to be re-written * @return -- rewritten query: - * - replaces all the prefix namespaces, if present, in the query by actual IRIs * - replaces all entity IRI by their counterpart in the ontology * * Caveats: @@ -152,6 +151,8 @@ public class QueryMediator implements QueryProcessor { * - This does not care for the *:x status of alignments * - This does work from ontology1 to ontology2, not the otherway round * (use invert() in this case). + * + * TODO: Could benefit from adding new namespaces. */ public String rewriteQuery( String aQuery ) throws AlignmentException { return rewriteSPARQLQuery( aQuery, alignment ); @@ -162,6 +163,9 @@ public class QueryMediator implements QueryProcessor { //aQuery = aQuery.replaceFirst("^[ \t\n]+","").replaceAll("PREFIX", "prefix"); aQuery = aQuery.trim().replaceAll("PREFIX", "prefix"); String mainQuery = ""; + String prefix[][] = null; + + // Collect and reduce prefix if( aQuery.indexOf("prefix") != -1 ) { String[] pref = aQuery.split("prefix"); for(int j=0; j < pref.length; j++) { @@ -172,25 +176,39 @@ public class QueryMediator implements QueryProcessor { str = pref[pref.length-1]; mainQuery = str.substring(str.indexOf('>')+1, str.length()); } - - for(int i = 0; i < pref.length; i++) { + + prefix = new String[pref.length][2]; + for( int i = 0; i < pref.length; i++ ) { String currPrefix = pref[i].trim(); if(!currPrefix.equals("") && currPrefix.indexOf('<') != -1 && currPrefix.indexOf('>') != -1) { int begin = currPrefix.indexOf('<'); int end = currPrefix.indexOf('>'); - String ns = currPrefix.substring(0, begin).trim(); + String ns = currPrefix.substring(0, currPrefix.indexOf(':')).trim(); String iri = currPrefix.substring(begin+1, end).trim(); - mainQuery = Pattern.compile(ns+"([A-Za-z0-9_-]+)").matcher(mainQuery).replaceAll("<"+iri+"#$1>"); + prefix[i][0] = ns; + prefix[i][1] = iri; + mainQuery = Pattern.compile(ns+":([A-Za-z0-9_-]+)").matcher(mainQuery).replaceAll("<"+iri+"$1>"); //mainQuery = mainQuery.replaceAll(ns+"([A-Za-z0-9_-]+)", "<"+iri+"#$1>"); } } } else mainQuery = aQuery; + // The second part replaces the named items by their counterparts for( Cell cell : align ){ mainQuery = mainQuery.replaceAll( cell.getObject1AsURI(align).toString(), cell.getObject2AsURI(align).toString() ); } + + // Post process prefix + for ( int i=0; i < prefix.length; i++ ) { + if ( prefix[i][0] != null ) { + mainQuery = Pattern.compile("<"+prefix[i][1]+"([A-Za-z0-9_-]+)>").matcher(mainQuery).replaceAll( prefix[i][0]+":$1" ); + mainQuery = "PREFIX "+prefix[i][0]+": <"+prefix[i][1]+"> .\n" + mainQuery; + } + } + + return mainQuery; }