Modeling an RDF Resource#
The following content highlights the key modifications to a Java class
to convert it into an RDF resource class. As a starting point, consider
a non-RDF class Expense
. Such a class may be implemented similarly
to the following sample code:
// Non-RDF Class
public class Expense {
private UUID _id;
private Date date;
private String description;
// ... Additional fields
public Expense() {
}
public Expense(date, description, //...) {
this.date = date;
this.description = descriptions;
//...
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
// ... Additional getters/setters and other content
}
1. Extend the SolidRDFSource#
The SolidRDFSource class maps to an RDF resource. A summary of parameters to the SolidRDFSource class constructors are as follows: [1]
Field |
Type |
Description |
---|---|---|
|
The URI (Uniform Resource Identifier) of the resource. |
|
|
The RDF dataset (i.e., the set(s) of triples) contained in the resource. |
|
|
Collection of HTTP headers. |
To model the Expense
class as an RDF resource, the class:
Extends the SolidRDFSource and
Adds constructors for the SolidRDFSource fields (
identifier
,dataset
,headers
). [1]
public class Expense extends SolidRDFSource {
private final Node subject;
// ...
public Expense(final URI identifier, final Dataset dataset, final Headers headers) {
super(identifier, dataset, headers);
// ...
}
public Expense(final URI identifier) {
this(identifier, null, null);
}
public Expense(final URI identifier,
String merchantProvider,
Date expenseDate,
String description,
BigDecimal amount,
String currency,
String category) {
this(identifier, null, null);
//...
}
}
2. Inner Class that Extends WrapperIRI#
A sample RDF file that for a sample Expense data is shown below in Turtle format:
<https://pod.example.com/container/expenses/202303/teamlunch>
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Invoice> ;
<https://schema.org/purchaseDate> "2023-03-07T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
<https://schema.org/provider> "Example Restaurant" ;
<https://schema.org/description> "Team Lunch" ;
<https://schema.org/category> "Travel and Entertainment" ;
<https://schema.org/priceCurrency> "USD" ;
<https://schema.org/totalPrice> "120"^^<http://www.w3.org/2001/XMLSchema#decimal> ;
<https://schema.org/image> <https://pod.example.com/container/expenses/202303/receipt1.jpg> .
where:
|
URL |
|
|
URL |
|
|
Literals or URLS |
|
To handle the mapping of the expense data (date, provider,
description, category, priceCurrency, total) to RDF triples
(<subject> <predicate> <object>
):
The
Expense
class defines the predicate IRIs. That is, instead of having a Class field nameddate
, for the RDF Resource, the value of the field is mapped to the IRI"https://schema.org/purchaseDate"
.The
Expense
class defines an inner classNode
that extends the WrapperIRI class.
public class Expense extends SolidRDFSource {
// ...
static IRI SCHEMA_DATE = rdf.createIRI("https://schema.org/purchaseDate");
static IRI SCHEMA_PROVIDER = rdf.createIRI("https://schema.org/provider");
static IRI SCHEMA_DESCRIPTION = rdf.createIRI("https://schema.org/description");
static IRI SCHEMA_TOTAL_PRICE = rdf.createIRI("https://schema.org/totalPrice");
static IRI SCHEMA_CURRENCY = rdf.createIRI("https://schema.org/priceCurrency");
static IRI SCHEMA_CATEGORY = rdf.createIRI("https://schema.org/category");
static IRI SCHEMA_IMAGE = rdf.createIRI("https://schema.org/image");
// ...
class Node extends WrapperIRI {
Node(final RDFTerm original, final Graph graph) {
super(original, graph);
}
URI getRDFType() {
return anyOrNull(RDF_TYPE, ValueMappings::iriAsUri);
}
void setRDFType(String type) {
overwriteNullable(RDF_TYPE, type, TermMappings::asIri);
}
String getMerchantProvider() {
return anyOrNull(SCHEMA_PROVIDER, ValueMappings::literalAsString);
}
String getMerchantProvider() {
return anyOrNull(SCHEMA_PROVIDER, ValueMappings::literalAsString);
}
void setMerchantProvider(String provider) {
overwriteNullable(SCHEMA_PROVIDER, provider, TermMappings::asStringLiteral);
}
// ...
}
}
Add the Inner Class Field to the RDF Resource Class#
To use the defined mappings in the inner class:
Update
Expense.java
to include a new fieldsubject
set to the inner classNode
.Update the
Expense.java
getters and setters to use thesubject
‘s getters and setters.
public class Expense extends SolidRDFSource {
// ...
private final Node subject;
// ...
public URI getRDFType() {
return subject.getRDFType();
}
public void setRdfType(String rdfType) {
subject.setRDFType(rdfType);
}
public String getMerchantProvider() {
return subject.getMerchantProvider();
}
public void setMerchantProvider(String merchantProvider) {
subject.setMerchantProvider(merchantProvider);
}
public Date getExpenseDate() {
return subject.getExpenseDate();
}
public void setExpenseDate(Date expenseDate) {
subject.setExpenseDate(expenseDate);
}
//...
}