Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 256 additions & 4 deletions src/main/java/fr/inria/corese/core/next/data/Values.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
package fr.inria.corese.core.next.data;

import fr.inria.corese.core.next.data.api.factory.ValueFactory;
import fr.inria.corese.core.next.data.api.factory.NativeValueFactory;
import fr.inria.corese.core.next.data.api.factory.ValueFactory;
import fr.inria.corese.core.next.data.api.model.Statement;
import fr.inria.corese.core.next.data.api.term.BNode;
import fr.inria.corese.core.next.data.api.term.IRI;
import fr.inria.corese.core.next.data.api.term.Literal;
import fr.inria.corese.core.next.data.api.term.Resource;
import fr.inria.corese.core.next.data.api.term.Triple;
import fr.inria.corese.core.next.data.api.term.Value;

import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAmount;
import java.util.Objects;

/**
* Public entry point for creating RDF terms and statements independently of a
* repository.
*
* <p>The returned factory is thread-safe and may be shared. When working with a
* repository, prefer its own value factory so backend-specific implementations
* remain possible.</p>
* <p>All static methods delegate to the thread-safe shared default {@link ValueFactory}.
* When working inside a specific repository or storage backend, prefer obtaining the factory
* from the repository itself so backend-optimized implementations can be used.</p>
*
* <h2>Usage Example</h2>
* <pre>{@code
* IRI person = Values.iri("http://schema.org/Person");
* IRI name = Values.iri("http://schema.org/name");
* BNode alice = Values.bnode();
* Literal label = Values.literal("Alice", "en");
* Statement stmt = Values.statement(alice, name, label);
* }</pre>
*/
public final class Values {

Expand All @@ -26,4 +49,233 @@ private Values() {
public static ValueFactory factory() {
return DEFAULT_FACTORY;
}

/**
* Creates an IRI from a full IRI string.
*
* @param iri valid IRI string
* @return IRI instance
*/
public static IRI iri(String iri) {
return DEFAULT_FACTORY.createIRI(iri);
}

/**
* Creates an IRI by concatenating a namespace and a local name.
*
* @param namespace namespace prefix or base URI
* @param localName local name
* @return IRI instance
*/
public static IRI iri(String namespace, String localName) {
return DEFAULT_FACTORY.createIRI(namespace, localName);
}

/**
* Creates an anonymous blank node with an automatically generated identifier.
*
* @return unique blank node
*/
public static BNode bnode() {
return DEFAULT_FACTORY.createBNode();
}

/**
* Creates a blank node with the given identifier.
*
* @param nodeId blank node label or identifier
* @return blank node instance
*/
public static BNode bnode(String nodeId) {
return DEFAULT_FACTORY.createBNode(nodeId);
}

/**
* Creates an untyped plain literal (xsd:string).
*
* @param label lexical value
* @return Literal instance
*/
public static Literal literal(String label) {
return DEFAULT_FACTORY.createLiteral(label);
}

/**
* Creates a language-tagged literal.
*
* @param label lexical value
* @param language BCP-47 language tag
* @return Literal instance typed as rdf:langString
*/
public static Literal literal(String label, String language) {
return DEFAULT_FACTORY.createLiteral(label, language);
}

/**
* Creates a typed literal with an explicit datatype IRI.
*
* @param label lexical value
* @param datatype datatype IRI
* @return Literal instance
*/
public static Literal literal(String label, IRI datatype) {
return DEFAULT_FACTORY.createLiteral(label, datatype);
}

/**
* Creates a literal typed as xsd:boolean.
*
* @param value boolean value
* @return Literal instance
*/
public static Literal literal(boolean value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:byte.
*
* @param value byte value
* @return Literal instance
*/
public static Literal literal(byte value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:short.
*
* @param value short value
* @return Literal instance
*/
public static Literal literal(short value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:int.
*
* @param value int value
* @return Literal instance
*/
public static Literal literal(int value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:long.
*
* @param value long value
* @return Literal instance
*/
public static Literal literal(long value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:float.
*
* @param value float value
* @return Literal instance
*/
public static Literal literal(float value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:double.
*
* @param value double value
* @return Literal instance
*/
public static Literal literal(double value) {
return DEFAULT_FACTORY.createLiteral(value);
}

/**
* Creates a literal typed as xsd:decimal.
*
* @param decimal BigDecimal value
* @return Literal instance
*/
public static Literal literal(BigDecimal decimal) {
return DEFAULT_FACTORY.createLiteral(decimal);
}

/**
* Creates a literal typed as xsd:integer.
*
* @param integer BigInteger value
* @return Literal instance
*/
public static Literal literal(BigInteger integer) {
return DEFAULT_FACTORY.createLiteral(integer);
}

/**
* Creates a literal typed as xsd:dateTime from a temporal accessor.
*
* @param temporal temporal value
* @return Literal instance
*/
public static Literal literal(TemporalAccessor temporal) {
return DEFAULT_FACTORY.createLiteral(temporal);
}

/**
* Creates a literal typed as xsd:duration from a temporal amount.
*
* @param amount temporal amount value
* @return Literal instance
*/
public static Literal literal(TemporalAmount amount) {
return DEFAULT_FACTORY.createLiteral(amount);
}

/**
* Creates a literal typed as xsd:dateTime from an XMLGregorianCalendar.
*
* @param calendar XMLGregorianCalendar value
* @return Literal instance
*/
public static Literal literal(XMLGregorianCalendar calendar) {
return DEFAULT_FACTORY.createLiteral(calendar);
}

/**
* Creates an RDF statement in the default graph (context is {@code null}).
*
* @param subject statement subject (Resource)
* @param predicate statement predicate (IRI)
* @param object statement object (Value)
* @return Statement instance
*/
public static Statement statement(Resource subject, IRI predicate, Value object) {
return DEFAULT_FACTORY.createStatement(subject, predicate, object);
}

/**
* Creates an RDF quad statement in the designated named graph context.
*
* @param subject statement subject (Resource)
* @param predicate statement predicate (IRI)
* @param object statement object (Value)
* @param context graph context (Resource), or {@code null} for default graph
* @return Statement instance
*/
public static Statement statement(Resource subject, IRI predicate, Value object, Resource context) {
return DEFAULT_FACTORY.createStatement(subject, predicate, object, context);
}

/**
* Creates an RDF-star embedded triple term.
*
* @param subject triple subject (Resource)
* @param predicate triple predicate (IRI)
* @param object triple object (Value)
* @return Triple instance
*/
public static Triple triple(Resource subject, IRI predicate, Value object) {
return DEFAULT_FACTORY.createTriple(subject, predicate, object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,72 @@
import fr.inria.corese.core.next.data.api.term.Value;

/**
* Represents an RDF statement or quad, composed of a subject, predicate, object, and optional context.
* Represents an RDF statement or quad in Corese v5, composed of a subject, predicate, object,
* and optional context (named graph).
*
* <h2>Immutability and Value Semantics</h2>
* <p>Implementations of this interface must be strictly immutable and thread-safe. Once constructed,
* neither the statement itself nor the references to its component terms may change.</p>
*
* <h2>Graph and Context Semantics</h2>
* <p>When {@link #getContext()} returns {@code null}, the statement belongs to the default graph.
* When {@link #getContext()} returns a non-null {@link Resource} (an {@link IRI} or {@link fr.inria.corese.core.next.data.api.term.BNode}),
* the statement is a quad belonging to that designated named graph.</p>
*
* <h2>Equality Contract</h2>
* <p>Two statements {@code s1} and {@code s2} are equal if and only if:
* <ul>
* <li>{@code s1.getSubject().equals(s2.getSubject())}</li>
* <li>{@code s1.getPredicate().equals(s2.getPredicate())}</li>
* <li>{@code s1.getObject().equals(s2.getObject())}</li>
* <li>{@code Objects.equals(s1.getContext(), s2.getContext())}</li>
* </ul>
* Equality must be symmetric across different implementations of this interface.</p>
*/
public interface Statement extends Serializable {

/**
* Gets the subject of this statement.
* Gets the subject resource of this statement (IRI, BNode, or Triple term).
*
* @return the non-null subject
*/
Resource getSubject();

/**
* Gets the predicate of this statement.
* Gets the predicate IRI of this statement.
*
* @return the non-null predicate IRI
*/
IRI getPredicate();

/**
* Gets the object of this statement.
* Gets the object value of this statement (Resource or Literal).
*
* @return the non-null object value
*/
Value getObject();

/**
* Gets the context of this statement.
* Gets the context of this statement, identifying its containing graph.
*
* @return the graph resource identifier, or {@code null} if this statement belongs to the default graph
*/
Resource getContext();

/**
* Compares this statement to another object.
* Compares this statement to another object according to RDF statement equality rules.
*
* @param other the object to compare against
* @return {@code true} if both statements have equal subjects, predicates, objects, and contexts
*/
@Override
boolean equals(Object other);

/**
* Computes the hash code of this statement.
* Computes the hash code of this statement based on its subject, predicate, object, and context.
*
* @return integer hash code consistent with {@link #equals(Object)}
*/
@Override
int hashCode();

}
31 changes: 27 additions & 4 deletions src/main/java/fr/inria/corese/core/next/data/package-info.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
/**
* RDF data model, public contracts, extension SPI, and Corese implementations.
* Core RDF data model, value representation, and terminology for Corese v5.
*
* <p>The package is split into stable {@code api} contracts, a public
* {@code spi} for implementers, and an implementation-only {@code impl}
* boundary.</p>
* <h2>Three-Tier Package Architecture</h2>
* <ul>
* <li>{@link fr.inria.corese.core.next.data.api}: Public API contracts (interfaces and models)
* intended for end-users, query evaluators, and client applications. Includes {@code term},
* {@code model}, {@code factory}, {@code namespace}, and {@code literal}.</li>
* <li>{@link fr.inria.corese.core.next.data.spi}: Service-provider interfaces (SPI) intended for
* backend implementers, custom datatypes, and parser/serializer plugins.</li>
* <li>{@link fr.inria.corese.core.next.data.impl}: Internal, encapsulated default implementations
* ({@code SimpleModel}, {@code SimpleStatement}, internal dictionary encoders).</li>
* </ul>
*
* <h2>Entry Points</h2>
* <ul>
* <li>{@link fr.inria.corese.core.next.data.Values}: Static convenience factory for creating
* IRIs, blank nodes, typed literals, statements, and RDF-star triple terms.</li>
* <li>{@link fr.inria.corese.core.next.data.api.model.Model}: Mutable and immutable in-memory
* RDF graphs supporting collection-like set operations, namespace mappings, and filtered views.</li>
* </ul>
*
* <h2>Thread Safety and Immutability</h2>
* <p>All RDF terms ({@link fr.inria.corese.core.next.data.api.term.IRI},
* {@link fr.inria.corese.core.next.data.api.term.Literal},
* {@link fr.inria.corese.core.next.data.api.term.BNode}, and
* {@link fr.inria.corese.core.next.data.api.model.Statement}) are strictly immutable and thread-safe.
* {@link fr.inria.corese.core.next.data.api.model.Model} instances are not thread-safe unless
* explicitly decorated or backed by a transactional storage manager.</p>
*/
package fr.inria.corese.core.next.data;
Loading
Loading