code: package it.unibz.inf.ontop.owlapi;
  
  /*
   * #%L
   * ontop-quest-owlapi
   * %%
   * Copyright (C) 2009 - 2014 Free University of Bozen-Bolzano
   * %%
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * #L%
   */
  
  import com.google.common.collect.ImmutableSet;
  import it.unibz.inf.ontop.injection.OntopSQLOWLAPIConfiguration;
  import it.unibz.inf.ontop.owlapi.connection.OWLConnection;
  import it.unibz.inf.ontop.owlapi.connection.OWLStatement;
  import it.unibz.inf.ontop.owlapi.impl.SimpleOntopOWLEngine;
  import it.unibz.inf.ontop.owlapi.resultset.GraphOWLResultSet;
  import it.unibz.inf.ontop.owlapi.resultset.OWLBindingSet;
  import it.unibz.inf.ontop.owlapi.resultset.TupleOWLResultSet;
  import org.junit.*;
  import org.semanticweb.owlapi.model.OWLAxiom;
  import org.semanticweb.owlapi.model.OWLLiteral;
  import org.semanticweb.owlapi.model.OWLObject;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.sql.*;
  import java.util.HashSet;
  import java.util.Set;
  
  import static it.unibz.inf.ontop.utils.OWLAPITestingTools.executeFromFile;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertTrue;
  
  
  public class MarriageTest {
  
  	private static final String ONTOLOGY_FILE = "src/test/resources/marriage/marriage.ttl";
  	private static final String OBDA_FILE = "src/test/resources/marriage/marriage.obda";
      private static final String CREATE_DB_FILE = "src/test/resources/marriage/create-db.sql";
  	private static final String JDBC_URL = "jdbc:h2:mem:questjunitdb";
  	private static final String JDBC_USER = "sa";
  	private static final String JDBC_PASSWORD = "";
  	private static final Logger LOGGER = LoggerFactory.getLogger(MarriageTest.class);
  
  	private static Connection CONNECTION;
  	private static OntopOWLEngine REASONER;
  
  	@BeforeClass
  	public static void setUp() throws Exception {
  		CONNECTION = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
  		executeFromFile(CONNECTION, CREATE_DB_FILE);
  
  		OntopSQLOWLAPIConfiguration config = OntopSQLOWLAPIConfiguration.defaultBuilder()
  				.nativeOntopMappingFile(OBDA_FILE)
  				.ontologyFile(ONTOLOGY_FILE)
  				.jdbcUrl(JDBC_URL)
  				.jdbcUser(JDBC_USER)
  				.jdbcPassword(JDBC_PASSWORD)
  				.enableTestMode()
  				.build();
  
  		REASONER = new SimpleOntopOWLEngine(config);
  	}
  
  	@AfterClass
  	public static void tearDown() throws Exception {
  		REASONER.close();
  		CONNECTION.close();
  	}
  
  
      /**
       * Tests that all the persons are not married.
       *
       * This test has been added to make sure the mapping saturation handles correctly domain
       * and nullable columns.
       *
       */
  	@Test
      public void testSpouse() throws Exception {
          String queryBind = "PREFIX : <http://example.org/marriage/voc#>\n" +
                  "\n" +
                  "SELECT DISTINCT ?x \n" +
                  "WHERE {\n" +
                  "  ?x a :Spouse .\n" +
                  "}";
  
          ImmutableSet<String> expectedValues = ImmutableSet.of(
                  "<http://example.com/person/1>",
                  "<http://example.com/person/2>"
          );
          checkReturnedValues(queryBind, expectedValues);
      }
  
  	/**
  	 * Complex Optional interaction
  	 */
  	@Test
  	public void testComplexOptionalInteraction() throws Exception {
  		String queryBind = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"SELECT ?x ?f2 \n" +
  				"WHERE {\n" +
  				"  ?x :firstName ?f1 .\n" +
  				"  OPTIONAL {\n" +
  				"     ?x :hasSpouse ?p2 .\n" +
  				"  }\n" +
  				"  OPTIONAL {\n" +
  				"     ?p2 :firstName ?f2 .\n" +
  				"  }\n" +
  				"}";
  
  		// All distinct values of x
  		ImmutableSet<String> expectedValues = ImmutableSet.of(
  				"<http://example.com/person/1>",
  				"<http://example.com/person/2>",
  				"<http://example.com/person/3>"
  		);
  		checkReturnedValues(queryBind, expectedValues);
  	}
  
  	@Test
  	public void testPersonConstruct() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}";
  
  		int count = runConstructQuery(query);
  		assertEquals(3, count);
  	}
  
  	@Test
  	public void testPersonConstructLimit() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}\n" +
  				"LIMIT 2";
  
  		int count = runConstructQuery(query);
  		assertEquals(2, count);
  	}
  
  	@Test
  	public void testPersonConstructOffset() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}\n" +
  				"OFFSET 1";
  
  		int count = runConstructQuery(query);
  		assertEquals(2, count);
  	}
  
  	@Test
  	public void testPersonConstructLimitOffset1() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}\n" +
  				"OFFSET 3\n" +
  				"LIMIT 1";
  
  		int count = runConstructQuery(query);
  		assertEquals(0, count);
  	}
  
  	@Test
  	public void testPersonConstructLimitOffset2() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}\n" +
  				"OFFSET 2\n" +
  				"LIMIT 1";
  
  		int count = runConstructQuery(query);
  		assertEquals(1, count);
  	}
  
  	@Test
  	public void testPersonConstructOrderByLimit() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"CONSTRUCT {\n" +
  				" ?x a :Persona . \n" +
  				"}\n" +
  				"WHERE {\n" +
  				"  ?x a :Person .\n" +
  				"}\n" +
  				"ORDER BY ?x\n" +
  				"LIMIT 2";
  
  		int count = runConstructQuery(query);
  		assertEquals(2, count);
  	}
  
  	@Test
  	public void testOptionallyMarriedToMusician() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"SELECT ?x ?s ?l2 \n" +
  				"WHERE {\n" +
  				"?x :firstName ?l1 .\n" +
  				   "OPTIONAL { \n" +
  				"    ?p :hasSpouse ?s .\n" +
  				"       OPTIONAL {\n" +
  				"        ?s :firstName ?l2 ;\n" +
  				"          a :Musician .\n" +
  				"       }\n" +
  				"  }\n" +
  				"}\n";
  
  		ImmutableSet<String> expectedValues = ImmutableSet.of(
  				"<http://example.com/person/1>",
  				"<http://example.com/person/2>",
  				"<http://example.com/person/3>"
  		);
  		checkReturnedValues(query, expectedValues);
  	}
  
  	@Test
  	public void testLJUnion() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"SELECT ?p ?x \n" +
  				"WHERE {\n" +
  				"?p a :Person .\n" +
  				"OPTIONAL { \n" +
  				"    { ?p :firstName ?x . }\n" +
  				"    UNION \n" +
  				"    { ?p :lastName ?x . }\n" +
  				"  }\n" +
  				"}\n";
  
  		ImmutableSet<String> expectedValues = ImmutableSet.of("Mary", "Bob", "John", "Smith", "Forester", "Doe");
  		checkReturnedValues(query, expectedValues);
  	}
  
  	@Ignore
  	@Test
  	public void testLJJoinUnion() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"SELECT ?p ?x \n" +
  				"WHERE {\n" +
  				"?p a :Person .\n" +
  				"OPTIONAL { \n" +
  				"    { ?p :firstName ?x . }\n" +
  				"    UNION \n" +
  				"    { ?p :lastName ?x . }\n" +
  				"    ?p a :Musician ." +
  				"  }\n" +
  				"}\n";
  
  		ImmutableSet<String> expectedValues = ImmutableSet.of("Mary", "Bob", "John", "Smith", "Forester", "Doe");
  		checkReturnedValues(query, expectedValues);
  	}
  
  	@Test
  	public void testEmptyClass1() throws Exception {
  		String query = "PREFIX : <http://example.org/marriage/voc#>\n" +
  				"\n" +
  				"SELECT ?x ?i ?e \n" +
  				"WHERE {\n" +
  				"?x :firstName ?l1 .\n" +
  				"OPTIONAL { \n" +
  				"    ?x :playsInstrument ?i .\n" +
  				"       OPTIONAL {\n" +
  				"         ?e a :EmptyElement .\n " +
  				"         ?r a :Musician \n" +
  				"       }\n" +
  				"  }\n" +
  				"}\n";
  
  		ImmutableSet<String> expectedValues = ImmutableSet.of(
  				"<http://example.com/person/1>",
  				"<http://example.com/person/2>",
  				"<http://example.com/person/3>"
  		);
  		checkReturnedValues(query, expectedValues);
  	}
  
      private void checkReturnedValues(String query, Set<String> expectedValues) throws Exception {
  
          // Now we are ready for querying
          OWLConnection conn = REASONER.getConnection();
          OWLStatement st = conn.createStatement();
  
          Set<String> returnedValues = new HashSet<>();
          try {
              TupleOWLResultSet rs = st.executeSelectQuery(query);
  
              while (rs.hasNext()) {
                  final OWLBindingSet bindingSet = rs.next();
  
  				OWLObject value = bindingSet.getOWLObject("x");
  				String stringValue = (value instanceof OWLLiteral)
  						? ((OWLLiteral) value).getLiteral()
  						: (value == null) ? null : value.toString();
  
                  returnedValues.add(stringValue);
              }
          } finally {
              conn.close();
          }
          assertTrue(String.format("%s instead of \n %s", returnedValues.toString(), expectedValues.toString()),
                  returnedValues.equals(expectedValues));
      }
  
      private int runConstructQuery(String constructQuery) throws Exception {
  		int count = 0;
  		try (OWLConnection conn = REASONER.getConnection();
  			 OWLStatement st = conn.createStatement()) {
  			GraphOWLResultSet rs = st.executeConstructQuery(constructQuery);
  			while (rs.hasNext()) {
  				OWLAxiom axiom = rs.next();
  				LOGGER.debug(axiom.toString());
  				count++;
  			}
  		}
  		return count;
  	}
  
  
  }
  