Skip to content

Commit

Permalink
Merge pull request #193 from kbss-cvut/development
Browse files Browse the repository at this point in the history
[1.1.1] Release
  • Loading branch information
ledsoft authored Aug 23, 2023
2 parents 24ab2d9 + a1aa3b0 commit 28a9fcb
Show file tree
Hide file tree
Showing 50 changed files with 582 additions and 230 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# JOPA - Change Log

## 1.1.1 - 2023-08-23
- Fix a possible deadlock in case RDF4J's HTTP client connection pool is exhausted by concurrent requests (Bug #191).
- Introduce a marker `@Property` annotation used on all OWL property mapping annotations.
- Dependency updates: AspectJ 1.9.20, RDF4J 4.3.5.

## 1.1.0 - 2023-07-28
- Add support for MEMBER OF in SOQL/Criteria API (Enhancement #176).
- Support language matching in SOQL/Criteria API (Enhancement #161).
Expand Down
2 changes: 1 addition & 1 deletion datatype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>jopa-all</artifactId>
<groupId>cz.cvut.kbss.jopa</groupId>
<version>1.1.0</version>
<version>1.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.time.*;
Expand All @@ -35,17 +36,43 @@ class XsdDatatypeMapperTest {

private final XsdDatatypeMapper sut = XsdDatatypeMapper.getInstance();

@Test
void mapReturnsUnsignedByteAsShort() {
final byte value = 115;
final Literal literal = Literal.from(Byte.toString(value), XSD.UNSIGNED_BYTE);
assertEquals((short) value, map(literal));
}

private Object map(Literal literal) {
@ParameterizedTest
@MethodSource("mapTestArguments")
void mapCorrectlyConvertsValues(Object expected, Literal literal) {
final Optional<Object> result = sut.map(literal);
assertTrue(result.isPresent());
return result.get();
assertEquals(expected, result.get());
}

static Stream<Arguments> mapTestArguments() {
final long longValue = System.currentTimeMillis();
final LocalDate date = LocalDate.now();
final OffsetTime time = OffsetTime.of(12, 45, 15, 0, ZoneOffset.UTC);
final OffsetDateTime dateTime = OffsetDateTime.of(2021, 11, 17, 12, 23, 10, 0, ZoneOffset.UTC);
final Duration duration = Duration.ofHours(24).plusMinutes(15).plusSeconds(44);
return Stream.of(
Arguments.of(true, Literal.from(Boolean.toString(true), XSD.BOOLEAN)),
Arguments.of((byte) 101, Literal.from(Byte.toString((byte) 101), XSD.BYTE)),
Arguments.of((short) 115, Literal.from(Byte.toString((byte) 115), XSD.UNSIGNED_BYTE)),
Arguments.of(1234, Literal.from(Short.toString((short) 1234), XSD.UNSIGNED_SHORT)),
Arguments.of((long) Integer.MAX_VALUE, Literal.from(Integer.toString(Integer.MAX_VALUE), XSD.UNSIGNED_INT)),
Arguments.of(BigInteger.valueOf(Integer.MIN_VALUE), Literal.from(Integer.toString(Integer.MIN_VALUE), XSD.INTEGER)),
Arguments.of(BigInteger.valueOf(longValue), Literal.from(Long.toString(longValue), XSD.UNSIGNED_LONG)),
Arguments.of("test", Literal.from("test", XSD.STRING)),
Arguments.of("test", Literal.from("test", XSD.NORMALIZED_STRING)),
Arguments.of(date,Literal.from(date.format(DateTimeFormatter.ISO_DATE), XSD.DATE) ),
Arguments.of(time, Literal.from(time.format(DateTimeFormatter.ISO_TIME), XSD.TIME)),
Arguments.of(dateTime, Literal.from(dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME), XSD.DATETIME)),
Arguments.of(duration, Literal.from(duration.toString(), XSD.DURATION)),
Arguments.of(URI.create("https://www.w3.org/TR/xmlschema-2/#anyURI"), Literal.from("https://www.w3.org/TR/xmlschema-2/#anyURI", XSD.ANY_URI)),
Arguments.of(new BigDecimal("3.141952"), Literal.from("3.141952", XSD.DECIMAL)),
Arguments.of(Float.NaN, Literal.from("NaN", XSD.FLOAT)),
Arguments.of(Float.NEGATIVE_INFINITY, Literal.from("-INF", XSD.FLOAT)),
Arguments.of(Float.POSITIVE_INFINITY, Literal.from("INF", XSD.FLOAT)),
Arguments.of(Double.NaN, Literal.from("NaN", XSD.DOUBLE)),
Arguments.of(Double.NEGATIVE_INFINITY, Literal.from("-INF", XSD.DOUBLE)),
Arguments.of(Double.POSITIVE_INFINITY, Literal.from("INF", XSD.DOUBLE))
);
}

@Test
Expand All @@ -54,103 +81,9 @@ void mapReturnsEmptyOptionalForUnknownDatatype() {
assertFalse(sut.map(Literal.from("jpeg", datatype)).isPresent());
}

@Test
void mapReturnsUnsignedShortAsInt() {
final short value = 1234;
final Literal literal = Literal.from(Short.toString(value), XSD.UNSIGNED_SHORT);
assertEquals((int) value, map(literal));
}

@Test
void mapThrowsDatatypeMappingExceptionForInvalidLiteralValue() {
final Literal invalidValue = Literal.from("abcd", XSD.INT);
assertThrows(DatatypeMappingException.class, () -> sut.map(invalidValue));
}

@Test
void mapReturnsUnsignedIntAsLong() {
final int value = Integer.MAX_VALUE;
final Literal literal = Literal.from(Integer.toString(value), XSD.UNSIGNED_INT);
assertEquals((long) value, map(literal));
}

@Test
void mapReturnsIntegerAsBigInteger() {
final int value = Integer.MIN_VALUE;
final Literal literal = Literal.from(Integer.toString(value), XSD.INTEGER);
assertEquals(BigInteger.valueOf(value), map(literal));
}

@Test
void mapReturnsUnsignedLongAsBigInteger() {
final long value = System.currentTimeMillis();
final Literal literal = Literal.from(Long.toString(value), XSD.UNSIGNED_LONG);
assertEquals(BigInteger.valueOf(value), map(literal));
}

@Test
void mapReturnsXsdStringAsString() {
final String value = "test";
final Literal literal = Literal.from(value, XSD.STRING);
assertEquals(value, map(literal));
}

@Test
void mapReturnsXsdNormalizedStringAsString() {
final String value = "test";
final Literal literal = Literal.from(value, XSD.NORMALIZED_STRING);
assertEquals(value, map(literal));
}

@Test
void mapReturnsLocalDateForXsdDate() {
final LocalDate date = LocalDate.now();
final Literal literal = Literal.from(date.format(DateTimeFormatter.ISO_DATE), XSD.DATE);
assertEquals(date, map(literal));
}

@Test
void mapReturnsOffsetTimeForXsdTime() {
final OffsetTime time = OffsetTime.of(12, 45, 15, 0, ZoneOffset.UTC);
assertEquals(time, map(Literal.from(time.format(DateTimeFormatter.ISO_TIME), XSD.TIME)));
}

@Test
void mapReturnsOffsetDateTimeForXsdDateTime() {
final OffsetDateTime dateTime = OffsetDateTime.of(2021, 11, 17, 12, 23, 10, 0, ZoneOffset.UTC);
assertEquals(dateTime,
map(Literal.from(dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME), XSD.DATETIME)));
}

@Test
void mapReturnsDurationForXsdDuration() {
final Duration duration = Duration.ofHours(24).plusMinutes(15).plusSeconds(44);
assertEquals(duration, map(Literal.from(duration.toString(), XSD.DURATION)));
}

@Test
void mapReturnsUriForXsdAnyUri() {
final String uri = "https://www.w3.org/TR/xmlschema-2/#anyURI";
assertEquals(URI.create(uri), map(Literal.from(uri, XSD.ANY_URI)));
}

/**
* Bug #108
*/
@ParameterizedTest
@MethodSource("floatingPointSpecialValuesGenerator")
void mapSupportsSpecialFloatingPointValuesMapping(Literal literal, Number expected) {
assertEquals(expected, map(literal));
}

private static Stream<Arguments> floatingPointSpecialValuesGenerator() {
return Stream.of(
Arguments.of(Literal.from("NaN", XSD.FLOAT), Float.NaN),
Arguments.of(Literal.from("-INF", XSD.FLOAT), Float.NEGATIVE_INFINITY),
Arguments.of(Literal.from("INF", XSD.FLOAT), Float.POSITIVE_INFINITY),
Arguments.of(Literal.from("NaN", XSD.DOUBLE), Double.NaN),
Arguments.of(Literal.from("-INF", XSD.DOUBLE), Double.NEGATIVE_INFINITY),
Arguments.of(Literal.from("INF", XSD.DOUBLE), Double.POSITIVE_INFINITY)
);
}
}
2 changes: 1 addition & 1 deletion jopa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>1.1.0</version>
<version>1.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;

/**
* Default implementation of the {@link PersistenceProviderResolver}, threadsafe.
Expand Down Expand Up @@ -63,14 +69,7 @@ public List<PersistenceProvider> getPersistenceProviders() {
List<PersistenceProvider> loadedProviders = new ArrayList<>();
Iterator<PersistenceProvider> ipp = ServiceLoader.load(PersistenceProvider.class, loader).iterator();
try {
while (ipp.hasNext()) {
try {
PersistenceProvider pp = ipp.next();
loadedProviders.add(pp);
} catch (ServiceConfigurationError sce) {
LOG.warn("Unable to load PersistenceProvider implementation via service loader.", sce);
}
}
loadProvider(ipp).ifPresent(loadedProviders::add);
} catch (ServiceConfigurationError sce) {
LOG.warn("Unable to load PersistenceProvider implementation via service loader.", sce);
}
Expand All @@ -86,6 +85,15 @@ public List<PersistenceProvider> getPersistenceProviders() {
return loadedProviders;
}

private Optional<PersistenceProvider> loadProvider(Iterator<PersistenceProvider> ipp) {
try {
return Optional.of(ipp.next());
} catch (ServiceConfigurationError sce) {
LOG.warn("Unable to load PersistenceProvider implementation via service loader.", sce);
return Optional.empty();
}
}

/**
* Remove garbage collected cache keys & providers.
*/
Expand All @@ -103,7 +111,8 @@ private static ClassLoader getContextClassLoader() {
if (System.getSecurityManager() == null) {
return Thread.currentThread().getContextClassLoader();
} else {
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader());
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> Thread.currentThread()
.getContextClassLoader());
}
}

