8.14 Oracle RDF Graph Adapter for Eclipse RDF4Jを使用した問合せの例

この項では、Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための問合せの例を示します。

これらの例を実行するには、Javaコードでアダプタを使用するためのサポート・ライブラリで説明されているすべてのサポート・ライブラリがCLASSPATH定義に含まれていることを確認します。

問合せを実行するには、次のアクションを実行する必要があります。
  1. コード例をJavaソース・ファイルに含めます。
  2. CPという名前のCLASSPATH環境変数を定義して、関連するjarファイルを含めます。たとえば、次のように定義できます。
    setenv CP .:ojdbc8.jar:ucp.jar:oracle-rdf4j-adapter-4.3.14-20250106.jar:sdordf-23.6.0-20241122.jar:
    sdordf-client-23.6.0-20241122.jar:sdoutl-23.6.0-20241122.jar:log4j-api-2.24.2.jar:log4j-core-2.24.2.jar:
    log4j-slf4j-impl-2.24.2.jar:slf4j-api-1.7.36.jar:eclipse-rdf4j-4.3.14-onejar.jar:commons-io-2.14.0.jar

    ノート:

    前述のsetenvコマンドは、jarファイルが現在のディレクトリにあることを前提としています。コマンドを変更して、これらのjarファイルの環境内の場所を示す必要がある場合があります。
  3. Javaソース・ファイルをコンパイルします。たとえば、ソース・ファイルTest.javaをコンパイルするには、次のコマンドを実行します。
    javac -classpath $CP Test.java
  4. 次のコマンドを実行することで、コンパイルされたファイルを、所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークのTestModelという名前のRDFグラフを実行します。
    java -classpath $CP Test jdbc:oracle:thin:@localhost:1521:orcl scott  <password-for-scott> TestModel scott net1

8.14.1 例1: 基本操作

例8-5に、add文やremove文などの基本操作を実行するBasicOper.javaファイルを示します。

例8-5 基本操作

import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.sail.SailException;

