OWL ORM provides a facade for working with native Java POJOs on top of an RDF4j model based on OWL ontologies. Instead of directly manipulating RDF statements, this framework enables developers to work with familiar Java objects, significantly simplifying business logic.
- Simplified access to RDF4j models using Java POJOs.
- Automatically generates Java classes and interfaces from OWL ontologies.
- Extensible API for custom type conversions.
- Maven plugin for seamless integration into your build process.
- Fully supports OSGi runtime environments.
OWL ORM is divided into modular components to support a variety of use cases:
The core API defining the interfaces and exceptions that make up the framework.
The primary implementation of the API, which proxies interfaces and wraps method calls to interact with the RDF4j model.
The logic responsible for generating Java interfaces based on the classes and properties defined in OWL ontologies.
A Maven plugin to generate ORM classes from your ontology during the build process.
Base implementations of the TypeConverter
API, enabling seamless translation of RDF datatype property values to and from Java primitives and objects.
The Maven plugin generates Java POJOs and interfaces directly from your OWL ontology.
Add the following to your pom.xml
:
<build>
<plugins>
<plugin>
<groupId>com.example.owlorm</groupId>
<artifactId>owl-orm-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>generate-orm</id>
<phase>generate-sources</phase>
<goals>
<goal>generate-orm</goal>
</goals>
</execution>
</executions>
<configuration>
<outputLocation>${project.build.directory}/generated-sources</outputLocation>
<generates>
<ontology>
<ontologyFile>${project.basedir}/src/main/resources/ontology.ttl</ontologyFile>
<outputPackage>com.example.generated</outputPackage>
<ontologyName>My Awesome Ontology</ontologyName>
</ontology>
</generates>
</configuration>
</plugin>
</plugins>
</build>
Run the following Maven command to generate Java classes:
mvn generate-sources
This will generate java interfaces into the target/generated-sources
directory. Ensuring your IDE
supports this as a gensrc directory will enable you to work with this generated source.
Once you have generated your interfaces, you can work with them by leveraging the ThingFactory to build instances of them on top of RDF4j Model instances. This process builds a delegated proxy that will allow you to operate on native java APIs while managing the underlying Model by adding/removing statements.
// Basic Spring Usage example...
package com.example.owlorm;
import com.example.owlorm.config.RdfConfig;
import com.example.owlorm.ontology.CustomOntologyClass;
import com.realmone.owl.orm.ThingFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.UUID;
@Service
public class ExampleEntityService {
@Value("${rdf.mything.template:urn://thing/{uuid}}")
private String template;
private final ThingFactory thingFactory;
public ExampleEntityService(ThingFactory thingFactory) {
this.thingFactory = thingFactory;
}
@PostConstruct
public void createEntity() {
// Generate a unique IRI for the entity
String iriString = template.replace("{uuid}", UUID.randomUUID().toString());
// Create an instance of the ontology class
CustomOntologyClass entity = thingFactory.create(
CustomOntologyClass.class, // Generated with the ORM Maven Plugin
iriString, // String IRI representation for our thing
thingFactory.getModelFactory().createEmptyModel() // Pass your own Model in!
);
// Populate the entity with data
entity.setHasSomeDate(new Date());
entity.setHasSomeId("exampleHash");
entity.setHasSomeInt(42);
entity.setHasFloat(3.141592F);
// ... other DataType and Object Properties Natively...
// RDF4j Model is updated with each interaction
}
}
This module contains the ValueConverter interface and its implementations. The ValueConverter API powers the seamless translation of data between RDF4j Value objects and native Java objects or primitives. This allows developers to work with familiar Java types while leveraging the flexibility and power of RDF.
The ValueConverter interface defines a contract for converting between RDF4j Value objects and specific Java types. This abstraction ensures extensibility and consistency in handling datatype properties across different ontologies.
public interface ValueConverter<T> {
/**
* Convert a value to the specified type.
*
* @param value The {@link Value} to convert
* @return The converted instance
* @throws ValueConversionException If there is an issue converting the value
*/
T convertValue(@NonNull Value value) throws ValueConversionException;
/**
* Convert an instance of the TYPE of object this {@link ValueConverter} works with back into a {@link Value}.
*
* @param type The object to convert into a {@link Value}
* @return The {@link Value} form of the object passed in
* @throws ValueConversionException If there is an issue performing the conversion
*/
Value convertType(@NonNull T type) throws ValueConversionException;
/**
* @return The type of class this convert works with
*/
Class<T> getType();
}
Developers can extend the ValueConverter API to define custom type converters for specific use cases. Here’s how you can add and register your own ValueConverter implementations:
public class OffsetDateTimeConverter implements ValueConverter<OffsetDateTime> {
@Override
public OffsetDateTime convertValue(@NonNull Value value) throws ValueConversionException {
try {
return OffsetDateTime.parse(value.stringValue());
} catch (Exception e) {
throw new ValueConversionException("Failed to convert Value to OffsetDateTime", e);
}
}
@Override
public Value convertType(@NonNull OffsetDateTime type) throws ValueConversionException {
try {
return SimpleValueFactory.getInstance().createLiteral(type.toString());
} catch (Exception e) {
throw new ValueConversionException("Failed to convert OffsetDateTime to Value", e);
}
}
@Override
public Class<OffsetDateTime> getType() {
return OffsetDateTime.class;
}
}
Add your converter to the appropriate configuration or service registry within the OWL ORM framework. This ensures that your custom converter is used automatically when working with the relevant type.
Benefits of ValueConverter
- Simplifies data handling by abstracting RDF4j details.
- Enables support for complex Java types through custom implementations.
- Ensures type safety and consistency in your ontology-backed applications.
OWL ORM is fully compatible with OSGi runtimes. It can be deployed as an OSGi bundle to enable modular development.
-
Clone the repository:
git clone https://github.com/inovexcorp/owl-orm.git cd owl-orm
-
Build the project:
mvn clean install
or
make build
We welcome contributions to OWL ORM! To get started:
- Fork the repository.
- Create a new branch for your feature or fix.
- Submit a pull request with a clear description of your changes.
- Follow standard Java coding conventions.
- Ensure all tests pass before submitting a pull request.
- Write tests for any new features or bug fixes.
This project is licensed under the MIT License. See the LICENSE file for details.
- Extend the documentation for custom
TypeConverter
implementations. - Add examples for OSGi deployment.
- Provide a detailed setup guide for the Maven plugin.
- Add more examples and tutorials.