Skip to content

Commit

Permalink
Merge pull request #77 from kbss-cvut/development
Browse files Browse the repository at this point in the history
[0.15.1] Release
  • Loading branch information
ledsoft authored Dec 17, 2024
2 parents 543a8ae + 1ebb650 commit 28836e5
Show file tree
Hide file tree
Showing 29 changed files with 594 additions and 82 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# JB4JSON-LD Changelog

## 0.15.1 - 2024-12-17
- Ensure datatype is output with numeric values to preserve their type on serialization (Enhancement #66).
- Dependency updates: JOPA 2.2.1, build plugins.

## 0.15.0 - 2024-08-26
- Support deserializing objects containing only identifier when `ASSUME_TARGET_TYPE` is enabled (Enhancement #69).
- Cache deserialization type map (Enhancement #68).
Expand Down
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>cz.cvut.kbss.jsonld</groupId>
<artifactId>jb4jsonld</artifactId>
<version>0.15.0</version>
<version>0.15.1</version>
<name>JB4JSON-LD</name>
<description>Java Binding for JSON-LD allows serialization and deserialization of Java POJOs to/from JSON-LD.
This is the core implementation, which has to be integrated with Jackson, Jersey etc.
Expand All @@ -19,12 +19,12 @@
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

<cz.cvut.kbss.jopa.version>2.0.4</cz.cvut.kbss.jopa.version>
<cz.cvut.kbss.jopa.version>2.2.1</cz.cvut.kbss.jopa.version>

<org.junit.jupiter.version>5.11.0</org.junit.jupiter.version>
<org.mockito.version>5.12.0</org.mockito.version>
<ch.qos.logback.version>1.5.7</ch.qos.logback.version>
<org.eclipse.rdf4j.version>5.0.2</org.eclipse.rdf4j.version>
<org.eclipse.rdf4j.version>5.0.3</org.eclipse.rdf4j.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -128,7 +128,7 @@
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.1</version>
<version>3.10.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
Expand Down Expand Up @@ -172,19 +172,19 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<version>3.5.1</version>
</plugin>

<!-- Code coverage plugin -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<version>0.8.12</version>
<executions>
<execution>
<goals>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* Utilities for mapping-related tasks.
*/
public class BeanAnnotationProcessor {

private static final String[] EMPTY_ARRAY = new String[0];
Expand Down
21 changes: 11 additions & 10 deletions src/main/java/cz/cvut/kbss/jsonld/common/BeanClassProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import java.lang.reflect.Type;
import java.util.*;

/**
* Reflection-related utilities.
*/
public class BeanClassProcessor {

private BeanClassProcessor() {
Expand Down Expand Up @@ -82,7 +85,8 @@ public static void setFieldValue(Field field, Object instance, Object value) {
public static <T> T createInstance(Class<T> cls) {
try {
return cls.getDeclaredConstructor().newInstance();
} catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
} catch (NoSuchMethodException | InstantiationException | InvocationTargetException |
IllegalAccessException e) {
throw new BeanProcessingException("Class " + cls + " is missing a public no-arg constructor.", e);
}
}
Expand All @@ -94,14 +98,10 @@ public static <T> T createInstance(Class<T> cls) {
* @return New collection instance
*/
public static Collection<?> createCollection(CollectionType type) {
switch (type) {
case LIST:
return new ArrayList<>();
case SET:
return new HashSet<>();
default:
throw new IllegalArgumentException("Unsupported collection type " + type);
}
return switch (type) {
case LIST -> new ArrayList<>();
case SET -> new HashSet<>();
};
}

/**
Expand Down Expand Up @@ -249,8 +249,9 @@ public static void verifyPropertiesFieldType(Field field) {

/**
* Checks whether the specified class represents an individual reference and not a complex object.
*
* <p>
* Individual references are identifiers or enum constants mapped to individuals.
*
* @param cls Class to check
* @return {@code true} when the type represents an individual, {@code false} otherwise
* @see #isIdentifierType(Class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ protected void processJarFile(URL jarResource, String packageName) {
}
}
} catch (IOException e) {
LOG.error("Unable to scan classes in JAR file " + jarPath, e);
LOG.error("Unable to scan classes in JAR file {}", jarPath, e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@
import cz.cvut.kbss.jsonld.serialization.serializer.LiteralValueSerializers;
import cz.cvut.kbss.jsonld.serialization.serializer.ObjectGraphValueSerializers;
import cz.cvut.kbss.jsonld.serialization.serializer.ValueSerializers;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.*;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.DefaultValueSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.IdentifierSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.IndividualSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.MultilingualStringSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.NumberSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.ObjectPropertyValueSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.TypesSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.datetime.TemporalAmountSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.compact.datetime.TemporalSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.datetime.DateSerializer;
import cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser;
import cz.cvut.kbss.jsonld.serialization.traversal.SerializationContextFactory;

import java.time.*;
import java.time.Duration;
import java.time.Period;
import java.util.Date;

/**
Expand All @@ -57,19 +64,14 @@ protected ValueSerializers initSerializers() {
valueSerializers.registerTypesSerializer(new TypesSerializer());
valueSerializers.registerIndividualSerializer(new IndividualSerializer());
final TemporalSerializer ts = new TemporalSerializer();
valueSerializers.registerSerializer(LocalDate.class, ts);
// Register the same temporal serializer for each of the types it supports (needed for key-based map access)
valueSerializers.registerSerializer(LocalDate.class, ts);
valueSerializers.registerSerializer(LocalTime.class, ts);
valueSerializers.registerSerializer(OffsetTime.class, ts);
valueSerializers.registerSerializer(LocalDateTime.class, ts);
valueSerializers.registerSerializer(OffsetDateTime.class, ts);
valueSerializers.registerSerializer(ZonedDateTime.class, ts);
valueSerializers.registerSerializer(Instant.class, ts);
TemporalSerializer.getSupportedTypes().forEach(cls -> valueSerializers.registerSerializer(cls, ts));
valueSerializers.registerSerializer(Date.class, new DateSerializer(ts));
final TemporalAmountSerializer tas = new TemporalAmountSerializer();
valueSerializers.registerSerializer(Duration.class, tas);
valueSerializers.registerSerializer(Period.class, tas);
final NumberSerializer numberSerializer = new NumberSerializer();
NumberSerializer.getSupportedTypes().forEach(cls -> valueSerializers.registerSerializer(cls, numberSerializer));
return valueSerializers;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,22 @@
import cz.cvut.kbss.jsonld.serialization.serializer.ObjectGraphValueSerializers;
import cz.cvut.kbss.jsonld.serialization.serializer.ValueSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.ValueSerializers;
import cz.cvut.kbss.jsonld.serialization.serializer.context.*;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingDefaultValueSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingIdentifierSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingIndividualSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingMultilingualStringSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingNumberSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingObjectPropertyValueSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingPluralMultilingualStringSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingTypesSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.datetime.ContextBuildingTemporalAmountSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.context.datetime.ContextBuildingTemporalSerializer;
import cz.cvut.kbss.jsonld.serialization.serializer.datetime.DateSerializer;
import cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser;
import cz.cvut.kbss.jsonld.serialization.traversal.SerializationContextFactory;

import java.time.*;
import java.time.Duration;
import java.time.Period;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;
Expand Down Expand Up @@ -69,19 +77,16 @@ protected ValueSerializers initSerializers() {
valueSerializers.registerTypesSerializer(new ContextBuildingTypesSerializer());
valueSerializers.registerIndividualSerializer(new ContextBuildingIndividualSerializer());
final ContextBuildingTemporalSerializer ts = new ContextBuildingTemporalSerializer();
valueSerializers.registerSerializer(LocalDate.class, ts);
// Register the same temporal serializer for each of the types it supports (needed for key-based map access)
valueSerializers.registerSerializer(LocalDate.class, ts);
valueSerializers.registerSerializer(LocalTime.class, ts);
valueSerializers.registerSerializer(OffsetTime.class, ts);
valueSerializers.registerSerializer(LocalDateTime.class, ts);
valueSerializers.registerSerializer(OffsetDateTime.class, ts);
valueSerializers.registerSerializer(ZonedDateTime.class, ts);
valueSerializers.registerSerializer(Instant.class, ts);
ContextBuildingTemporalSerializer.getSupportedTypes()
.forEach(cls -> valueSerializers.registerSerializer(cls, ts));
valueSerializers.registerSerializer(Date.class, new DateSerializer(ts));
final ContextBuildingTemporalAmountSerializer tas = new ContextBuildingTemporalAmountSerializer();
valueSerializers.registerSerializer(Duration.class, tas);
valueSerializers.registerSerializer(Period.class, tas);
final ContextBuildingNumberSerializer ns = new ContextBuildingNumberSerializer();
ContextBuildingNumberSerializer.getSupportedTypes()
.forEach(cls -> valueSerializers.registerSerializer(cls, ns));
return valueSerializers;
}

Expand Down Expand Up @@ -114,7 +119,8 @@ private void ensureContextNodeNotPresent(CompositeNode<?> root, JsonNode rootCtx

private JsonLdTreeBuilder initTreeBuilder(ObjectGraphTraverser traverser,
JsonLdContextFactory jsonLdContextFactory) {
final ContextBuildingObjectPropertyValueSerializer opSerializer = new ContextBuildingObjectPropertyValueSerializer(traverser);
final ContextBuildingObjectPropertyValueSerializer opSerializer =
new ContextBuildingObjectPropertyValueSerializer(traverser);
opSerializer.configure(configuration());
return new JsonLdTreeBuilder(new ObjectGraphValueSerializers(serializers, opSerializer), jsonLdContextFactory);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,11 @@ public static LiteralNode<?> createLiteralNode(Object value) {

public static LiteralNode<?> createLiteralNode(String name, Object value) {
final LiteralType type = determineLiteralType(value);
switch (type) {
case BOOLEAN:
return createBooleanLiteralNode(name, (Boolean) value);
case NUMBER:
return createNumericLiteralNode(name, (Number) value);
default:
return createStringLiteralNode(name, value.toString());
}
return switch (type) {
case BOOLEAN -> createBooleanLiteralNode(name, (Boolean) value);
case NUMBER -> createNumericLiteralNode(name, (Number) value);
default -> createStringLiteralNode(name, value.toString());
};
}

private static LiteralType determineLiteralType(Object value) {
Expand Down Expand Up @@ -84,14 +81,10 @@ public static StringLiteralNode createStringLiteralNode(String name, String valu
*/
public static CollectionNode<?> createCollectionNode(String name, Collection<?> value) {
final CollectionType type = determineCollectionType(value);
switch (type) {
case LIST:
return new ListNode(name);
case SET:
return createSetNode(name);
default:
throw new IllegalArgumentException("Unsupported collection type " + type);
}
return switch (type) {
case LIST -> new ListNode(name);
case SET -> createSetNode(name);
};
}

private static CollectionType determineCollectionType(Collection<?> collection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

import java.util.Collection;

/**
* JSON node representing a collection.
*
* @param <T> Node type
*/
public abstract class CollectionNode<T extends Collection<JsonNode>> extends CompositeNode<T> {

CollectionNode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static ObjectNode createTypedTermDefinition(String term, String id, Strin
* @param type Value type to use
* @return Resulting JSON node
*/
public static JsonNode createdTypedValueNode(String term, String value, String type) {
public static JsonNode createdTypedValueNode(String term, Object value, String type) {
final ObjectNode node = JsonNodeFactory.createObjectNode(term);
node.addItem(JsonNodeFactory.createLiteralNode(JsonLd.TYPE, type));
node.addItem(JsonNodeFactory.createLiteralNode(JsonLd.VALUE, value));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package cz.cvut.kbss.jsonld.serialization.serializer.compact;

import cz.cvut.kbss.jopa.vocabulary.XSD;
import cz.cvut.kbss.jsonld.serialization.model.JsonNode;
import cz.cvut.kbss.jsonld.serialization.serializer.SerializerUtils;
import cz.cvut.kbss.jsonld.serialization.serializer.ValueSerializer;
import cz.cvut.kbss.jsonld.serialization.traversal.SerializationContext;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Objects;

/**
* Serializes numeric values.
*/
public class NumberSerializer implements ValueSerializer<Number> {

@Override
public JsonNode serialize(Number value, SerializationContext<Number> ctx) {
Objects.requireNonNull(value);
return SerializerUtils.createdTypedValueNode(ctx.getTerm(), value, getDatatype(value));
}

protected String getDatatype(Number value) {
if (value instanceof Integer) {
return XSD.INT;
} else if (value instanceof Long) {
return XSD.LONG;
} else if (value instanceof Double) {
return XSD.DOUBLE;
} else if (value instanceof Float) {
return XSD.FLOAT;
} else if (value instanceof Short) {
return XSD.SHORT;
} else if (value instanceof BigInteger) {
return XSD.INTEGER;
} else if (value instanceof BigDecimal) {
return XSD.DECIMAL;
} else {
throw new IllegalArgumentException("Unsupported numeric literal type " + value.getClass());
}
}

/**
* Gets a list of Java types supported by this serializer.
*
* @return List of Java classes
*/
public static List<Class<? extends Number>> getSupportedTypes() {
return List.of(Integer.class, Long.class, Double.class, Float.class, Short.class, BigInteger.class,
BigDecimal.class);
}
}
Loading

0 comments on commit 28836e5

Please sign in to comment.