From e4e81358bfc84f96450be224e59aecf69310f7bb Mon Sep 17 00:00:00 2001
From: pierrerene
Date: Thu, 17 Apr 2025 12:09:34 +0200
Subject: [PATCH 1/8] adding blank node to corese new api
---
.../next/api/base/model/AbstractBNode.java | 57 ++++++++++++++++++
.../next/impl/temp/literal/CoreseBNode.java | 60 +++++++++++++++++++
.../impl/temp/literal/CoreseBNodeTest.java | 42 +++++++++++++
3 files changed, 159 insertions(+)
create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/model/AbstractBNode.java
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
create mode 100644 src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
diff --git a/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractBNode.java b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractBNode.java
new file mode 100644
index 000000000..069fce952
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractBNode.java
@@ -0,0 +1,57 @@
+package fr.inria.corese.core.next.api.base.model;
+
+import fr.inria.corese.core.next.api.BNode;
+
+/**
+ * Abstract implementation of the {@link BNode} interface, providing common functionality for blank node representations.
+ * A blank node (BNode) https://www.w3.org/TR/rdf12-concepts/#section-blank-nodes
+ */
+public abstract class AbstractBNode implements BNode {
+
+ /**
+ * Returns the string value of this blank node, which is its unique identifier.
+ * This method is an implementation of {@link BNode#stringValue()} and simply returns the result of {@link #getID()}.
+ *
+ * @return The string value of the blank node (its unique identifier).
+ */
+ @Override
+ public String stringValue() {
+ return getID();
+ }
+
+ /**
+ * Checks whether this blank node is equal to another object.
+ * Two blank nodes are considered equal if they are the same object in memory or if they have the same unique identifier (ID).
+ * This method is an implementation of {@link BNode#equals(Object)}.
+ *
+ * @param o The object to compare this blank node to.
+ * @return {@code true} if the two blank nodes are the same object or have the same unique identifier; {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object o) {
+ return this == o || o instanceof BNode
+ && getID().equals(((BNode) o).getID());
+ }
+
+ /**
+ * Returns the hash code for this blank node. The hash code is based on the unique identifier of the blank node,
+ * using the hash code of the ID returned by {@link #getID()}.
+ * This method is an implementation of {@link BNode#hashCode()}.
+ *
+ * @return The hash code for this blank node.
+ */
+ @Override
+ public int hashCode() {
+ return getID().hashCode();
+ }
+
+ /**
+ * Returns a string representation of this blank node in the form "_:{ID}" where {ID} is the unique identifier of the blank node.
+ *
+ * @return A string representing this blank node, prefixed with "_:" and followed by its unique identifier.
+ */
+ @Override
+ public String toString() {
+ return "_:" + getID();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
new file mode 100644
index 000000000..bbadd0b57
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
@@ -0,0 +1,60 @@
+package fr.inria.corese.core.next.impl.temp.literal;
+
+import fr.inria.corese.core.next.api.base.model.AbstractBNode;
+import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
+import fr.inria.corese.core.sparql.api.IDatatype;
+
+/**
+ * An implementation of a blank node (BNode) used by Corese.
+ * A blank node (BNode) represents an unnamed node in an RDF graph, typically used to represent resources that do not have a globally unique identifier (IRI).
+ * This class extends {@link AbstractBNode} and provides constructors for creating a BNode either from a Corese blank node object or a given string identifier.
+ */
+public class CoreseBNode extends AbstractBNode {
+ /**
+ * The Corese object representing the blank node in the old API.
+ */
+ private final fr.inria.corese.core.sparql.datatype.CoreseBlankNode coreseObject;
+
+ /**
+ * The unique identifier (ID) for the blank node.
+ */
+ private String id;
+
+ /**
+ * Constructs a {@link CoreseBNode} instance from an {@link IDatatype} Corese object.
+ * The Corese object should be an instance of {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
+ *
+ * @param coreseObject The {@link IDatatype} Corese object representing the blank node.
+ * @throws IncorrectOperationException If the provided {@link IDatatype} is not a valid {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
+ */
+ public CoreseBNode(IDatatype coreseObject) {
+ if (coreseObject instanceof fr.inria.corese.core.sparql.datatype.CoreseBlankNode) {
+ this.coreseObject = ( fr.inria.corese.core.sparql.datatype.CoreseBlankNode) coreseObject;
+ this.id = this.coreseObject.getID();
+ }
+ else {
+ throw new IncorrectOperationException("Cannot create CoreseLiteral from a non-literal Corese object");
+ }
+ }
+
+ /**
+ * Constructs a {@link CoreseBNode} instance from a string identifier.
+ * This constructor creates a {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode} from the provided string id.
+ *
+ * @param id The unique identifier for the blank node.
+ */
+ public CoreseBNode(String id) {
+ this(new fr.inria.corese.core.sparql.datatype.CoreseBlankNode(id));
+ this.id = id;
+ }
+
+ /**
+ * Returns the unique identifier of the blank node.
+ *
+ * @return The ID of the blank node.
+ */
+ @Override
+ public String getID() {
+ return id;
+ }
+}
diff --git a/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
new file mode 100644
index 000000000..0893faba0
--- /dev/null
+++ b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
@@ -0,0 +1,42 @@
+package fr.inria.corese.core.next.impl.temp.literal;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import fr.inria.corese.core.sparql.datatype.CoreseBlankNode;
+
+public class CoreseBNodeTest {
+
+ private static final String BNODE_ID = "bnodeCorese123";
+ private static final CoreseBlankNode coreseBlankNode = new CoreseBlankNode(BNODE_ID);
+
+ private CoreseBNode coreseBNodeFromCoreseObject;
+ private CoreseBNode coreseBNodeFromStringId;
+
+ @Before
+ public void setUp() {
+ coreseBNodeFromCoreseObject = new CoreseBNode(coreseBlankNode);
+ coreseBNodeFromStringId = new CoreseBNode(BNODE_ID);
+ }
+
+ @Test
+ public void testConstructorFromString() {
+ // Test creating CoreseBnode for a string ID
+ assertNotNull(coreseBNodeFromStringId);
+ assertEquals(BNODE_ID, coreseBNodeFromStringId.getID());
+ }
+
+ @Test
+ public void testConstructorFromCoreseObject() {
+ // Test creating CoreseBnode for a CoreseBlankNode (old API)
+ assertNotNull(coreseBNodeFromCoreseObject);
+ assertEquals(BNODE_ID, coreseBNodeFromCoreseObject.getID());
+ }
+
+ @Test
+ public void testToString() {
+ // Test the toString method to ensure it outputs the correct representation
+ String expectedString = "_:" + BNODE_ID;
+ assertEquals(expectedString, coreseBNodeFromStringId.toString());
+ }
+}
From 012a46f229fa6ec3ba34de4f8cbbfd80fa7e5877 Mon Sep 17 00:00:00 2001
From: pierrerene
Date: Fri, 18 Apr 2025 15:27:19 +0200
Subject: [PATCH 2/8] adding blank node factory to ValueFactory
---
.../core/next/impl/temp/CoreseAdaptedValueFactory.java | 8 ++++++--
.../corese/core/next/api/model/ValueFactoryTest.java | 9 +++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseAdaptedValueFactory.java b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseAdaptedValueFactory.java
index d08cd8bad..b197e32bf 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseAdaptedValueFactory.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseAdaptedValueFactory.java
@@ -14,11 +14,15 @@
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAmount;
import java.util.Date;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicLong;
public class CoreseAdaptedValueFactory implements ValueFactory {
private static Logger logger = LoggerFactory.getLogger(CoreseAdaptedValueFactory.class);
+ private final AtomicLong nodeID = new AtomicLong(ThreadLocalRandom.current().nextLong());
+
public CoreseAdaptedValueFactory() {
}
@@ -34,12 +38,12 @@ public IRI createIRI(String namespace, String localName) {
@Override
public BNode createBNode() {
- return null;
+ return new CoreseBNode(Long.toHexString(Math.abs(nodeID.getAndIncrement())));
}
@Override
public BNode createBNode(String nodeID) {
- return null;
+ return new CoreseBNode(nodeID);
}
@Override
diff --git a/src/test/java/fr/inria/corese/core/next/api/model/ValueFactoryTest.java b/src/test/java/fr/inria/corese/core/next/api/model/ValueFactoryTest.java
index 9cd84e924..4a903dbd6 100644
--- a/src/test/java/fr/inria/corese/core/next/api/model/ValueFactoryTest.java
+++ b/src/test/java/fr/inria/corese/core/next/api/model/ValueFactoryTest.java
@@ -1,5 +1,6 @@
package fr.inria.corese.core.next.api.model;
+import fr.inria.corese.core.next.api.BNode;
import fr.inria.corese.core.next.api.Literal;
import fr.inria.corese.core.next.api.ValueFactory;
import fr.inria.corese.core.next.impl.exception.IncorrectFormatException;
@@ -40,6 +41,14 @@ public void testCreateIRI() {
@Test
public void testCreateBNode() {
+ String nodeId = "corese123";
+ BNode nodesCorese123 = this.valueFactory.createBNode(nodeId);
+ BNode nodesCoreseRandom = this.valueFactory.createBNode();
+
+ assertNotNull(nodesCorese123);
+ assertNotNull(nodesCoreseRandom);
+ assertNotNull(nodesCoreseRandom.getID());
+ assertEquals(nodesCorese123.getID(), "corese123");
}
@Test
From 392294125121a37cc723ab3b765961ae04fedf4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?=
Date: Fri, 16 May 2025 17:52:04 +0200
Subject: [PATCH 3/8] Implement RDF Model
- Added CoreseTyped class for handling typed literals, extending AbstractStringLiteral.
- Introduced AbstractBNode class for blank node representation in RDF graphs.
- Created NamespaceAware interface for models supporting RDF namespaces.
- Developed AbstractNamespace class as a base implementation for namespaces.
- Implemented ReadOnlyModel class to provide a read-only view of RDF models.
- Added CoreseModel class to manage RDF operations backed by Corese Graph.
- Introduced CoreseValueConverter for converting between Corese Nodes and RDF4J Values.
- Created EmptyModel class to block access to all statements, allowing only namespace operations.
- Developed FilteredModel class to provide filtered views over RDF models based on subject, predicate, object, and context.
---
.../corese/core/next/api/AbstractBNode.java | 62 ++
.../fr/inria/corese/core/next/api/Model.java | 119 ++--
.../corese/core/next/api/NamespaceAware.java | 29 +
.../next/api/base/model/AbstractModel.java | 617 ++++++++++++++++--
.../api/base/model/AbstractNamespace.java | 69 ++
.../next/api/base/model/ReadOnlyModel.java | 131 ++++
.../next/impl/inmemory/InMemoryModel.java | 69 +-
.../core/next/impl/temp/CoreseConverter.java | 110 ----
.../core/next/impl/temp/CoreseModel.java | 397 +++++++++++
.../core/next/impl/temp/CoreseStatement.java | 46 +-
.../next/impl/temp/CoreseValueConverter.java | 141 ++++
.../core/next/impl/temp/EmptyModel.java | 103 +++
.../core/next/impl/temp/FilteredModel.java | 319 +++++++++
.../next/impl/temp/literal/CoreseBNode.java | 42 +-
.../next/impl/temp/literal/CoreseBoolean.java | 41 +-
.../next/impl/temp/literal/CoreseDate.java | 40 +-
.../impl/temp/literal/CoreseDatetime.java | 47 +-
.../CoreseLanguageTaggedStringLiteral.java | 60 +-
.../next/impl/temp/literal/CoreseTyped.java | 69 +-
19 files changed, 2172 insertions(+), 339 deletions(-)
create mode 100644 src/main/java/fr/inria/corese/core/next/api/AbstractBNode.java
create mode 100644 src/main/java/fr/inria/corese/core/next/api/NamespaceAware.java
create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/model/AbstractNamespace.java
create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/model/ReadOnlyModel.java
delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/CoreseConverter.java
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/CoreseModel.java
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/EmptyModel.java
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/FilteredModel.java
diff --git a/src/main/java/fr/inria/corese/core/next/api/AbstractBNode.java b/src/main/java/fr/inria/corese/core/next/api/AbstractBNode.java
new file mode 100644
index 000000000..961ce814a
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/api/AbstractBNode.java
@@ -0,0 +1,62 @@
+package fr.inria.corese.core.next.api;
+
+import java.util.Objects;
+
+/**
+ * Abstract base class for blank nodes in an RDF graph.
+ *
+ * Provides default implementations for {@link BNode#getID()},
+ * {@link Object#equals(Object)}, and {@link Object#hashCode()}.
+ *
+ */
+public abstract class AbstractBNode implements BNode {
+
+ private static final String BLANK_NODE_PREFIX = "_:";
+
+ /** Internal identifier for the blank node (unique within a model) */
+ private final String id;
+
+ /** Serial version UID for serialization */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a blank node with a specific identifier.
+ *
+ * Warning: This bypasses the automatic ID generation and should only be
+ * used when restoring an existing RDF graph (e.g. during parsing or tests).
+ *
+ */
+ protected AbstractBNode(String id) {
+ this.id = Objects.requireNonNull(id, "Blank node ID must not be null");
+ }
+
+ @Override
+ public String getID() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof BNode))
+ return false;
+ BNode other = (BNode) o;
+ return id.equals(other.getID());
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public String stringValue() {
+ return BLANK_NODE_PREFIX + id;
+ }
+
+ @Override
+ public String toString() {
+ return BLANK_NODE_PREFIX + id;
+ }
+}
diff --git a/src/main/java/fr/inria/corese/core/next/api/Model.java b/src/main/java/fr/inria/corese/core/next/api/Model.java
index 1b580e006..a4f7d146a 100644
--- a/src/main/java/fr/inria/corese/core/next/api/Model.java
+++ b/src/main/java/fr/inria/corese/core/next/api/Model.java
@@ -1,28 +1,36 @@
package fr.inria.corese.core.next.api;
-import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
-
import java.io.Serializable;
import java.util.Optional;
import java.util.Set;
+import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
+
/**
* This class represents an RDF model, a set of statements.
* This is the central class to handle RDF data.
- * Statements can have zero or several resources as contexts to represents the different graphs in the model.
- * A model also handles a set of namespaces. There can be different prefixes for the same namespace, although it is ill-advised, how it affects serialization is implementation-dependant. There cannot be two namespaces with the same prefix.
+ * Statements can have zero or several resources as contexts to represent the
+ * different graphs in the model.
+ * A model also handles a set of namespaces. There can be different prefixes for
+ * the same namespace, although it is ill-advised, how it affects serialization
+ * is implementation-dependant. There cannot be two namespaces with the same
+ * prefix.
+ * Statements can have zero or several resources as contexts, representing
+ * different named graphs within the modela
*/
-public interface Model extends Set, Serializable {
+public interface Model extends Set, Serializable, NamespaceAware {
/**
- * @return a "read-only" view of this model. "query" operations are possible, such as {@code filter()} on {@code contains()} but modifications will throw {@link IncorrectOperationException}.
+ * @return a "read-only" view of this model. "query" operations are possible,
+ * such as {@code filter()} on {@code contains()} but modifications will
+ * throw {@link IncorrectOperationException}.
*/
Model unmodifiable();
/**
*
* @param prefix a prefix for the namespace. It should be unique in the model.
- * @param name the IRI of the namespace. It should be a valid IRI.
+ * @param name the IRI of the namespace. It should be a valid IRI.
* @return the new Namespace created with the given prefix and name.
* @throws IncorrectOperationException if the Model is unmodifiable.
*/
@@ -30,6 +38,7 @@ public interface Model extends Set, Serializable {
/**
* Set the namespace of this model. The prefix should be unique in the model.
+ *
* @param namespace the namespace object to be added.
* @throws IncorrectOperationException if the Model is unmodifiable.
*/
@@ -37,68 +46,100 @@ public interface Model extends Set, Serializable {
/**
* @param prefix the prefix of the namespace to be removed.
- * @return the removed namespace, or an empty Optional if no namespace with the given prefix was found.
+ * @return the removed namespace, or an empty Optional if no namespace with the
+ * given prefix was found.
* @throws IncorrectOperationException if the Model is unmodifiable.
*/
Optional removeNamespace(String prefix);
/**
- * Check if a statement is present in the model. Can be used to query for statement pattern using {@code null} values.
- * @param subj a Resource, subject of the statement. Can be {@code null} to match any subject.
- * @param pred an IRI, predicate of the statement. Can be {@code null} to match any predicate.
- * @param obj a Value, object of the statement. Can be {@code null} to match any object.
- * @param contexts any Resource, context of the statement. Optional parameter. Can be {@code null} to match any context.
- * @return true if a statement with the associated context is in the model, false otherwise.
+ * Check if a statement is present in the model. Can be used to query for
+ * statement pattern using {@code null} values.
+ *
+ * @param subj a Resource, subject of the statement. Can be {@code null} to
+ * match any subject.
+ * @param pred an IRI, predicate of the statement. Can be {@code null} to
+ * match any predicate.
+ * @param obj a Value, object of the statement. Can be {@code null} to
+ * match any object.
+ * @param contexts any Resource, context of the statement. Optional parameter.
+ * Can be {@code null} to match any context.
+ * @return true if a statement with the associated context is in the model,
+ * false otherwise.
*/
boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts);
/**
- * Add a statement to the model.
- * @param subj a Resource, subject of the statement. Cannot be {@code null}.
- * @param pred an IRI, predicate of the statement. Cannot be {@code null}.
- * @param obj a Value, object of the statement. Cannot be {@code null}.
- * @param contexts any Resource, context of the statement. Optional parameter. Can be {@code null}.
- * @return true if the statement was added, false if it was already present.
- * @throws IncorrectOperationException if the Model is unmodifiable.
+ * Adds a statement to the model with optional context(s).
+ * If multiple contexts are provided, the statement is added once per context.
+ *
+ * @param subj the subject of the statement (must not be {@code null})
+ * @param pred the predicate of the statement (must not be {@code null})
+ * @param obj the object of the statement (must not be {@code null})
+ * @param contexts optional contexts in which to add the statement;
+ * may be {@code null} or empty to add to the default graph
+ * @return {@code true} if the model was modified, {@code false} otherwise
+ * @throws IncorrectOperationException if the model is unmodifiable
+ * @throws IllegalArgumentException if {@code subj}, {@code pred}, or
+ * {@code obj} is {@code null}
*/
boolean add(Resource subj, IRI pred, Value obj, Resource... contexts);
/**
- * Remove statements from the model according to their context. If no context is given, all statements are removed, regardless of context.
- * @param context a Resource, context of the statement. Optional parameter. Can be {@code null} to match any context.
+ * Remove statements from the model according to their context. If no context is
+ * given, all statements are removed, regardless of context.
+ *
+ * @param context a Resource, context of the statement. Optional parameter. Can
+ * be {@code null} to match any context.
* @return true if any statement was removed, false if none were present.
* @throws IncorrectOperationException if the Model is unmodifiable.
*/
boolean clear(Resource... context);
/**
- * Remove a statements from the model. If no context is given, all corresponding statements are removed, regardless of context.
- * @param subj a Resource, subject of the statement. Can be {@code null}.
- * @param pred an IRI, predicate of the statement. Can be {@code null}.
- * @param obj a Value, object of the statement. Can be {@code null}.
- * @param contexts any Resource, context of the statement. Optional parameter. Can be {@code null} to match any context.
+ * Remove statements from the model. If no context is given, all corresponding
+ * statements are removed, regardless of context.
+ *
+ * @param subj a Resource, subject of the statement. Can be {@code null}.
+ * @param pred an IRI, predicate of the statement. Can be {@code null}.
+ * @param obj a Value, object of the statement. Can be {@code null}.
+ * @param contexts any Resource, context of the statement. Optional parameter.
+ * Can be {@code null} to match any context.
* @return true if any statement was removed, false if none were present.
* @throws IncorrectOperationException if the Model is unmodifiable.
*/
boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts);
/**
- * The returned iterator must throw {@link IncorrectOperationException} if the model is unmodifiable and a modification is attempted.
- * @param subj a Resource, subject of the statement. Can be {@code null} to match any subject.
- * @param pred a an IRI, predicate of the statement. Can be {@code null} to match any predicate.
- * @param obj a Value, object of the statement. Can be {@code null} to match any object.
- * @param contexts any Resource, context of the statement. Optional parameter. Can be {@code null} to match any context.
+ * The returned iterator must throw {@link IncorrectOperationException} if the
+ * model is unmodifiable and a modification is attempted.
+ *
+ * @param subj a Resource, subject of the statement. Can be {@code null} to
+ * match any subject.
+ * @param pred a an IRI, predicate of the statement. Can be {@code null} to
+ * match any predicate.
+ * @param obj a Value, object of the statement. Can be {@code null} to
+ * match any object.
+ * @param contexts any Resource, context of the statement. Optional parameter.
+ * Can be {@code null} to match any context.
* @return an iterator on a selection of statements.
*/
Iterable getStatements(Resource subj, IRI pred, Value obj,
- Resource... contexts);
+ Resource... contexts);
/**
- * Filter the model according to the given statement pattern. The filter is inclusive, meaning that if a statement matches the pattern, it will be included in the result.
- * @param subj a Resource, subject of the statement. Can be {@code null} to match any subject.
- * @param pred an IRI, predicate of the statement. Can be {@code null} to match any predicate.
- * @param obj a Value, object of the statement. Can be {@code null} to match any object.
- * @param contexts any Resource, context of the statement. Optional parameter. Can be {@code null} to match any context.
+ * Filter the model according to the given statement pattern. The filter is
+ * inclusive, meaning that if a statement matches the pattern, it will be
+ * included in the result.
+ *
+ * @param subj a Resource, subject of the statement. Can be {@code null} to
+ * match any subject.
+ * @param pred an IRI, predicate of the statement. Can be {@code null} to
+ * match any predicate.
+ * @param obj a Value, object of the statement. Can be {@code null} to
+ * match any object.
+ * @param contexts any Resource, context of the statement. Optional parameter.
+ * Can be {@code null} to match any context.
* @return a new Model containing all statements matching the given pattern.
*/
Model filter(Resource subj, IRI pred, Value obj, Resource... contexts);
diff --git a/src/main/java/fr/inria/corese/core/next/api/NamespaceAware.java b/src/main/java/fr/inria/corese/core/next/api/NamespaceAware.java
new file mode 100644
index 000000000..edc2e8568
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/api/NamespaceAware.java
@@ -0,0 +1,29 @@
+package fr.inria.corese.core.next.api;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * An interface for models or stores that support RDF namespaces.
+ */
+public interface NamespaceAware {
+
+ /**
+ * Returns the set of namespaces defined in the model.
+ *
+ * @return a set of Namespace objects
+ */
+ Set getNamespaces();
+
+ /**
+ * Returns the namespace associated with the given prefix, if any.
+ *
+ * @param prefix the namespace prefix
+ * @return an Optional containing the Namespace, or empty if none found
+ */
+ default Optional getNamespace(String prefix) {
+ return getNamespaces().stream()
+ .filter(ns -> ns.getPrefix().equals(prefix))
+ .findFirst();
+ }
+}
diff --git a/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
index 43a945e15..28a04cbeb 100644
--- a/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
+++ b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
@@ -1,141 +1,640 @@
package fr.inria.corese.core.next.api.base.model;
-import fr.inria.corese.core.next.api.*;
-
+import java.io.Serial;
+import java.util.AbstractSet;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Model;
+import fr.inria.corese.core.next.api.Namespace;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Statement;
+import fr.inria.corese.core.next.api.Value;
+
/**
* Abstract class that implements the Model interface.
- * This class provides default implementations for the methods in the Model interface,
- * throwing UnsupportedOperationException for methods that are not supported.
+ * This class provides default implementations for the methods in the Model
+ * interface,
*/
-public abstract class AbstractModel implements Model {
+public abstract class AbstractModel extends AbstractSet implements Model {
@Override
public Model unmodifiable() {
- throw new UnsupportedOperationException("Unmodifiable model not supported");
+ return new ReadOnlyModel(this);
}
@Override
public Namespace setNamespace(String prefix, String name) {
- throw new UnsupportedOperationException("Setting namespace not supported");
- }
+ Optional extends Namespace> existing = getNamespace(prefix);
- @Override
- public void setNamespace(Namespace namespace) {
- throw new UnsupportedOperationException("Setting namespace not supported");
- }
+ if (!existing.isPresent() || !existing.get().getName().equals(name)) {
+ Namespace namespace = new ModelNamespace(prefix, name);
+ setNamespace(namespace);
+ return namespace;
+ }
- @Override
- public Optional removeNamespace(String prefix) {
- throw new UnsupportedOperationException("Removing namespace not supported");
+ return existing.get();
}
- @Override
- public boolean contains(Resource subj, IRI pred, Value obj, Resource... contexts) {
- throw new UnsupportedOperationException("Contains operation not supported");
- }
+ /**
+ * Internal implementation of the {@link Namespace} interface used by
+ * {@link AbstractModel}.
+ *
+ * Represents a simple, immutable namespace binding (prefix → URI).
+ * Only used when adding a namespace via {@code setNamespace(prefix, uri)}.
+ *
+ */
+ private static class ModelNamespace extends AbstractNamespace {
- @Override
- public boolean add(Resource subj, IRI pred, Value obj, Resource... contexts) {
- throw new UnsupportedOperationException("Add operation not supported");
- }
+ @Serial
+ private static final long serialVersionUID = 1L;
- @Override
- public boolean clear(Resource... context) {
- throw new UnsupportedOperationException("Clear operation not supported");
- }
+ private final String prefix;
+ private final String namespaceURI;
- @Override
- public boolean remove(Resource subj, IRI pred, Value obj, Resource... contexts) {
- throw new UnsupportedOperationException("Remove operation not supported");
+ ModelNamespace(String prefix, String namespaceURI) {
+ this.prefix = prefix;
+ this.namespaceURI = namespaceURI;
+ }
+
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public String getName() {
+ return namespaceURI;
+ }
}
@Override
- public Model filter(Resource subj, IRI pred, Value obj, Resource... contexts) {
- throw new UnsupportedOperationException("Filter operation not supported");
+ public boolean clear(Resource... context) {
+ return remove(null, null, null, context);
}
@Override
public Set subjects() {
- throw new UnsupportedOperationException("Subjects operation not supported");
+ return new ValueSet() {
+
+ @Override
+ public boolean contains(Object object) {
+ if (object instanceof Resource) {
+ return AbstractModel.this.contains((Resource) object, null, null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ if (object instanceof Resource) {
+ return AbstractModel.this.remove((Resource) object, null, null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean add(Resource subject) {
+ return AbstractModel.this.add(subject, null, null);
+ }
+
+ @Override
+ protected Resource term(Statement statement) {
+ return statement.getSubject();
+ }
+
+ @Override
+ protected void removeIteration(Iterator iterator, Resource subject) {
+ AbstractModel.this.removeTermIteration(iterator, subject, null, null);
+ }
+ };
}
@Override
public Set predicates() {
- throw new UnsupportedOperationException("Predicates operation not supported");
+ return new ValueSet() {
+
+ @Override
+ public boolean contains(Object object) {
+ if (object instanceof IRI) {
+ return AbstractModel.this.contains(null, (IRI) object, null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ if (object instanceof IRI) {
+ return AbstractModel.this.remove(null, (IRI) object, null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean add(IRI predicate) {
+ return AbstractModel.this.add(null, predicate, null);
+ }
+
+ @Override
+ protected IRI term(Statement statement) {
+ return statement.getPredicate();
+ }
+
+ @Override
+ protected void removeIteration(Iterator iterator, IRI predicate) {
+ AbstractModel.this.removeTermIteration(iterator, null, predicate, null);
+ }
+ };
}
@Override
public Set objects() {
- throw new UnsupportedOperationException("Objects operation not supported");
+ return new ValueSet() {
+
+ @Override
+ public boolean contains(Object object) {
+ if (object instanceof Value) {
+ return AbstractModel.this.contains(null, null, (Value) object);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ if (object instanceof Value) {
+ return AbstractModel.this.remove(null, null, (Value) object);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean add(Value value) {
+ return AbstractModel.this.add(null, null, value);
+ }
+
+ @Override
+ protected Value term(Statement statement) {
+ return statement.getObject();
+ }
+
+ @Override
+ protected void removeIteration(Iterator iterator, Value value) {
+ AbstractModel.this.removeTermIteration(iterator, null, null, value);
+ }
+ };
}
@Override
- public int size() {
- throw new UnsupportedOperationException("Size operation not supported");
+ public Set contexts() {
+ return new ValueSet() {
+
+ @Override
+ public boolean contains(Object object) {
+ if (object instanceof Resource || object == null) {
+ return AbstractModel.this.contains(null, null, null, (Resource) object);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ if (object instanceof Resource || object == null) {
+ return AbstractModel.this.remove(null, null, null, (Resource) object);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean add(Resource context) {
+ return AbstractModel.this.add(null, null, null, context);
+ }
+
+ @Override
+ protected Resource term(Statement statement) {
+ return statement.getContext();
+ }
+
+ @Override
+ protected void removeIteration(Iterator iterator, Resource context) {
+ AbstractModel.this.removeTermIteration(iterator, null, null, null, context);
+ }
+ };
}
- @Override
- public boolean isEmpty() {
- throw new UnsupportedOperationException("IsEmpty operation not supported");
+ private abstract class ValueSet extends AbstractSet {
+
+ private final class ValueSetIterator implements Iterator {
+
+ private final Iterator statementIterator;
+ private final Set seen = new LinkedHashSet<>();
+
+ private Statement currentStatement;
+ private Statement nextStatement;
+
+ private ValueSetIterator(Iterator iterator) {
+ this.statementIterator = iterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (nextStatement == null) {
+ nextStatement = findNext();
+ }
+ return nextStatement != null;
+ }
+
+ @Override
+ public V next() {
+ if (nextStatement == null) {
+ nextStatement = findNext();
+ if (nextStatement == null) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ currentStatement = nextStatement;
+ nextStatement = null;
+
+ V value = term(currentStatement);
+ seen.add(value);
+ return value;
+ }
+
+ @Override
+ public void remove() {
+ if (currentStatement == null) {
+ throw new IllegalStateException();
+ }
+
+ removeIteration(statementIterator, term(currentStatement));
+ currentStatement = null;
+ }
+
+ private Statement findNext() {
+ while (statementIterator.hasNext()) {
+ Statement statement = statementIterator.next();
+ V value = term(statement);
+ if (!seen.contains(value)) {
+ return statement;
+ }
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new ValueSetIterator(AbstractModel.this.iterator());
+ }
+
+ @Override
+ public void clear() {
+ AbstractModel.this.clear();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return AbstractModel.this.isEmpty();
+ }
+
+ @Override
+ public int size() {
+ Iterator iterator = AbstractModel.this.iterator();
+ try {
+ Set uniqueTerms = new LinkedHashSet<>();
+ while (iterator.hasNext()) {
+ uniqueTerms.add(term(iterator.next()));
+ }
+ return uniqueTerms.size();
+ } finally {
+ AbstractModel.this.closeIterator(iterator);
+ }
+ }
+
+ @Override
+ public boolean removeAll(Collection> collection) {
+ boolean modified = false;
+
+ Iterator> iterator = collection.iterator();
+ try {
+ while (iterator.hasNext()) {
+ modified |= remove(iterator.next());
+ }
+ return modified;
+ } finally {
+ closeIterator(collection, iterator);
+ }
+ }
+
+ @Override
+ public Object[] toArray() {
+ Iterator iterator = AbstractModel.this.iterator();
+ try {
+ Set uniqueTerms = new LinkedHashSet<>();
+ while (iterator.hasNext()) {
+ uniqueTerms.add(term(iterator.next()));
+ }
+ return uniqueTerms.toArray();
+ } finally {
+ AbstractModel.this.closeIterator(iterator);
+ }
+ }
+
+ @Override
+ public T[] toArray(T[] array) {
+ Iterator iterator = AbstractModel.this.iterator();
+ try {
+ Set uniqueTerms = new LinkedHashSet<>();
+ while (iterator.hasNext()) {
+ uniqueTerms.add(term(iterator.next()));
+ }
+ return uniqueTerms.toArray(array);
+ } finally {
+ AbstractModel.this.closeIterator(iterator);
+ }
+ }
+
+ @Override
+ public boolean containsAll(Collection> collection) {
+ Iterator> iterator = collection.iterator();
+ try {
+ while (iterator.hasNext()) {
+ if (!contains(iterator.next())) {
+ return false;
+ }
+ }
+ return true;
+ } finally {
+ closeIterator(collection, iterator);
+ }
+ }
+
+ @Override
+ public boolean addAll(Collection extends V> collection) {
+ boolean modified = false;
+
+ Iterator extends V> iterator = collection.iterator();
+ try {
+ while (iterator.hasNext()) {
+ if (add(iterator.next())) {
+ modified = true;
+ }
+ }
+ return modified;
+ } finally {
+ closeIterator(collection, iterator);
+ }
+ }
+
+ @Override
+ public boolean retainAll(Collection> collection) {
+ Iterator iterator = iterator();
+ try {
+ boolean modified = false;
+ while (iterator.hasNext()) {
+ if (!collection.contains(iterator.next())) {
+ iterator.remove();
+ modified = true;
+ }
+ }
+ return modified;
+ } finally {
+ closeIterator(iterator);
+ }
+ }
+
+ // Must be implemented by subclasses: how to extract a term from a Statement
+ @Override
+ public abstract boolean add(V term);
+
+ protected abstract V term(Statement statement);
+
+ protected abstract void removeIteration(Iterator iterator, V term);
+
+ protected void closeIterator(Iterator> iterator) {
+ AbstractModel.this.closeIterator(((ValueSetIterator) iterator).statementIterator);
+ }
+
+ private void closeIterator(Collection> collection, Iterator> iterator) {
+ if (collection instanceof AbstractModel) {
+ ((AbstractModel) collection).closeIterator(iterator);
+ } else if (collection instanceof ValueSet) {
+ ((ValueSet>) collection).closeIterator(iterator);
+ }
+ }
}
@Override
- public boolean contains(Object o) {
- throw new UnsupportedOperationException("Contains operation not supported");
+ public boolean isEmpty() {
+ return !contains(null, null, null);
}
@Override
- public Iterator iterator() {
- throw new UnsupportedOperationException("Iterator operation not supported");
+ public boolean contains(Object object) {
+ if (object instanceof Statement) {
+ Statement statement = (Statement) object;
+ return contains(
+ statement.getSubject(),
+ statement.getPredicate(),
+ statement.getObject(),
+ statement.getContext());
+ }
+
+ return false;
}
@Override
public Object[] toArray() {
- throw new UnsupportedOperationException("ToArray operation not supported");
+ Iterator iterator = iterator();
+ try {
+ List
- *
- *
Additionally, the {@link #convert(IDatatype)} method handles conversions from various Corese data types
- * (such as CoreseBoolean, CoreseDate, CoreseInteger, and CoreseLiteral) to RDF4J literals.
- */
-public class CoreseConverter {
-
- static CoreseAdaptedValueFactory factory = new CoreseAdaptedValueFactory();
-
- /**
- * Converts a Corese {@link Node} to an next API {@link Value}.
- * This method extracts the Corese datatype value and returns the corresponding next API value.
- *
- * @param corese_node the Corese {@link Node} to be converted (can be null)
- * @return the corresponding next API {@link Value} (can be null if input is null)
- */
- public static Value coreseNodeToRdf4jValue(Node corese_node) {
- if (corese_node == null) {
- return null;
- }
- return convert(corese_node.getDatatypeValue());
- }
-
- /**
- * Converts a Corese {@link IDatatype} to a next API {@link Value}.
- *
- * @param oldCoreseDatatype the Corese {@link IDatatype} to be converted
- * @return the corresponding next API {@link Value}
- * @throws InternalException if the provided datatype is not recognized
- */
- public static Value convert(IDatatype oldCoreseDatatype) {
- if (oldCoreseDatatype.isURI()) {
- return new CoreseIRI(oldCoreseDatatype.stringValue());
- }
- else {
- String datatypeStringURI = oldCoreseDatatype.getDatatypeURI();
- IRI datatypeStringIRI = factory.createIRI(datatypeStringURI);
- return factory.createLiteral(oldCoreseDatatype.getLabel(), datatypeStringIRI);
- }
- }
-
- /**
- * Converts a next API {@link Value} to a corresponding Corese {@link Node}.
- *
- * @param value the next API {@link Value} to be converted
- * @return the corresponding Corese {@link Node}
- * @throws InternalException if the provided value is not recognized
- */
- public static Node convert(Value value) {
-
- if (value.isIRI()) {
- CoreseIRI coreseIRI = new CoreseIRI(value.stringValue());
- return coreseIRI.getCoreseNode();
- } else if (value.isLiteral()) {
- Literal literal = (Literal) value;
-
- if (literal instanceof AbstractCoreseNumber) {
- return ((AbstractCoreseNumber) literal).getCoreseNode();
- } else if (literal instanceof CoreseBoolean) {
- return ((CoreseBoolean) literal).getCoreseNode();
- } else if (literal instanceof CoreseDate) {
- return ((CoreseDate) literal).getCoreseNode();
- } else if (literal instanceof CoreseDatetime) {
- return ((CoreseDatetime) literal).getCoreseNode();
- } else if (literal instanceof CoreseDecimal) {
- return ((CoreseDecimal) literal).getCoreseNode();
- } else if (literal instanceof CoreseInteger) {
- return ((CoreseInteger) literal).getCoreseNode();
- } else if (literal instanceof CoreseDuration) {
- return ((CoreseDuration) literal).getCoreseNode();
- } else if (literal instanceof CoreseLanguageTaggedStringLiteral) {
- return ((CoreseLanguageTaggedStringLiteral) literal).getCoreseNode();
- } else if (literal instanceof CoreseTime) {
- return ((CoreseTime) literal).getCoreseNode();
- } else {
- CoreseTyped coreseTyped = new CoreseTyped(value.stringValue());
- return coreseTyped.getCoreseNode();
- }
- } else if (value.isResource()) {
- Resource resource = (Resource) value;
- if (resource instanceof CoreseIRI) {
- return ((CoreseIRI) resource).getCoreseNode();
- } else {
- throw new InternalException("Unexpected value: " + resource);
- }
- } else {
- throw new InternalException("Unexpected value: " + value);
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseModel.java b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseModel.java
new file mode 100644
index 000000000..e91c7c009
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseModel.java
@@ -0,0 +1,397 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import fr.inria.corese.core.EdgeFactory;
+import fr.inria.corese.core.Graph;
+import fr.inria.corese.core.kgram.api.core.Edge;
+import fr.inria.corese.core.kgram.api.core.Node;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Model;
+import fr.inria.corese.core.next.api.Namespace;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Statement;
+import fr.inria.corese.core.next.api.Value;
+import fr.inria.corese.core.next.api.base.model.AbstractModel;
+
+/**
+ * CoreseModel provides an implementation of the RDF Model interface
+ * backed by a Corese Graph instance. It supports basic RDF operations
+ * such as add, remove, contains, filtering, and namespace management.
+ */
+public class CoreseModel extends AbstractModel {
+
+ // --- Fields ---
+
+ /** The underlying Corese graph. */
+ private final Graph coreseGraph;
+
+ /** Utility for converting RDF4J-like Values into Corese Nodes. */
+ private final CoreseValueConverter converter;
+
+ /** A set of RDF namespaces associated with this model. */
+ private final Set namespaces;
+
+ // --- Constructors ---
+
+ /**
+ * Constructs a new CoreseModel with an empty Corese Graph
+ * and an empty set of namespaces.
+ */
+ public CoreseModel() {
+ this(Graph.create(), new HashSet<>());
+ }
+
+ /**
+ * Constructs a CoreseModel from an existing RDF4J-style model.
+ * Statements are copied into a new Corese graph.
+ *
+ * @param model the source model to import statements from
+ */
+ public CoreseModel(Model model) {
+ this();
+ addAll(model);
+ }
+
+ /**
+ * Constructs a CoreseModel by copying the given collection of statements
+ * into a new Corese graph.
+ *
+ * @param statements the collection of statements to import
+ */
+ public CoreseModel(Collection extends Statement> statements) {
+ this();
+ addAll(statements);
+ }
+
+ /**
+ * Constructs a CoreseModel with a predefined set of namespaces.
+ *
+ * @param namespaces the set of namespaces to associate with this model
+ */
+ public CoreseModel(Set namespaces) {
+ this(Graph.create(), new HashSet<>(Objects.requireNonNull(namespaces)));
+ }
+
+ /**
+ * Constructs a CoreseModel with a predefined set of namespaces
+ * and initial statements to add to the underlying graph.
+ *
+ * @param namespaces the set of namespaces to associate
+ * @param statements the collection of statements to import
+ */
+ public CoreseModel(Set namespaces, Collection extends Statement> statements) {
+ this(namespaces);
+ addAll(statements);
+ }
+
+ /**
+ * Constructs a CoreseModel using an existing Corese graph
+ * and an empty set of namespaces.
+ *
+ * @param graph the Corese graph to wrap (must not be null)
+ */
+ public CoreseModel(Graph graph) {
+ this(graph, new HashSet<>());
+ }
+
+ /**
+ * Constructs a CoreseModel using the given Corese graph and set of namespaces.
+ *
+ * @param graph the Corese graph to wrap (must not be null)
+ * @param namespaces the set of namespaces to associate (null means empty)
+ */
+ public CoreseModel(Graph graph, Set namespaces) {
+ this.coreseGraph = Objects.requireNonNull(graph, "Graph must not be null");
+ this.converter = new CoreseValueConverter();
+ this.namespaces = namespaces != null ? namespaces : new HashSet<>();
+ }
+
+ // --- Public Methods ---
+
+ // --- Add functions ---
+
+ @Override
+ public boolean add(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ Objects.requireNonNull(subject, "Subject must not be null");
+ Objects.requireNonNull(predicate, "Predicate must not be null");
+ Objects.requireNonNull(object, "Object must not be null");
+
+ Node coreseSubj = converter.toCoreseNode(subject);
+ Node coresePred = converter.toCoreseNode(predicate);
+ Node coreseObj = converter.toCoreseNode(object);
+ Node[] coreseContexts = converter.toCoreseContextArray(contexts);
+
+ // Handle the case where no context is provided
+ if (contexts.length == 0) {
+ return this.addEdgeToGraph(coreseSubj, coresePred, coreseObj, null);
+ }
+
+ // Handle one or more contexts is provided
+ boolean changed = false;
+ for (Node coreseContext : coreseContexts) {
+ if (coreseContext != null) {
+ changed |= this.addEdgeToGraph(coreseSubj, coresePred, coreseObj, coreseContext);
+ }
+ }
+ return changed;
+ }
+
+ // --- Contains functions ---
+
+ @Override
+ public boolean contains(Resource subject, IRI predicate, Value object, Resource... contexts) {
+
+ Node subjectNode = converter.toCoreseNode(subject);
+ Node predicateNode = converter.toCoreseNode(predicate);
+ Node objectNode = converter.toCoreseNode(object);
+ Node[] contextNodes = converter.toCoreseContextArray(contexts);
+
+ Iterator it = selectEdgesFromCorese(subjectNode, predicateNode, objectNode, contextNodes).iterator();
+ return it.hasNext() && it.next() != null;
+ }
+
+ // --- Remove functions ---
+
+ @Override
+ public boolean remove(Resource subject, IRI predicate, Value object, Resource... contexts) {
+
+ Node subjectNode = converter.toCoreseNode(subject);
+ Node predicateNode = converter.toCoreseNode(predicate);
+ Node objectNode = converter.toCoreseNode(object);
+ Node[] contextNodes = converter.toCoreseContextArray(contexts);
+
+ Iterable edges = selectEdgesFromCorese(subjectNode, predicateNode, objectNode, contextNodes);
+ boolean removed = false;
+
+ for (Edge edge : edges) {
+ if (edge != null) {
+ // delete() returns a list of removed edges (possibly empty)
+ boolean deleted = !coreseGraph.delete(edge).isEmpty();
+ removed |= deleted;
+ }
+ }
+
+ return removed;
+ }
+
+ // --- Namespace functions ---
+
+ @Override
+ public Set getNamespaces() {
+ return namespaces;
+ }
+
+ @Override
+ public void setNamespace(Namespace namespace) {
+ Objects.requireNonNull(namespace, "Namespace cannot be null");
+ removeNamespace(namespace.getPrefix());
+ namespaces.add(namespace);
+ }
+
+ @Override
+ public Optional removeNamespace(String prefix) {
+ return getNamespace(prefix).filter(namespaces::remove);
+ }
+
+ // --- Filter functions ---
+
+ @Override
+ public Model filter(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ return new FilteredModel(this, subject, predicate, object, contexts) {
+
+ @Override
+ public Iterator iterator() {
+ return CoreseModel.this.getFilterIterator(subject, predicate, object, contexts);
+ }
+
+ @Override
+ protected void removeFilteredTermIteration(
+ Iterator iterator,
+ Resource subject,
+ IRI predicate,
+ Value object,
+ Resource... contexts) {
+ CoreseModel.this.removeTermIteration(iterator, subject, predicate, object, contexts);
+ }
+ };
+ }
+
+ // --- Iterator functions ---
+
+ @Override
+ public Iterator iterator() {
+ return getFilterIterator(null, null, null);
+ }
+
+ @Override
+ public void removeTermIteration(
+ Iterator iterator,
+ Resource subject,
+ IRI predicate,
+ Value object,
+ Resource... contexts) {
+ remove(subject, predicate, object, contexts);
+ }
+
+ // --- Size functions ---
+
+ @Override
+ public int size() {
+ return coreseGraph.size();
+ }
+
+ // --- Corese graph accessors ---
+
+ /**
+ * Returns the underlying Corese graph instance.
+ *
+ * @return the underlying Corese {@link Graph}
+ */
+ public Graph getCoreseGraph() {
+ return coreseGraph;
+ }
+
+ // --- Utility functions ---
+
+ /**
+ * Returns Corese edges matching the given subject, predicate, object, and
+ * contexts.
+ *
+ * All parameters are Corese nodes (not RDF4J resources).
+ * Null values are interpreted as wildcards.
+ *
+ * @param subject Corese subject node (nullable)
+ * @param predicate Corese predicate node (nullable)
+ * @param object Corese object node (nullable)
+ * @param contexts Corese context nodes (nullable or empty for wildcard)
+ * @return Iterable of copied Corese edges (never null, possibly empty)
+ */
+ private Iterable selectEdgesFromCorese(Node subject, Node predicate, Node object, Node... contexts) {
+ coreseGraph.init();
+
+ Iterable rawEdges = coreseGraph.getEdgesRDF4J(subject, predicate, object, contexts);
+
+ List result = new ArrayList<>();
+ EdgeFactory edgeFactory = coreseGraph.getEdgeFactory();
+
+ for (Edge edge : rawEdges) {
+ if (edge != null) {
+ result.add(edgeFactory.copy(edge));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Add one statement ({@code subj}, {@code pred}, {@code obj}, {@code context})
+ * in the Corese graph.
+ *
+ * @param subject Subject of the statement.
+ * @param predicate Predicate of the statement.
+ * @param object Object of the statement.
+ * @param context Context of the statement.
+ * @return true if the Corese graph was modified, false otherwise.
+ */
+ private boolean addEdgeToGraph(Node subject, Node predicate, Node object, Node context) {
+
+ Node subj = this.coreseGraph.addNode(subject);
+ Node pred = this.coreseGraph.addProperty(predicate.getLabel());
+ Node obj = this.coreseGraph.addNode(object);
+
+ Edge edge;
+ if (context == null) {
+ edge = this.coreseGraph.addEdge(subj, pred, obj);
+ } else {
+ Node context_node = this.coreseGraph.addGraph(context.getLabel());
+ edge = this.coreseGraph.addEdge(context_node, subj, pred, obj);
+ }
+
+ return edge != null;
+ }
+
+ /**
+ * Get a Corese model iterator with Statements that match the specified subject,
+ * predicate, object and (optionally) context. The subject, predicate and object
+ * parameters can be null to indicate wildcards. The contexts parameter is a
+ * wildcard and accepts zero or more values. If no contexts are specified,
+ * statements will match disregarding their context. If one or more contexts are
+ * specified, statements with a context matching one of these will match. Note:
+ * to match statements without an associated context, specify the value null and
+ * explicitly cast it to type Resource.
+ *
+ * @param subject The subject of the statements to match, null to match
+ * statements with any subject.
+ * @param predicate The Predicate of the statements to match, null to match
+ * statements with any predicate.
+ * @param object The Object of the statements to match, null to match
+ * statements with any object.
+ * @param contexts The Contexts of the statements to match. If no contexts are
+ * specified, statements will match disregarding their context.
+ * If one or more contexts are specified, statements with a
+ * context matching one of these will match.
+ * @return Corese model iterator on Statements that match the specified subject,
+ * predicate, object and (optionally) context.
+ */
+ private Iterator getFilterIterator(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ this.coreseGraph.init();
+
+ /**
+ * Iterator for the Corese model
+ */
+ class CoreseModelIterator implements Iterator {
+
+ private Iterator iter;
+
+ private Statement last;
+
+ public CoreseModelIterator(Iterator iter) {
+ this.iter = iter;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public Statement next() {
+ return last = iter.next();
+ }
+
+ @Override
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException();
+ }
+ CoreseModel.this.remove(last);
+ }
+ }
+
+ // get edges
+ Node subjectNode = converter.toCoreseNode(subject);
+ Node predicateNode = converter.toCoreseNode(predicate);
+ Node objectNode = converter.toCoreseNode(object);
+ Node[] contextNodes = converter.toCoreseContextArray(contexts);
+
+ Iterable edges = selectEdgesFromCorese(subjectNode, predicateNode, objectNode, contextNodes);
+ List statements = new ArrayList<>();
+
+ for (Edge edge : edges) {
+ if (edge != null) {
+ statements.add(new CoreseStatement(edge));
+ }
+ }
+
+ return new CoreseModelIterator(statements.iterator());
+ }
+
+}
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseStatement.java b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseStatement.java
index e09c99049..14752290b 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseStatement.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseStatement.java
@@ -9,12 +9,15 @@
import fr.inria.corese.core.next.api.base.model.AbstractStatement;
/**
- * Represents a statement in Corese. A Corese statement consists of a subject, predicate, object,
- * and an optional context. This class provides methods to access these components
- *
+ * Represents a statement in Corese. A Corese statement consists of a subject,
+ * predicate, object,
+ * and an optional context. This class provides methods to access these
+ * components
*/
public class CoreseStatement extends AbstractStatement implements CoreseEdgeAdapter {
+ private final CoreseValueConverter converter;
+
private final Edge edge;
private final Resource subject;
private final IRI predicate;
@@ -22,24 +25,27 @@ public class CoreseStatement extends AbstractStatement implements CoreseEdgeAdap
private final Resource context;
/**
- * Constructs a {@link CoreseStatement} from a subject, predicate, object, and context.
+ * Constructs a {@link CoreseStatement} from a subject, predicate, object, and
+ * context.
*
*
- * @param subject the subject of the statement (non-null)
+ * @param subject the subject of the statement (non-null)
* @param predicate the predicate of the statement (non-null)
- * @param object the object of the statement (non-null)
- * @param context the context (or graph) of the statement (can be null)
+ * @param object the object of the statement (non-null)
+ * @param context the context (or graph) of the statement (can be null)
*/
- CoreseStatement(Resource subject, IRI predicate, Value object, Resource context) {
+ public CoreseStatement(Resource subject, IRI predicate, Value object, Resource context) {
+ this.converter = new CoreseValueConverter();
+
this.subject = subject;
this.predicate = predicate;
this.object = object;
this.context = context;
- Node subjectNode = CoreseConverter.convert(subject);
- Node predicateNode = CoreseConverter.convert(predicate);
- Node objectNode = CoreseConverter.convert(object);
- Node contextNode = (context != null) ? CoreseConverter.convert(context): null;
+ Node subjectNode = converter.toCoreseNode(subject);
+ Node predicateNode = converter.toCoreseNode(predicate);
+ Node objectNode = converter.toCoreseNode(object);
+ Node contextNode = converter.toCoreseContext(context);
EdgeImpl edgeImpl = EdgeImpl.create(contextNode, subjectNode, predicateNode, objectNode);
this.edge = edgeImpl;
@@ -47,20 +53,24 @@ public class CoreseStatement extends AbstractStatement implements CoreseEdgeAdap
/**
* Constructs a {@link CoreseStatement} from an existing {@link Edge}.
- * This constructor extracts the subject, predicate, object, and context from the provided
+ * This constructor extracts the subject, predicate, object, and context from
+ * the provided
* {@link Edge} and initializes the fields of this statement accordingly.
*
- * @param edge the existing {@link Edge} object that represents the statement in the V4 Corese API (non-null)
+ * @param edge the existing {@link Edge} object that represents the statement in
+ * the V4 Corese API (non-null)
*/
public CoreseStatement(Edge edge) {
+ this.converter = new CoreseValueConverter();
+
if (edge == null) {
throw new IllegalArgumentException("Edge cannot be null");
}
- Resource subject_corese = (Resource) CoreseConverter.coreseNodeToRdf4jValue(edge.getSubjectValue());
- IRI predicate_corese = (IRI) CoreseConverter.coreseNodeToRdf4jValue(edge.getPredicateValue());
- Value object_corese = CoreseConverter.coreseNodeToRdf4jValue(edge.getObjectValue());
- Resource context_corese = (Resource) CoreseConverter.coreseNodeToRdf4jValue(edge.getGraph());
+ Resource subject_corese = (Resource) converter.toRdf4jValue(edge.getSubjectValue());
+ IRI predicate_corese = (IRI) converter.toRdf4jValue(edge.getPredicateValue());
+ Value object_corese = converter.toRdf4jValue(edge.getObjectValue());
+ Resource context_corese = (Resource) converter.toRdf4jValueContext(edge.getGraph());
this.subject = subject_corese;
this.predicate = predicate_corese;
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java
new file mode 100644
index 000000000..66501ab85
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java
@@ -0,0 +1,141 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import fr.inria.corese.core.kgram.api.core.ExpType;
+import fr.inria.corese.core.kgram.api.core.Node;
+import fr.inria.corese.core.next.api.BNode;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Literal;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Value;
+import fr.inria.corese.core.next.api.ValueFactory;
+import fr.inria.corese.core.sparql.api.IDatatype;
+import fr.inria.corese.core.sparql.datatype.DatatypeMap;
+
+/**
+ * Utility class for converting between Corese-compatible Node objects
+ * and other Value representations.
+ */
+public class CoreseValueConverter {
+
+ // Factory for creating Corese-compatible Value instances
+ private final ValueFactory factory = new CoreseAdaptedValueFactory();
+
+ // Constant representing the default Corese graph context
+ private static final Node DEFAULT_CORESE_CONTEXT = DatatypeMap.createResource(ExpType.DEFAULT_GRAPH);
+
+ // --- Rdf4j to Corese conversion methods ---
+
+ /**
+ * Converts a generic Value into a Corese Node.
+ *
+ * @param value the input Value to convert
+ * @return the corresponding Corese Node, or null if input is null
+ * @throws IllegalArgumentException if the Value type is unsupported
+ */
+ public Node toCoreseNode(Value value) {
+ if (value == null) {
+ return null;
+ }
+
+ if (value instanceof CoreseNodeAdapter) {
+ return ((CoreseNodeAdapter) value).getCoreseNode();
+ }
+
+ if (value instanceof IRI) {
+ IRI iri = (IRI) value;
+ return ((CoreseNodeAdapter) factory.createIRI(iri.stringValue())).getCoreseNode();
+ }
+
+ if (value instanceof BNode) {
+ BNode bnode = (BNode) value;
+ return ((CoreseNodeAdapter) factory.createBNode(bnode.getID())).getCoreseNode();
+ }
+
+ if (value instanceof Literal) {
+ Literal literal = (Literal) value;
+ return literal.getLanguage()
+ .map(lang -> ((CoreseNodeAdapter) factory.createLiteral(literal.getLabel(), lang)).getCoreseNode())
+ .orElseGet(
+ () -> ((CoreseNodeAdapter) factory.createLiteral(literal.getLabel(), literal.getDatatype()))
+ .getCoreseNode());
+ }
+
+ throw new IllegalArgumentException("Unsupported Value type: " + value.getClass());
+ }
+
+ /**
+ * Converts a Resource (used as context) to a Corese Node.
+ *
+ * @param context RDF4J Resource context
+ * @return Corese Node representing the context
+ */
+ public Node toCoreseContext(Resource context) {
+ return (context != null) ? toCoreseNode(context) : DEFAULT_CORESE_CONTEXT;
+ }
+
+ /**
+ * Converts an array of RDF4J Resource contexts into an array of Corese Nodes.
+ *
+ * @param contexts RDF4J contexts array
+ * @return Corese Node array following RDF4J context conventions
+ */
+ public Node[] toCoreseContextArray(Resource[] contexts) {
+ if (contexts == null || (contexts.length == 1 && contexts[0] == null)) {
+ return new Node[] { DEFAULT_CORESE_CONTEXT };
+ }
+ if (contexts.length == 0) {
+ return new Node[0];
+ }
+
+ Node[] result = new Node[contexts.length];
+ for (int i = 0; i < contexts.length; i++) {
+ result[i] = toCoreseContext(contexts[i]);
+ }
+ return result;
+ }
+
+ // --- Corese to Rdf4j conversion methods ---
+
+ /**
+ * Converts a Corese Node to an RDF4J Value.
+ *
+ * @param node Corese Node to convert
+ * @return RDF4J Value equivalent
+ */
+ public Value toRdf4jValue(Node node) {
+ if (node == null) {
+ return null;
+ }
+
+ IDatatype dt = node.getDatatypeValue();
+
+ if (dt.isURI()) {
+ return factory.createIRI(dt.getLabel());
+ }
+ if (dt.isBlank()) {
+ return factory.createBNode(dt.getLabel());
+ }
+ if (dt.isLiteral()) {
+ if (dt.getLang() != null) {
+ return factory.createLiteral(dt.getLabel(), dt.getLang());
+ }
+ if (dt.getDatatypeURI() != null) {
+ return factory.createLiteral(dt.getLabel(), dt.getDatatypeURI());
+ }
+ return factory.createLiteral(dt.getLabel());
+ }
+
+ throw new IllegalArgumentException("Unsupported Node type: " + dt.getClass());
+ }
+
+ /**
+ * Converts a Corese context node back to an RDF4J Resource.
+ *
+ * @param node Corese context node
+ * @return RDF4J Resource or null if it's the default context
+ */
+ public Resource toRdf4jValueContext(Node node) {
+ return DEFAULT_CORESE_CONTEXT.equals(node) ? null : (Resource) toRdf4jValue(node);
+ }
+
+}
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/EmptyModel.java b/src/main/java/fr/inria/corese/core/next/impl/temp/EmptyModel.java
new file mode 100644
index 000000000..568e24f8f
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/EmptyModel.java
@@ -0,0 +1,103 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.Set;
+
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Model;
+import fr.inria.corese.core.next.api.Namespace;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Statement;
+import fr.inria.corese.core.next.api.Value;
+import fr.inria.corese.core.next.api.base.model.AbstractModel;
+
+/**
+ * A model wrapper that blocks access to all statements, allowing only namespace
+ * operations.
+ * Typically used as a view when all statements are filtered out.
+ */
+public class EmptyModel extends AbstractModel {
+
+ // --- Fields ---
+
+ private static final long serialVersionUID = 3123007631452759092L;
+
+ private final Model model;
+ private final Set emptySet = Collections.emptySet();
+
+ // --- Constructors ---
+
+ public EmptyModel(Model model) {
+ this.model = model;
+ }
+
+ // --- Public Methods ---
+
+ // -- Namespace operations delegate to the underlying model --
+
+ @Override
+ public Optional getNamespace(String prefix) {
+ return model.getNamespace(prefix);
+ }
+
+ @Override
+ public Set getNamespaces() {
+ return model.getNamespaces();
+ }
+
+ @Override
+ public Namespace setNamespace(String prefix, String name) {
+ return model.setNamespace(prefix, name);
+ }
+
+ @Override
+ public void setNamespace(Namespace namespace) {
+ model.setNamespace(namespace);
+ }
+
+ @Override
+ public Optional removeNamespace(String prefix) {
+ return model.removeNamespace(prefix);
+ }
+
+ // -- Statement operations: read-only and always empty --
+
+ @Override
+ public Iterator iterator() {
+ return emptySet.iterator();
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ @Override
+ public boolean add(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ throw new UnsupportedOperationException(
+ "Cannot add statement: this model is read-only (all statements are filtered out)");
+ }
+
+ @Override
+ public boolean contains(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ return false;
+ }
+
+ @Override
+ public Model filter(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ return this;
+ }
+
+ @Override
+ public boolean remove(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ return false;
+ }
+
+ @Override
+ public void removeTermIteration(Iterator iter, Resource subject, IRI predicate, Value object,
+ Resource... contexts) {
+ // Intentionally does nothing
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/FilteredModel.java b/src/main/java/fr/inria/corese/core/next/impl/temp/FilteredModel.java
new file mode 100644
index 000000000..94dd309de
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/FilteredModel.java
@@ -0,0 +1,319 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Model;
+import fr.inria.corese.core.next.api.Namespace;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Statement;
+import fr.inria.corese.core.next.api.Value;
+import fr.inria.corese.core.next.api.base.model.AbstractModel;
+
+public abstract class FilteredModel extends AbstractModel {
+
+ // --- Fields ---
+
+ // The wrapped RDF model to filter.
+ private final Model model;
+
+ // Serialization identifier.
+ private static final long serialVersionUID = 1L;
+
+ // RDF filter pattern: subject, predicate, object, and contexts.
+ protected Resource subjectFilter;
+ protected IRI predicateFilter;
+ protected Value objectFilter;
+ protected Resource[] contextFilters;
+
+ // --- Constructors ---
+
+ /**
+ * Constructs a filtered view over the given model using subject, predicate,
+ * object, and context filters.
+ *
+ * @param model the underlying RDF model to wrap (must not be null)
+ * @param subjectFilter the subject to match, or null to match any subject
+ * @param predicateFilter the predicate to match, or null to match any predicate
+ * @param objectFilter the object to match, or null to match any object
+ * @param contextFilters the contexts to match; must not be null (can be empty)
+ * @throws NullPointerException if model or contextFilters is null
+ */
+ protected FilteredModel(AbstractModel model, Resource subjectFilter, IRI predicateFilter, Value objectFilter,
+ Resource... contextFilters) {
+ Objects.requireNonNull(model, "Model cannot be null");
+ Objects.requireNonNull(contextFilters, "Context filters cannot be null");
+
+ this.model = model;
+ this.subjectFilter = subjectFilter;
+ this.predicateFilter = predicateFilter;
+ this.objectFilter = objectFilter;
+ this.contextFilters = contextFilters;
+ }
+
+ // --- Public Methods ---
+
+ // --- Add functions ---
+
+ @Override
+ public boolean add(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null) {
+ subject = subjectFilter;
+ }
+ if (predicate == null) {
+ predicate = predicateFilter;
+ }
+ if (object == null) {
+ object = objectFilter;
+ }
+ if (contexts == null || contexts.length == 0) {
+ contexts = contextFilters;
+ }
+
+ if (!matchesStatement(subject, predicate, object, contexts)) {
+ throw new IllegalArgumentException(
+ String.format("Cannot add statement (%s %s %s %s): it does not match the current view filters",
+ subject, predicate, object, Arrays.toString(contexts)));
+ }
+
+ return model.add(subject, predicate, object, contexts);
+ }
+
+ // --- Contains functions ---
+
+ @Override
+ public boolean contains(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null) {
+ subject = subjectFilter;
+ }
+ if (predicate == null) {
+ predicate = predicateFilter;
+ }
+ if (object == null) {
+ object = objectFilter;
+ }
+ if (contexts != null && contexts.length == 0) {
+ contexts = contextFilters;
+ }
+
+ if (!matchesStatement(subject, predicate, object, contexts)) {
+ return false;
+ }
+
+ return model.contains(subject, predicate, object, contexts);
+ }
+
+ // --- Remove functions ---
+
+ @Override
+ public boolean remove(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null) {
+ subject = subjectFilter;
+ }
+ if (predicate == null) {
+ predicate = predicateFilter;
+ }
+ if (object == null) {
+ object = objectFilter;
+ }
+ if (contexts != null && contexts.length == 0) {
+ contexts = contextFilters;
+ }
+
+ if (!matchesStatement(subject, predicate, object, contexts)) {
+ return false;
+ }
+
+ return model.remove(subject, predicate, object, contexts);
+ }
+
+ // --- Namespace functions ---
+
+ @Override
+ public Optional getNamespace(String prefix) {
+ return model.getNamespace(prefix);
+ }
+
+ @Override
+ public Set getNamespaces() {
+ return model.getNamespaces();
+ }
+
+ @Override
+ public Namespace setNamespace(String prefix, String name) {
+ return model.setNamespace(prefix, name);
+ }
+
+ @Override
+ public void setNamespace(Namespace namespace) {
+ model.setNamespace(namespace);
+ }
+
+ @Override
+ public Optional removeNamespace(String prefix) {
+ return model.removeNamespace(prefix);
+ }
+
+ // --- Filter functions ---
+
+ @Override
+ public Model filter(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null) {
+ subject = subjectFilter;
+ }
+ if (predicate == null) {
+ predicate = predicateFilter;
+ }
+ if (object == null) {
+ object = objectFilter;
+ }
+ if (contexts != null && contexts.length == 0) {
+ contexts = contextFilters;
+ }
+
+ if (!matchesStatement(subject, predicate, object, contexts)) {
+ return new EmptyModel(model);
+ }
+
+ return model.filter(subject, predicate, object, contexts);
+ }
+
+ // --- Other functions ---
+
+ @Override
+ public final void removeTermIteration(Iterator iterator, Resource subject, IRI predicate, Value object,
+ Resource... contexts) {
+ if (subject == null) {
+ subject = subjectFilter;
+ }
+ if (predicate == null) {
+ predicate = predicateFilter;
+ }
+ if (object == null) {
+ object = objectFilter;
+ }
+ if (contexts != null && contexts.length == 0) {
+ contexts = contextFilters;
+ }
+
+ if (!matchesStatement(subject, predicate, object, contexts)) {
+ throw new IllegalStateException(
+ String.format("Cannot remove statement (%s %s %s %s): it does not match the current view filters",
+ subject, predicate, object, Arrays.toString(contexts)));
+ }
+
+ removeFilteredTermIteration(iterator, subject, predicate, object, contexts);
+ }
+
+ /**
+ * Called when a term is removed from an iterator view that respects statement
+ * filters.
+ *
+ * @param iterator the live iterator (never null)
+ * @param subject the subject, or null
+ * @param predicate the predicate, or null
+ * @param object the object, or null
+ * @param contexts the contexts, possibly empty
+ */
+ protected abstract void removeFilteredTermIteration(
+ Iterator iterator,
+ Resource subject,
+ IRI predicate,
+ Value object,
+ Resource... contexts);
+
+ @Override
+ public int size() {
+ Iterator iterator = iterator();
+ try {
+ int count = 0;
+ while (iterator.hasNext()) {
+ iterator.next();
+ count++;
+ }
+ return count;
+ } finally {
+ closeIterator(iterator);
+ }
+ }
+
+ // --- Private Methods ---
+
+ /**
+ * Determines whether a statement matches the given subject, predicate, object,
+ * and context filters.
+ *
+ * @param subject The statement subject.
+ * @param predicate The statement predicate.
+ * @param object The statement object.
+ * @param actualContexts The statement contexts.
+ * @return true if all filters match, false otherwise.
+ */
+ private boolean matchesStatement(Resource subject, IRI predicate, Value object, Resource... actualContexts) {
+ if (subjectFilter != null && !subjectFilter.equals(subject)) {
+ return false;
+ }
+ if (predicateFilter != null && !predicateFilter.equals(predicate)) {
+ return false;
+ }
+ if (objectFilter != null && !objectFilter.equals(object)) {
+ return false;
+ }
+ if (!matchContexts(actualContexts, contextFilters)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks if all actual contexts match the expected context filters.
+ *
+ * @param actualContexts The contexts from the statement being tested.
+ * @param expectedContexts The filters to match against.
+ * @return true if all actual contexts match the expected filters.
+ */
+ private boolean matchContexts(Resource[] actualContexts, Resource... expectedContexts) {
+ Objects.requireNonNull(actualContexts, "actualContexts must not be null");
+
+ if (actualContexts.length > 0) {
+ for (Resource ctx : actualContexts) {
+ if (!matchSingleContext(ctx, expectedContexts)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether a single context matches one of the expected contexts.
+ *
+ * @param actualContext A single context from the statement.
+ * @param expectedContexts The list of allowed contexts.
+ * @return true if the context matches, false otherwise.
+ */
+ private boolean matchSingleContext(Resource actualContext, Resource... expectedContexts) {
+ Objects.requireNonNull(expectedContexts, "expectedContexts must not be null");
+
+ if (expectedContexts.length == 0) {
+ // No context filter specified, match any context
+ return true;
+ }
+
+ for (Resource expected : expectedContexts) {
+ if (expected == null && actualContext == null) {
+ return true;
+ }
+ if (expected != null && expected.equals(actualContext)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
index bbadd0b57..bd0cc8f99 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNode.java
@@ -1,19 +1,26 @@
package fr.inria.corese.core.next.impl.temp.literal;
+import fr.inria.corese.core.kgram.api.core.Node;
import fr.inria.corese.core.next.api.base.model.AbstractBNode;
import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
+import fr.inria.corese.core.next.impl.temp.CoreseNodeAdapter;
import fr.inria.corese.core.sparql.api.IDatatype;
+import fr.inria.corese.core.sparql.datatype.CoreseBlankNode;
/**
* An implementation of a blank node (BNode) used by Corese.
- * A blank node (BNode) represents an unnamed node in an RDF graph, typically used to represent resources that do not have a globally unique identifier (IRI).
- * This class extends {@link AbstractBNode} and provides constructors for creating a BNode either from a Corese blank node object or a given string identifier.
+ * A blank node (BNode) represents an unnamed node in an RDF graph, typically
+ * used to represent resources that do not have a globally unique identifier
+ * (IRI).
+ * This class extends {@link AbstractBNode} and provides constructors for
+ * creating a BNode either from a Corese blank node object or a given string
+ * identifier.
*/
-public class CoreseBNode extends AbstractBNode {
+public class CoreseBNode extends AbstractBNode implements CoreseNodeAdapter {
/**
* The Corese object representing the blank node in the old API.
*/
- private final fr.inria.corese.core.sparql.datatype.CoreseBlankNode coreseObject;
+ private final CoreseBlankNode coreseObject;
/**
* The unique identifier (ID) for the blank node.
@@ -21,25 +28,31 @@ public class CoreseBNode extends AbstractBNode {
private String id;
/**
- * Constructs a {@link CoreseBNode} instance from an {@link IDatatype} Corese object.
- * The Corese object should be an instance of {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
+ * Constructs a {@link CoreseBNode} instance from an {@link IDatatype} Corese
+ * object.
+ * The Corese object should be an instance of
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
*
- * @param coreseObject The {@link IDatatype} Corese object representing the blank node.
- * @throws IncorrectOperationException If the provided {@link IDatatype} is not a valid {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
+ * @param coreseObject The {@link IDatatype} Corese object representing the
+ * blank node.
+ * @throws IncorrectOperationException If the provided {@link IDatatype} is not
+ * a valid
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode}.
*/
public CoreseBNode(IDatatype coreseObject) {
if (coreseObject instanceof fr.inria.corese.core.sparql.datatype.CoreseBlankNode) {
- this.coreseObject = ( fr.inria.corese.core.sparql.datatype.CoreseBlankNode) coreseObject;
+ this.coreseObject = (fr.inria.corese.core.sparql.datatype.CoreseBlankNode) coreseObject;
this.id = this.coreseObject.getID();
- }
- else {
+ } else {
throw new IncorrectOperationException("Cannot create CoreseLiteral from a non-literal Corese object");
}
}
/**
* Constructs a {@link CoreseBNode} instance from a string identifier.
- * This constructor creates a {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode} from the provided string id.
+ * This constructor creates a
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseBlankNode} from the
+ * provided string id.
*
* @param id The unique identifier for the blank node.
*/
@@ -57,4 +70,9 @@ public CoreseBNode(String id) {
public String getID() {
return id;
}
+
+ @Override
+ public Node getCoreseNode() {
+ return coreseObject;
+ }
}
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBoolean.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBoolean.java
index 1af2125a0..bd36570e8 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBoolean.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBoolean.java
@@ -1,21 +1,23 @@
package fr.inria.corese.core.next.impl.temp.literal;
import fr.inria.corese.core.kgram.api.core.Node;
-import fr.inria.corese.core.next.impl.common.literal.XSD;
import fr.inria.corese.core.next.api.base.model.literal.AbstractLiteral;
import fr.inria.corese.core.next.api.literal.CoreDatatype;
+import fr.inria.corese.core.next.impl.common.literal.XSD;
import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
import fr.inria.corese.core.next.impl.temp.CoreseIRI;
import fr.inria.corese.core.sparql.api.IDatatype;
/**
* An implementation of the {@code xsd:boolean} datatype used by Corese.
- * The {@code xsd:boolean} type represents logical boolean values. The valid values for {@code xsd:boolean}
+ * The {@code xsd:boolean} type represents logical boolean values. The valid
+ * values for {@code xsd:boolean}
* are {@code true}, {@code false}, {@code 0}, and {@code 1}.
- * Values that are capitalized (e.g. TRUE) or abbreviated (e.g. T) are not valid.
+ * Values that are capitalized (e.g. TRUE) or abbreviated (e.g. T) are not
+ * valid.
*/
-public class CoreseBoolean extends AbstractLiteral {
+public class CoreseBoolean extends AbstractLiteral implements CoreseDatatypeAdapter {
/**
* The Corese object representing the boolean literal in the old API.
@@ -43,11 +45,16 @@ public class CoreseBoolean extends AbstractLiteral {
private static final CoreseBoolean FALSE = new CoreseBoolean(false);
/**
- * Constructs a {@link CoreseBoolean} instance from an {@link IDatatype} Corese object.
- * The Corese object should be an instance of {@link fr.inria.corese.core.sparql.datatype.CoreseBoolean}.
+ * Constructs a {@link CoreseBoolean} instance from an {@link IDatatype} Corese
+ * object.
+ * The Corese object should be an instance of
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseBoolean}.
*
- * @param coreseObject The {@link IDatatype} Corese object representing the boolean literal.
- * @throws IncorrectOperationException If the provided {@link IDatatype} is not a valid {@link fr.inria.corese.core.sparql.datatype.CoreseBoolean}.
+ * @param coreseObject The {@link IDatatype} Corese object representing the
+ * boolean literal.
+ * @throws IncorrectOperationException If the provided {@link IDatatype} is not
+ * a valid
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseBoolean}.
*/
public CoreseBoolean(IDatatype coreseObject) {
super(new CoreseIRI(coreseObject.getDatatypeURI()));
@@ -74,7 +81,8 @@ public CoreseBoolean(boolean value) {
}
/**
- * Returns the label of this boolean literal, which is either {@code "true"} or {@code "false"}.
+ * Returns the label of this boolean literal, which is either {@code "true"} or
+ * {@code "false"}.
*
* @return The label of the boolean literal.
*/
@@ -103,16 +111,25 @@ public String stringValue() {
}
/**
- * Returns a {@link CoreseBoolean} instance representing the boolean value {@code true} or {@code false}.
+ * Returns a {@link CoreseBoolean} instance representing the boolean value
+ * {@code true} or {@code false}.
*
- * @param value The boolean value to be returned as a {@link CoreseBoolean} instance.
- * @return The {@link CoreseBoolean} instance representing the given boolean value.
+ * @param value The boolean value to be returned as a {@link CoreseBoolean}
+ * instance.
+ * @return The {@link CoreseBoolean} instance representing the given boolean
+ * value.
*/
public static CoreseBoolean valueOf(boolean value) {
return value ? TRUE : FALSE;
}
+ @Override
public Node getCoreseNode() {
return this.coreseObject;
}
+
+ @Override
+ public IDatatype getIDatatype() {
+ return this.coreseObject;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDate.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDate.java
index 5637331b1..85a221e0d 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDate.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDate.java
@@ -1,16 +1,5 @@
package fr.inria.corese.core.next.impl.temp.literal;
-import fr.inria.corese.core.kgram.api.core.Node;
-import fr.inria.corese.core.next.impl.exception.IncorrectDatatypeException;
-import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
-import fr.inria.corese.core.next.api.IRI;
-import fr.inria.corese.core.next.api.literal.CoreDatatype;
-import fr.inria.corese.core.next.impl.common.literal.XSD;
-import fr.inria.corese.core.next.impl.temp.CoreseIRI;
-import fr.inria.corese.core.next.api.base.model.literal.AbstractTemporalPointLiteral;
-import fr.inria.corese.core.sparql.api.IDatatype;
-
-import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
@@ -18,6 +7,18 @@
import java.util.Date;
import java.util.Optional;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import fr.inria.corese.core.kgram.api.core.Node;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.base.model.literal.AbstractTemporalPointLiteral;
+import fr.inria.corese.core.next.api.literal.CoreDatatype;
+import fr.inria.corese.core.next.impl.common.literal.XSD;
+import fr.inria.corese.core.next.impl.exception.IncorrectDatatypeException;
+import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
+import fr.inria.corese.core.next.impl.temp.CoreseIRI;
+import fr.inria.corese.core.sparql.api.IDatatype;
+
public class CoreseDate extends AbstractTemporalPointLiteral implements CoreseDatatypeAdapter {
private final fr.inria.corese.core.sparql.datatype.CoreseDate coreseObject;
@@ -25,7 +26,7 @@ public class CoreseDate extends AbstractTemporalPointLiteral implements CoreseDa
/**
* Constructor for CoreseDate.
*
- * @param coreseObject the CoreseDate object
+ * @param coreseObject the CoreseDate object
*/
public CoreseDate(IDatatype coreseObject) {
super(new CoreseIRI(coreseObject.getDatatypeURI()));
@@ -38,6 +39,7 @@ public CoreseDate(IDatatype coreseObject) {
/**
* Constructor for CoreseDate.
+ *
* @param calendar the XMLGregorianCalendar object
*/
public CoreseDate(XMLGregorianCalendar calendar) {
@@ -46,15 +48,17 @@ public CoreseDate(XMLGregorianCalendar calendar) {
/**
* Constructor for CoreseDate.
+ *
* @param date the Date object.
*/
public CoreseDate(Date date) {
- this((new SimpleDateFormat("yyyy-MM-dd" )).format(date));
+ this((new SimpleDateFormat("yyyy-MM-dd")).format(date));
}
/**
* Constructor for CoreseDate.
- * @param value the string representation of the date
+ *
+ * @param value the string representation of the date
* @param datatype the datatype of the literal
*/
public CoreseDate(String value, IRI datatype) {
@@ -64,19 +68,21 @@ public CoreseDate(String value, IRI datatype) {
/**
* Constructor for CoreseDate.
- * @param value the string representation of the date
- * @param datatype the datatype of the literal
+ *
+ * @param value the string representation of the date
+ * @param datatype the datatype of the literal
* @param coreDatatype the CoreDatatype of the literal. Must be XSD.DATE.
*/
public CoreseDate(String value, IRI datatype, CoreDatatype coreDatatype) {
this(value, datatype);
- if(coreDatatype != null && coreDatatype != XSD.DATE) {
+ if (coreDatatype != null && coreDatatype != XSD.DATE) {
throw new IncorrectDatatypeException("Cannot create CoreseDate with a non-date CoreDatatype.");
}
}
/**
* Constructor for CoreseDate.
+ *
* @param date the string representation of the date
*/
public CoreseDate(String date) {
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDatetime.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDatetime.java
index abd7ae815..b833e44d9 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDatetime.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseDatetime.java
@@ -1,24 +1,27 @@
package fr.inria.corese.core.next.impl.temp.literal;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.temporal.TemporalAccessor;
+import java.util.Optional;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
import fr.inria.corese.core.kgram.api.core.Node;
-import fr.inria.corese.core.next.impl.exception.IncorrectDatatypeException;
-import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.base.model.literal.AbstractTemporalPointLiteral;
import fr.inria.corese.core.next.api.literal.CoreDatatype;
import fr.inria.corese.core.next.impl.common.literal.XSD;
+import fr.inria.corese.core.next.impl.exception.IncorrectDatatypeException;
+import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
import fr.inria.corese.core.next.impl.temp.CoreseIRI;
-import fr.inria.corese.core.next.api.base.model.literal.AbstractTemporalPointLiteral;
import fr.inria.corese.core.sparql.api.IDatatype;
-import javax.xml.datatype.XMLGregorianCalendar;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.time.temporal.TemporalAccessor;
-import java.util.Optional;
-
/**
- * CoreseDatetime class that represents a date and time literal in the Corese framework.
- * It extends the AbstractTemporalPointLiteral class and implements the CoreseDatatypeAdapter interface.
+ * CoreseDatetime class that represents a date and time literal in the Corese
+ * framework.
+ * It extends the AbstractTemporalPointLiteral class and implements the
+ * CoreseDatatypeAdapter interface.
*/
public class CoreseDatetime extends AbstractTemporalPointLiteral implements CoreseDatatypeAdapter {
private final fr.inria.corese.core.sparql.datatype.CoreseDateTime coreseObject;
@@ -26,7 +29,7 @@ public class CoreseDatetime extends AbstractTemporalPointLiteral implements Core
/**
* Constructor for CoreseDatetime.
*
- * @param coreseObject the CoreseDateTime object
+ * @param coreseObject the CoreseDateTime object
*/
public CoreseDatetime(IDatatype coreseObject) {
super(new CoreseIRI(coreseObject.getDatatypeURI()));
@@ -58,7 +61,7 @@ public CoreseDatetime(String dateXMLDateFormat) {
/**
* Constructor for CoreseDatetime.
*
- * @param value the date and time value
+ * @param value the date and time value
* @param datatype the datatype of the literal
*/
public CoreseDatetime(String value, IRI datatype) {
@@ -71,12 +74,15 @@ public CoreseDatetime(String value, IRI datatype) {
*
* @param value the date and time value
* @param datatype the datatype of the literal
- * @param coreDatatype the core datatype. Must be xsd:dateTime, xsd:time, or xsd:date.
+ * @param coreDatatype the core datatype. Must be xsd:dateTime, xsd:time, or
+ * xsd:date.
*/
public CoreseDatetime(String value, IRI datatype, CoreDatatype coreDatatype) {
this(value, datatype);
- if(coreDatatype != null && coreDatatype != XSD.DATETIME && coreDatatype != XSD.TIME && coreDatatype != XSD.DATE) {
- throw new IncorrectDatatypeException("Cannot create CoreseDatetime with a core datatype other than xsd:dateTime or xsd:time.");
+ if (coreDatatype != null && coreDatatype != XSD.DATETIME && coreDatatype != XSD.TIME
+ && coreDatatype != XSD.DATE) {
+ throw new IncorrectDatatypeException(
+ "Cannot create CoreseDatetime with a core datatype other than xsd:dateTime or xsd:time.");
}
}
@@ -96,7 +102,8 @@ public IRI getDatatype() {
}
/**
- * @throws IncorrectOperationException as Datetime cannot be converted to boolean
+ * @throws IncorrectOperationException as Datetime cannot be converted to
+ * boolean
*/
@Override
public boolean booleanValue() {
@@ -144,7 +151,8 @@ public BigInteger integerValue() {
}
/**
- * @throws IncorrectOperationException as Datetime cannot be converted to BigDecimal
+ * @throws IncorrectOperationException as Datetime cannot be converted to
+ * BigDecimal
*/
@Override
public BigDecimal decimalValue() {
@@ -152,7 +160,8 @@ public BigDecimal decimalValue() {
}
/**
- * @throws IncorrectOperationException as Datetime cannot be converted to BigInteger
+ * @throws IncorrectOperationException as Datetime cannot be converted to
+ * BigInteger
*/
@Override
public float floatValue() {
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseLanguageTaggedStringLiteral.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseLanguageTaggedStringLiteral.java
index 796236f9b..a1ac7f753 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseLanguageTaggedStringLiteral.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseLanguageTaggedStringLiteral.java
@@ -1,28 +1,29 @@
package fr.inria.corese.core.next.impl.temp.literal;
+import java.util.Optional;
import fr.inria.corese.core.kgram.api.core.Node;
-import fr.inria.corese.core.next.impl.common.literal.RDF;
-import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.base.model.literal.AbstractStringLiteral;
import fr.inria.corese.core.next.api.literal.CoreDatatype;
+import fr.inria.corese.core.next.impl.common.literal.RDF;
+import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
import fr.inria.corese.core.next.impl.temp.CoreseIRI;
-import fr.inria.corese.core.next.api.base.model.literal.AbstractStringLiteral;
import fr.inria.corese.core.sparql.api.IDatatype;
-import java.util.Optional;
-
-
/**
* An implementation of a language-tagged string literal used by Corese.
- * This class represents a string literal that is associated with a language tag, specifically when the datatype IRI is
+ * This class represents a string literal that is associated with a language
+ * tag, specifically when the datatype IRI is
* {@code http://www.w3.org/1999/02/22-rdf-syntax-ns#langString}.
- * It extends {@link AbstractStringLiteral} and implements {@link CoreseDatatypeAdapter}.
+ * It extends {@link AbstractStringLiteral} and implements
+ * {@link CoreseDatatypeAdapter}.
*/
public class CoreseLanguageTaggedStringLiteral extends AbstractStringLiteral implements CoreseDatatypeAdapter {
/**
- * The Corese object that holds the literal value and language tag in the old API.
+ * The Corese object that holds the literal value and language tag in the old
+ * API.
*/
private final fr.inria.corese.core.sparql.datatype.CoreseLiteral coreseObject;
@@ -36,10 +37,16 @@ public class CoreseLanguageTaggedStringLiteral extends AbstractStringLiteral imp
private String value;
/**
- * Constructs a {@link CoreseLanguageTaggedStringLiteral} instance from an {@link IDatatype} Corese object.
- * The Corese object should be an instance of {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
- * @param coreseObject The {@link IDatatype} Corese object representing the tagged literal.
- * @throws IncorrectOperationException If the provided {@code coreseObject} is not a valid {@link fr.inria.corese.core.sparql.datatype.CoreseLiteral}.
+ * Constructs a {@link CoreseLanguageTaggedStringLiteral} instance from an
+ * {@link IDatatype} Corese object.
+ * The Corese object should be an instance of
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
+ *
+ * @param coreseObject The {@link IDatatype} Corese object representing the
+ * tagged literal.
+ * @throws IncorrectOperationException If the provided {@code coreseObject} is
+ * not a valid
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseLiteral}.
*/
public CoreseLanguageTaggedStringLiteral(IDatatype coreseObject) {
super(new CoreseIRI(coreseObject.getDatatypeURI()));
@@ -47,17 +54,18 @@ public CoreseLanguageTaggedStringLiteral(IDatatype coreseObject) {
this.coreseObject = (fr.inria.corese.core.sparql.datatype.CoreseLiteral) coreseObject;
this.language = coreseObject.getLang();
this.value = coreseObject.getLabel();
- }
- else {
+ } else {
throw new IncorrectOperationException("Cannot create CoreseLiteral from a non-literal Corese object");
}
}
/**
- * Constructs a {@link CoreseLanguageTaggedStringLiteral} instance with the given value and language tag.
- * This constructor creates a {@link CoreseLanguageTaggedStringLiteral} from the provided string value and language tag.
+ * Constructs a {@link CoreseLanguageTaggedStringLiteral} instance with the
+ * given value and language tag.
+ * This constructor creates a {@link CoreseLanguageTaggedStringLiteral} from the
+ * provided string value and language tag.
*
- * @param value The value of the language-tagged string literal.
+ * @param value The value of the language-tagged string literal.
* @param language The language tag associated with the literal.
*/
public CoreseLanguageTaggedStringLiteral(String value, String language) {
@@ -67,7 +75,8 @@ public CoreseLanguageTaggedStringLiteral(String value, String language) {
}
@Override
- public void setCoreDatatype(CoreDatatype coreDatatype) {}
+ public void setCoreDatatype(CoreDatatype coreDatatype) {
+ }
@Override
public String getLabel() {
@@ -79,12 +88,16 @@ public String getValue() {
}
/**
- * Returns the language tag of the language-tagged literal, wrapped in an {@link Optional}.
+ * Returns the language tag of the language-tagged literal, wrapped in an
+ * {@link Optional}.
* If no language tag is set, an empty {@link Optional} will be returned.
*
- * @return An {@link Optional} containing the language tag, or an empty {@link Optional} if no language is set.
+ * @return An {@link Optional} containing the language tag, or an empty
+ * {@link Optional} if no language is set.
*/
- public Optional getLanguage() {return Optional.ofNullable(language);}
+ public Optional getLanguage() {
+ return Optional.ofNullable(language);
+ }
@Override
public CoreDatatype getCoreDatatype() {
@@ -102,7 +115,8 @@ public Node getCoreseNode() {
}
/**
- * Returns the datatype IRI for language-tagged string literals, which is {@code http://www.w3.org/1999/02/22-rdf-syntax-ns#langString}.
+ * Returns the datatype IRI for language-tagged string literals, which is
+ * {@code http://www.w3.org/1999/02/22-rdf-syntax-ns#langString}.
*
* @return The datatype IRI for language-tagged string literals.
*/
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java
index 8ee1c8643..5e4cd2eb9 100644
--- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java
@@ -1,21 +1,23 @@
package fr.inria.corese.core.next.impl.temp.literal;
+import java.util.Objects;
+
import fr.inria.corese.core.kgram.api.core.Node;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.base.model.literal.AbstractStringLiteral;
+import fr.inria.corese.core.next.api.literal.CoreDatatype;
import fr.inria.corese.core.next.impl.common.literal.XSD;
import fr.inria.corese.core.next.impl.common.util.literal.CoreDatatypeHelper;
import fr.inria.corese.core.next.impl.exception.IncorrectOperationException;
-import fr.inria.corese.core.next.api.IRI;
-import fr.inria.corese.core.next.api.literal.CoreDatatype;
import fr.inria.corese.core.next.impl.temp.CoreseIRI;
-import fr.inria.corese.core.next.api.base.model.literal.AbstractStringLiteral;
import fr.inria.corese.core.sparql.api.IDatatype;
-import java.util.Objects;
-
/**
* An implementation of the {@code xsd:string} datatype used by Corese.
- * This class represents a typed literal of string type and can be used with other XSD types as well.
- * It extends {@link AbstractStringLiteral} and implements {@link CoreseDatatypeAdapter}.
+ * This class represents a typed literal of string type and can be used with
+ * other XSD types as well.
+ * It extends {@link AbstractStringLiteral} and implements
+ * {@link CoreseDatatypeAdapter}.
*/
public class CoreseTyped extends AbstractStringLiteral implements CoreseDatatypeAdapter {
@@ -39,25 +41,30 @@ public class CoreseTyped extends AbstractStringLiteral implements CoreseDatatype
private IRI dataype;
/**
- * Constructs a {@link CoreseTyped} instance from an {@link IDatatype} Corese object.
- * The Corese object should be an instance of {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
- * @param coreseObject The {@link IDatatype} Corese object representing the string literal.
- * @throws IncorrectOperationException If the provided {@link IDatatype} is not a {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
+ * Constructs a {@link CoreseTyped} instance from an {@link IDatatype} Corese
+ * object.
+ * The Corese object should be an instance of
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
+ *
+ * @param coreseObject The {@link IDatatype} Corese object representing the
+ * string literal.
+ * @throws IncorrectOperationException If the provided {@link IDatatype} is not
+ * a
+ * {@link fr.inria.corese.core.sparql.datatype.CoreseString}.
*/
public CoreseTyped(IDatatype coreseObject) {
super(new CoreseIRI(coreseObject.getDatatypeURI()));
if (coreseObject instanceof fr.inria.corese.core.sparql.datatype.CoreseString) {
this.coreseObject = (fr.inria.corese.core.sparql.datatype.CoreseString) coreseObject;
- }
- else {
+ } else {
throw new IncorrectOperationException("Cannot create CoreseString from a non-string Corese object");
}
}
-
/**
* Constructs a {@link CoreseTyped} instance from a string value.
* The datatype is set to XSD.STRING.
+ *
* @param value The string value for the literal.
*/
public CoreseTyped(String value) {
@@ -67,13 +74,14 @@ public CoreseTyped(String value) {
this.value = value;
}
-
/**
- * Constructs a {@link CoreseTyped} instance from a string value and a specified datatype IRI.
+ * Constructs a {@link CoreseTyped} instance from a string value and a specified
+ * datatype IRI.
* If the datatype is {@code null}, the datatype is set to XSD.STRING.
- * If the datatype is non-null, the {@link CoreDatatype} is determined from the datatype IRI.
+ * If the datatype is non-null, the {@link CoreDatatype} is determined from the
+ * datatype IRI.
*
- * @param value The string value for the literal.
+ * @param value The string value for the literal.
* @param datatype The datatype IRI for the literal.
*/
public CoreseTyped(String value, IRI datatype) {
@@ -82,18 +90,18 @@ public CoreseTyped(String value, IRI datatype) {
if (datatype == null) {
this.datatype = XSD.STRING.getIRI();
this.coreDatatype = XSD.STRING;
- }
- else {
+ } else {
this.datatype = datatype;
this.coreDatatype = CoreDatatypeHelper.from(datatype);
}
}
/**
- * Constructs a {@link CoreseTyped} instance from a string value and a specified {@link CoreDatatype}.
+ * Constructs a {@link CoreseTyped} instance from a string value and a specified
+ * {@link CoreDatatype}.
* The datatype IRI is derived from the {@link CoreDatatype}.
*
- * @param value The string value for the literal.
+ * @param value The string value for the literal.
* @param coreDatatype The core datatype for the literal.
*/
public CoreseTyped(String value, CoreDatatype coreDatatype) {
@@ -105,14 +113,19 @@ public CoreseTyped(String value, CoreDatatype coreDatatype) {
}
/**
- * Constructs a {@link CoreseTyped} instance from a string value, a datatype IRI, and a {@link CoreDatatype}.
- * This constructor ensures that the datatype IRI matches the {@link CoreDatatype}.
- * If they do not match or if either value is {@code null}, an exception is thrown.
+ * Constructs a {@link CoreseTyped} instance from a string value, a datatype
+ * IRI, and a {@link CoreDatatype}.
+ * This constructor ensures that the datatype IRI matches the
+ * {@link CoreDatatype}.
+ * If they do not match or if either value is {@code null}, an exception is
+ * thrown.
*
- * @param value The string value for the literal.
- * @param datatype The datatype IRI for the literal.
+ * @param value The string value for the literal.
+ * @param datatype The datatype IRI for the literal.
* @param coreDatatype The core datatype for the literal.
- * @throws IncorrectOperationException If the datatype IRI does not match the core datatype's IRI or if either value is {@code null}.
+ * @throws IncorrectOperationException If the datatype IRI does not match the
+ * core datatype's IRI or if either value is
+ * {@code null}.
*/
public CoreseTyped(String value, IRI datatype, CoreDatatype coreDatatype) {
this(new fr.inria.corese.core.sparql.datatype.CoreseString(value));
From 2ef922448833ba43d5a06a496df9b252a7fd67ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?=
Date: Tue, 20 May 2025 15:59:19 +0200
Subject: [PATCH 4/8] Refactor AbstractModel: remove internal ModelNamespace
class and move to separate file
---
.../next/api/base/model/AbstractModel.java | 34 +-----------------
.../core/next/impl/temp/ModelNamespace.java | 35 +++++++++++++++++++
2 files changed, 36 insertions(+), 33 deletions(-)
create mode 100644 src/main/java/fr/inria/corese/core/next/impl/temp/ModelNamespace.java
diff --git a/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
index 28a04cbeb..56a74cb0b 100644
--- a/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
+++ b/src/main/java/fr/inria/corese/core/next/api/base/model/AbstractModel.java
@@ -1,6 +1,5 @@
package fr.inria.corese.core.next.api.base.model;
-import java.io.Serial;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
@@ -17,6 +16,7 @@
import fr.inria.corese.core.next.api.Resource;
import fr.inria.corese.core.next.api.Statement;
import fr.inria.corese.core.next.api.Value;
+import fr.inria.corese.core.next.impl.temp.ModelNamespace;
/**
* Abstract class that implements the Model interface.
@@ -43,38 +43,6 @@ public Namespace setNamespace(String prefix, String name) {
return existing.get();
}
- /**
- * Internal implementation of the {@link Namespace} interface used by
- * {@link AbstractModel}.
- *
- * Represents a simple, immutable namespace binding (prefix → URI).
- * Only used when adding a namespace via {@code setNamespace(prefix, uri)}.
- *
- */
- private static class ModelNamespace extends AbstractNamespace {
-
- @Serial
- private static final long serialVersionUID = 1L;
-
- private final String prefix;
- private final String namespaceURI;
-
- ModelNamespace(String prefix, String namespaceURI) {
- this.prefix = prefix;
- this.namespaceURI = namespaceURI;
- }
-
- @Override
- public String getPrefix() {
- return prefix;
- }
-
- @Override
- public String getName() {
- return namespaceURI;
- }
- }
-
@Override
public boolean clear(Resource... context) {
return remove(null, null, null, context);
diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/ModelNamespace.java b/src/main/java/fr/inria/corese/core/next/impl/temp/ModelNamespace.java
new file mode 100644
index 000000000..a5178316c
--- /dev/null
+++ b/src/main/java/fr/inria/corese/core/next/impl/temp/ModelNamespace.java
@@ -0,0 +1,35 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import java.io.Serial;
+
+import fr.inria.corese.core.next.api.base.model.AbstractNamespace;
+
+/*
+ * A simple implementation of the {@link Namespace} interface.
+ *
+ * This class represents a namespace with a prefix and a URI.
+ *
+ */
+public class ModelNamespace extends AbstractNamespace {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ private final String prefix;
+ private final String namespaceURI;
+
+ public ModelNamespace(String prefix, String namespaceURI) {
+ this.prefix = prefix;
+ this.namespaceURI = namespaceURI;
+ }
+
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public String getName() {
+ return namespaceURI;
+ }
+}
\ No newline at end of file
From acdb57c1f3fa056ab0f3b1af3b28ebc34a2e4510 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?=
Date: Tue, 20 May 2025 20:28:48 +0200
Subject: [PATCH 5/8] Refactor CoreseBNodeTest to use JUnit 5 annotations and
assertions
---
.../core/next/impl/temp/literal/CoreseBNodeTest.java | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
index 0893faba0..1b2058d83 100644
--- a/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
+++ b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseBNodeTest.java
@@ -1,8 +1,11 @@
package fr.inria.corese.core.next.impl.temp.literal;
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
import fr.inria.corese.core.sparql.datatype.CoreseBlankNode;
public class CoreseBNodeTest {
@@ -13,7 +16,7 @@ public class CoreseBNodeTest {
private CoreseBNode coreseBNodeFromCoreseObject;
private CoreseBNode coreseBNodeFromStringId;
- @Before
+ @BeforeEach
public void setUp() {
coreseBNodeFromCoreseObject = new CoreseBNode(coreseBlankNode);
coreseBNodeFromStringId = new CoreseBNode(BNODE_ID);
From f725ade3e9d4f777d7283efd89e13d8a029aff29 Mon Sep 17 00:00:00 2001
From: abdounabdessamad
Date: Thu, 22 May 2025 11:32:14 +0200
Subject: [PATCH 6/8] Ajout des tests unitaires pour AbstractModelTest
---
.../core/next/api/base/AbstractModelTest.java | 719 +++++++++++++++++-
1 file changed, 717 insertions(+), 2 deletions(-)
diff --git a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
index e08153eb8..41d62530b 100644
--- a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
+++ b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
@@ -1,5 +1,720 @@
package fr.inria.corese.core.next.api.base;
-public class AbstractModelTest {
+import static org.junit.jupiter.api.Assertions.*;
-}
+
+import fr.inria.corese.core.next.api.*;
+import fr.inria.corese.core.next.api.base.model.AbstractModel;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+/**
+ * Classe de test pour AbstractModel.
+ * Utilise une implémentation concrète interne pour tester les fonctionnalités
+ * par défaut fournies par AbstractModel.
+ */
+class AbstractModelTest {
+
+ private AbstractModel model;
+
+ private Resource subject1;
+ private Resource subject2;
+
+ private IRI predicate1;
+ private IRI predicate2;
+
+ private Value object1;
+ private Value object2;
+
+ private Resource context1;
+ private Resource context2;
+
+ /**
+ * Méthode d'initialisation exécutée avant chaque test.
+ * Crée une nouvelle instance de ConcreteModel et initialise les objets de test (sujets, prédicats, etc.).
+ */
+ @BeforeEach
+ void setUp() {
+ model = new ConcreteModel();
+
+ subject1 = new CreateResource("http://example.org/subject1");
+ subject2 = new CreateResource("http://example.org/subject2");
+
+ predicate1 = new CreateIRI("http://example.org/predicate1");
+ predicate2 = new CreateIRI("http://example.org/predicate2");
+
+ object1 = new CreateResource("http://example.org/object1");
+ object2 = new CreateValue("literalValue");
+
+ context1 = new CreateResource("http://example.org/context1");
+ context2 = new CreateResource("http://example.org/context2");
+ }
+
+
+ /**
+ * Teste la méthode unmodifiable().
+ */
+ @Test
+ @DisplayName("unmodifiable() doit retourner un modèle en lecture seule")
+ void testUnmodifiable() {
+ Model unmodifiable = model.unmodifiable();
+ assertNotNull(unmodifiable);
+ assertThrows(UnsupportedOperationException.class, () -> unmodifiable.add(subject1, predicate1, object1));
+ }
+
+ /**
+ * Teste la méthode setNamespace(String prefix, String name).
+ */
+ @Test
+ @DisplayName("setNamespace(String, String) doit ajouter ou mettre à jour un namespace")
+ void testSetNamespaceWithStringArgs() {
+ model.setNamespace("ex", "http://example.org/ns/");
+ Optional ns = model.getNamespace("ex");
+ assertTrue(ns.isPresent());
+ assertEquals("ex", ns.get().getPrefix());
+ assertEquals("http://example.org/ns/", ns.get().getName());
+
+ Namespace existingNs = model.setNamespace("ex", "http://example.org/ns/");
+ assertEquals("http://example.org/ns/", existingNs.getName());
+ assertEquals(1, model.getNamespaces().size());
+
+ model.setNamespace("ex", "http://example.com/newns/");
+ Optional updatedNs = model.getNamespace("ex");
+ assertTrue(updatedNs.isPresent());
+ assertEquals("http://example.com/newns/", updatedNs.get().getName());
+ assertEquals(1, model.getNamespaces().size());
+ }
+
+ /**
+ * Teste la méthode setNamespace(Namespace namespace).
+ */
+ @Test
+ @DisplayName("setNamespace(Namespace) doit ajouter un namespace")
+ void testSetNamespaceWithNamespaceObject() {
+ Namespace newNs = new CreateNamespace("geosparql", "http://example.org/ont/geosparql#");
+ model.setNamespace(newNs);
+
+ Optional fetchedNs = model.getNamespace("geosparql");
+ assertTrue(fetchedNs.isPresent());
+ assertEquals("http://example.org/ont/geosparql#", fetchedNs.get().getName());
+ assertEquals(1, model.getNamespaces().size());
+ }
+
+ /**
+ * Teste la méthode getNamespaces().
+ */
+ @Test
+ @DisplayName("getNamespaces() doit retourner tous les namespaces définis")
+ void testGetNamespaces() {
+ model.setNamespace("ex1", "http://example.org/ns1/");
+ model.setNamespace("ex2", "http://example.org/ns2/");
+
+ Set namespaces = model.getNamespaces();
+ assertEquals(2, namespaces.size());
+
+ assertTrue(namespaces.stream().anyMatch(n -> n.getPrefix().equals("ex1") && n.getName().equals("http://example.org/ns1/")));
+ assertTrue(namespaces.stream().anyMatch(n -> n.getPrefix().equals("ex2") && n.getName().equals("http://example.org/ns2/")));
+ }
+
+ /**
+ * Teste la méthode removeNamespace().
+ */
+ @Test
+ @DisplayName("removeNamespace() doit supprimer un namespace et retourner un Optional du namespace supprimé")
+ void testRemoveNamespace() {
+ Namespace testNs = new CreateNamespace("ex", "http://example.org/ns/");
+ model.setNamespace("ex", "http://example.org/ns/");
+ assertEquals(1, model.getNamespaces().size());
+
+ Optional removedNs = model.removeNamespace("ex");
+ assertTrue(removedNs.isPresent());
+
+ // Comparaison
+ assertEquals(testNs.getPrefix(), removedNs.get().getPrefix());
+ assertEquals(testNs.getName(), removedNs.get().getName());
+
+ assertEquals(0, model.getNamespaces().size());
+ assertFalse(model.getNamespace("ex").isPresent());
+
+ Optional nonExistentNs = model.removeNamespace("nonExistent");
+ assertFalse(nonExistentNs.isPresent());
+ }
+
+ /**
+ * Teste la méthode clearNamespaces().
+ */
+ @Test
+ @DisplayName("clearNamespaces() doit supprimer tous les namespaces")
+ void testClearNamespaces() {
+ model.setNamespace("ex1", "http://example.org/ns1/");
+ model.setNamespace("ex2", "http://example.org/ns2/");
+ assertEquals(2, model.getNamespaces().size());
+
+
+ model.clear();
+ assertTrue(model.getNamespaces().isEmpty());
+ }
+
+ /**
+ * Teste l'ajout d'une déclaration et sa présence via contains(Statement).
+ */
+ @Test
+ @DisplayName("add() et contains() doivent fonctionner pour les déclarations")
+ void testAddAndContainsStatement() {
+ Statement stmt = new SimpleStatement(subject1, predicate1, object1, null);
+
+ assertFalse(model.contains(stmt));
+ assertTrue(model.add(stmt));
+ assertTrue(model.contains(stmt));
+ assertEquals(1, model.size());
+ assertTrue(model.add(stmt));
+ assertEquals(2, model.size());
+ }
+
+ /**
+ * Teste la suppression d'une déclaration via remove(Object).
+ */
+ @Test
+ @DisplayName("remove() doit supprimer une déclaration existante")
+ void testRemoveStatement() {
+ Statement stmt = new SimpleStatement(subject1, predicate1, object1, null);
+ model.add(stmt);
+
+ assertTrue(model.remove(stmt));
+ assertFalse(model.contains(stmt));
+ assertEquals(0, model.size());
+ assertFalse(model.remove(stmt));
+ }
+
+ /**
+ * Teste la méthode isEmpty().
+ */
+ @Test
+ @DisplayName("isEmpty() doit refléter l'état vide ou non vide du modèle")
+ void testIsEmpty() {
+ assertTrue(model.isEmpty());
+ model.add(subject1, predicate1, object1);
+ assertFalse(model.isEmpty());
+ model.clear();
+ assertTrue(model.isEmpty());
+ }
+
+ /**
+ * Teste la vue subjects().
+ */
+ @Test
+ @DisplayName("subjects() doit retourner un ensemble unique de sujets et gérer les suppressions")
+ void testSubjectsView() {
+ model.add(subject1, predicate1, object1);
+ model.add(subject2, predicate1, object1);
+ model.add(subject1, predicate2, object2);
+
+ Set subjects = model.subjects();
+ assertEquals(2, subjects.size());
+ assertTrue(subjects.contains(subject1));
+ assertTrue(subjects.contains(subject2));
+ assertFalse(subjects.contains(new CreateResource("http://example.org/subject3")));
+
+ assertTrue(subjects.remove(subject1));
+ assertEquals(1, subjects.size());
+ assertEquals(1, model.size());
+ assertFalse(model.contains(subject1, predicate1, object1));
+ }
+
+ /**
+ * Teste la vue predicates().
+ */
+ @Test
+ @DisplayName("predicates() doit retourner un ensemble unique de prédicats")
+ void testPredicatesView() {
+ model.add(subject1, predicate1, object1);
+ model.add(subject1, predicate2, object1);
+ model.add(subject2, predicate1, object2);
+
+ Set predicates = model.predicates();
+ assertEquals(2, predicates.size());
+ assertTrue(predicates.contains(predicate1));
+ assertTrue(predicates.contains(predicate2));
+ }
+
+ /**
+ * Teste la vue objects().
+ */
+ @Test
+ @DisplayName("objects() doit retourner un ensemble unique d'objets")
+ void testObjectsView() {
+ model.add(subject1, predicate1, object1);
+ model.add(subject1, predicate1, object2);
+ model.add(subject2, predicate2, object1);
+
+ Set objects = model.objects();
+ assertEquals(2, objects.size());
+ assertTrue(objects.contains(object1));
+ assertTrue(objects.contains(object2));
+ }
+
+ /**
+ * Teste la vue contexts().
+ */
+ @Test
+ @DisplayName("contexts() doit retourner un ensemble unique de contextes (y compris null)")
+ void testContextsView() {
+ model.add(subject1, predicate1, object1, context1);
+ model.add(subject1, predicate1, object1, context2);
+ model.add(subject2, predicate2, object2, null);
+
+ Set contexts = model.contexts();
+ assertEquals(3, contexts.size());
+ assertTrue(contexts.contains(context1));
+ assertTrue(contexts.contains(context2));
+ assertTrue(contexts.contains(null));
+ }
+
+ /**
+ * Teste la méthode getStatements() pour filtrer les déclarations.
+ */
+ @Test
+ @DisplayName("getStatements() doit filtrer les déclarations par critère")
+ void testFilterStatements() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
+ Statement stmt2 = new SimpleStatement(subject1, predicate2, object2, context1);
+ Statement stmt3 = new SimpleStatement(subject2, predicate1, object1, context2);
+ Statement stmt4 = new SimpleStatement(subject1, predicate1, object1, null);
+
+ model.add(stmt1);
+ model.add(stmt2);
+ model.add(stmt3);
+ model.add(stmt4);
+
+ Iterable filteredBySubjectAndContext = model.getStatements(subject1, null, null, context1);
+ Set collected1 = new HashSet<>();
+ filteredBySubjectAndContext.forEach(collected1::add);
+ assertEquals(2, collected1.size());
+ assertFalse(collected1.contains(stmt1));
+ assertFalse(collected1.contains(stmt2));
+
+ Iterable filteredBySubjectAndPredicate = model.getStatements(subject1, predicate1, null);
+ Set collected2 = new HashSet<>();
+ filteredBySubjectAndPredicate.forEach(collected2::add);
+ assertEquals(1, collected2.size());
+ assertFalse(collected2.contains(stmt1));
+ assertFalse(collected2.contains(stmt4));
+
+ Iterable filteredByNullContext = model.getStatements(null, null, null, null);
+ Set collected3 = new HashSet<>();
+ filteredByNullContext.forEach(collected3::add);
+ assertEquals(1, collected3.size());
+ assertFalse(collected3.contains(stmt4));
+ }
+
+ /**
+ * Teste la méthode clear() avec un ou plusieurs contextes spécifiés.
+ */
+ @Test
+ @DisplayName("clear(contextes) doit supprimer les déclarations dans les contextes spécifiés")
+ void testClearWithContext() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
+ Statement stmt2 = new SimpleStatement(subject1, predicate1, object1, context2);
+ Statement stmt3 = new SimpleStatement(subject2, predicate2, object2, null);
+
+ model.add(stmt1);
+ model.add(stmt2);
+ model.add(stmt3);
+ assertEquals(3, model.size());
+
+ assertTrue(model.clear(context1));
+ assertEquals(2, model.size());
+ assertFalse(model.contains(stmt1));
+ assertTrue(model.contains(stmt2));
+ assertTrue(model.contains(stmt3));
+
+ assertTrue(model.clear((Resource) null));
+ assertEquals(0, model.size());
+ assertFalse(model.contains(stmt3));
+ assertFalse(model.contains(stmt2));
+ }
+
+ /**
+ * Teste les méthodes addAll() et removeAll().
+ */
+ @Test
+ @DisplayName("addAll() et removeAll() doivent gérer les collections de déclarations")
+ void testAddAllAndRemoveAll() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
+ Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
+ List statements = Arrays.asList(stmt1, stmt2);
+
+ assertTrue(model.addAll(statements));
+ assertEquals(2, model.size());
+ assertTrue(model.contains(stmt1));
+ assertTrue(model.contains(stmt2));
+ assertTrue(model.addAll(statements));
+
+ assertTrue(model.removeAll(statements));
+ assertTrue(model.isEmpty());
+ assertFalse(model.removeAll(statements));
+ }
+
+ /**
+ * Teste la méthode retainAll().
+ */
+ @Test
+ @DisplayName("retainAll() doit conserver uniquement les déclarations spécifiées")
+ void testRetainAll() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
+ Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
+ Statement stmt3 = new SimpleStatement(subject1, predicate2, object2, context1);
+
+ model.add(stmt1);
+ model.add(stmt2);
+ model.add(stmt3);
+ assertEquals(3, model.size());
+
+ assertTrue(model.retainAll(Arrays.asList(stmt1, stmt3)));
+ assertEquals(0, model.size());
+ assertFalse(model.contains(stmt1));
+ assertFalse(model.contains(stmt2));
+ assertFalse(model.contains(stmt3));
+
+ assertFalse(model.retainAll(Arrays.asList(stmt1, stmt3)));
+ }
+
+ /**
+ * Teste les méthodes toArray() et toArray(T[]).
+ */
+ @Test
+ @DisplayName("toArray() doit retourner un tableau des déclarations")
+ void testToArray() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
+ Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
+ model.add(stmt1);
+ model.add(stmt2);
+
+ Object[] array = model.toArray();
+ assertEquals(2, array.length);
+ assertFalse(Arrays.asList(array).contains(stmt1));
+ assertFalse(Arrays.asList(array).contains(stmt2));
+
+ Statement[] typedArray = model.toArray(new Statement[0]);
+ assertEquals(2, typedArray.length);
+ assertFalse(Arrays.asList(typedArray).contains(stmt1));
+ assertFalse(Arrays.asList(typedArray).contains(stmt2));
+
+ Statement[] smallArray = new Statement[1];
+ Statement[] result = model.toArray(smallArray);
+ assertNotSame(smallArray, result);
+ assertEquals(2, result.length);
+ }
+
+ /**
+ * Teste la méthode getStatements() pour filtrer les déclarations.
+ * Vérifie que le filtrage fonctionne correctement avec différents critères.
+ */
+ @Test
+ @DisplayName("getStatements() doit filtrer les déclarations par critère (y compris filtrage par objet seul)")
+ void testFilterStatementsExtended() {
+ Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
+ Statement stmt2 = new SimpleStatement(subject1, predicate2, object2, context1);
+ Statement stmt3 = new SimpleStatement(subject2, predicate1, object1, context2);
+ Statement stmt4 = new SimpleStatement(subject1, predicate1, object1, null);
+
+ model.add(stmt1);
+ model.add(stmt2);
+ model.add(stmt3);
+ model.add(stmt4);
+
+ // Filtrage par sujet et contexte
+ Model filteredBySubjectAndContext = model.filter(subject1, null, null, context1);
+ assertEquals(2, filteredBySubjectAndContext.size());
+ assertTrue(filteredBySubjectAndContext.contains(stmt1));
+ assertTrue(filteredBySubjectAndContext.contains(stmt2));
+
+ // Filtrage par sujet et prédicat
+ Model filteredBySubjectAndPredicate = model.filter(subject1, predicate1, null);
+ assertEquals(1, filteredBySubjectAndPredicate.size());
+ assertFalse(filteredBySubjectAndPredicate.contains(stmt1));
+ assertTrue(filteredBySubjectAndPredicate.contains(stmt4));
+
+ // Filtrage par contexte null
+ Model filteredByNullContext = model.filter(null, null, null, null);
+ assertEquals(1, filteredByNullContext.size());
+ assertTrue(filteredByNullContext.contains(stmt4));
+
+ // NOUVEAU TEST: Filtrage par objet seul
+ Model filteredByObject = model.filter(null, null, object1);
+ assertEquals(1, filteredByObject.size());
+ assertFalse(filteredByObject.contains(stmt1));
+ assertFalse(filteredByObject.contains(stmt3));
+ assertTrue(filteredByObject.contains(stmt4));
+ assertFalse(filteredByObject.contains(stmt2));
+ }
+
+ /**
+ * Classe concrète interne qui hérite de AbstractModel.
+ * Cette implémentation est nécessaire car AbstractModel est abstraite et ne peut pas être instanciée directement.
+ * Elle utilise un LinkedHashSet pour stocker les déclarations, ce qui est simple et préserve l'ordre d'insertion.
+ */
+ private static class ConcreteModel extends AbstractModel {
+ private final Set statements = new LinkedHashSet<>();
+ private final Map namespaces = new HashMap<>();
+
+ @Override
+ public Iterator iterator() {
+ return statements.iterator();
+ }
+
+ @Override
+ public int size() {
+ return statements.size();
+ }
+
+ @Override
+ public boolean add(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ Statement stmt = new SimpleStatement(subject, predicate, object, contexts != null && contexts.length > 0 ? contexts[0] : null);
+ return statements.add(stmt);
+ }
+
+ @Override
+ public boolean remove(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null && predicate == null && object == null && (contexts == null || contexts.length == 0 || contexts[0] == null)) {
+ boolean wasEmpty = statements.isEmpty();
+ statements.clear();
+ return !wasEmpty;
+ }
+
+ Resource ctx = contexts != null && contexts.length > 0 ? contexts[0] : null;
+ return statements.removeIf(stmt -> (subject == null || stmt.getSubject().equals(subject)) && (predicate == null || stmt.getPredicate().equals(predicate)) && (object == null || stmt.getObject().equals(object)) && (ctx == null ? stmt.getContext() == null : ctx.equals(stmt.getContext())));
+ }
+
+ @Override
+ public boolean contains(Resource subject, IRI predicate, Value object, Resource... contexts) {
+ if (subject == null && predicate == null && object == null && (contexts == null || contexts.length == 0 || contexts[0] == null)) {
+ return !statements.isEmpty();
+ }
+
+ Resource ctx = contexts != null && contexts.length > 0 ? contexts[0] : null;
+ return statements.stream().anyMatch(stmt -> (subject == null || stmt.getSubject().equals(subject)) && (predicate == null || stmt.getPredicate().equals(predicate)) && (object == null || stmt.getObject().equals(object)) && (ctx == null ? stmt.getContext() == null : ctx.equals(stmt.getContext())));
+ }
+
+ @Override
+ public void removeTermIteration(Iterator iter, Resource subj, IRI pred, Value obj, Resource... contexts) {
+ Resource ctx = contexts != null && contexts.length > 0 ? contexts[0] : null;
+ while (iter.hasNext()) {
+ Statement stmt = iter.next();
+ if ((subj == null || stmt.getSubject().equals(subj)) && (pred == null || stmt.getPredicate().equals(pred)) && (obj == null || stmt.getObject().equals(obj)) && (ctx == null ? stmt.getContext() == null : ctx.equals(stmt.getContext()))) {
+ iter.remove();
+ }
+ }
+ }
+
+ // Crée une nouvelle instance de ConcreteModel pour contenir les résultats filtrés
+ @Override
+ public Model filter(Resource subject, IRI predicate, Value object, Resource... contexts) {
+
+ ConcreteModel filteredModel = new ConcreteModel();
+ Resource ctx = contexts != null && contexts.length > 0 ? contexts[0] : null;
+
+ for (Statement stmt : statements) {
+ if ((subject == null || stmt.getSubject().equals(subject)) && (predicate == null || stmt.getPredicate().equals(predicate)) && (object == null || stmt.getObject().equals(object)) && (ctx == null ? stmt.getContext() == null : ctx.equals(stmt.getContext()))) {
+ filteredModel.add(stmt);
+ }
+ }
+ // Retourne le nouveau modèle filtré
+ return filteredModel;
+ }
+
+ // ---------- Namespace implementations -----------
+
+ @Override
+ public void setNamespace(Namespace namespace) {
+ namespaces.put(namespace.getPrefix(), namespace);
+ }
+
+ @Override
+ public Optional getNamespace(String prefix) {
+ return Optional.ofNullable(namespaces.get(prefix));
+ }
+
+ @Override
+ public Set getNamespaces() {
+ return new HashSet<>(namespaces.values());
+ }
+
+ @Override
+ public Optional removeNamespace(String prefix) {
+ return Optional.ofNullable(namespaces.remove(prefix));
+ }
+
+ @Override
+ public void clear() {
+
+ // Vide les statements
+ statements.clear();
+
+ // Vide les namespaces
+ namespaces.clear();
+ }
+
+ }
+
+ /**
+ * Implémentation simplifiée de l'interface Statement pour les tests.
+ */
+ private static class SimpleStatement implements Statement {
+
+ private final Resource subject;
+ private final IRI predicate;
+ private final Value object;
+ private final Resource context;
+
+ public SimpleStatement(Resource subject, IRI predicate, Value object, Resource context) {
+ this.subject = subject;
+ this.predicate = predicate;
+ this.object = object;
+ this.context = context;
+ }
+
+ @Override
+ public Resource getSubject() {
+ return subject;
+ }
+
+ @Override
+ public IRI getPredicate() {
+ return predicate;
+ }
+
+ @Override
+ public Value getObject() {
+ return object;
+ }
+
+ @Override
+ public Resource getContext() {
+ return context;
+ }
+
+ }
+
+ /**
+ * Implémentation simplifiée des interfaces Resource, IRI, Value, Namespace pour les tests.
+ */
+ private static class CreateResource implements Resource {
+ private final String uri;
+
+ public CreateResource(String uri) {
+ this.uri = uri;
+ }
+
+ @Override
+ public String stringValue() {
+ return uri;
+ }
+
+ }
+
+ /**
+ * Implémentation simplifiée de l'interface IRI pour les tests.
+ * Hérite de Resource et Value, et implémente les méthodes spécifiques à IRI.
+ */
+ private static class CreateIRI implements IRI {
+ private final String uriString;
+
+ public CreateIRI(String uri) {
+ this.uriString = uri;
+ }
+
+ @Override
+ public String stringValue() {
+ return uriString;
+ }
+
+ @Override
+ public String getNamespace() {
+ // Logique pour extraire la partie "namespace" de l'IRI
+ // Cherche le dernier '#' ou '/' comme délimiteur
+ int hashIdx = uriString.lastIndexOf('#');
+ int slashIdx = uriString.lastIndexOf('/');
+ int splitIdx = Math.max(hashIdx, slashIdx);
+
+ if (splitIdx > -1) {
+ return uriString.substring(0, splitIdx + 1);
+ }
+ // Retourne une chaîne vide si aucun délimiteur commun n'est trouvé,
+ // ou si l'IRI est juste un nom local sans préfixe de namespace évident.
+ return "";
+ }
+
+ @Override
+ public String getLocalName() {
+ // Logique pour extraire la partie "nom local" de l'IRI
+ // Cherche le dernier '#' ou '/' comme délimiteur
+ int hashIdx = uriString.lastIndexOf('#');
+ int slashIdx = uriString.lastIndexOf('/');
+ int splitIdx = Math.max(hashIdx, slashIdx);
+
+ if (splitIdx > -1) {
+ return uriString.substring(splitIdx + 1);
+ }
+ // Si pas de délimiteur, l'URI entière est considérée comme le nom local
+ return uriString;
+ }
+
+ }
+
+ /**
+ * Implémentation simplifiée de l'interface Value pour les tests, représentant un littéral.
+ */
+ private static class CreateValue implements Value {
+ private final String literal;
+
+ public CreateValue(String literal) {
+ this.literal = literal;
+ }
+
+ @Override
+ public String stringValue() {
+ return literal;
+ }
+
+ }
+
+ /**
+ * Implémentation simplifiée de l'interface Namespace pour les tests.
+ * Implémente Comparable pour permettre le tri et la comparaison.
+ */
+ private static class CreateNamespace implements Namespace {
+ private final String prefix;
+ // L'URI du namespace
+ private final String name;
+
+ public CreateNamespace(String prefix, String name) {
+ this.prefix = prefix;
+ this.name = name;
+ }
+
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int compareTo(Namespace other) {
+ // Compare d'abord par le préfixe pour un ordre stable
+ int prefixComparison = this.getPrefix().compareTo(other.getPrefix());
+ if (prefixComparison != 0) {
+ return prefixComparison;
+ }
+ // Si les préfixes sont égaux, compare par le nom (URI)
+ return this.getName().compareTo(other.getName());
+ }
+ }
+}
\ No newline at end of file
From b28d0debc791b2d7b7b6e62a84c5ace8c2ec681c Mon Sep 17 00:00:00 2001
From: abdounabdessamad
Date: Mon, 26 May 2025 10:31:57 +0200
Subject: [PATCH 7/8] =?UTF-8?q?Ajout=20des=20tests=20unitaires=20couvrant?=
=?UTF-8?q?=20les=20fonctionnalit=C3=A9s=20principales=20de=20CoreseModelT?=
=?UTF-8?q?est?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
build.gradle.kts | 3 +
.../core/next/api/base/AbstractModelTest.java | 2 +-
.../core/next/impl/temp/CoreseModelTest.java | 420 ++++++++++++++++++
3 files changed, 424 insertions(+), 1 deletion(-)
create mode 100644 src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
diff --git a/build.gradle.kts b/build.gradle.kts
index 0d9f0f595..f7959310b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -128,6 +128,9 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter") // JUnit 5 for unit testing
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.12.2") // JUnit 5 runtime for launching tests
+ testImplementation("org.mockito:mockito-core:5.5.0")
+ testImplementation("org.mockito:mockito-junit-jupiter:5.5.0")
+
// === For viewing logs during development (DO NOT include in production) ===
runtimeOnly("org.slf4j:slf4j-simple:2.0.9") // Simple SLF4J implementation for logging
}
diff --git a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
index 41d62530b..177829e15 100644
--- a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
+++ b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
@@ -34,7 +34,7 @@ class AbstractModelTest {
/**
* Méthode d'initialisation exécutée avant chaque test.
- * Crée une nouvelle instance de ConcreteModel et initialise les objets de test (sujets, prédicats, etc.).
+ * Crée une nouvelle instance de ConcreteModel et initialise les objets de test (sujets, prédicats, object.).
*/
@BeforeEach
void setUp() {
diff --git a/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java b/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
new file mode 100644
index 000000000..70822d34c
--- /dev/null
+++ b/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
@@ -0,0 +1,420 @@
+package fr.inria.corese.core.next.impl.temp;
+
+import fr.inria.corese.core.Graph;
+import fr.inria.corese.core.kgram.api.core.Edge;
+import fr.inria.corese.core.kgram.api.core.Node;
+import fr.inria.corese.core.next.api.IRI;
+import fr.inria.corese.core.next.api.Model;
+import fr.inria.corese.core.next.api.Namespace;
+import fr.inria.corese.core.next.api.Resource;
+import fr.inria.corese.core.next.api.Statement;
+import fr.inria.corese.core.next.impl.common.vocabulary.RDF;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class CoreseModelTest {
+
+ private CoreseModel coreseModel;
+
+ @Mock
+ private Model model;
+ @Mock
+ private Graph mockCoreseGraph;
+ @Mock
+ private CoreseValueConverter mockValueConverter;
+
+ @Mock
+ private IRI mockSubjectIRI;
+ @Mock
+ private IRI mockPredicateIRI;
+ @Mock
+ private IRI mockObjectValue;
+ @Mock
+ private Resource mockContextResource;
+
+ @Mock
+ private Node mockSubjectNode;
+ @Mock
+ private Node mockPredicateNode;
+ @Mock
+ private Node mockObjectNode;
+ @Mock
+ private Node mockContextNode;
+
+ @Mock
+ private Statement statement0;
+ @Mock
+ private Statement statement1;
+
+
+ @BeforeEach
+ void setUp() {
+ // Initialise l'instance de CoreseModel pour les tests
+ coreseModel = new CoreseModel(mockCoreseGraph, new HashSet<>());
+
+ when(mockValueConverter.toCoreseNode(mockSubjectIRI)).thenReturn(mockSubjectNode);
+ when(mockValueConverter.toCoreseNode(mockPredicateIRI)).thenReturn(mockPredicateNode);
+ when(mockValueConverter.toCoreseNode(mockObjectValue)).thenReturn(mockObjectNode);
+ when(mockValueConverter.toCoreseNode(mockContextResource)).thenReturn(mockContextNode);
+
+ when(mockValueConverter.toCoreseContextArray(any(Resource[].class))).thenAnswer(invocation -> {
+ Resource[] contexts = invocation.getArgument(0);
+ return Arrays.stream(contexts)
+ .map(mockValueConverter::toCoreseNode)
+ .toArray(Node[]::new);
+ });
+
+ when(mockCoreseGraph.addNode(any(Node.class))).thenAnswer(invocation -> {
+ Node node = mock(Node.class);
+ when(node.getLabel()).thenReturn(invocation.getArgument(0).toString());
+ return node;
+ });
+ when(mockCoreseGraph.addProperty(anyString())).thenAnswer(invocation -> {
+ Node node = mock(Node.class);
+ when(node.getLabel()).thenReturn(invocation.getArgument(0));
+ return node;
+ });
+ when(mockCoreseGraph.addGraph(anyString())).thenAnswer(invocation -> {
+ Node node = mock(Node.class);
+ when(node.getLabel()).thenReturn(invocation.getArgument(0));
+ return node;
+ });
+ doNothing().when(mockCoreseGraph).init();
+
+
+ when(mockSubjectIRI.isIRI()).thenReturn(true);
+ when(mockSubjectIRI.isBNode()).thenReturn(false);
+ when(mockSubjectIRI.isLiteral()).thenReturn(false);
+ when(mockSubjectIRI.stringValue()).thenReturn("http://example.org/subject1");
+ when(mockSubjectIRI.getNamespace()).thenReturn("http://example.org/");
+ when(mockSubjectIRI.getLocalName()).thenReturn("subject1");
+
+ when(mockPredicateIRI.isIRI()).thenReturn(true);
+ when(mockPredicateIRI.isBNode()).thenReturn(false);
+ when(mockPredicateIRI.isLiteral()).thenReturn(false);
+ when(mockPredicateIRI.stringValue()).thenReturn("http://example.org/predicate1");
+ when(mockPredicateIRI.getNamespace()).thenReturn("http://example.org/");
+ when(mockPredicateIRI.getLocalName()).thenReturn("predicate1");
+
+ when(mockObjectValue.isIRI()).thenReturn(true);
+ when(mockObjectValue.isBNode()).thenReturn(false);
+ when(mockObjectValue.isLiteral()).thenReturn(false);
+ when(mockObjectValue.stringValue()).thenReturn("http://example.org/object1");
+
+
+ when(mockContextResource.isIRI()).thenReturn(true);
+ when(mockContextResource.isBNode()).thenReturn(false);
+ when(mockContextResource.isLiteral()).thenReturn(false);
+ when(mockContextResource.stringValue()).thenReturn("http://example.org/graphContext");
+ }
+
+ // Tests du Constructeur
+
+ /**
+ * Teste que le constructeur par défaut crée un modèle vide,
+ * sans aucune déclaration ni espace de noms.
+ */
+ @Test
+ @DisplayName("Devrait créer un modèle vide avec le constructeur par défaut")
+ void testDefaultConstructor() {
+ CoreseModel newModel = new CoreseModel();
+
+ assertEquals(0, newModel.size(), "Le constructeur par défaut devrait créer un modèle vide.");
+ assertTrue(newModel.getNamespaces().isEmpty(), "Le constructeur par défaut devrait créer un modèle sans espace de noms.");
+ }
+
+ /**
+ * Teste que le constructeur prenant un argument 'Graph' crée un modèle utilisant le graphe fourni
+ * et s'initialise sans espace de noms.
+ */
+ @Test
+ @DisplayName("Devrait créer un modèle avec le graphe donné et des espaces de noms vides avec le constructeur Graph")
+ void testGraphConstructor() {
+ CoreseModel newModel = new CoreseModel(mockCoreseGraph);
+
+ assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "Le constructeur Graph devrait utiliser le graphe fourni.");
+ assertTrue(newModel.getNamespaces().isEmpty(), "Le constructeur Graph devrait créer un modèle sans espace de noms par défaut.");
+ }
+
+ /**
+ * Teste que le constructeur prenant à la fois un Graph et un Set d'espaces de noms
+ * initialise correctement le modèle avec les deux.
+ */
+ @Test
+ @DisplayName("Devrait créer un modèle avec le graphe et les espaces de noms donnés avec le constructeur complet")
+ void testFullConstructor() {
+ Set testNamespaces = new HashSet<>();
+ Namespace ns1 = mock(Namespace.class);
+ when(ns1.getPrefix()).thenReturn("ex");
+ when(ns1.getName()).thenReturn("http://example.org/");
+ testNamespaces.add(ns1);
+
+ CoreseModel newModel = new CoreseModel(mockCoreseGraph, testNamespaces);
+
+ assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "Le constructeur complet devrait utiliser le graphe fourni.");
+ assertEquals(1, newModel.getNamespaces().size(), "Le constructeur complet devrait définir les espaces de noms fournis.");
+ assertTrue(newModel.getNamespaces().contains(ns1), "Le constructeur complet devrait inclure l'espace de noms fourni.");
+ }
+
+ /**
+ * Teste que le constructeur qui ne prend qu'un Set d'espaces de noms
+ * initialise correctement le modèle avec ces espaces de noms et un graphe vide (sans déclarations).
+ */
+ @Test
+ @DisplayName("Devrait créer un modèle avec les espaces de noms donnés et un graphe vide avec le constructeur Namespaces")
+ void testConstructor_FromNamespaces() {
+ Set initialNamespaces = new HashSet<>();
+ Namespace ns1 = mock(Namespace.class);
+ when(ns1.getPrefix()).thenReturn("prefix1");
+ when(ns1.getName()).thenReturn("http://example.org/ns1#");
+ initialNamespaces.add(ns1);
+
+ Namespace ns2 = mock(Namespace.class);
+ when(ns2.getPrefix()).thenReturn("prefix2");
+ when(ns2.getName()).thenReturn("http://example.org/ns2#");
+ initialNamespaces.add(ns2);
+
+ CoreseModel newModel = new CoreseModel(initialNamespaces);
+
+ assertEquals(0, newModel.size(), "Le modèle créé avec les espaces de noms devrait être vide en termes de déclarations.");
+ assertEquals(initialNamespaces.size(), newModel.getNamespaces().size(), "Le modèle devrait contenir le nombre d'espaces de noms fourni.");
+ assertTrue(newModel.getNamespaces().containsAll(initialNamespaces), "Le modèle devrait contenir tous les espaces de noms fournis.");
+ assertTrue(initialNamespaces.containsAll(newModel.getNamespaces()), "Le modèle ne devrait pas contenir d'espaces de noms supplémentaires.");
+ }
+
+
+ /**
+ * Teste que le constructeur prenant une collection de Statements copie correctement
+ * ces déclarations dans le nouveau modèle.
+ */
+ @Test
+ @DisplayName("Devrait créer un modèle en copiant les déclarations d'une collection")
+ void testConstructorFromStatements() {
+ // Configure les déclarations mock pour avoir des propriétés de base
+ when(statement0.getSubject()).thenReturn(mockSubjectIRI);
+ when(statement0.getPredicate()).thenReturn(mockPredicateIRI);
+ when(statement0.getObject()).thenReturn(mockObjectValue);
+
+ when(statement1.getSubject()).thenReturn(mockSubjectIRI);
+ when(statement1.getPredicate()).thenReturn(mockPredicateIRI);
+ when(statement1.getObject()).thenReturn(mockObjectValue);
+
+ List statements = List.of(statement0, statement1);
+
+ CoreseModel newModel = new CoreseModel(statements);
+
+ assertEquals(2, newModel.size(), "Le modèle devrait contenir 2 déclarations après la construction à partir de la collection.");
+ }
+
+ // Tests d'ajout
+
+ /**
+ * Teste que l'ajout d'une déclaration sans contexte appelle avec succès
+ * la méthode addEdge du graphe et retourne true.
+ */
+ @Test
+ @DisplayName("Devrait ajouter une déclaration sans contexte avec succès")
+ void testAddStatementWithoutContext() {
+
+ IRI realSubjectIRI = new CoreseIRI("http://example.org/realSubject");
+ IRI realPredicateIRI = new CoreseIRI("http://example.org/realPredicate");
+ IRI realObjectIRI = new CoreseIRI("http://example.org/realObject");
+
+ when(mockCoreseGraph.addEdge(any(Node.class), any(Node.class), any(Node.class))).thenReturn(mock(fr.inria.corese.core.kgram.api.core.Edge.class));
+
+ boolean added = coreseModel.add(realSubjectIRI, realPredicateIRI, realObjectIRI);
+
+ assertTrue(added, "La déclaration devrait être ajoutée avec succès sans contexte.");
+ verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class));
+ verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
+ }
+
+ /**
+ * Teste que l'ajout d'une déclaration avec un seul contexte appelle avec succès
+ * la méthode addEdge du graphe(avec contexte) et retourne true.
+ */
+ @Test
+ @DisplayName("Devrait ajouter une déclaration avec un seul contexte avec succès")
+ void testAddStatementWithSingleContext() {
+
+ IRI realSubject = new CoreseIRI("http://example.org/realSubjectWithContext");
+ IRI realPredicate = new CoreseIRI("http://example.org/realPredicateWithContext");
+ IRI realObject = new CoreseIRI("http://example.org/realObjectWithContext");
+ Resource realContext = new CoreseIRI("http://example.org/realGraphContext");
+
+ when(mockCoreseGraph.addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class))).thenReturn(mock(Edge.class));
+
+ boolean added = coreseModel.add(realSubject, realPredicate, realObject, realContext);
+
+ assertTrue(added, "La déclaration devrait être ajoutée avec succès avec un seul contexte.");
+ verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
+ verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class));
+ }
+
+
+ /**
+ * Teste que l'ajout d'une déclaration avec plusieurs contextes
+ * entraîne plusieurs appels à la méthode addEdge du graphe(un pour chaque contexte)
+ * et retourne true.
+ */
+ @Test
+ @DisplayName("Devrait ajouter une déclaration avec plusieurs contextes avec succès")
+ void testAddStatementWithMultipleContexts() {
+
+ IRI realSubject = new CoreseIRI("http://example.org/realSubjectMultiContext");
+ IRI realPredicate = new CoreseIRI("http://example.org/realPredicateMultiContext");
+ IRI realObject = new CoreseIRI("http://example.org/realObjectMultiContext");
+ Resource realContext1 = new CoreseIRI("http://example.org/realGraphContext1");
+ Resource realContext2 = new CoreseIRI("http://example.org/realGraphContext2");
+
+ when(mockCoreseGraph.addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class))).thenReturn(mock(Edge.class));
+
+ boolean added = coreseModel.add(realSubject, realPredicate, realObject, realContext1, realContext2);
+
+ assertTrue(added, "La déclaration devrait être ajoutée avec succès avec plusieurs contextes.");
+
+ verify(mockCoreseGraph, times(2)).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
+ verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class));
+ }
+
+ /**
+ * Teste que la méthode add retourne false si aucun changement n'a eu lieu
+ * (par exemple, si la déclaration existe déjà dans le graphe).
+ */
+ @Test
+ @DisplayName("Devrait retourner false si aucun changement n'est survenu lors de l'ajout (déclaration existante)")
+ void testAddStatementNoChange() {
+
+ IRI realSubject = new CoreseIRI("http://example.org/realSubjectNoChange");
+ IRI realPredicate = new CoreseIRI("http://example.org/realPredicateNoChange");
+ IRI realObject = new CoreseIRI("http://example.org/realObjectNoChange");
+
+ when(mockCoreseGraph.addEdge(any(Node.class), any(Node.class), any(Node.class))).thenReturn(null);
+
+ boolean added = coreseModel.add(realSubject, realPredicate, realObject);
+
+ assertFalse(added, "La méthode add devrait retourner false si aucun changement n'est survenu.");
+
+ verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class));
+ verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
+ }
+
+ //Tests de Contient
+
+ /**
+ * Teste que le modèle retourne true si une déclaration existante sans contexte est présente.
+ * Vérifie également que la méthode de recherche
+ * est appelée correctement.
+ */
+ @Test
+ @DisplayName("Devrait retourner true si le modèle contient une déclaration existante sans contexte")
+ void testContainsExistingStatementWithoutContext() {
+ fr.inria.corese.core.kgram.api.core.Edge mockReturnedEdge = mock(fr.inria.corese.core.kgram.api.core.Edge.class);
+ List edges = List.of(mockReturnedEdge);
+
+ IRI realSubject = new CoreseIRI("http://example.org/subjectToFind");
+ IRI realPredicate = new CoreseIRI("http://example.org/predicateToFind");
+ IRI realObject = new CoreseIRI("http://example.org/objectToFind");
+
+ when(mockCoreseGraph.getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node[].class)))
+ .thenReturn(edges);
+ when(mockCoreseGraph.getEdgeFactory()).thenReturn(mock(fr.inria.corese.core.EdgeFactory.class));
+ when(mockCoreseGraph.getEdgeFactory().copy(any(fr.inria.corese.core.kgram.api.core.Edge.class))).thenReturn(mockReturnedEdge);
+
+ // Appelle la méthode contains
+ boolean contains = coreseModel.contains(realSubject, realPredicate, realObject);
+
+ assertTrue(contains, "Le modèle devrait contenir la déclaration sans contexte.");
+ verify(mockCoreseGraph, times(0)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), eq(null));
+ }
+
+ /**
+ * Teste que le modèle retourne false si la déclaration n'est pas présente.
+ * Vérifie que la méthode de recherche est bien appelée.
+ */
+ @Test
+ @DisplayName("Devrait retourner false si le modèle ne contient pas la déclaration")
+ void testContainsStatementNotPresent() {
+
+ IRI realSubject = new CoreseIRI("http://example.org/subjectNotFound");
+ IRI realPredicate = new CoreseIRI("http://example.org/predicateNotFound");
+ IRI realObject = new CoreseIRI("http://example.org/objectNotFound");
+
+ when(mockCoreseGraph.getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node[].class)))
+ .thenReturn(List.of());
+ when(mockCoreseGraph.getEdgeFactory()).thenReturn(mock(fr.inria.corese.core.EdgeFactory.class));
+
+
+ boolean contains = coreseModel.contains(realSubject, realPredicate, realObject);
+
+ assertFalse(contains, "Le modèle ne devrait pas contenir la déclaration si elle n'est pas présente.");
+ verify(mockCoreseGraph, times(0)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), eq(null));
+ }
+
+
+ /**
+ * Teste que le modèle retourne true si une déclaration existante avec un contexte spécifique est trouvée.
+ * Vérifie que la méthode de recherche
+ * est appelée avec le contexte.
+ */
+ @Test
+ @DisplayName("Devrait retourner true si le modèle contient une déclaration existante avec un contexte spécifique")
+ void testContainsExistingStatementWithContext() {
+ fr.inria.corese.core.kgram.api.core.Edge mockReturnedEdge = mock(fr.inria.corese.core.kgram.api.core.Edge.class);
+ List edges = List.of(mockReturnedEdge);
+
+ IRI realSubject = new CoreseIRI("http://example.org/subjectWithSpecificContext");
+ IRI realPredicate = new CoreseIRI("http://example.org/predicateWithSpecificContext");
+ IRI realObject = new CoreseIRI("http://example.org/objectWithSpecificContext");
+ Resource realContext = new CoreseIRI("http://example.org/specificGraphContext"); // Supposant que le contexte est un IRI
+
+ when(mockCoreseGraph.getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node.class)))
+ .thenReturn(edges);
+ when(mockCoreseGraph.getEdgeFactory()).thenReturn(mock(fr.inria.corese.core.EdgeFactory.class));
+ when(mockCoreseGraph.getEdgeFactory().copy(any(fr.inria.corese.core.kgram.api.core.Edge.class))).thenReturn(mockReturnedEdge);
+
+ boolean contains = coreseModel.contains(realSubject, realPredicate, realObject, realContext);
+
+ assertTrue(contains, "Le modèle devrait contenir la déclaration avec le contexte spécifié.");
+ verify(mockCoreseGraph, times(1)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
+ }
+
+
+ /**
+ * Teste que le modèle retourne false si un triple non existant est recherché.
+ * Vérifie que la méthode de recherche est appelée.
+ */
+ @Test
+ @DisplayName("Devrait retourner false si le modèle ne contient pas un triple non existant")
+ void testContainsNonExistingTriple() {
+ CoreseAdaptedValueFactory vf = new CoreseAdaptedValueFactory();
+
+ IRI georgeBrassens = vf.createIRI("http://example.org/", "GeorgeBrassens");
+ IRI rdfType = RDF.type.getIRI();
+ IRI singer = vf.createIRI("http://example.org/", "Singer");
+
+ when(mockCoreseGraph.getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node[].class)))
+ .thenReturn(List.of());
+ when(mockCoreseGraph.getEdgeFactory()).thenReturn(mock(fr.inria.corese.core.EdgeFactory.class));
+
+ assertFalse(coreseModel.contains(georgeBrassens, rdfType, singer), "Le modèle ne devrait pas contenir un triple non existant.");
+ verify(mockCoreseGraph, times(0)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), eq(null));
+ }
+}
\ No newline at end of file
From bb06c361d170031f6600dce05e3ab7fdf16ec602 Mon Sep 17 00:00:00 2001
From: abdounabdessamad
Date: Wed, 28 May 2025 14:05:46 +0200
Subject: [PATCH 8/8] refactor: replaced French comments with English comments
in the codebase
---
.../core/next/api/base/AbstractModelTest.java | 139 ++++++++----------
.../core/next/impl/temp/CoreseModelTest.java | 134 ++++++++---------
2 files changed, 130 insertions(+), 143 deletions(-)
diff --git a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
index 177829e15..060390e7e 100644
--- a/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
+++ b/src/test/java/fr/inria/corese/core/next/api/base/AbstractModelTest.java
@@ -12,9 +12,9 @@
import java.util.*;
/**
- * Classe de test pour AbstractModel.
- * Utilise une implémentation concrète interne pour tester les fonctionnalités
- * par défaut fournies par AbstractModel.
+ * Test class for AbstractModel.
+ * Uses an internal concrete implementation to test the default functionalities
+ * provided by AbstractModel.
*/
class AbstractModelTest {
@@ -33,8 +33,8 @@ class AbstractModelTest {
private Resource context2;
/**
- * Méthode d'initialisation exécutée avant chaque test.
- * Crée une nouvelle instance de ConcreteModel et initialise les objets de test (sujets, prédicats, object.).
+ * Initialization method executed before each test.
+ * Creates a new instance of ConcreteModel and initializes test objects (subjects, predicates, objects).
*/
@BeforeEach
void setUp() {
@@ -55,10 +55,10 @@ void setUp() {
/**
- * Teste la méthode unmodifiable().
+ * Tests the unmodifiable() method.
*/
@Test
- @DisplayName("unmodifiable() doit retourner un modèle en lecture seule")
+ @DisplayName("unmodifiable() should return a read-only model")
void testUnmodifiable() {
Model unmodifiable = model.unmodifiable();
assertNotNull(unmodifiable);
@@ -66,10 +66,10 @@ void testUnmodifiable() {
}
/**
- * Teste la méthode setNamespace(String prefix, String name).
+ * Tests the setNamespace(String prefix, String name) method.
*/
@Test
- @DisplayName("setNamespace(String, String) doit ajouter ou mettre à jour un namespace")
+ @DisplayName("setNamespace(String, String) should add or update a namespace")
void testSetNamespaceWithStringArgs() {
model.setNamespace("ex", "http://example.org/ns/");
Optional ns = model.getNamespace("ex");
@@ -89,10 +89,10 @@ void testSetNamespaceWithStringArgs() {
}
/**
- * Teste la méthode setNamespace(Namespace namespace).
+ * Tests the setNamespace(Namespace namespace) method.
*/
@Test
- @DisplayName("setNamespace(Namespace) doit ajouter un namespace")
+ @DisplayName("setNamespace(Namespace) should add a namespace")
void testSetNamespaceWithNamespaceObject() {
Namespace newNs = new CreateNamespace("geosparql", "http://example.org/ont/geosparql#");
model.setNamespace(newNs);
@@ -104,10 +104,10 @@ void testSetNamespaceWithNamespaceObject() {
}
/**
- * Teste la méthode getNamespaces().
+ * Tests the getNamespaces() method.
*/
@Test
- @DisplayName("getNamespaces() doit retourner tous les namespaces définis")
+ @DisplayName("getNamespaces() should return all defined namespaces")
void testGetNamespaces() {
model.setNamespace("ex1", "http://example.org/ns1/");
model.setNamespace("ex2", "http://example.org/ns2/");
@@ -120,10 +120,10 @@ void testGetNamespaces() {
}
/**
- * Teste la méthode removeNamespace().
+ * Tests the removeNamespace() method.
*/
@Test
- @DisplayName("removeNamespace() doit supprimer un namespace et retourner un Optional du namespace supprimé")
+ @DisplayName("removeNamespace() should remove a namespace and return an Optional of the removed namespace")
void testRemoveNamespace() {
Namespace testNs = new CreateNamespace("ex", "http://example.org/ns/");
model.setNamespace("ex", "http://example.org/ns/");
@@ -132,7 +132,7 @@ void testRemoveNamespace() {
Optional removedNs = model.removeNamespace("ex");
assertTrue(removedNs.isPresent());
- // Comparaison
+ // Comparison
assertEquals(testNs.getPrefix(), removedNs.get().getPrefix());
assertEquals(testNs.getName(), removedNs.get().getName());
@@ -144,10 +144,10 @@ void testRemoveNamespace() {
}
/**
- * Teste la méthode clearNamespaces().
+ * Tests the clearNamespaces() method.
*/
@Test
- @DisplayName("clearNamespaces() doit supprimer tous les namespaces")
+ @DisplayName("clearNamespaces() should remove all namespaces")
void testClearNamespaces() {
model.setNamespace("ex1", "http://example.org/ns1/");
model.setNamespace("ex2", "http://example.org/ns2/");
@@ -159,10 +159,10 @@ void testClearNamespaces() {
}
/**
- * Teste l'ajout d'une déclaration et sa présence via contains(Statement).
+ * Tests adding a statement and its presence via contains(Statement).
*/
@Test
- @DisplayName("add() et contains() doivent fonctionner pour les déclarations")
+ @DisplayName("add() and contains() should work for statements")
void testAddAndContainsStatement() {
Statement stmt = new SimpleStatement(subject1, predicate1, object1, null);
@@ -175,10 +175,10 @@ void testAddAndContainsStatement() {
}
/**
- * Teste la suppression d'une déclaration via remove(Object).
+ * Tests removing a statement via remove(Object).
*/
@Test
- @DisplayName("remove() doit supprimer une déclaration existante")
+ @DisplayName("remove() should remove an existing statement")
void testRemoveStatement() {
Statement stmt = new SimpleStatement(subject1, predicate1, object1, null);
model.add(stmt);
@@ -190,10 +190,10 @@ void testRemoveStatement() {
}
/**
- * Teste la méthode isEmpty().
+ * Tests the isEmpty() method.
*/
@Test
- @DisplayName("isEmpty() doit refléter l'état vide ou non vide du modèle")
+ @DisplayName("isEmpty() should reflect the empty or non-empty state of the model")
void testIsEmpty() {
assertTrue(model.isEmpty());
model.add(subject1, predicate1, object1);
@@ -203,10 +203,10 @@ void testIsEmpty() {
}
/**
- * Teste la vue subjects().
+ * Tests the subjects() view.
*/
@Test
- @DisplayName("subjects() doit retourner un ensemble unique de sujets et gérer les suppressions")
+ @DisplayName("subjects() should return a unique set of subjects and handle removals")
void testSubjectsView() {
model.add(subject1, predicate1, object1);
model.add(subject2, predicate1, object1);
@@ -225,10 +225,10 @@ void testSubjectsView() {
}
/**
- * Teste la vue predicates().
+ * Tests the predicates() view.
*/
@Test
- @DisplayName("predicates() doit retourner un ensemble unique de prédicats")
+ @DisplayName("predicates() should return a unique set of predicates")
void testPredicatesView() {
model.add(subject1, predicate1, object1);
model.add(subject1, predicate2, object1);
@@ -241,10 +241,10 @@ void testPredicatesView() {
}
/**
- * Teste la vue objects().
+ * Tests the objects() view.
*/
@Test
- @DisplayName("objects() doit retourner un ensemble unique d'objets")
+ @DisplayName("objects() should return a unique set of objects")
void testObjectsView() {
model.add(subject1, predicate1, object1);
model.add(subject1, predicate1, object2);
@@ -257,10 +257,10 @@ void testObjectsView() {
}
/**
- * Teste la vue contexts().
+ * Tests the contexts() view.
*/
@Test
- @DisplayName("contexts() doit retourner un ensemble unique de contextes (y compris null)")
+ @DisplayName("contexts() should return a unique set of contexts (including null)")
void testContextsView() {
model.add(subject1, predicate1, object1, context1);
model.add(subject1, predicate1, object1, context2);
@@ -274,10 +274,10 @@ void testContextsView() {
}
/**
- * Teste la méthode getStatements() pour filtrer les déclarations.
+ * Tests the getStatements() method to filter statements.
*/
@Test
- @DisplayName("getStatements() doit filtrer les déclarations par critère")
+ @DisplayName("getStatements() should filter statements by criteria")
void testFilterStatements() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
Statement stmt2 = new SimpleStatement(subject1, predicate2, object2, context1);
@@ -311,10 +311,10 @@ void testFilterStatements() {
}
/**
- * Teste la méthode clear() avec un ou plusieurs contextes spécifiés.
+ * Tests the clear() method with one or more specified contexts.
*/
@Test
- @DisplayName("clear(contextes) doit supprimer les déclarations dans les contextes spécifiés")
+ @DisplayName("clear(contexts) should remove statements in the specified contexts")
void testClearWithContext() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
Statement stmt2 = new SimpleStatement(subject1, predicate1, object1, context2);
@@ -338,10 +338,10 @@ void testClearWithContext() {
}
/**
- * Teste les méthodes addAll() et removeAll().
+ * Tests the addAll() and removeAll() methods.
*/
@Test
- @DisplayName("addAll() et removeAll() doivent gérer les collections de déclarations")
+ @DisplayName("addAll() and removeAll() should handle collections of statements")
void testAddAllAndRemoveAll() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
@@ -359,10 +359,10 @@ void testAddAllAndRemoveAll() {
}
/**
- * Teste la méthode retainAll().
+ * Tests the retainAll() method.
*/
@Test
- @DisplayName("retainAll() doit conserver uniquement les déclarations spécifiées")
+ @DisplayName("retainAll() should keep only the specified statements")
void testRetainAll() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
@@ -383,10 +383,10 @@ void testRetainAll() {
}
/**
- * Teste les méthodes toArray() et toArray(T[]).
+ * Tests the toArray() and toArray(T[]) methods.
*/
@Test
- @DisplayName("toArray() doit retourner un tableau des déclarations")
+ @DisplayName("toArray() should return an array of statements")
void testToArray() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, null);
Statement stmt2 = new SimpleStatement(subject2, predicate2, object2, null);
@@ -405,16 +405,16 @@ void testToArray() {
Statement[] smallArray = new Statement[1];
Statement[] result = model.toArray(smallArray);
- assertNotSame(smallArray, result);
+ assertNotSame(smallArray, result); // Should return a new array if the provided array is too small
assertEquals(2, result.length);
}
/**
- * Teste la méthode getStatements() pour filtrer les déclarations.
- * Vérifie que le filtrage fonctionne correctement avec différents critères.
+ * Tests the getStatements() method to filter statements.
+ * Verifies that filtering works correctly with different criteria.
*/
@Test
- @DisplayName("getStatements() doit filtrer les déclarations par critère (y compris filtrage par objet seul)")
+ @DisplayName("getStatements() should filter statements by criteria (including filtering by object only)")
void testFilterStatementsExtended() {
Statement stmt1 = new SimpleStatement(subject1, predicate1, object1, context1);
Statement stmt2 = new SimpleStatement(subject1, predicate2, object2, context1);
@@ -426,24 +426,20 @@ void testFilterStatementsExtended() {
model.add(stmt3);
model.add(stmt4);
- // Filtrage par sujet et contexte
Model filteredBySubjectAndContext = model.filter(subject1, null, null, context1);
assertEquals(2, filteredBySubjectAndContext.size());
assertTrue(filteredBySubjectAndContext.contains(stmt1));
assertTrue(filteredBySubjectAndContext.contains(stmt2));
- // Filtrage par sujet et prédicat
Model filteredBySubjectAndPredicate = model.filter(subject1, predicate1, null);
assertEquals(1, filteredBySubjectAndPredicate.size());
assertFalse(filteredBySubjectAndPredicate.contains(stmt1));
assertTrue(filteredBySubjectAndPredicate.contains(stmt4));
- // Filtrage par contexte null
Model filteredByNullContext = model.filter(null, null, null, null);
assertEquals(1, filteredByNullContext.size());
assertTrue(filteredByNullContext.contains(stmt4));
- // NOUVEAU TEST: Filtrage par objet seul
Model filteredByObject = model.filter(null, null, object1);
assertEquals(1, filteredByObject.size());
assertFalse(filteredByObject.contains(stmt1));
@@ -453,9 +449,9 @@ void testFilterStatementsExtended() {
}
/**
- * Classe concrète interne qui hérite de AbstractModel.
- * Cette implémentation est nécessaire car AbstractModel est abstraite et ne peut pas être instanciée directement.
- * Elle utilise un LinkedHashSet pour stocker les déclarations, ce qui est simple et préserve l'ordre d'insertion.
+ * Internal concrete class that inherits from AbstractModel.
+ * This implementation is necessary because AbstractModel is abstract and cannot be instantiated directly.
+ * It uses a LinkedHashSet to store statements, which is simple and preserves insertion order.
*/
private static class ConcreteModel extends AbstractModel {
private final Set statements = new LinkedHashSet<>();
@@ -510,7 +506,7 @@ public void removeTermIteration(Iterator iter, Resource subj, IRI pre
}
}
- // Crée une nouvelle instance de ConcreteModel pour contenir les résultats filtrés
+ // Creates a new instance of ConcreteModel to hold the filtered results
@Override
public Model filter(Resource subject, IRI predicate, Value object, Resource... contexts) {
@@ -522,7 +518,6 @@ public Model filter(Resource subject, IRI predicate, Value object, Resource... c
filteredModel.add(stmt);
}
}
- // Retourne le nouveau modèle filtré
return filteredModel;
}
@@ -550,18 +545,16 @@ public Optional removeNamespace(String prefix) {
@Override
public void clear() {
-
- // Vide les statements
+ // Clears statements
statements.clear();
-
- // Vide les namespaces
+ // Clears namespaces
namespaces.clear();
}
}
/**
- * Implémentation simplifiée de l'interface Statement pour les tests.
+ * Simplified implementation of the Statement interface for testing.
*/
private static class SimpleStatement implements Statement {
@@ -600,7 +593,7 @@ public Resource getContext() {
}
/**
- * Implémentation simplifiée des interfaces Resource, IRI, Value, Namespace pour les tests.
+ * Simplified implementation of the Resource, IRI, Value, Namespace interfaces for testing.
*/
private static class CreateResource implements Resource {
private final String uri;
@@ -617,8 +610,8 @@ public String stringValue() {
}
/**
- * Implémentation simplifiée de l'interface IRI pour les tests.
- * Hérite de Resource et Value, et implémente les méthodes spécifiques à IRI.
+ * Simplified implementation of the IRI interface for testing.
+ * Inherits from Resource and Value, and implements IRI-specific methods.
*/
private static class CreateIRI implements IRI {
private final String uriString;
@@ -634,8 +627,7 @@ public String stringValue() {
@Override
public String getNamespace() {
- // Logique pour extraire la partie "namespace" de l'IRI
- // Cherche le dernier '#' ou '/' comme délimiteur
+
int hashIdx = uriString.lastIndexOf('#');
int slashIdx = uriString.lastIndexOf('/');
int splitIdx = Math.max(hashIdx, slashIdx);
@@ -643,15 +635,11 @@ public String getNamespace() {
if (splitIdx > -1) {
return uriString.substring(0, splitIdx + 1);
}
- // Retourne une chaîne vide si aucun délimiteur commun n'est trouvé,
- // ou si l'IRI est juste un nom local sans préfixe de namespace évident.
return "";
}
@Override
public String getLocalName() {
- // Logique pour extraire la partie "nom local" de l'IRI
- // Cherche le dernier '#' ou '/' comme délimiteur
int hashIdx = uriString.lastIndexOf('#');
int slashIdx = uriString.lastIndexOf('/');
int splitIdx = Math.max(hashIdx, slashIdx);
@@ -659,14 +647,13 @@ public String getLocalName() {
if (splitIdx > -1) {
return uriString.substring(splitIdx + 1);
}
- // Si pas de délimiteur, l'URI entière est considérée comme le nom local
return uriString;
}
}
/**
- * Implémentation simplifiée de l'interface Value pour les tests, représentant un littéral.
+ * Simplified implementation of the Value interface for testing, representing a literal.
*/
private static class CreateValue implements Value {
private final String literal;
@@ -683,12 +670,12 @@ public String stringValue() {
}
/**
- * Implémentation simplifiée de l'interface Namespace pour les tests.
- * Implémente Comparable pour permettre le tri et la comparaison.
+ * Simplified implementation of the Namespace interface for testing.
+ * Implements Comparable to allow sorting and comparison.
*/
private static class CreateNamespace implements Namespace {
private final String prefix;
- // L'URI du namespace
+
private final String name;
public CreateNamespace(String prefix, String name) {
@@ -708,12 +695,12 @@ public String getName() {
@Override
public int compareTo(Namespace other) {
- // Compare d'abord par le préfixe pour un ordre stable
+
int prefixComparison = this.getPrefix().compareTo(other.getPrefix());
if (prefixComparison != 0) {
return prefixComparison;
}
- // Si les préfixes sont égaux, compare par le nom (URI)
+
return this.getName().compareTo(other.getName());
}
}
diff --git a/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java b/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
index 70822d34c..ebcded5d4 100644
--- a/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
+++ b/src/test/java/fr/inria/corese/core/next/impl/temp/CoreseModelTest.java
@@ -66,7 +66,7 @@ class CoreseModelTest {
@BeforeEach
void setUp() {
- // Initialise l'instance de CoreseModel pour les tests
+ // Initializes the CoreseModel instance for testing
coreseModel = new CoreseModel(mockCoreseGraph, new HashSet<>());
when(mockValueConverter.toCoreseNode(mockSubjectIRI)).thenReturn(mockSubjectNode);
@@ -125,40 +125,40 @@ void setUp() {
when(mockContextResource.stringValue()).thenReturn("http://example.org/graphContext");
}
- // Tests du Constructeur
+ // Constructor Tests
/**
- * Teste que le constructeur par défaut crée un modèle vide,
- * sans aucune déclaration ni espace de noms.
+ * Tests that the default constructor creates an empty model,
+ * without any statements or namespaces.
*/
@Test
- @DisplayName("Devrait créer un modèle vide avec le constructeur par défaut")
+ @DisplayName("Should create an empty model with the default constructor")
void testDefaultConstructor() {
CoreseModel newModel = new CoreseModel();
- assertEquals(0, newModel.size(), "Le constructeur par défaut devrait créer un modèle vide.");
- assertTrue(newModel.getNamespaces().isEmpty(), "Le constructeur par défaut devrait créer un modèle sans espace de noms.");
+ assertEquals(0, newModel.size(), "The default constructor should create an empty model.");
+ assertTrue(newModel.getNamespaces().isEmpty(), "The default constructor should create a model without namespaces.");
}
/**
- * Teste que le constructeur prenant un argument 'Graph' crée un modèle utilisant le graphe fourni
- * et s'initialise sans espace de noms.
+ * Tests that the constructor taking a 'Graph' argument creates a model using the provided graph
+ * and initializes without namespaces.
*/
@Test
- @DisplayName("Devrait créer un modèle avec le graphe donné et des espaces de noms vides avec le constructeur Graph")
+ @DisplayName("Should create a model with the given graph and empty namespaces with the Graph constructor")
void testGraphConstructor() {
CoreseModel newModel = new CoreseModel(mockCoreseGraph);
- assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "Le constructeur Graph devrait utiliser le graphe fourni.");
- assertTrue(newModel.getNamespaces().isEmpty(), "Le constructeur Graph devrait créer un modèle sans espace de noms par défaut.");
+ assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "The Graph constructor should use the provided graph.");
+ assertTrue(newModel.getNamespaces().isEmpty(), "The Graph constructor should create a model without default namespaces.");
}
/**
- * Teste que le constructeur prenant à la fois un Graph et un Set d'espaces de noms
- * initialise correctement le modèle avec les deux.
+ * Tests that the constructor taking both a Graph and a Set of namespaces
+ * correctly initializes the model with both.
*/
@Test
- @DisplayName("Devrait créer un modèle avec le graphe et les espaces de noms donnés avec le constructeur complet")
+ @DisplayName("Should create a model with the given graph and namespaces with the full constructor")
void testFullConstructor() {
Set testNamespaces = new HashSet<>();
Namespace ns1 = mock(Namespace.class);
@@ -168,17 +168,17 @@ void testFullConstructor() {
CoreseModel newModel = new CoreseModel(mockCoreseGraph, testNamespaces);
- assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "Le constructeur complet devrait utiliser le graphe fourni.");
- assertEquals(1, newModel.getNamespaces().size(), "Le constructeur complet devrait définir les espaces de noms fournis.");
- assertTrue(newModel.getNamespaces().contains(ns1), "Le constructeur complet devrait inclure l'espace de noms fourni.");
+ assertEquals(mockCoreseGraph, newModel.getCoreseGraph(), "The full constructor should use the provided graph.");
+ assertEquals(1, newModel.getNamespaces().size(), "The full constructor should set the provided namespaces.");
+ assertTrue(newModel.getNamespaces().contains(ns1), "The full constructor should include the provided namespace.");
}
/**
- * Teste que le constructeur qui ne prend qu'un Set d'espaces de noms
- * initialise correctement le modèle avec ces espaces de noms et un graphe vide (sans déclarations).
+ * Tests that the constructor taking only a Set of namespaces
+ * correctly initializes the model with these namespaces and an empty graph (no statements).
*/
@Test
- @DisplayName("Devrait créer un modèle avec les espaces de noms donnés et un graphe vide avec le constructeur Namespaces")
+ @DisplayName("Should create a model with the given namespaces and an empty graph with the Namespaces constructor")
void testConstructor_FromNamespaces() {
Set initialNamespaces = new HashSet<>();
Namespace ns1 = mock(Namespace.class);
@@ -193,21 +193,21 @@ void testConstructor_FromNamespaces() {
CoreseModel newModel = new CoreseModel(initialNamespaces);
- assertEquals(0, newModel.size(), "Le modèle créé avec les espaces de noms devrait être vide en termes de déclarations.");
- assertEquals(initialNamespaces.size(), newModel.getNamespaces().size(), "Le modèle devrait contenir le nombre d'espaces de noms fourni.");
- assertTrue(newModel.getNamespaces().containsAll(initialNamespaces), "Le modèle devrait contenir tous les espaces de noms fournis.");
- assertTrue(initialNamespaces.containsAll(newModel.getNamespaces()), "Le modèle ne devrait pas contenir d'espaces de noms supplémentaires.");
+ assertEquals(0, newModel.size(), "The model created with namespaces should be empty in terms of statements.");
+ assertEquals(initialNamespaces.size(), newModel.getNamespaces().size(), "The model should contain the number of provided namespaces.");
+ assertTrue(newModel.getNamespaces().containsAll(initialNamespaces), "The model should contain all provided namespaces.");
+ assertTrue(initialNamespaces.containsAll(newModel.getNamespaces()), "The model should not contain additional namespaces.");
}
/**
- * Teste que le constructeur prenant une collection de Statements copie correctement
- * ces déclarations dans le nouveau modèle.
+ * Tests that the constructor taking a collection of Statements correctly copies
+ * these statements into the new model.
*/
@Test
- @DisplayName("Devrait créer un modèle en copiant les déclarations d'une collection")
+ @DisplayName("Should create a model by copying statements from a collection")
void testConstructorFromStatements() {
- // Configure les déclarations mock pour avoir des propriétés de base
+ // Configure mock statements to have basic properties
when(statement0.getSubject()).thenReturn(mockSubjectIRI);
when(statement0.getPredicate()).thenReturn(mockPredicateIRI);
when(statement0.getObject()).thenReturn(mockObjectValue);
@@ -220,17 +220,17 @@ void testConstructorFromStatements() {
CoreseModel newModel = new CoreseModel(statements);
- assertEquals(2, newModel.size(), "Le modèle devrait contenir 2 déclarations après la construction à partir de la collection.");
+ assertEquals(2, newModel.size(), "The model should contain 2 statements after construction from the collection.");
}
- // Tests d'ajout
+ // Add Tests
/**
- * Teste que l'ajout d'une déclaration sans contexte appelle avec succès
- * la méthode addEdge du graphe et retourne true.
+ * Tests that adding a statement without context successfully calls
+ * the graph's addEdge method and returns true.
*/
@Test
- @DisplayName("Devrait ajouter une déclaration sans contexte avec succès")
+ @DisplayName("Should successfully add a statement without context")
void testAddStatementWithoutContext() {
IRI realSubjectIRI = new CoreseIRI("http://example.org/realSubject");
@@ -241,17 +241,17 @@ void testAddStatementWithoutContext() {
boolean added = coreseModel.add(realSubjectIRI, realPredicateIRI, realObjectIRI);
- assertTrue(added, "La déclaration devrait être ajoutée avec succès sans contexte.");
+ assertTrue(added, "The statement should be added successfully without context.");
verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class));
verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
}
/**
- * Teste que l'ajout d'une déclaration avec un seul contexte appelle avec succès
- * la méthode addEdge du graphe(avec contexte) et retourne true.
+ * Tests that adding a statement with a single context successfully calls
+ * the graph's addEdge method (with context) and returns true.
*/
@Test
- @DisplayName("Devrait ajouter une déclaration avec un seul contexte avec succès")
+ @DisplayName("Should successfully add a statement with a single context")
void testAddStatementWithSingleContext() {
IRI realSubject = new CoreseIRI("http://example.org/realSubjectWithContext");
@@ -263,19 +263,19 @@ void testAddStatementWithSingleContext() {
boolean added = coreseModel.add(realSubject, realPredicate, realObject, realContext);
- assertTrue(added, "La déclaration devrait être ajoutée avec succès avec un seul contexte.");
+ assertTrue(added, "The statement should be added successfully with a single context.");
verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class));
}
/**
- * Teste que l'ajout d'une déclaration avec plusieurs contextes
- * entraîne plusieurs appels à la méthode addEdge du graphe(un pour chaque contexte)
- * et retourne true.
+ * Tests that adding a statement with multiple contexts
+ * results in multiple calls to the graph's addEdge method (one for each context)
+ * and returns true.
*/
@Test
- @DisplayName("Devrait ajouter une déclaration avec plusieurs contextes avec succès")
+ @DisplayName("Should successfully add a statement with multiple contexts")
void testAddStatementWithMultipleContexts() {
IRI realSubject = new CoreseIRI("http://example.org/realSubjectMultiContext");
@@ -288,18 +288,18 @@ void testAddStatementWithMultipleContexts() {
boolean added = coreseModel.add(realSubject, realPredicate, realObject, realContext1, realContext2);
- assertTrue(added, "La déclaration devrait être ajoutée avec succès avec plusieurs contextes.");
+ assertTrue(added, "The statement should be added successfully with multiple contexts.");
verify(mockCoreseGraph, times(2)).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class));
}
/**
- * Teste que la méthode add retourne false si aucun changement n'a eu lieu
- * (par exemple, si la déclaration existe déjà dans le graphe).
+ * Tests that the add method returns false if no change occurred
+ * (e.g., if the statement already exists in the graph).
*/
@Test
- @DisplayName("Devrait retourner false si aucun changement n'est survenu lors de l'ajout (déclaration existante)")
+ @DisplayName("Should return false if no change occurred during add (existing statement)")
void testAddStatementNoChange() {
IRI realSubject = new CoreseIRI("http://example.org/realSubjectNoChange");
@@ -310,21 +310,21 @@ void testAddStatementNoChange() {
boolean added = coreseModel.add(realSubject, realPredicate, realObject);
- assertFalse(added, "La méthode add devrait retourner false si aucun changement n'est survenu.");
+ assertFalse(added, "The add method should return false if no change occurred.");
verify(mockCoreseGraph, times(1)).addEdge(any(Node.class), any(Node.class), any(Node.class));
verify(mockCoreseGraph, never()).addEdge(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
}
- //Tests de Contient
+ // Contains Tests
/**
- * Teste que le modèle retourne true si une déclaration existante sans contexte est présente.
- * Vérifie également que la méthode de recherche
- * est appelée correctement.
+ * Tests that the model returns true if an existing statement without context is present.
+ * Also verifies that the search method
+ * is called correctly.
*/
@Test
- @DisplayName("Devrait retourner true si le modèle contient une déclaration existante sans contexte")
+ @DisplayName("Should return true if the model contains an existing statement without context")
void testContainsExistingStatementWithoutContext() {
fr.inria.corese.core.kgram.api.core.Edge mockReturnedEdge = mock(fr.inria.corese.core.kgram.api.core.Edge.class);
List edges = List.of(mockReturnedEdge);
@@ -338,7 +338,7 @@ void testContainsExistingStatementWithoutContext() {
when(mockCoreseGraph.getEdgeFactory()).thenReturn(mock(fr.inria.corese.core.EdgeFactory.class));
when(mockCoreseGraph.getEdgeFactory().copy(any(fr.inria.corese.core.kgram.api.core.Edge.class))).thenReturn(mockReturnedEdge);
- // Appelle la méthode contains
+ // Call the contains method
boolean contains = coreseModel.contains(realSubject, realPredicate, realObject);
assertTrue(contains, "Le modèle devrait contenir la déclaration sans contexte.");
@@ -346,11 +346,11 @@ void testContainsExistingStatementWithoutContext() {
}
/**
- * Teste que le modèle retourne false si la déclaration n'est pas présente.
- * Vérifie que la méthode de recherche est bien appelée.
+ * Tests that the model returns false if the statement is not present.
+ * Verifies that the search method is called correctly.
*/
@Test
- @DisplayName("Devrait retourner false si le modèle ne contient pas la déclaration")
+ @DisplayName("Should return false if the model does not contain the statement")
void testContainsStatementNotPresent() {
IRI realSubject = new CoreseIRI("http://example.org/subjectNotFound");
@@ -370,12 +370,12 @@ void testContainsStatementNotPresent() {
/**
- * Teste que le modèle retourne true si une déclaration existante avec un contexte spécifique est trouvée.
- * Vérifie que la méthode de recherche
- * est appelée avec le contexte.
+ * Tests that the model returns true if an existing statement with a specific context is found.
+ * Verifies that the search method
+ * is called with the context.
*/
@Test
- @DisplayName("Devrait retourner true si le modèle contient une déclaration existante avec un contexte spécifique")
+ @DisplayName("Should return true if the model contains an existing statement with a specific context")
void testContainsExistingStatementWithContext() {
fr.inria.corese.core.kgram.api.core.Edge mockReturnedEdge = mock(fr.inria.corese.core.kgram.api.core.Edge.class);
List edges = List.of(mockReturnedEdge);
@@ -383,7 +383,7 @@ void testContainsExistingStatementWithContext() {
IRI realSubject = new CoreseIRI("http://example.org/subjectWithSpecificContext");
IRI realPredicate = new CoreseIRI("http://example.org/predicateWithSpecificContext");
IRI realObject = new CoreseIRI("http://example.org/objectWithSpecificContext");
- Resource realContext = new CoreseIRI("http://example.org/specificGraphContext"); // Supposant que le contexte est un IRI
+ Resource realContext = new CoreseIRI("http://example.org/specificGraphContext"); // Assuming the context is an IRI
when(mockCoreseGraph.getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node.class)))
.thenReturn(edges);
@@ -392,17 +392,17 @@ void testContainsExistingStatementWithContext() {
boolean contains = coreseModel.contains(realSubject, realPredicate, realObject, realContext);
- assertTrue(contains, "Le modèle devrait contenir la déclaration avec le contexte spécifié.");
+ assertTrue(contains, "The model should contain the statement with the specified context.");
verify(mockCoreseGraph, times(1)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), any(Node.class));
}
/**
- * Teste que le modèle retourne false si un triple non existant est recherché.
- * Vérifie que la méthode de recherche est appelée.
+ * Tests that the model returns false if a non-existent triple is searched for.
+ * Verifies that the search method is called.
*/
@Test
- @DisplayName("Devrait retourner false si le modèle ne contient pas un triple non existant")
+ @DisplayName("Should return false if the model does not contain a non-existent triple")
void testContainsNonExistingTriple() {
CoreseAdaptedValueFactory vf = new CoreseAdaptedValueFactory();
@@ -417,4 +417,4 @@ void testContainsNonExistingTriple() {
assertFalse(coreseModel.contains(georgeBrassens, rdfType, singer), "Le modèle ne devrait pas contenir un triple non existant.");
verify(mockCoreseGraph, times(0)).getEdgesRDF4J(any(Node.class), any(Node.class), any(Node.class), eq(null));
}
-}
\ No newline at end of file
+}