Expand Down Expand Up @@ -192,7 +201,7 @@ public Object clone() {
return clone;
} catch (CloneNotSupportedException e) {
// this should never happen
throw new InternalError();
throw new InternalError(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,21 @@
*/
package cz.cvut.kbss.jopa.model.annotations;

import java.lang.annotation.*;
import cz.cvut.kbss.jopa.model.annotations.util.Property;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks an attribute mapped to an OWL annotation property.
* <p>
* This means that the attribute can contain a literal or a reference to another object.
*/
@Documented
@Property
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface OWLAnnotationProperty {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
*/
package cz.cvut.kbss.jopa.model.annotations;

import java.lang.annotation.*;
import cz.cvut.kbss.jopa.model.annotations.util.Property;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks an attribute mapped to an OWL datatype property.
Expand All @@ -24,6 +30,7 @@
* Note that for use with RDF(S), attributes annotated with this annotation are expected to reference literals.
*/
@Documented
@Property
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface OWLDataProperty{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
*/
package cz.cvut.kbss.jopa.model.annotations;

import java.lang.annotation.*;
import cz.cvut.kbss.jopa.model.annotations.util.Property;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks an attribute mapped to an OWL object property.
Expand All @@ -24,6 +30,7 @@
* Note that for use with RDF(S), attributes annotated with this annotation are expected to reference other RDF resources.
*/
@Documented
@Property
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface OWLObjectProperty {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cz.cvut.kbss.jopa.model.annotations.util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks annotations that represent property mapping.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Property {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cz.cvut.kbss.jopa.model.util;

import cz.cvut.kbss.jopa.model.annotations.OWLAnnotationProperty;
import cz.cvut.kbss.jopa.model.annotations.OWLDataProperty;
import cz.cvut.kbss.jopa.model.annotations.OWLObjectProperty;
import cz.cvut.kbss.jopa.model.annotations.util.Property;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class PropertyTest {

@Test
void owlPropertiesAreMarkedWithPropertyAnnotation() {
assertTrue(OWLAnnotationProperty.class.isAnnotationPresent(Property.class));
assertTrue(OWLDataProperty.class.isAnnotationPresent(Property.class));
assertTrue(OWLObjectProperty.class.isAnnotationPresent(Property.class));
}
}
2 changes: 1 addition & 1 deletion jopa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>1.1.0</version>
<version>1.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>1.1.0</version>
<version>1.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ protected void processClass(String className) {
try {
final Class<?> cls = Class.forName(className, true, classLoader);
listeners.forEach(listener -> listener.accept(cls));
} catch (Throwable e) {
} catch (Exception | NoClassDefFoundError e) {
LOG.debug("Unable to load class {}, got error {}: {}. Skipping the class. If it is an entity class, ensure it is available on classpath and is built with supported Java version.", className, e.getClass()
.getName(), e.getMessage());
}
Expand Down
Loading

0 comments on commit 28a9fcb

Please sign in to comment.