Difference between revisions of "Java Examples"

From Info216
Jump to: navigation, search
(Language-tagged literals (and functions, and services...))
Line 243: Line 243:
 
To go the other way (if our local labels were language-tagged and DBpedia's not, we could do a  
 
To go the other way (if our local labels were language-tagged and DBpedia's not, we could do a  
 
similar thing, but use the reverse ''str''-function instead of ''strlang''.
 
similar thing, but use the reverse ''str''-function instead of ''strlang''.
 +
 +
===Explanation of table.forEachRemaining(...)===
 +
 +
The lambda-syntax in this code line may be new for you:
 +
<nowiki>
 +
table.forEachRemaining(row -> System.out.println(row.toString()));</nowiki>
 +
 +
The straightforward way to write it '''(that doesn't work)''', would be just:
 +
<nowiki>
 +
table.forEachRemaining(System.out.println(row.toString()));</nowiki>
 +
But this doesn't work because we cannot send a method call as a paramter like that, and we
 +
introduce a ''row'' variable that is not declared anywhere.
 +
 +
Instead, we could try to define a new method somewhere else inside our class:
 +
<nowiki>
 +
void printRow(QuerySolution row) {
 +
System.out.println(row.toString());
 +
};</nowiki>
 +
and then pass that function to forEachRemaining
 +
'''(doesn't work either)''':
 +
<nowiki>
 +
table.forEachRemaining(printRow);</nowiki>
 +
But this doesn't work because you cannot pass functions as arguments like that in Java.
 +
 +
Finally, we could try to define a whole new class - a subclass of a Consumer class:
 +
<nowiki>
 +
class RowPrinter implements Consumer<QuerySolution> {
 +
public void accept(QuerySolution row) {
 +
System.out.println(row.toString());
 +
}
 +
}</nowiki>
 +
Here, we define the class RowPrinter as a ''Consumer'' or ''QuerySolution'', because Jena defines each row in a Query-Set-table to be a QuerySolution. In other words, we can view a ResultSet (table) as a ''stream'' of QuerySolutions (rows) that the RowPrinter consumes one by one.
 +
 +
We ''can'' pass an object of this class to forEachRemaining - it is exactly what it expects ('''this works!'''):
 +
<nowiki>
 +
table.forEachRemaining(new RowPrinter());</nowiki>
 +
 +
But it is pretty cumbersome to write a new class like RowPrinter every time we want to do a forEachRemaining-call - or another streaming call. Therefore Java 8 has introduced a shorthand, a ''lambda expression'':
 +
<nowiki>
 +
table.forEachRemaining(row -> )System.out.println(row.toString();</nowiki>
 +
Whenever Java 8 or later sees code like this, it behaves as if we had implemented a RowPrinter or similar Consumer-class like the one above.
  
 
&nbsp;
 
&nbsp;
  
 
<div class="credits" style="text-align: right; direction: ltr; margin-left: 1em;">''INFO216, UiB, Spring 2017-2018, Andreas L. Opdahl (c). All code examples are [https://creativecommons.org/choose/zero/ CC0].'' </div>
 
<div class="credits" style="text-align: right; direction: ltr; margin-left: 1em;">''INFO216, UiB, Spring 2017-2018, Andreas L. Opdahl (c). All code examples are [https://creativecommons.org/choose/zero/ CC0].'' </div>

Revision as of 15:18, 1 February 2018

Here are the code examples we have used in the live sessions during the lectures - along with a few additional ones.

(More will appear as the course progresses.)

Lecture 1: Java, Jena, and Eclipse

Hello Jena

package no.uib.sinoa.info216;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.FOAF;

public class HelloJena {

    public static void main(String[] args) {
       
        Model model = ModelFactory.createDefaultModel();
       
	Resource andreas = model.createResource(base + "Andreas");
	Resource info216 = model.createResource(base + "INFO216");
	Property teaches = model.createProperty(base + "teaches");
	andreas.addProperty(teaches, info216);

	andreas.addLiteral(FOAF.name, "Andreas L Opdahl");

        model.write(System.out, "TURTLE");
    }   
}

Lecture 2: RDF

Resource objects

package no.uib.infomedia.info216;

...

public class HelloJena {
    public static void main(String[] args) {
        String iriBase = "http://no.uib.infomedia.info216/";
        String iriDbpedia = "http://dbpedia.org/resource/";
       
        Model model = ModelFactory.createDefaultModel();
       
        Resource resCadeTracy = model.createResource(iriBase + "Cade_Tracy");
        resCadeTracy.addLiteral(FOAF.name, "Cade Tracy");
       
        Resource resCanada = model.createResource(iriDbpedia + "Canada");
        Resource resFrance = model.createResource(iriDbpedia + "France");
        Property propVisited = model.createProperty(iriBase + "visited");
        resCadeTracy.addProperty(propVisited, resCanada);
        resCadeTracy.addProperty(propVisited, resFrance);

        model.write(System.out, "TURTLE");
    }
}

Language-tagged literals

        resFrance.addProperty(RDFS.label, "Frankrike", "no");
        resFrance.addProperty(RDFS.label, "France", "en");
        resFrance.addProperty(RDFS.label, "Francia", "es");

Typed literals

        Property propPopEst = model.createProperty(iriDbpedia + "ontology/populationEstimate");
        resFrance.addProperty(propPopEst, "66644000", XSDDatatype.XSDinteger);

Looping through statements

        for (Statement stmt : model.listStatements().toList()) {
            System.out.println(stmt.toString());
        }

Selecting statements

        for (Statement stmt : model
                .listStatements((Resource)null, RDFS.label, (RDFNode)null)
                .toList()) {
            System.out.println("Subject:   " + stmt.getSubject().toString());
            System.out.println("Predicate: " + stmt.getPredicate().toString());
            System.out.println("Object:    " + stmt.getObject().toString());
        }

Using a selector

        for (Statement stmt : model
                .listStatements(new SimpleSelector() {
                    public boolean test(Statement s) {
                        return (s.getPredicate().equals(FOAF.name));
                    }
                })
                .toList()) {
            System.out.println(stmt.getObject().toString());
        }

Writing to file

        try {
            model.write(new FileOutputStream("test.ttl"), "TURTLE");
        } catch (Exception e) {
            // TODO: handle exception
        }

Contents of test.ttl

<http://no.uib.infomedia.info216/Cade_Tracy>
        <http://no.uib.infomedia.info216/visited>
                <http://dbpedia.org/resource/France> , <http://dbpedia.org/resource/Canada> ;
        <http://xmlns.com/foaf/0.1/name>
                "Cade Tracy" .

<http://dbpedia.org/resource/France>
        <http://www.w3.org/2000/01/rdf-schema#label>
                "Francia"@es , "France"@en , "Frankrike"@no ;
        <http://dbpedia.org/resource/ontology/populationEstimate>
                66644000 .

Reading from file

package no.uib.infomedia.sinoa.info216;

import java.io.FileInputStream;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;

public class ReadJena {

    public static void main(String[] args) {
        Model model = ModelFactory.createDefaultModel();
       
        try {
            model.read(new FileInputStream("test.ttl"), "http://ex.org/", "TURTLE");
        } catch (Exception e) {
            // TODO: handle exception
        }
       
        model.write(System.out);
    }
}

Reading from web resource

package no.uib.infomedia.sinoa.info216;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;

public class HttpTest {

    public static void main(String[] args) {
        Model model = ModelFactory.createDefaultModel();
       
        try {
            URL url = new URL("http://people.uib.no/sinoa/test.ttl");  
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 
            InputStream is = urlConnection.getInputStream();
            model.read(is, "http://ex.org/", "TURTLE");
        } catch (Exception e) {
            // TODO: handle exception
        }
       
        model.write(System.out);
    }
}

(There are more advanced ways to download web resources from Java, but HttpUrlConnection is a straightforward and built-in way to get started.)

Lecture 3: SPARQL Query and Update

Basic INSERT DATA update

		Dataset dataset = DatasetFactory.create();
		
		UpdateAction.parseExecute(""
				+ "PREFIX info216: <http://ex.org/teaching#>"
				+ "INSERT DATA {"
				+ "    info216:cade info216:teaches info216:ECO001 . "
				+ "    GRAPH <http://ex.org/personal#Graph> {"
				+ "        info216:cade info216:age '29' . "
				+ "    }"
				+ "}", dataset);

		RDFDataMgr.write(System.out, dataset, Lang.TRIG);

To output only the default graph use:

		dataset.getDefaultModel().write(System.out, "TURTLE");

The method dataset.getNamedModel("http://ex.org/personal#Graph"); lets you output a named model instead.

Language-tagged literals (and functions, and services...)

This works because we use the language-tagged literal 'Copenhagen'@en in the INSERT DATA update (and, as a result, it outputs DBpedia-triples about Copenhagen):

		Dataset dataset = DatasetFactory.create();
		
		String prefixes = ""
				+ "PREFIX rex: <http://ex.org#>"
				+ "PREFIX dbpedia: <http://dbpedia.org/resource/>";
		UpdateAction.parseExecute(prefixes
				+ "INSERT DATA {"
				+ "    rex:Margrethe <" + FOAF.based_near + "> 'Copenhagen'@en ."
				+ "}", dataset);

		ResultSet table = QueryExecutionFactory.create(prefixes
				+ "SELECT * WHERE {"
				+ "    ?person <" + FOAF.based_near + "> ?label ."
				+ "    SERVICE <http://dbpedia.org/sparql> {"
				+ "        ?city <" + RDFS.label + "> ?label ."
				+ "    }"
				+ "}", dataset).execSelect();
		
		table.forEachRemaining(row -> System.out.println(row.toString()));

If we do INSERT DATA without the language tag @en, we get no result (because the city labels in DBpedia are language-tagged):

		UpdateAction.parseExecute(prefixes
				+ "INSERT DATA {"
				+ "    rex:Margrethe <" + FOAF.based_near + "> 'Copenhagen'@en ."
				+ "}", dataset);

We can, however, rewrite the query to use the strlang function that adds language tags to labels. So this works with the previous INSERT DATA:

		ResultSet table = QueryExecutionFactory.create(prefixes
				+ "SELECT * WHERE {"
				+ "    ?person <" + FOAF.based_near + "> ?label ."
				+ "    BIND(strlang(?label, 'en') AS ?taglabel)"				
				+ "    SERVICE <http://dbpedia.org/sparql> {"
				+ "        ?city <" + RDFS.label + "> ?taglabel ."
				+ "    }"
				+ "}", dataset).execSelect();

To go the other way (if our local labels were language-tagged and DBpedia's not, we could do a similar thing, but use the reverse str-function instead of strlang.

Explanation of table.forEachRemaining(...)

The lambda-syntax in this code line may be new for you:

	table.forEachRemaining(row -> System.out.println(row.toString()));

The straightforward way to write it (that doesn't work), would be just:

	table.forEachRemaining(System.out.println(row.toString()));

But this doesn't work because we cannot send a method call as a paramter like that, and we introduce a row variable that is not declared anywhere.

Instead, we could try to define a new method somewhere else inside our class:

	void printRow(QuerySolution row) {
		System.out.println(row.toString());
	};
and then pass that function to forEachRemaining 

(doesn't work either):

	table.forEachRemaining(printRow);

But this doesn't work because you cannot pass functions as arguments like that in Java.

Finally, we could try to define a whole new class - a subclass of a Consumer class:

class RowPrinter implements Consumer<QuerySolution> {
	public void accept(QuerySolution row) {
		System.out.println(row.toString());
	}
}

Here, we define the class RowPrinter as a Consumer or QuerySolution, because Jena defines each row in a Query-Set-table to be a QuerySolution. In other words, we can view a ResultSet (table) as a stream of QuerySolutions (rows) that the RowPrinter consumes one by one.

We can pass an object of this class to forEachRemaining - it is exactly what it expects (this works!):

	table.forEachRemaining(new RowPrinter());

But it is pretty cumbersome to write a new class like RowPrinter every time we want to do a forEachRemaining-call - or another streaming call. Therefore Java 8 has introduced a shorthand, a lambda expression:

	table.forEachRemaining(row -> )System.out.println(row.toString();

Whenever Java 8 or later sees code like this, it behaves as if we had implemented a RowPrinter or similar Consumer-class like the one above.

 

INFO216, UiB, Spring 2017-2018, Andreas L. Opdahl (c). All code examples are CC0.