Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
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>> {
Expand All @@ -30,7 +32,7 @@ public PojoCloudEventData<T> map(CloudEventData data) throws CloudEventRWExcepti
} 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
Expand All @@ -41,11 +43,12 @@ public PojoCloudEventData<T> map(CloudEventData data) throws CloudEventRWExcepti
} 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}&lt;T&gt;.
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}&lt;T&gt;
* using a Jackson {@link ObjectMapper}.
*
* <p>
* When working with generic types (e.g. {@link List}&lt;{@link String}&gt;),
Expand All @@ -62,7 +65,8 @@ public static <T> PojoCloudEventDataMapper<T> from(ObjectMapper mapper, Class<T>
}

/**
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}&lt;T&gt;.
* Creates a {@link PojoCloudEventDataMapper} mapping {@link CloudEventData} into {@link PojoCloudEventData}&lt;T&gt;
* using a Jackson {@link ObjectMapper}.
*
* <p>
* This overload is more suitable for mapping generic objects (e.g. {@link List}&lt;{@link String}&gt;),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
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;
Expand Down