Fix the extension marshalling and unmarshalling: Closes #31

Signed-off-by: Fabio José <fabiojose@gmail.com>
This commit is contained in:
Fabio José 2019-08-14 14:19:58 -03:00
parent 2acad53ba8
commit 937a3abe5a
3 changed files with 94 additions and 8 deletions

View File

@ -2,12 +2,18 @@ package io.cloudevents.v02;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@ -25,7 +31,7 @@ import io.cloudevents.json.ZonedDateTimeDeserializer;
*/
@JsonInclude(value = Include.NON_ABSENT)
public class CloudEvent<T> {
@NotBlank
private final String type;
@ -44,10 +50,12 @@ public class CloudEvent<T> {
private final String contenttype;
private final T data;
private final Map<String, Object> extensions;
CloudEvent(String id, URI source, String specversion, String type,
ZonedDateTime time, URI schemaurl, String contenttype,
T data) {
T data, Set<ExtensionFormat> extensions) {
this.id = id;
this.source = source;
@ -59,6 +67,12 @@ public class CloudEvent<T> {
this.contenttype = contenttype;
this.data = data;
this.extensions = extensions
.stream()
.collect(Collectors
.toMap(ExtensionFormat::getKey,
ExtensionFormat::getExtension));
}
public String getType() {
@ -87,6 +101,16 @@ public class CloudEvent<T> {
public Optional<T> getData() {
return Optional.ofNullable(data);
}
@JsonAnyGetter
Map<String, Object> getExtensions() {
return Collections.unmodifiableMap(extensions);
}
@JsonAnySetter
void addExtension(String name, Object value) {
extensions.put(name, value);
}
@JsonCreator
public static <T> CloudEvent<T> build(

View File

@ -4,6 +4,7 @@ import static java.lang.String.format;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -34,6 +35,8 @@ public class CloudEventBuilder<T> {
private String contenttype;
private T data;
private final Set<ExtensionFormat> extensions = new HashSet<>();
private Validator getValidator() {
return Validation.buildDefaultValidatorFactory().getValidator();
}
@ -46,7 +49,7 @@ public class CloudEventBuilder<T> {
*/
public CloudEvent<T> build() {
CloudEvent<T> event = new CloudEvent<>(id, source, SPEC_VERSION, type,
time, schemaurl, contenttype, data);
time, schemaurl, contenttype, data, extensions);
Set<ConstraintViolation<CloudEvent<T>>> violations =
getValidator().validate(event);
@ -100,4 +103,9 @@ public class CloudEventBuilder<T> {
this.data = data;
return this;
}
public CloudEventBuilder<T> withExtension(ExtensionFormat extension) {
this.extensions.add(extension);
return this;
}
}

View File

@ -2,6 +2,7 @@ package io.cloudevents.v02;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.InputStream;
@ -11,6 +12,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import io.cloudevents.extensions.DistributedTracingExtension;
import io.cloudevents.json.Json;
/**
@ -74,10 +76,38 @@ public class CloudEventJacksonTest {
assertTrue(json.contains("my-data"));
}
@Test
public void should_serialize_extension() {
// setup
String expected = "\"distributedTracing\":{\"traceparent\":\"0\",\"tracestate\":\"congo=4\"}";
final DistributedTracingExtension dt = new DistributedTracingExtension();
dt.setTraceparent("0");
dt.setTracestate("congo=4");
final ExtensionFormat tracing = new DistributedTracingExtension.InMemory(dt);
CloudEvent<Object> ce =
new CloudEventBuilder<>()
.withId("x10")
.withSource(URI.create("/source"))
.withType("event-type")
.withSchemaurl(URI.create("/schema"))
.withContenttype("text/plain")
.withData("my-data")
.withExtension(tracing)
.build();
// act
String actual = Json.encode(ce);
// assert
assertTrue(actual.contains(expected));
}
@Test
public void should_have_type() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_aws.json"), CloudEvent.class);
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_new.json"), CloudEvent.class);
// assert
assertEquals("aws.s3.object.created", ce.getType());
@ -86,7 +116,7 @@ public class CloudEventJacksonTest {
@Test
public void should_have_id() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_aws.json"), CloudEvent.class);
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_new.json"), CloudEvent.class);
// assert
assertEquals("C234-1234-1234", ce.getId());
@ -96,7 +126,7 @@ public class CloudEventJacksonTest {
@Test
public void should_have_time() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_aws.json"), CloudEvent.class);
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_new.json"), CloudEvent.class);
// assert
assertTrue(ce.getTime().isPresent());
@ -105,7 +135,7 @@ public class CloudEventJacksonTest {
@Test
public void should_have_source() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_aws.json"), CloudEvent.class);
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_new.json"), CloudEvent.class);
// assert
assertEquals(URI.create("https://serverless.com"), ce.getSource());
@ -124,7 +154,7 @@ public class CloudEventJacksonTest {
@Test
public void should_have_specversion() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_aws.json"), CloudEvent.class);
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_new.json"), CloudEvent.class);
// assert
assertEquals("0.2", ce.getSpecversion());
@ -139,4 +169,28 @@ public class CloudEventJacksonTest {
// act
Json.fromInputStream(resourceOf("02_absent.json"), CloudEvent.class);
}
@Test
public void should_have_tracing_extension() {
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_extension.json"), CloudEvent.class);
// assert
assertNotNull(ce.getExtensions()
.get(DistributedTracingExtension.InMemory.IN_MEMORY_KEY));
}
@Test
public void should_have_custom_extension() {
// setup
String extensionKey = "my-extension";
String expected = "extension-value";
// act
CloudEvent<?> ce = Json.fromInputStream(resourceOf("02_extension.json"), CloudEvent.class);
// assert
assertEquals(expected, ce.getExtensions()
.get(extensionKey));
}
}