public class BasicOper {
  public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;
    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    OracleSailConnection conn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);

      ValueFactory f = sr.getValueFactory();
      conn = store.getConnection();

      // create some resources and literals to make statements out of
      IRI p = f.createIRI("http://p");
      IRI domain = f.createIRI("http://www.w3.org/2000/01/rdf-schema#domain");
      IRI cls = f.createIRI("http://cls");
      IRI a = f.createIRI("http://a");
      IRI b = f.createIRI("http://b");
      IRI ng1 = f.createIRI("http://ng1");

      conn.addStatement(p, domain, cls);
      conn.addStatement(p, domain, cls, ng1);
      conn.addStatement(a, p, b, ng1);
      psOut.println("size for given contexts " + ng1 + ": " + conn.size(ng1));
      
      // returns OracleStatements
      CloseableIteration < ?extends Statement, SailException > it;
      int cnt;
      
      // retrieves all statements that appear in the repository(regardless of context)
      cnt = 0;
      it = conn.getStatements(null, null, null, false);
      while (it.hasNext()) {
        Statement stmt = it.next();
        psOut.println("getStatements: stmt#" + (++cnt) + ":" + stmt.toString());
      }
      it.close();
      conn.removeStatements(null, null, null, ng1);
      psOut.println("size of context " + ng1 + ":" + conn.size(ng1));
      conn.removeAll();
      psOut.println("size of store: " + conn.size());
    }
    
    finally {
      if (conn != null && conn.isOpen()) {
        conn.close();
      }
      if (op != null && op.getOracleDB() != null)

      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      if (sr != null) sr.shutDown();
      if (store != null) store.shutDown();
      if (op != null) op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP BasicOper.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP BasicOper jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1

javaコマンドの出力は、次のようになります。

size for given contexts http://ng1: 2
getStatements: stmt#1: (http://a, http://p, http://b) [http://ng1]
getStatements: stmt#2: (http://p, http://www.w3.org/2000/01/rdf-schema#domain, http://cls) [http://ng1]
getStatements: stmt#3: (http://p, http://www.w3.org/2000/01/rdf-schema#domain, http://cls) [null]
size of context http://ng1:0
size of store: 0

8.14.2 例2: TRIG形式でのデータ・ファイルの追加

例8-6に、TRIG形式でファイルをロードする方法を示すLoadFile.javaファイルを示します。

例8-6 TRIG形式のデータ・ファイルの追加

import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;

public class LoadFile {
  public static void main(String[] args) throws ConnectionSetupException,
    SQLException, SailException, RDFParseException, RepositoryException,
    IOException {
    
      PrintStream psOut = System.out;
      String jdbcUrl = args[0];
      String user = args[1];
      String password = args[2];
      String model = args[3];
      String trigFile = args[4];
      String networkOwner = (args.length > 6) ? args[5] : null;
      String networkName = (args.length > 6) ? args[6] : null;

 
      OraclePool op = null;
      OracleSailStore store = null;
      Repository sr = null;
      RepositoryConnection repConn = null;
 
      try {
        op = new OraclePool(jdbcUrl, user, password);
        store = new OracleSailStore(op, model, networkOwner, networkName);
        sr = new OracleRepository(store);
        repConn = sr.getConnection();
        psOut.println("testBulkLoad: start: before-load Size=" + repConn.size());
        repConn.add(new File(trigFile), "http://my.com/", RDFFormat.TRIG);
        repConn.commit();
        psOut.println("size " + Long.toString(repConn.size()));
      }
      finally {
        if (repConn != null) {
          repConn.close();
        }
        if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
        if (sr != null) sr.shutDown();
        if (store != null) store.shutDown();
        if (op != null) op.close();
      }
  }
}

この例を実行するため、次のようなサンプルのTriGデータ・ファイルがtest.trigという名前で作成されているとします。


@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix swp: <http://www.w3.org/2004/03/trix/swp-1/>.
@prefix dc: <http://purl.org/dc/elements/1.1/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix ex: <http://example.org/>.
@prefix : <http://example.org/>.
# default graph
{
  <http://example.org/bob>   dc:publisher "Bob Hacker".
  <http://example.org/alice> dc:publisher "Alice Hacker".
} 
:bob{
    _:a foaf:mbox <mailto:bob@oldcorp.example.org>.
    } 
:alice{
      _:a foaf:name "Alice".
      _:a foaf:mbox <mailto:alice@work.example.org>.
      } 
:jack {
      _:a foaf:name "Jack".
      _:a foaf:mbox <mailto:jack@oracle.example.org>.
      }

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP LoadFile.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP LoadFile jdbc:oracle:thin:@localhost:1521:ORCL scott <password>  TestModel ./test.trig scott net1

javaコマンドの出力は、次のようになります。

testBulkLoad: start: before-load Size=0
size 7

8.14.3 例3: 単純な問合せ

例3: 単純な問合せに、単純な問合せの実行方法を示すSimpleQuery.javaファイルを示します。

例8-7 単純な問合せ


import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class SimpleQuery {
  public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);

      ValueFactory f = sr.getValueFactory();
      conn = sr.getConnection();

      // create some resources and literals to make statements out of
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI name = f.createIRI("http://example.org/ontology/name");
      IRI person = f.createIRI("http://example.org/ontology/Person");
      Literal alicesName = f.createLiteral("Alice");

      conn.clear(); // to start from scratch
      conn.add(alice, RDF.TYPE, person);
      conn.add(alice, name, alicesName);
      conn.commit();
      
      //run a query against the repository
      String queryString = 
        "PREFIX ex: <http://example.org/ontology/>\n" + 
        "SELECT * WHERE {?x ex:name ?y}\n" + 
        "ORDER BY ASC(STR(?y)) LIMIT 1 ";
      TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);

      try (TupleQueryResult result = tupleQuery.evaluate()) {
        while (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("value of x: " + bindingSet.getValue("x"));
          psOut.println("value of y: " + bindingSet.getValue("y"));
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SimpleQuery.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SimpleQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1

javaコマンドの出力は、次のようになります。


value of x: http://example.org/people/alice
value of y: "Alice"

8.14.4 例4: 単純なバルク・ロード

例8-8に、NTriplesデータからバルク・ロードする方法を示すSimpleBulkload.javaファイルを示します。

例8-8 単純なバルク・ロード


import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.repository.Repository;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;

public class SimpleBulkLoad {
  public static void main(String[] args) throws ConnectionSetupException, SQLException,
    SailException, RDFParseException, RepositoryException, IOException {
      PrintStream psOut = System.out;
      String jdbcUrl = args[0];
      String user = args[1];
      String password = args[2];
      String model = args[3];
      String filename = args[4]; // N-TRIPLES file
      String networkOwner = (args.length > 6) ? args[5] : null;
      String networkName = (args.length > 6) ? args[6] : null;


      OraclePool op = new OraclePool(jdbcUrl, user, password);
      OracleSailStore store = new OracleSailStore(op, model, networkOwner, networkName);
      OracleSailConnection osc = store.getConnection();
      Repository sr = new OracleRepository(store);
      ValueFactory f = sr.getValueFactory();

      try {
        psOut.println("testBulkLoad: start");

        FileInputStream fis = new
        FileInputStream(filename);

        long loadBegin = System.currentTimeMillis();
        IRI ng1 = f.createIRI("http://QuadFromTriple");
        osc.getBulkUpdateHandler().addInBulk(
        fis, "http://abc",  // baseURI
        RDFFormat.NTRIPLES, // dataFormat
        null,               // tablespaceName
        50,                 // batchSize
        null,               // flags
        ng1                 // Resource... for contexts
        );

        long loadEnd = System.currentTimeMillis();
        long size_no_contexts = osc.size((Resource) null);
        long size_all_contexts = osc.size();

        psOut.println("testBulkLoad: " + (loadEnd - loadBegin) +
         "ms. Size:" + " NO_CONTEXTS=" + size_no_contexts + " ALL_CONTEXTS=" + size_all_contexts);
        // cleanup
        osc.removeAll();
        psOut.println("size of store: " + osc.size());

      }
      finally {
        if (osc != null && osc.isOpen()) osc.close();
        if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
        if (sr != null) sr.shutDown();
        if (store != null) store.shutDown();
        if (op != null) op.close();
      }
  }
}

この例を実行するため、次のようなサンプルのntripleデータ・ファイルがtest.ntriplesという名前で作成されているとします。


<urn:JohnFrench> <urn:name> "John".
<urn:JohnFrench> <urn:speaks> "French".
<urn:JohnFrench> <urn:height> <urn:InchValue>.
<urn:InchValue> <urn:value> "63".
<urn:InchValue> <urn:unit> "inch".
<http://data.linkedmdb.org/movie/onto/genreNameChainElem1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://data.linkedmdb.org/movie/genre>.

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SimpleBulkLoad.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SimpleBulkLoad jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.ntriples scott net1

javaコマンドの出力は、次のようになります。

testBulkLoad: start
testBulkLoad: 8222ms. 
Size: NO_CONTEXTS=0 ALL_CONTEXTS=6
size of store: 0

8.14.5 例5: RDF/XMLのバルク・ロード

例5: RDF/XMLのバルク・ロードに、RDF/XMLファイルからバルク・ロードする方法を示すBulkLoadRDFXML.javaファイルを示します。

例8-9 RDF/XMLのバルク・ロード


import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;

public class BulkLoadRDFXML {
  public static void main(String[] args) throws
    ConnectionSetupException, SQLException, SailException,
    RDFParseException, RepositoryException, IOException {
      PrintStream psOut = System.out;
      String jdbcUrl = args[0];
      String user = args[1];
      String password = args[2];
      String model = args[3];
      String rdfxmlFile = args[4]; // RDF/XML-format data file
      String networkOwner = (args.length > 6) ? args[5] : null;
      String networkName = (args.length > 6) ? args[6] : null;


      OraclePool op = null;
      OracleSailStore store = null;
      Repository sr = null;
      OracleSailConnection conn = null;
            
      try {
        op = new OraclePool(jdbcUrl, user, password);
        store = new OracleSailStore(op, model, networkOwner, networkName);
        sr = new OracleRepository(store);
        conn = store.getConnection();
        
        FileInputStream fis = new FileInputStream(rdfxmlFile);
        psOut.println("testBulkLoad: start: before-load Size=" + conn.size());
        long loadBegin = System.currentTimeMillis();
        conn.getBulkUpdateHandler().addInBulk(
          fis, 
          "http://abc",      // baseURI
          RDFFormat.RDFXML,  // dataFormat
          null,              // tablespaceName
          null,              // flags
          null,             //  StatusListener
          (Resource[]) null //  Resource...for contexts
        );

        long loadEnd = System.currentTimeMillis();
        psOut.println("testBulkLoad: " + (loadEnd - loadBegin) + "ms. Size=" + conn.size() + "\n");
      }
      finally {
        if (conn != null && conn.isOpen()) {
          conn.close();
        }
        if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
        if (sr != null) sr.shutDown();
        if (store != null) store.shutDown();
        if (op != null) op.close();
      }
  }
}

この例を実行するため、次のようなサンプル・ファイルがRdfXmlData.rdfxmlという名前で作成されているとします。


<?xml version="1.0"?>
<!DOCTYPE owl [     
  <!ENTITY owl  "http://www.w3.org/2002/07/owl#" >     
  <!ENTITY xsd  "http://www.w3.org/2001/XMLSchema#" >   
]> 
<rdf:RDF  
  xmlns     = "http://a/b#" xml:base  = "http://a/b#" xmlns:my  = "http://a/b#"  
  xmlns:owl = "http://www.w3.org/2002/07/owl#"  
  xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
  xmlns:rdfs= "http://www.w3.org/2000/01/rdf-schema#"  
  xmlns:xsd = "http://www.w3.org/2001/XMLSchema#">  
  <owl:Class rdf:ID="Color">    
    <owl:oneOf rdf:parseType="Collection">      
      <owl:Thing rdf:ID="Red"/>      
      <owl:Thing rdf:ID="Blue"/>    
    </owl:oneOf>  
  </owl:Class>
</rdf:RDF>

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP BulkLoadRDFXML.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP BulkLoadRDFXML jdbc:oracle:thin:@localhost:1521:ORCL scott <password>  TestModel ./RdfXmlData.rdfxml scott net1

javaコマンドの出力は、次のようになります。

testBulkLoad: start: before-load Size=0
testBulkLoad: 6732ms. Size=8

8.14.6 例6: SPARQL ASK問合せ

例6: SPARQL ASK問合せに、SPARQL ASK問合せの実行方法を示すSparqlASK.javaファイルを示します。

例8-10 SPARQL ASK問合せ

import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BooleanQuery;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class SparqlASK {
  public static void main(String[] args) throws ConnectionSetupException, SQLException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();
      OracleSailConnection osc = 
        (OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();

      ValueFactory vf = sr.getValueFactory();
      IRI p = vf.createIRI("http://p");
      IRI cls = vf.createIRI("http://cls");

      conn.clear();
      conn.add(p, RDFS.DOMAIN, cls);
      conn.commit();

      osc.analyze();                 // analyze the semantic model
      osc.analyzeApplicationTable(); // and then the application table
      BooleanQuery tq = null;
      tq = conn.prepareBooleanQuery(QueryLanguage.SPARQL, "ASK { ?x ?p <http://cls> }");
      boolean b = tq.evaluate();
      psOut.println("\nAnswer is " + Boolean.toString(b));
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SparqlASK.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SparqlASK jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1

javaコマンドの出力は、次のようになります。

Answer is true

8.14.7 例7: SPARQLのCONSTRUCT問合せ

例8-11に、SPARQLのCONSTRUCT問合せの実行方法を示すSparqlConstruct.javaファイルを示します。

例8-11 SPARQL CONSTRUCT問合せ


import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.GraphQuery;
import org.eclipse.rdf4j.query.GraphQueryResult;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class SparqlConstruct {
  public static void main(String[] args) throws ConnectionSetupException, SQLException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      ValueFactory vf = sr.getValueFactory();
      IRI p = vf.createIRI("http://p");
      IRI cls = vf.createIRI("http://cls");

      conn.clear();
      conn.add(p, RDFS.DOMAIN, cls);
      conn.commit();
      OracleSailConnection osc = 
        (OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
      osc.analyze();                 // analyze the RDF graph
      osc.analyzeApplicationTable(); // and then the application table
                                     
      GraphQuery tq = null;          // Construct Query
      tq = conn.prepareGraphQuery(QueryLanguage.SPARQL, 
        "CONSTRUCT {?x <http://new_eq_p> ?o } WHERE { ?x ?p ?o }");
      psOut.println("Start construct query");

      try (GraphQueryResult result = tq.evaluate()) {
        while (result.hasNext()) {
          Statement stmt = (Statement) result.next();
          psOut.println(stmt.toString());
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SparqlConstruct.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SparqlConstruct jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1

javaコマンドの出力は、次のようになります。

Start construct query
(http://p, http://new_eq_p, http://cls)

8.14.8 例8: 名前付きグラフ問合せ

例8-12に、名前付きグラフ問合せの実行方法を示すNamedGraph.javaファイルを示します。

例8-12 名前付きグラフ問合せ


import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.rio.RDFFormat;

public class NamedGraph {
  public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String trigFile = args[4]; // TRIG-format data file
    String networkOwner = (args.length > 6) ? args[5] : null;
    String networkName = (args.length > 6) ? args[6] : null;

    
    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      conn.begin();
      conn.clear();

      // load the data incrementally since it is very small file
      conn.add(new File(trigFile), "http://my.com/", RDFFormat.TRIG);
      conn.commit();

      OracleSailConnection osc = (OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();

      osc.analyze(); // analyze the RDF graph
      osc.analyzeApplicationTable(); // and then the application table
      TupleQuery tq = null;
      tq = conn.prepareTupleQuery(QueryLanguage.SPARQL,
             "PREFIX : <http://purl.org/dc/elements/1.1/>\n" +
             "SELECT ?g ?s ?p ?o\n" +
             "WHERE {?g :publisher ?o1 . GRAPH ?g {?s ?p ?o}}\n" +
             "ORDER BY ?g ?s ?p ?o");
      try (TupleQueryResult result = tq.evaluate()) {
        int idx = 0;
        while (result.hasNext()) {
          idx++;
          BindingSet bindingSet = result.next();
          psOut.print("\nsolution " + bindingSet.toString());
        }
        psOut.println("\ntotal # of solution " + Integer.toString(idx));
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null,  networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例を実行するため、TRIG形式のtest.trigファイルが次のように作成されているとします。


@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix swp: <http://www.w3.org/2004/03/trix/swp-1/>.
@prefix dc: <http://purl.org/dc/elements/1.1/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix : <http://example.org/>.
# default graph
{
  :bobGraph    dc:publisher  "Bob Hacker" .
  :aliceGraph  dc:publisher  "Alice Hacker" .
}
 
:bobGraph {
  :bob foaf:mbox <mailto:bob@oldcorp.example.org> .
}
 
:aliceGraph {
  :alice foaf:name "Alice" .
  :alice foaf:mbox <mailto:alice@work.example.org> .
}
 
:jackGraph {
  :jack foaf:name "Jack" .
  :jack foaf:mbox <mailto:jack@oracle.example.org> .
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP NamedGraph.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP NamedGraph jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.trig scott net1

javaコマンドの出力は、次のようになります。


solution 
[p=http://xmlns.com/foaf/0.1/mbox;s=http://example.org/alice;g=http://example.org/aliceGraph;o=mailto:alice@work.example.org]
solution 
[p=http://xmlns.com/foaf/0.1/name;s=http://example.org/alice;g=http://example.org/aliceGraph;o="Alice"]
solution 
[p=http://xmlns.com/foaf/0.1/mbox;s=http://example.org/bob;g=http://example.org/bobGraph;o=mailto:bob@oldcorp.example.org]
total # of solution 3

8.14.9 例9: 一致件数の取得

例8-13に、一致の合計件数(COUNT)を返す問合せの実行方法を示すCountQuery.javaファイルを示します。

例8-13 一致件数の取得

import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class CountQuery {
  public static void main(String[] args) throws
    ConnectionSetupException, SQLException 
  {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      ValueFactory f = conn.getValueFactory();

      // create some resources and literals to make statements out of
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI name = f.createIRI("http://example.org/ontology/name");
      IRI person = f.createIRI("http://example.org/ontology/Person");
      Literal alicesName = f.createLiteral("Alice");

      conn.begin();
      // clear model to start fresh
      conn.clear();
      conn.add(alice, RDF.TYPE, person);
      conn.add(alice, name, alicesName);
      conn.commit();

      OracleSailConnection osc = 
        (OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
      osc.analyze();
      osc.analyzeApplicationTable();

      // Run a query and only return the number of matches (the count ! )
      String queryString = " SELECT (COUNT(*) AS ?totalCount) WHERE {?s ?p ?y} ";

      TupleQuery tupleQuery = conn.prepareTupleQuery(
      QueryLanguage.SPARQL, queryString);

      try (TupleQueryResult result = tupleQuery.evaluate()) {
        if (result.hasNext()) {
          BindingSet bindingSet = result.next();
          String totalCount = bindingSet.getValue("totalCount").stringValue();
          psOut.println("number of matches: " + totalCount);
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP CountQuery.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP CountQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1

javaコマンドの出力は、次のようになります。


number of matches: 2

8.14.10 例10: 問合せパターンの定数に対するバインド変数の指定

例8-13に、SPARQL問合せパターンの定数に対するバインド変数を指定する問合せの実行方法を示すBindVar.javaファイルを示します。

例8-14 問合せパターンの定数に対するバインド変数の指定


import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class BindVar {
  public static void main(String[] args) throws ConnectionSetupException, SQLException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();
      ValueFactory f = conn.getValueFactory();

      conn.begin();
      conn.clear();

      // create some resources and literals to make statements out of
      
      // Alice
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI name = f.createIRI("http://example.org/ontology/name");
      IRI person = f.createIRI("http://example.org/ontology/Person");
      Literal alicesName = f.createLiteral("Alice");
      conn.add(alice, RDF.TYPE, person);
      conn.add(alice, name, alicesName);

      //Bob
      IRI bob = f.createIRI("http://example.org/people/bob");
      Literal bobsName = f.createLiteral("Bob");
      conn.add(bob, RDF.TYPE, person);
      conn.add(bob, name, bobsName);

      conn.commit();

      String queryString = 
        " PREFIX ex: <http://example.org/ontology/> " + 
        " Select ?name \n" + " WHERE \n" + " { SELECT * WHERE { ?person ex:name ?name} }\n" + 
        " ORDER BY ?name";

      TupleQuery tupleQuery = conn.prepareTupleQuery(
      QueryLanguage.SPARQL, queryString);

      // set binding for ?person = Alice
      tupleQuery.setBinding("person", alice);
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        if (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("solution " + bindingSet.toString());
        }
      }

      // re-run with ?person = Bob
      tupleQuery.setBinding("person", bob);
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        if (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("solution " + bindingSet.toString());
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP BindVar.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP BindVar jdbc:oracle:thin:@localhost:1521:ORCL scott  <password> TestModel scott net1

javaコマンドの出力は、次のようになります。


solution [name="Alice";person=http://example.org/people/alice]
solution [name="Bob";person=http://example.org/people/bob]

8.14.11 例11: SPARQLの更新

例8-15に、SPARQL更新文の実行方法を示すSparqlUpdate.javaファイルを示します。

例8-15 SPARQLの更新

import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.query.Update;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class SparqlUpdate {
  private static final String DATA_1 =
    "[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Sue\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";

  private static final String DATA_2 =
    "[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";

  private static final String DATA_3 =
    "[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
    "[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";

  private static final String DATA_4 = 
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
    "[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";

  private static final String DATA_5 =
    "[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
    "[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
    "[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
  
  private static String getRepositoryData(RepositoryConnection conn, PrintStream out) 
  {
    String dataStr = "";
    String queryString = "SELECT * WHERE { GRAPH ?g { ?x ?p ?y } } ORDER BY ?g ?x ?p ?y";
    TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
    try (TupleQueryResult result = tupleQuery.evaluate()) {
      while (result.hasNext()) {
        BindingSet bindingSet = result.next();
        out.println(bindingSet.toString());
        dataStr += bindingSet.toString();
      }
    }
    return dataStr;
  }
  public static void main(String[] args) throws
    ConnectionSetupException, SQLException 
  {
    PrintStream out = new PrintStream(System.out);
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      conn.clear(); // to start from scratch
      
      // Insert some initial data
      String updString = "PREFIX people: <http://example.org/people/>\n" +
                         "PREFIX    ont: <http://example.org/ontology/>\n" +
                         "INSERT DATA { GRAPH <urn:g1> { \n" + 
                         "              people:Sue a ont:Person; \n" + 
                         "                ont:name \"Sue\" . } }";
      Update upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();
      String repositoryData = getRepositoryData(conn, out);
      if (! (DATA_1.equals(repositoryData)) ) out.println("DATA_1 mismatch");
      // Change Sue's name to Susan
      updString = "PREFIX people: <http://example.org/people/>\n" +
                  "PREFIX    ont: <http://example.org/ontology/>\n" +
                  "DELETE { GRAPH ?g { ?s ont:name ?n } }\n" +
                  "INSERT { GRAPH ?g { ?s ont:name \"Susan\" } }\n" +
                  "WHERE  { GRAPH ?g { ?s ont:name ?n FILTER (?n = \"Sue\") }}";
      upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();
      repositoryData = getRepositoryData(conn, out);
      if (! (DATA_2.equals(repositoryData)) ) out.println("DATA_2 mismatch");

      // Copy to contents of g1 to a new graph g2
      updString = "PREFIX people: <http://example.org/people/>\n" +
                  "PREFIX ont: <http://example.org/ontology/>\n" +
                  "COPY <urn:g1> TO <urn:g2>";
      upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();

      repositoryData = getRepositoryData(conn, out);
      if (! (DATA_3.equals(repositoryData)) ) out.println("DATA_3 mismatch");

      // Delete ont:name triple from graph g1
      updString = "PREFIX people: <http://example.org/people/>\n" + 
                  "PREFIX  ont: <http://example.org/ontology/>\n" +
                  "DELETE DATA { GRAPH <urn:g1> { people:Sue ont:name \"Susan\" } }";
      upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();
      repositoryData = getRepositoryData(conn, out);
      if (! (DATA_4.equals(repositoryData)) ) out.println("DATA_4 mismatch");

      // Add contents of g2 to g1
      updString = "PREFIX people: <http://example.org/people/>\n" +
                  "PREFIX    ont: <http://example.org/ontology/>\n" +
                  "ADD <urn:g2> TO <urn:g1>";
      upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();
      repositoryData = getRepositoryData(conn, out);
      if (! (DATA_5.equals(repositoryData)) ) out.println("DATA_5 mismatch");
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SparqlUpdate.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SparqlUpdate jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1

javaコマンドの出力は、次のようになります。

[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Sue"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]

8.14.12 例12: Oracleヒント

例8-16に、SPARQL問合せまたはSPARQL更新でOracleヒントを使用する方法を示すOracleHint.javaファイルを示します。

例8-16 Oracleヒント

import java.sql.SQLException;
import oracle.rdf4j.adapter.OracleDB;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.query.Update;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class OracleHint {
  public static void main(String[] args) throws ConnectionSetupException, SQLException {
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;


    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      conn.clear(); // to start from scratch
      
      // Insert some initial data
      String updString = 
        "PREFIX ex: <http://example.org/>\n" +
        "INSERT DATA {  " +
        "  ex:a ex:p1 ex:b . " +
        "  ex:b ex:p1 ex:c . " + 
        "  ex:c ex:p1 ex:d . " +
        "  ex:d ex:p1 ex:e . " +
        "  ex:e ex:p1 ex:f . " + 
        "  ex:f ex:p1 ex:g . " + 
        "  ex:g ex:p1 ex:h . " + 
        "  ex:h ex:p1 ex:i . " + 
        "  ex:i ex:p1 ex:j . " + 
        "  ex:j ex:p1 ex:k . " + 
        "}";
      Update upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
      upd.execute();
      conn.commit();
      
      // default behavior for property path is 10 hop max, so we get 11 results
      String sparql = 
        "PREFIX ex: <http://example.org/>\n" + 
        "SELECT (COUNT(*) AS ?cnt)\n" + 
        "WHERE { ex:a ex:p1* ?y }";
      
      TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);

      try (TupleQueryResult result = tupleQuery.evaluate()) {
        while (result.hasNext()) {
          BindingSet bindingSet = result.next();
          if (11 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 11");
        }
      }

      // ORACLE_SEM_FS_NS prefix hint to use parallel(2) and dynamic_sampling(6)
      // ORACLE_SEM_SM_NS prefix hint to use a 5 hop max and to use CONNECT BY instead of simple join
      sparql = 
        "PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=2,ods=6>\n" +
        "PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(5),all_disable_pp_sj>\n" +
        "PREFIX ex: <http://example.org/>\n" + 
        "SELECT (COUNT(*) AS ?cnt)\n" + 
        "WHERE { ex:a ex:p1* ?y }";
      
      tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql, "http://example.org/");

      try (TupleQueryResult result = tupleQuery.evaluate()) {
        while (result.hasNext()) {
          BindingSet bindingSet = result.next();
          if (6 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 6");
        }
      }

      // query options for SPARQL Update      
      sparql = 
        "PREFIX ORACLE_SEM_UM_NS: <http://oracle.com/semtech#parallel(2)>\n" +
        "PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(5),all_disable_pp_sj>\n" +
        "PREFIX ex: <http://example.org/>\n" + 
        "INSERT { GRAPH ex:g1 { ex:a ex:reachable ?y } }\n" + 
        "WHERE { ex:a ex:p1* ?y }";

      Update u = conn.prepareUpdate(sparql);
      u.execute();

      // graph ex:g1 should have 6 results because of all_max_pp_depth(5)
      sparql = 
        "PREFIX ex: <http://example.org/>\n" + 
        "SELECT (COUNT(*) AS ?cnt)\n" + 
        "WHERE { GRAPH ex:g1 { ?s ?p ?o } }";
      
      tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql, "http://example.org/");

      try (TupleQueryResult result = tupleQuery.evaluate()) {
        while (result.hasNext()) {
          BindingSet bindingSet = result.next();
          if (6 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 6");
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP OracleHint.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP OracleHint jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1

8.14.13 例13: JDBCバインド値の使用

例8-17に、JDBCバインド値の使用方法を示すJDBCBindVar.javaファイルを示します。

例8-17 JDBCバインド値の使用

import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OracleDB;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;

public class JDBCBindVar {

  public static void main(String[] args) throws ConnectionSetupException, SQLException {
    PrintStream psOut = System.out;
    
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;
    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null; 

    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = (networkName == null) ? new OracleSailStore(op, model) : new OracleSailStore(op, model, networkOwner, networkName);   
      sr = new OracleRepository(store);
      conn = sr.getConnection();

      ValueFactory f = conn.getValueFactory();
      
      conn.begin();
      conn.clear();
  
      // create some resources and literals to make statements out of
      // Alice
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI name = f.createIRI("http://example.org/ontology/name");
      IRI person = f.createIRI("http://example.org/ontology/Person");
      Literal alicesName = f.createLiteral("Alice");   
      conn.add(alice, RDF.TYPE, person);
      conn.add(alice, name, alicesName);
      
      //Bob
      IRI bob = f.createIRI("http://example.org/people/bob");
      Literal bobsName = f.createLiteral("Bob");   
      conn.add(bob, RDF.TYPE, person);
      conn.add(bob, name, bobsName);
      
      conn.commit();
      
      // Query using USE_BIND_VAR=JDBC option for JDBC bind values
      // Simple BIND clause for ?person marks ?person as a bind variable
      String queryString =
        " PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>\n" +
        " PREFIX ex: <http://example.org/ontology/>\n" +
        " Select ?name \n" +
        " WHERE \n" +
        " { SELECT * WHERE { \n" +
        "     BIND (\"\" AS ?person) \n" +
        "     ?person ex:name ?name } \n" +
        " }\n" +
        " ORDER BY ?name";      
      TupleQuery tupleQuery = conn.prepareTupleQuery(
          QueryLanguage.SPARQL, queryString);
      
      // set binding for ?person = Alice
      tupleQuery.setBinding("person", alice);
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        if (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("solution " + bindingSet.toString());
        }
      }
      
      // re-run with ?person = Bob
      tupleQuery.setBinding("person", bob);
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        if (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("solution " + bindingSet.toString());        
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      if (op != null) {
        OracleDB oracleDB = op.getOracleDB();
        if (networkName == null)
          OracleUtils.dropSemanticModelAndTables(oracleDB, model);
        else
          OracleUtils.dropSemanticModelAndTables(oracleDB, model, null, null, networkOwner, networkName);
        op.returnOracleDBtoPool(oracleDB);
      }
      sr.shutDown();
      store.shutDown();
      op.close();    
      }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP JDBCBindVar.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP JDBCBindVar jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1

Javaコマンドの出力は、次のようになります。

solution [name="Alice";person=http://example.org/people/alice]
solution [name="Bob";person=http://example.org/people/bob]

8.14.14 例14: 単純な推論

例8-18に、SimpleInference.javaファイルを示します。このファイルは、OWL2RLルール・ベースを使用する単一のRDFグラフの推論を示します。

例8-18 単純な推論

import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import oracle.rdf4j.adapter.Attachment;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;

public class SimpleInference {
  public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String networkOwner = (args.length > 5) ? args[4] : null;
    String networkName = (args.length > 5) ? args[5] : null;

    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);

      // create a single-model, single-rulebase OracleSailStore object
      Attachment attachment = Attachment.createInstance(Attachment.NO_ADDITIONAL_MODELS, new String[] {"OWL2RL"});
      store = new OracleSailStore(op, model, attachment, networkOwner, networkName);
      sr = new OracleRepository(store);

      ValueFactory f = sr.getValueFactory();
      conn = sr.getConnection();

      // create some resources and literals to make statements out of
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI bob = f.createIRI("http://example.org/people/bob");
      IRI friendOf = f.createIRI("http://example.org/ontology/friendOf");
      IRI Person = f.createIRI("http://example.org/ontology/Person");
      IRI Engineer = f.createIRI("http://example.org/ontology/Engineer");
      IRI Doctor = f.createIRI("http://example.org/ontology/Doctor");

      conn.clear(); // to start from scratch

      // add some statements to the RDF graph
      conn.add(alice, RDF.TYPE, Engineer);
      conn.add(bob, RDF.TYPE, Doctor);
      conn.add(alice, friendOf, bob);
      conn.commit();

      OracleSailConnection osc = (OracleSailConnection)((OracleSailRepositoryConnection)conn).getSailConnection();

      // perform inference (this will not generate any inferred triples)
      osc.performInference();   

      // prepare a query to run against the repository
      String queryString = 
        "PREFIX ex: <http://example.org/ontology/>\n" + 
        "SELECT * WHERE {?x ex:friendOf ?y . ?x a ex:Person . ?y a ex:Person}\n" ;
      TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);

      // run the query: no results will be returned because nobody is a Person
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        int resultCount = 0;
        while (result.hasNext()) {
          resultCount++;
          BindingSet bindingSet = result.next();
          psOut.println("value of x: " + bindingSet.getValue("x"));
          psOut.println("value of y: " + bindingSet.getValue("y"));
        }
        psOut.println("number of results: " + resultCount);
      }

      // add class hierarchy
      conn.add(Doctor, RDFS.SUBCLASSOF, Person);
      conn.add(Engineer, RDFS.SUBCLASSOF, Person);
      conn.commit();

      // perform inference again
      osc.performInference();   

      // run the same query again: returns some results because alice and bob now belong to superclass Person
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        while (result.hasNext()) {
          BindingSet bindingSet = result.next();
          psOut.println("value of x: " + bindingSet.getValue("x"));
          psOut.println("value of y: " + bindingSet.getValue("y"));
        }
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SimpleInference.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SimpleInference jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1

Javaコマンドの出力は、次のようになります。

number of results: 0
value of x: http://example.org/people/alice
value of y: http://example.org/people/bob

8.14.15 例15: 単純なグラフ・コレクション

例8-19に、2つのRDFグラフで構成されるRDFグラフ・コレクションの作成と使用を示すSimpleVirtualModel.javaファイルを示します。

例8-19 単純なグラフ・コレクション

import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import oracle.rdf4j.adapter.Attachment;

public class SimpleVirtualModel {
  public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
    PrintStream psOut = System.out;
    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String model = args[3];
    String model2 = args[4];
    String virtualModelName = args[5];
    String networkOwner = (args.length > 7) ? args[6] : null;
    String networkName = (args.length > 7) ? args[7] : null;

    OraclePool op = null;

    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;

    OracleSailStore store2 = null;
    Repository sr2 = null;
    RepositoryConnection conn2 = null;

    OracleSailStore vmStore = null;
    Repository vmSr = null;
    RepositoryConnection vmConn = null;

    try {
      op = new OraclePool(jdbcUrl, user, password);

      // create two RDF graphs and then an RDF graph collection that uses those two graphs

      // create the first RDF grapj
      store = new OracleSailStore(op, model, networkOwner, networkName);
      sr = new OracleRepository(store);
      ValueFactory f = sr.getValueFactory();
      conn = sr.getConnection();
	  
      // create the second RDF graph (this one will be used as an additional graph in the attachment object)
      store2 = new OracleSailStore(op, model2, networkOwner, networkName);
      sr2 = new OracleRepository(store2);
      conn2 = sr2.getConnection();

      // create a two-graph RDF graph collection OracleSailStore object
      Attachment attachment = Attachment.createInstance(model2);
      vmStore = new OracleSailStore(op, model, /*ignored*/true, /*useVirtualModel*/true, virtualModelName, attachment, networkOwner, networkName);
      vmSr = new OracleRepository(vmStore);
      vmConn = vmSr.getConnection();

      // create some resources and literals to make statements out of
      IRI alice = f.createIRI("http://example.org/people/alice");
      IRI bob = f.createIRI("http://example.org/people/bob");
      IRI friendOf = f.createIRI("http://example.org/ontology/friendOf");
      IRI Person = f.createIRI("http://example.org/ontology/Person");
      IRI Engineer = f.createIRI("http://example.org/ontology/Engineer");
      IRI Doctor = f.createIRI("http://example.org/ontology/Doctor");

      // clear any data (in case any of the two non-virtual models were already present)
      conn.clear();
      conn2.clear();

      // add some statements to the first RDF model
      conn.add(alice, RDF.TYPE, Engineer);
      conn.add(bob, RDF.TYPE, Doctor);
      conn.add(alice, friendOf, bob);
      conn.commit();

      // prepare a query to run against the virtual model repository
      String queryString = 
        "PREFIX ex: <http://example.org/ontology/>\n" + 
        "SELECT * WHERE {" + 
        "?x ex:friendOf ?y . ?x rdf:type/rdfs:subClassOf* ?xC . ?y rdf:type/rdfs:subClassOf* ?yC" + 
        "} ORDER BY ?x ?xC ?y ?yC\n" ;
        ;
      TupleQuery tupleQuery = vmConn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);

      // run the query: no results will be returned because nobody is a Person
      try (TupleQueryResult result = tupleQuery.evaluate()) {
        int resultCount = 0;
        while (result.hasNext()) {
          resultCount++;
          BindingSet bindingSet = result.next();
          psOut.println("values of x | xC | y | yC: " + 
        		  bindingSet.getValue("x") + " | " + bindingSet.getValue("xC") + " | " + 
        		  bindingSet.getValue("y") + " | " + bindingSet.getValue("yC"));
        }
        psOut.println("number of results: " + resultCount);
      }

      // add class hierarchy info to the second model
      conn2.add(Doctor, RDFS.SUBCLASSOF, Person);
      conn2.add(Engineer, RDFS.SUBCLASSOF, Person);
      conn2.commit();

      // run the same query again: returns some additional info in the results
      try (TupleQueryResult result = tupleQuery.evaluate()) {
    	int resultCount = 0;
        while (result.hasNext()) {
          resultCount++;
          BindingSet bindingSet = result.next();
          psOut.println("values of x | xC | y | yC: " + 
        		  bindingSet.getValue("x") + " | " + bindingSet.getValue("xC") + " | " + 
        		  bindingSet.getValue("y") + " | " + bindingSet.getValue("yC"));
        }
        psOut.println("number of results: " + resultCount);
      }
    }
    finally {
      if (conn != null && conn.isOpen()) {
        conn.clear();
        conn.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
      sr.shutDown();
      store.shutDown();

      if (conn2 != null && conn2.isOpen()) {
          conn2.clear();
          conn2.close();
      }
      OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model2, null, null, networkOwner, networkName);
      sr2.shutDown();
      store2.shutDown();
      
      vmSr.shutDown();
      vmStore.shutDown();

      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP SimpleVirtualModel.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP SimpleVirtualModel jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel TestOntology TestVM scott net1

Javaコマンドの出力は、次のようになります。

values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Engineer | http://example.org/people/bob | http://example.org/ontology/Doctor
number of results: 1
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Person   | http://example.org/people/bob | http://example.org/ontology/Doctor
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Person   | http://example.org/people/bob | http://example.org/ontology/Person
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Engineer | http://example.org/people/bob | http://example.org/ontology/Doctor
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Engineer | http://example.org/people/bob | http://example.org/ontology/Person
number of results: 4

8.14.16 例16: SHACLによるグラフ検証

例8-20に、データ・グラフをRDFグラフDATA_GRAPH1にロードしてからこのデータをSHACL形状ex:AgeCountShapeに対して検証する、ShaclExample.javaファイルを示します。

例8-20 SHACL検証

import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;
import java.sql.SQLException;

import org.eclipse.rdf4j.common.exception.ValidationException;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.vocabulary.RDF4J;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.WriterConfig;
import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;

import oracle.rdf4j.adapter.OracleDB;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.shacl.OracleShaclSail;
import oracle.rdf4j.adapter.utils.OracleUtils;

public class ShaclExample {

  public static void main(String[] args) {
    PrintStream psOut = System.out;

    String jdbcUrl = args[0];
    String user = args[1];
    String password = args[2];
    String networkOwner = args[3];
    String networkName = args[4];
    
    String model = "DATA_GRAPH1";
    
    OraclePool op = null;
    OracleSailStore store = null;
    Repository sr = null;
    RepositoryConnection conn = null;
    
    try {
      op = new OraclePool(jdbcUrl, user, password);
      store = new OracleSailStore(op, model, networkOwner, networkName);   

      // load sample data graph
      try {
        sr = new OracleRepository(store);
        conn = sr.getConnection();
        
        StringReader sampleData = new StringReader(
            String.join(
              "\n", "",
              "@prefix ex: <http://oracle.example.com/ns#> .",
              
              "ex:Alice a ex:Person .",
              
              "ex:Bob a ex:Person ;",
              "  ex:age 20 .",
              
              "ex:Fred a ex:Person ;",
              "  ex:age 30 ;",
              "  ex:age 32 ."
            )
          );
      
        conn.begin();
        conn.add(sampleData, null, RDFFormat.TURTLE);
        conn.commit();
      } 
      catch (IOException e) {
        e.printStackTrace(psOut);
      }
      finally {
        conn.close();
        sr.shutDown();
      }
      
      // load SHACL shapes graph and validate data
      ShaclSail shaclSail = null;
      SailRepository shaclRepo = null;
      SailRepositoryConnection shaclConn = null;
      try {
        shaclSail = new OracleShaclSail(store);
        shaclRepo = new SailRepository(shaclSail);
        shaclRepo.init();
        
        shaclConn = shaclRepo.getConnection();

        // add SHACL shapes in a transaction
        // All instances of ex:Person should have exactly one value for ex:age
        StringReader sampleShape = new StringReader(
            String.join(
              "\n", "",
              "@prefix ex: <http://oracle.example.com/ns#> .",
              "@prefix sh: <http://www.w3.org/ns/shacl#> .",
              
              "ex:AgeCountShape",
              "  a sh:NodeShape ;",
              "  sh:targetClass ex:Person ;",
              "  sh:property [",
              "    sh:path ex:age ;",
              "    sh:maxCount 1 ;",
              "    sh:minCount 1 ;",
              "  ] ."
            )
          );
      
        shaclConn.begin();
        // add shape to the reserved named graph http://rdf4j.org/schema/rdf4j#SHACLShapeGraph
        // clear any existing shapes
        shaclConn.clear(RDF4J.SHACL_SHAPE_GRAPH);
        // add new shapes graph
        shaclConn.add(sampleShape, null, RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
        // commit runs bulk validation against the data graph
        shaclConn.commit();
      }
      catch (RDFParseException | IOException e) {
        e.printStackTrace(psOut);
      }
      // SHACL violation will throw a Repository Exception
      catch (RepositoryException e) {
        Throwable cause = e.getCause();
        // Handle validation exception
        if (cause instanceof ValidationException) {
          // Get validation report and print it out
          Model validationReportModel = ((ValidationException) cause).validationReportAsModel();

          WriterConfig writerConfig = new WriterConfig()
            .set(BasicWriterSettings.INLINE_BLANK_NODES, true)
            .set(BasicWriterSettings.XSD_STRING_TO_PLAIN_LITERAL, true)
            .set(BasicWriterSettings.PRETTY_PRINT, true);
         
          Rio.write(validationReportModel, psOut, RDFFormat.TURTLE, writerConfig);
        }
        else {
          e.printStackTrace(psOut);
        }
      }
      finally {
        shaclConn.close();
        shaclRepo.shutDown();
        shaclSail.shutDown();
      }
    }
    catch (SQLException e) {
      e.printStackTrace(psOut);
    }
    finally {
      if (op != null) {
        try {
          OracleDB oracleDB = op.getOracleDB();
          OracleUtils.dropSemanticModelAndTables(oracleDB, model, null, null, networkOwner, networkName);
          op.returnOracleDBtoPool(oracleDB);
        }
        catch (SQLException e) {
          e.printStackTrace(psOut);
        }
      }

      store.shutDown();
      op.close();
    }
  }
}

この例をコンパイルするには、次のコマンドを実行します。

javac -classpath $CP ShaclExample.java

所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。

java -classpath $CP ShaclExample jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> scott net1

このJavaコマンドの出力は、想定では次のようになります。なお、この場合は、ex:Aliceex:ageプロパティがないため制約に違反し、ex:Fredex:ageに2つの個別値があるため制約に違反します。

@prefix dash: <http://datashapes.org/dash#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rsx: <http://rdf4j.org/shacl-extensions#> .
@prefix rdf4j: <http://rdf4j.org/schema/rdf4j#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

[] a sh:ValidationReport;
  sh:conforms false;
  rdf4j:truncated false;
  sh:result [ a sh:ValidationResult;
      sh:focusNode <http://oracle.example.com/ns#Alice>;
      rsx:shapesGraph rdf4j:SHACLShapeGraph;
      sh:resultPath <http://oracle.example.com/ns#age>;
      sh:sourceConstraintComponent sh:MinCountConstraintComponent;
      sh:resultSeverity sh:Violation;
      sh:sourceShape _:c0d709142bb44448ad347272955741bc9
    ], [ a sh:ValidationResult;
      sh:focusNode <http://oracle.example.com/ns#Fred>;
      rsx:shapesGraph rdf4j:SHACLShapeGraph;
      sh:resultPath <http://oracle.example.com/ns#age>;
      sh:sourceConstraintComponent sh:MaxCountConstraintComponent;
      sh:resultSeverity sh:Violation;
      sh:sourceShape _:c0d709142bb44448ad347272955741bc9
    ] .

_:c0d709142bb44448ad347272955741bc9 a sh:PropertyShape;
  sh:path <http://oracle.example.com/ns#age>;
  sh:minCount 1;
  sh:maxCount 1 .