Move PojoCloudEventData in core (#289)
* Add a static method to wrap a pojo in PojoCloudEventData Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * WIP Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Cleanup Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Reverted BytesCloudEventData and moved to a separate PR Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
394347db07
commit
c9b3fa4b65
|
@ -0,0 +1,74 @@
|
|||
package io.cloudevents.core.data;
|
||||
|
||||
import io.cloudevents.CloudEventData;
|
||||
import io.cloudevents.rw.CloudEventRWException;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PojoCloudEventData<T> implements CloudEventData {
|
||||
|
||||
/**
|
||||
* Interface defining a conversion from T to byte array. This is similar to {@link java.util.function.Function}
|
||||
* but it allows checked exceptions.
|
||||
*
|
||||
* @param <T> the source type of the conversion
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToBytes<T> {
|
||||
byte[] convert(T data) throws Exception;
|
||||
}
|
||||
|
||||
private final T value;
|
||||
private byte[] memoizedValue;
|
||||
private final ToBytes<T> mapper;
|
||||
|
||||
private PojoCloudEventData(T value, ToBytes<T> mapper) {
|
||||
this(value, null, mapper);
|
||||
}
|
||||
|
||||
private PojoCloudEventData(T value, byte[] memoizedValue, ToBytes<T> mapper) {
|
||||
Objects.requireNonNull(value);
|
||||
if (memoizedValue == null && mapper == null) {
|
||||
throw new NullPointerException("You must provide the serialized data value or a mapper");
|
||||
}
|
||||
this.value = value;
|
||||
this.memoizedValue = memoizedValue;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
if (this.memoizedValue == null) {
|
||||
try {
|
||||
this.memoizedValue = mapper.convert(this.value);
|
||||
} catch (Exception e) {
|
||||
throw CloudEventRWException.newDataConversion(e, value.getClass().toString(), "byte[]");
|
||||
}
|
||||
}
|
||||
return this.memoizedValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PojoCloudEventData<?> that = (PojoCloudEventData<?>) o;
|
||||
return Objects.equals(getValue(), that.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the provided data in a {@link PojoCloudEventData} serializable by the provided mapper.
|
||||
*/
|
||||
public static <T> PojoCloudEventData<T> wrap(T data, ToBytes<T> mapper) {
|
||||
return new PojoCloudEventData<>(data, mapper);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package io.cloudevents.core.data;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PojoCloudEventDataTest {
|
||||
|
||||
@Test
|
||||
void testWrapAndMemoization() {
|
||||
PojoCloudEventData<Integer> data = PojoCloudEventData.wrap(10, i -> i.toString().getBytes());
|
||||
|
||||
assertThat(data.getValue())
|
||||
.isEqualTo(10);
|
||||
|
||||
byte[] firstConversion = data.toBytes();
|
||||
|
||||
assertThat(firstConversion)
|
||||
.isEqualTo("10".getBytes());
|
||||
|
||||
assertThat(data.toBytes())
|
||||
.isSameAs(firstConversion);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAlreadySerializedValue() {
|
||||
byte[] serialized = "10".getBytes();
|
||||
PojoCloudEventData<Integer> data = PojoCloudEventData.wrap(10, v -> serialized);
|
||||
|
||||
assertThat(data.getValue())
|
||||
.isEqualTo(10);
|
||||
|
||||
assertThat(data.toBytes())
|
||||
.isSameAs(serialized);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package io.cloudevents.jackson;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.cloudevents.CloudEventData;
|
||||
import io.cloudevents.rw.CloudEventRWException;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PojoCloudEventData<T> implements CloudEventData {
|
||||
|
||||
private final ObjectMapper mapper;
|
||||
private byte[] memoizedValue;
|
||||
private final T value;
|
||||
|
||||
protected PojoCloudEventData(ObjectMapper mapper, T value) {
|
||||
this(mapper, value, null);
|
||||
}
|
||||
|
||||
protected PojoCloudEventData(ObjectMapper mapper, T value, byte[] memoizedValue) {
|
||||
this.mapper = mapper;
|
||||
this.value = value;
|
||||
this.memoizedValue = memoizedValue;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
if (this.memoizedValue == null) {
|
||||
try {
|
||||
this.memoizedValue = mapper.writeValueAsBytes(value);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw CloudEventRWException.newDataConversion(e, value.getClass().toString(), "byte[]");
|
||||
}
|
||||
}
|
||||
return this.memoizedValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PojoCloudEventData<?> that = (PojoCloudEventData<?>) o;
|
||||
return Objects.equals(getValue(), that.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getValue());
|
||||
}
|
||||
}
|
|
@ -5,8 +5,10 @@ import com.fasterxml.jackson.databind.JavaType;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.cloudevents.CloudEventData;
|
||||
import io.cloudevents.core.data.PojoCloudEventData;
|
||||
import io.cloudevents.rw.CloudEventDataMapper;
|
||||
import io.cloudevents.rw.CloudEventRWException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PojoCloudEventDataMapper<T> implements CloudEventDataMapper<PojoCloudEventData<T>> {
|
||||
|
@ -30,7 +32,7 @@ public class PojoCloudEventDataMapper<T> implements CloudEventDataMapper<PojoClo
|
|||
} catch (Exception e) {
|
||||
throw CloudEventRWException.newDataConversion(e, JsonNode.class.toString(), target.getTypeName());
|
||||
}
|
||||
return new PojoCloudEventData<>(mapper, value);
|
||||
return PojoCloudEventData.wrap(value, mapper::writeValueAsBytes);
|
||||
}
|
||||
|
||||
// Worst case, deserialize from bytes
|
||||
|
@ -41,11 +43,12 @@ public class PojoCloudEventDataMapper<T> implements CloudEventDataMapper<PojoClo
|
|||
} catch (Exception e) {
|
||||
throw CloudEventRWException.newDataConversion(e, byte[].class.toString(), target.getTypeName());
|
||||
}
|
||||
return new PojoCloudEventData<>(mapper, value, bytes);
|
||||
return PojoCloudEventData.wrap(value, v -> bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}<T>.
|
||||
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}<T>
|
||||
* using a Jackson {@link ObjectMapper}.
|
||||
*
|
||||
* <p>
|
||||
* When working with generic types (e.g. {@link List}<{@link String}>),
|
||||
|
@ -62,7 +65,8 @@ public class PojoCloudEventDataMapper<T> implements CloudEventDataMapper<PojoClo
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}<T>.
|
||||
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}<T>
|
||||
* using a Jackson {@link ObjectMapper}.
|
||||
*
|
||||
* <p>
|
||||
* This overload is more suitable for mapping generic objects (e.g. {@link List}<{@link String}>),
|
||||
|
|
|
@ -7,8 +7,8 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
|||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.core.CloudEventUtils;
|
||||
import io.cloudevents.core.builder.CloudEventBuilder;
|
||||
import io.cloudevents.core.data.PojoCloudEventData;
|
||||
import io.cloudevents.core.test.Data;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
|
Loading…
Reference in New Issue