Skip to content

Commit

Permalink
[Bug #252] Add test reproducing the issue.
Browse files Browse the repository at this point in the history
  • Loading branch information
ledsoft committed Jun 24, 2024
1 parent 1bb93d2 commit bd3e73c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,26 @@ public class OWLClassL implements HasUri {
@Sequence(type = SequenceType.simple)
@OWLObjectProperty(iri = Vocabulary.p_l_simpleListAttribute, fetch = FetchType.LAZY)
@ParticipationConstraints({
@ParticipationConstraint(min = 1,
owlObjectIRI = "http://krizik.felk.cvut.cz/ontologies/jopa/entities#OWLClassA")
@ParticipationConstraint(min = 1, owlObjectIRI = Vocabulary.C_OWL_CLASS_A)
})
private List<OWLClassA> simpleList;

@Sequence(type = SequenceType.referenced)
@OWLObjectProperty(iri = Vocabulary.p_l_referencedListAttribute, fetch = FetchType.LAZY)
@ParticipationConstraints({
@ParticipationConstraint(max = 2,
owlObjectIRI = "http://krizik.felk.cvut.cz/ontologies/jopa/entities#OWLClassA")
@ParticipationConstraint(max = 2, owlObjectIRI = Vocabulary.C_OWL_CLASS_A)
})
private List<OWLClassA> referencedList;

@OWLObjectProperty(iri = Vocabulary.p_l_aSetAttribute, fetch = FetchType.LAZY)
@ParticipationConstraints({
@ParticipationConstraint(min = 1, max = 5,
owlObjectIRI = "http://krizik.felk.cvut.cz/ontologies/jopa/entities#OWLClassA")
@ParticipationConstraint(min = 1, max = 5, owlObjectIRI = Vocabulary.C_OWL_CLASS_A)
})
private Set<OWLClassA> set;

@OWLObjectProperty(iri = Vocabulary.p_l_singleOwlClassAAttribute, fetch = FetchType.LAZY)
@ParticipationConstraints({
@ParticipationConstraint(min = 1,
owlObjectIRI = "http://krizik.felk.cvut.cz/ontologies/jopa/entities#OWLClassA")
@ParticipationConstraint(min = 1, owlObjectIRI = Vocabulary.C_OWL_CLASS_A)
})
private OWLClassA singleA;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
import cz.cvut.kbss.jopa.model.annotations.OWLClass;
import cz.cvut.kbss.jopa.model.annotations.PrePersist;
import cz.cvut.kbss.jopa.oom.exception.UnpersistedChangeException;
import cz.cvut.kbss.jopa.proxy.lazy.LazyLoadingProxy;
import cz.cvut.kbss.jopa.test.OWLClassA;
import cz.cvut.kbss.jopa.test.OWLClassD;
import cz.cvut.kbss.jopa.test.OWLClassE;
import cz.cvut.kbss.jopa.test.OWLClassF;
import cz.cvut.kbss.jopa.test.OWLClassJ;
import cz.cvut.kbss.jopa.test.OWLClassL;
import cz.cvut.kbss.jopa.test.OWLClassO;
import cz.cvut.kbss.jopa.test.OWLClassR;
import cz.cvut.kbss.jopa.test.Vocabulary;
Expand All @@ -45,6 +47,7 @@
import cz.cvut.kbss.ontodriver.model.Value;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.junit.jupiter.MockitoExtension;

import java.net.URI;
Expand All @@ -64,6 +67,8 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -278,4 +283,39 @@ void cascadeMergeOnLazyLoadingProxyDoesNothing() throws Exception {
em.merge(subject);
verify(connectionMock, never()).update(any(AxiomValueDescriptor.class));
}

/**
* Bug #252
*/
@Test
void isInferredTriggersLazyLoadingForLazyLoadingProxy() throws Exception {
final OWLClassL owner = new OWLClassL(Generators.generateUri());
final OWLClassA ref = Generators.generateOwlClassA();
final NamedResource subject = NamedResource.create(owner.getUri());
final Assertion classAssertion = Assertion.createClassAssertion(false);
final Assertion hasAAssertion = Assertion.createObjectPropertyAssertion(URI.create(Vocabulary.p_l_singleOwlClassAAttribute), false);
final AxiomDescriptor ownerDesc = new AxiomDescriptor(subject);
ownerDesc.addAssertion(classAssertion);
ownerDesc.addAssertion(hasAAssertion);
ownerDesc.addAssertion(Assertion.createObjectPropertyAssertion(URI.create(Vocabulary.p_l_simpleListAttribute), false));
ownerDesc.addAssertion(Assertion.createObjectPropertyAssertion(URI.create(Vocabulary.p_l_referencedListAttribute), false));
ownerDesc.addAssertion(Assertion.createObjectPropertyAssertion(URI.create(Vocabulary.p_l_aSetAttribute), false));
final List<Axiom<?>> ownerAxioms = List.of(
new AxiomImpl<>(subject, classAssertion, new Value<>(URI.create(Vocabulary.C_OWL_CLASS_L))),
new AxiomImpl<Object>(subject, hasAAssertion, new Value<>(NamedResource.create(ref.getUri())))
);
when(connectionMock.find(ownerDesc)).thenReturn(ownerAxioms);
initAxiomsForOWLClassA(NamedResource.create(ref.getUri()), ref.getStringAttribute(), false);

em.getTransaction().begin();
final OWLClassL instance = em.find(OWLClassL.class, owner.getUri());
assertInstanceOf(LazyLoadingProxy.class, instance.getSingleA());
assertFalse(em.isInferred(instance, em.getMetamodel().entity(OWLClassL.class).getAttribute("singleA"), instance.getSingleA()));
final ArgumentCaptor<Axiom<?>> axiomCaptor = ArgumentCaptor.forClass(Axiom.class);
verify(connectionMock).isInferred(axiomCaptor.capture(), eq(Collections.emptySet()));
assertEquals(new Value<>(NamedResource.create(ref.getUri())), axiomCaptor.getValue().getValue());
final ArgumentCaptor<AxiomDescriptor> captor = ArgumentCaptor.forClass(AxiomDescriptor.class);
verify(connectionMock, atLeastOnce()).find(captor.capture());
assertTrue(captor.getAllValues().stream().anyMatch(ad -> ad.getSubject().equals(NamedResource.create(ref.getUri()))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ private Rdf4jUtils() {
/**
* Gets value of the specified literal as the corresponding Java object.
* <p>
* Primitives are returned boxed. If the type cannot be mapped to a corresponding Java type,
* it is returned as {@link cz.cvut.kbss.ontodriver.model.Literal}.
* Primitives are returned boxed. If the type cannot be mapped to a corresponding Java type, it is returned as
* {@link cz.cvut.kbss.ontodriver.model.Literal}.
*
* @param literal RDF literal value
* @return Java value corresponding to datatype
Expand All @@ -71,8 +71,8 @@ public static Object getLiteralValue(Literal literal) {
/**
* Checks whether the language of the specified literal matches the specified assertion language.
* <p>
* If the assertion does not specify a language, any literal will match. If the literal is not a string, it
* matches as well.
* If the assertion does not specify a language, any literal will match. If the literal is not a string, it matches
* as well.
*
* @param literal Literal to check
* @param assertion Assertion
Expand Down Expand Up @@ -110,10 +110,9 @@ public static Literal createLiteral(Object value, String language, ValueFactory
return vf.createLiteral((Integer) value);
} else if (value instanceof String) {
return language != null ? vf.createLiteral((String) value, language) : vf.createLiteral((String) value);
} else if (value instanceof LangString) {
final LangString ls = (LangString) value;
} else if (value instanceof LangString ls) {
return ls.getLanguage().isPresent() ? vf.createLiteral(ls.getValue(), ls.getLanguage().get()) :
vf.createLiteral(ls.getValue());
vf.createLiteral(ls.getValue());
} else if (value instanceof Byte) {
return vf.createLiteral((Byte) value);
} else if (value instanceof Short) {
Expand Down Expand Up @@ -141,8 +140,7 @@ public static Literal createLiteral(Object value, String language, ValueFactory
return createLiteral(vf, ontoLiteral);
} else if (value.getClass().isEnum()) {
return vf.createLiteral(value.toString());
} else if (value instanceof cz.cvut.kbss.ontodriver.model.Literal) {
final cz.cvut.kbss.ontodriver.model.Literal ontoLiteral = (cz.cvut.kbss.ontodriver.model.Literal) value;
} else if (value instanceof cz.cvut.kbss.ontodriver.model.Literal ontoLiteral) {
return createLiteral(vf, ontoLiteral);
} else {
throw new IllegalArgumentException("Unsupported literal type " + value.getClass());
Expand All @@ -166,7 +164,7 @@ public static boolean isBlankNode(Value value) {

/**
* Resolves whether the specified value is a resource identifier.
*
* <p>
* Only values of supported identifier types are considered identifiers.
*
* @param value The value to check
Expand All @@ -189,8 +187,9 @@ public static IRI toRdf4jIri(java.net.URI javaUri, ValueFactory factory) {

/**
* Constructs a RDF4J IRI from identifier of the specified resource.
*
* @param resource Resource whose identifier to transform
* @param factory RDF4J value factory used for the conversion
* @param factory RDF4J value factory used for the conversion
* @return RDF4J IRI
* @see #toRdf4jIri(URI, ValueFactory)
*/
Expand All @@ -208,7 +207,7 @@ public static java.net.URI toJavaUri(Resource resource) {
return java.net.URI.create(resource.stringValue());
} catch (IllegalArgumentException e) {
// This shouldn't happen
LoggerFactory.getLogger(Rdf4jUtils.class).error("RDF4J resource is not a valid URI: " + e);
LoggerFactory.getLogger(Rdf4jUtils.class).error("RDF4J resource is not a valid URI.", e);
return null;
}
}
Expand Down

0 comments on commit bd3e73c

Please sign in to comment.