# Modeling an RDF Resource

The following content highlights the key modifications to a Java class to convert it into an [RDF resource](https://docs.inrupt.com/reference/glossary#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:

```java
// 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](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidRDFSource.html) class maps to an RDF resource. A summary of parameters to the [SolidRDFSource](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidRDFSource.html) class constructors are as follows:

<table><thead><tr><th width="138.55078125">Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>identifier</code></strong></td><td><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URI.html">java.net.URI</a></td><td>The URI (Uniform Resource Identifier) of the resource.</td></tr><tr><td><strong><code>dataset</code></strong></td><td><a href="https://commons.apache.org/proper/commons-rdf/apidocs/org/apache/commons/rdf/api/Dataset.html">org.apache.commons.rdf.api.Dataset</a></td><td>The RDF dataset (i.e., the sets of triples) contained in the resource.</td></tr><tr><td><strong><code>headers</code></strong></td><td><a href="https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/Headers.html">com.inrupt.client.Headers</a></td><td>Collection of HTTP headers.</td></tr></tbody></table>

To model the **`Expense`** class as an RDF resource, the class:

* Extends the [SolidRDFSource](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidRDFSource.html) and
* Adds constructors for the [SolidRDFSource](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidRDFSource.html) fields (**`identifier`**, **`dataset`**, **`headers`**).

```java
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);
       //...
   }
}
```

{% hint style="warning" %}
The SolidRDFSource constructor that accepts Metadata as a parameter (instead of Headers) has been deprecated.
{% endhint %}

### 2. Inner Class that Extends WrapperIRI

A sample RDF file that for a sample Expense data is shown below in [Turtle format](https://docs.inrupt.com/reference/glossary#turtle):

```turtle
<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:

<table data-header-hidden><thead><tr><th width="121.48828125"></th><th width="103.29296875"></th><th></th></tr></thead><tbody><tr><td><code>subject</code></td><td>URL</td><td><code>&#x3C;https://pod.example.com/container/expenses/202303/teamlunch></code></td></tr><tr><td><code>predicates</code></td><td>URL</td><td><ul><li><code>&#x3C;http://www.w3.org/1999/02/22-rdf-syntax-ns#type></code></li><li><code>&#x3C;https://schema.org/purchaseDate></code></li><li><code>&#x3C;https://schema.org/provider></code></li><li>etc.</li></ul></td></tr><tr><td><code>objects</code></td><td>Literals or URLS</td><td><ul><li><code>"2023-03-07T00:00:00Z"^^&#x3C;http://www.w3.org/2001/XMLSchema#dateTime></code></li><li><code>"Example Restaurant"</code>,</li><li><code>&#x3C;https://pod.example.com/expenses/receipt1.jpg></code></li><li>etc.</li></ul></td></tr></tbody></table>

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 named **`date`**, for the RDF Resource, the value of the field is mapped to the IRI **`"https://schema.org/purchaseDate"`**.
* The **`Expense`** class defines an inner class **`Node`** that extends the [WrapperIRI](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/rdf/wrapping/commons/WrapperIRI.html) class.

```java
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 field **`subject`** set to the inner class **`Node`**.
* Update the **`Expense.java`** getters and setters to use the **`subject`**‘s getters and setters.

```java
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);
    }

    //...

}
```
