SURF Reference Implementation

GlobalMentor, Inc. provides a reference implementation of SURF in Java, with both a SURF parser and a SURF serializer included.

Source Code
https://bitbucket.org/globalmentor/urf-surf
Issues
https://globalmentor.atlassian.net/projects/URF
Maven
io.urf:surf

SURF Parser

1. Include SURF Parser Dependency

Include the appropriate SURF dependency from Maven by adding io.urf:surf:x.x.x to your POM.

pom.xml
<project>
  …
  <dependencies>
    …
    <dependency>
      <groupId>io.urf</groupId>
      <artifactId>surf</artifactId>
      <version>x.x.x</version>
    </dependency>
  </dependencies>
</project>

2. Make a SURF File

Here is an example SURF file storing the definition of a user. SURF documents are stored in files using the UTF-8 charset with no BOM.

user.surf
|<&bb8e7dbe-f0b4-4d94-a1cf-46ed0e920832>|*User:
  name = "Jane Doe"
  email = ^jane_doe@example.com
  phone = +12015550123
  joined = @2016-01-23
;

3. Use a SurfParser

Create an instance of io.urf.surf.SurfParser and call one of its SurfParser.parse(…) methods.

MyApp.java
import static java.nio.file.Files.*;
import java.time.temporal.ChronoUnit.*;

import java.io.*;
import java.net.*;
import java.nio.file.Paths;
import java.time.*;
import java.util.Optional;
import io.urf.surf.*;SurfParser parser = new SurfParser();
Optional<Object> surf;
try (final InputStream inputStream = newInputStream(Paths.get("user.surf"))) {
  surf = parser.parse(inputStream);
}

4. Access SURF Data

The returned SURF data will be one of the following, based upon the root resource in the file:

  • Optional.empty() if the file was empty.
  • A value object (e.g. java.lang.Integer) if the root resource was a SURF literal.
  • A implementation of a collection type (e.g. java.util.Set<>) if the root resource was a SURF collection.
  • An instance of SurfObject if the root resource was a SURF object.
MyApp.java
Optional<Object> surf = parser.parse(inputStream);

SurfObject user = (SurfObject)surf
    .orElseThrow(() -> new IOException("User file empty."));
URI userTag = user.getTag()
    .orElseThrow(() -> new IOException("Missing user identifier."));
String userName = (String)user.getPropertyValue("name")
    .orElseThrow(() -> new IOException("Missing user name."));
Optional<Object> userJoined = user.getPropertyValue("joined");
userJoined.ifPresent(joined -> {
  System.out.println(String.format("User joined %d days ago.",
      DAYS.between((LocalDate)joined, LocalDate.now()));
});

SURF Serializer

1. Include SURF Serializer Dependency

Include the appropriate SURF dependency from Maven by adding io.urf:surf:x.x.x to your POM.

pom.xml
<project>
  …
  <dependencies>
    …
    <dependency>
      <groupId>io.urf</groupId>
      <artifactId>surf</artifactId>
      <version>x.x.x</version>
    </dependency>
  </dependencies>
</project>

2. Create a SurfObject

Create an instance of io.urf.surf.SurfObject to represent the object to serialize. You can optionally give the object a tag IRI and/or a type string.

MyApp.java
import static java.nio.file.Files.*;

import java.io.*;
import java.net.*;
import java.nio.file.Paths;
import java.time.*;
import io.urf.surf.*;

…

userTag = URI.fromString("urn:uuid:bb8e7dbe-f0b4-4d94"
    +"-a1cf-46ed0e920832");
SurfObject user = new SurfObject(userTag, "User");
user.setPropertyValue("name", "Jane Doe");
…
LocalDate joined = LocalDate.of(2016, Month.JANUARY, 23);
user.setPropertyValue("joined", joined);

3. Use a SurfSerializer

Create an instance of io.urf.surf.SurfSerializer and call one of its SurfSerializer.serialize(…) methods.

MyApp.java
SurfSerializer serializer = new SurfSerializer();
serializer.setFormatted(true);

Path = Paths.get("user.surf");
try (final OutputStream outputStream = newOutputStream(path)) {
  serializer.serialize(outputStream, user);
}