Added conversion between spec versions
Added copy builder Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
ad5ab5d491
commit
d54dcf7f83
|
@ -60,4 +60,8 @@ public interface Attributes {
|
|||
|
||||
Optional<ZonedDateTime> getTime();
|
||||
|
||||
Attributes toV03();
|
||||
|
||||
Attributes toV1();
|
||||
|
||||
}
|
||||
|
|
|
@ -54,23 +54,23 @@ public interface CloudEvent {
|
|||
*/
|
||||
Map<String, Object> getExtensions();
|
||||
|
||||
/**
|
||||
* Write an extension into this cloud event
|
||||
* @param e
|
||||
*/
|
||||
default void writeExtension(Extension e) {
|
||||
e.writeToEvent(this);
|
||||
}
|
||||
CloudEvent toV03();
|
||||
|
||||
static io.cloudevents.v1.CloudEventBuilder build() {
|
||||
return buildV1();
|
||||
}
|
||||
CloudEvent toV1();
|
||||
|
||||
static io.cloudevents.v1.CloudEventBuilder buildV1() {
|
||||
return new io.cloudevents.v1.CloudEventBuilder();
|
||||
}
|
||||
|
||||
static io.cloudevents.v1.CloudEventBuilder buildV1(CloudEvent event) {
|
||||
return new io.cloudevents.v1.CloudEventBuilder(event);
|
||||
}
|
||||
|
||||
static io.cloudevents.v03.CloudEventBuilder buildV03() {
|
||||
return new io.cloudevents.v03.CloudEventBuilder();
|
||||
}
|
||||
|
||||
static io.cloudevents.v03.CloudEventBuilder buildV03(CloudEvent event) {
|
||||
return new io.cloudevents.v03.CloudEventBuilder(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.cloudevents;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface Extension {
|
||||
|
||||
void readFromEvent(CloudEvent event);
|
||||
|
||||
void writeToEvent(CloudEvent event);
|
||||
Map<String, Object> asMap();
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ package io.cloudevents.extensions;
|
|||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.Extension;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class DistributedTracingExtension implements Extension {
|
||||
|
||||
public static final String TRACEPARENT = "traceparent";
|
||||
|
@ -42,13 +46,11 @@ public final class DistributedTracingExtension implements Extension {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void writeToEvent(CloudEvent event) {
|
||||
if (traceparent != null) {
|
||||
event.getExtensions().put(TRACEPARENT, this.traceparent);
|
||||
}
|
||||
if (tracestate != null) {
|
||||
event.getExtensions().put(TRACESTATE, this.tracestate);
|
||||
}
|
||||
public Map<String, Object> asMap() {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put(TRACEPARENT, this.traceparent);
|
||||
map.put(TRACESTATE, this.tracestate);
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,8 @@ public final class ExtensionsParser {
|
|||
|
||||
private HashMap<Class<?>, Supplier<Extension>> extensionFactories;
|
||||
|
||||
|
||||
// TODO SPI in future?
|
||||
private ExtensionsParser() {
|
||||
this.extensionFactories = new HashMap<>();
|
||||
registerExtension(DistributedTracingExtension.class, DistributedTracingExtension::new);
|
||||
|
|
|
@ -6,9 +6,7 @@ import io.cloudevents.CloudEvent;
|
|||
import io.cloudevents.Extension;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class BaseCloudEventBuilder<B extends BaseCloudEventBuilder<B, T>, T extends Attributes> {
|
||||
|
@ -18,15 +16,25 @@ public abstract class BaseCloudEventBuilder<B extends BaseCloudEventBuilder<B, T
|
|||
|
||||
private Object data;
|
||||
private Map<String, Object> extensions;
|
||||
private List<Extension> materializedExtensions;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BaseCloudEventBuilder() {
|
||||
this.self = (B)this;
|
||||
this.extensions = new HashMap<>();
|
||||
this.materializedExtensions = new ArrayList<>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BaseCloudEventBuilder(CloudEvent event) {
|
||||
this.self = (B)this;
|
||||
|
||||
CloudEventImpl ev = (CloudEventImpl) event;
|
||||
this.setAttributes(ev.getAttributes());
|
||||
this.data = ev.getRawData();
|
||||
this.extensions = new HashMap<>(ev.getExtensions());
|
||||
}
|
||||
|
||||
protected abstract void setAttributes(Attributes attributes);
|
||||
|
||||
protected abstract B withDataContentType(String contentType);
|
||||
|
||||
protected abstract B withDataSchema(URI dataSchema);
|
||||
|
@ -49,15 +57,15 @@ public abstract class BaseCloudEventBuilder<B extends BaseCloudEventBuilder<B, T
|
|||
}
|
||||
|
||||
public B withData(String contentType, URI dataSchema, String data) {
|
||||
return withEncodedata(contentType, dataSchema, (Object) data);
|
||||
return withEncodeData(contentType, dataSchema, (Object) data);
|
||||
}
|
||||
|
||||
public B withData(String contentType, URI dataSchema, byte[] data) {
|
||||
return withEncodedata(contentType, dataSchema, (Object) data);
|
||||
return withEncodeData(contentType, dataSchema, (Object) data);
|
||||
}
|
||||
|
||||
public B withData(String contentType, URI dataSchema, JsonNode data) {
|
||||
return withEncodedata(contentType, dataSchema, (Object) data);
|
||||
return withEncodeData(contentType, dataSchema, (Object) data);
|
||||
}
|
||||
|
||||
public B withExtension(String key, String value) {
|
||||
|
@ -76,19 +84,12 @@ public abstract class BaseCloudEventBuilder<B extends BaseCloudEventBuilder<B, T
|
|||
}
|
||||
|
||||
public B withExtension(Extension extension) {
|
||||
this.materializedExtensions.add(extension);
|
||||
this.extensions.putAll(extension.asMap());
|
||||
return self;
|
||||
}
|
||||
|
||||
public CloudEvent build() {
|
||||
CloudEvent event = new CloudEventImpl(this.buildAttributes(), data, extensions);
|
||||
|
||||
// Write materialized extensions into the event
|
||||
for (Extension ext : this.materializedExtensions) {
|
||||
ext.writeToEvent(event);
|
||||
}
|
||||
|
||||
return event;
|
||||
return new CloudEventImpl(this.buildAttributes(), data, extensions);
|
||||
}
|
||||
|
||||
private B withEncodedData(String contentType, Object data) {
|
||||
|
@ -97,7 +98,7 @@ public abstract class BaseCloudEventBuilder<B extends BaseCloudEventBuilder<B, T
|
|||
return self;
|
||||
}
|
||||
|
||||
private B withEncodedata(String contentType, URI dataSchema, Object data) {
|
||||
private B withEncodeData(String contentType, URI dataSchema, Object data) {
|
||||
withDataContentType(contentType);
|
||||
withDataSchema(dataSchema);
|
||||
this.data = data;
|
||||
|
|
|
@ -13,14 +13,11 @@ import io.cloudevents.json.Json;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
@JsonSerialize(using = CloudEventSerializer.class)
|
||||
@JsonDeserialize(using = CloudEventDeserializer.class)
|
||||
public class CloudEventImpl implements CloudEvent {
|
||||
public final class CloudEventImpl implements CloudEvent {
|
||||
|
||||
private final Attributes attributes;
|
||||
private final Object data;
|
||||
|
@ -109,6 +106,28 @@ public class CloudEventImpl implements CloudEvent {
|
|||
|
||||
@Override
|
||||
public Map<String, Object> getExtensions() {
|
||||
return extensions;
|
||||
return Collections.unmodifiableMap(extensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudEvent toV03() {
|
||||
return new CloudEventImpl(
|
||||
attributes.toV03(),
|
||||
data,
|
||||
extensions
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudEvent toV1() {
|
||||
return new CloudEventImpl(
|
||||
attributes.toV1(),
|
||||
data,
|
||||
extensions
|
||||
);
|
||||
}
|
||||
|
||||
protected Object getRawData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,21 +32,16 @@ import java.util.Optional;
|
|||
public class AttributesImpl implements Attributes {
|
||||
|
||||
private final String id;
|
||||
|
||||
private final URI source;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final ZonedDateTime time;
|
||||
private final URI schemaurl;
|
||||
|
||||
private final String datacontenttype;
|
||||
|
||||
private final String subject;
|
||||
|
||||
AttributesImpl(String id, URI source, String type,
|
||||
ZonedDateTime time, URI schemaurl,
|
||||
String datacontenttype, String subject) {
|
||||
public AttributesImpl(String id, URI source, String type,
|
||||
ZonedDateTime time, URI schemaurl,
|
||||
String datacontenttype, String subject) {
|
||||
this.id = id;
|
||||
this.source = source;
|
||||
this.type = type;
|
||||
|
@ -72,6 +67,25 @@ public class AttributesImpl implements Attributes {
|
|||
public Optional<ZonedDateTime> getTime() {
|
||||
return Optional.ofNullable(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attributes toV03() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attributes toV1() {
|
||||
return new io.cloudevents.v1.AttributesImpl(
|
||||
this.id,
|
||||
this.source,
|
||||
this.type,
|
||||
this.datacontenttype,
|
||||
this.schemaurl,
|
||||
this.subject,
|
||||
this.time
|
||||
);
|
||||
}
|
||||
|
||||
public Optional<URI> getDataSchema() {
|
||||
return getSchemaUrl();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package io.cloudevents.v03;
|
||||
|
||||
import io.cloudevents.Attributes;
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.impl.BaseCloudEventBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -29,20 +31,35 @@ import java.time.ZonedDateTime;
|
|||
*/
|
||||
public final class CloudEventBuilder extends BaseCloudEventBuilder<CloudEventBuilder, AttributesImpl> {
|
||||
|
||||
public CloudEventBuilder() {
|
||||
super();
|
||||
}
|
||||
|
||||
private String id;
|
||||
private URI source;
|
||||
|
||||
private String type;
|
||||
|
||||
private ZonedDateTime time;
|
||||
private URI schemaurl;
|
||||
private String datacontenttype;
|
||||
private String subject;
|
||||
|
||||
public CloudEventBuilder() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CloudEventBuilder(CloudEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAttributes(Attributes attributes) {
|
||||
AttributesImpl attr = (AttributesImpl) attributes.toV03();
|
||||
this
|
||||
.withId(attr.getId())
|
||||
.withSource(attr.getSource())
|
||||
.withType(attr.getType());
|
||||
attr.getDataContentType().ifPresent(this::withDataContentType);
|
||||
attr.getSchemaUrl().ifPresent(this::withSchemaUrl);
|
||||
attr.getSubject().ifPresent(this::withSubject);
|
||||
attr.getTime().ifPresent(this::withTime);
|
||||
}
|
||||
|
||||
public CloudEventBuilder withId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v03.http;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.cloudevents.fun.BinaryFormatAttributeMapper;
|
||||
import io.cloudevents.v03.ContextAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 0.3
|
||||
*/
|
||||
public class AttributeMapper {
|
||||
private AttributeMapper() {}
|
||||
|
||||
static final String HEADER_PREFIX = "ce-";
|
||||
|
||||
/**
|
||||
* Following the signature of {@link BinaryFormatAttributeMapper#map(Map)}
|
||||
* @param headers Map of HTTP request
|
||||
* @return Map with spec attributes and values without parsing
|
||||
* @see ContextAttributes
|
||||
*/
|
||||
public static Map<String, String> map(final Map<String, Object> headers) {
|
||||
Objects.requireNonNull(headers);
|
||||
|
||||
final AtomicReference<Optional<Entry<String, Object>>> ct =
|
||||
new AtomicReference<>();
|
||||
|
||||
ct.set(Optional.empty());
|
||||
|
||||
Map<String, String> result = headers.entrySet()
|
||||
.stream()
|
||||
.filter(header -> null!= header.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue()))
|
||||
.peek(header -> {
|
||||
if("content-type".equals(header.getKey())) {
|
||||
ct.set(Optional.ofNullable(header));
|
||||
}
|
||||
})
|
||||
.filter(header -> header.getKey().startsWith(HEADER_PREFIX))
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.substring(HEADER_PREFIX.length()), header.getValue()))
|
||||
.map(header -> new SimpleEntry<>(header.getKey(),
|
||||
header.getValue().toString()))
|
||||
.collect(toMap(Entry::getKey, Entry::getValue));
|
||||
|
||||
ct.get().ifPresent(contentType -> {
|
||||
result.put(ContextAttributes.DATACONTENTTYPE.name(),
|
||||
contentType.getValue().toString());
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v03.http;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.cloudevents.fun.FormatExtensionMapper;
|
||||
import io.cloudevents.v03.ContextAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 0.3
|
||||
*/
|
||||
public class ExtensionMapper {
|
||||
private ExtensionMapper() {}
|
||||
|
||||
private static final List<String> RESERVED_HEADERS =
|
||||
ContextAttributes.VALUES.stream()
|
||||
.map(attribute -> AttributeMapper
|
||||
.HEADER_PREFIX + attribute)
|
||||
.collect(Collectors.toList());
|
||||
static {
|
||||
RESERVED_HEADERS.add("content-type");
|
||||
};
|
||||
|
||||
/**
|
||||
* Following the signature of {@link FormatExtensionMapper}
|
||||
* @param headers The HTTP headers
|
||||
* @return The potential extensions without parsing
|
||||
*/
|
||||
public static Map<String, String> map(Map<String, Object> headers) {
|
||||
Objects.requireNonNull(headers);
|
||||
|
||||
// remove all reserved words and the remaining may be extensions
|
||||
return
|
||||
headers.entrySet()
|
||||
.stream()
|
||||
.filter(header -> null!= header.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue().toString()))
|
||||
.filter(header -> !RESERVED_HEADERS.contains(header.getKey()))
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v03.http;
|
||||
|
||||
import static io.cloudevents.v03.http.AttributeMapper.HEADER_PREFIX;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.cloudevents.fun.FormatHeaderMapper;
|
||||
import io.cloudevents.v03.ContextAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
*
|
||||
*/
|
||||
public class HeaderMapper {
|
||||
private HeaderMapper() {}
|
||||
|
||||
private static final String HTTP_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
/**
|
||||
* Following the signature of {@link FormatHeaderMapper}
|
||||
* @param attributes The map of attributes created by {@link AttributeMapper}
|
||||
* @param extensions The map of extensions created by {@link ExtensionMapper}
|
||||
* @return The map of HTTP Headers
|
||||
*/
|
||||
public static Map<String, String> map(Map<String, String> attributes,
|
||||
Map<String, String> extensions) {
|
||||
Objects.requireNonNull(attributes);
|
||||
Objects.requireNonNull(extensions);
|
||||
|
||||
Map<String, String> result = attributes.entrySet()
|
||||
.stream()
|
||||
.filter(attribute -> null!= attribute.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue()))
|
||||
.filter(header -> !header.getKey()
|
||||
.equals(ContextAttributes.DATACONTENTTYPE.name()))
|
||||
.map(header -> new SimpleEntry<>(HEADER_PREFIX+header.getKey(),
|
||||
header.getValue()))
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
|
||||
result.putAll(
|
||||
extensions.entrySet()
|
||||
.stream()
|
||||
.filter(extension -> null!= extension.getValue())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
|
||||
);
|
||||
|
||||
Optional.ofNullable(attributes
|
||||
.get(ContextAttributes.DATACONTENTTYPE.name()))
|
||||
.ifPresent((dct) -> {
|
||||
result.put(HTTP_CONTENT_TYPE, dct);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v03.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.extensions.ExtensionFormat;
|
||||
import io.cloudevents.format.BinaryMarshaller;
|
||||
import io.cloudevents.format.StructuredMarshaller;
|
||||
import io.cloudevents.format.Wire;
|
||||
import io.cloudevents.format.builder.EventStep;
|
||||
import io.cloudevents.json.Json;
|
||||
import io.cloudevents.v03.Accessor;
|
||||
import io.cloudevents.v03.AttributesImpl;
|
||||
import io.cloudevents.v03.CloudEventImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 0.3
|
||||
*/
|
||||
public class Marshallers {
|
||||
private Marshallers() {}
|
||||
|
||||
private static final Map<String, String> NO_HEADERS =
|
||||
new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode marshaller to marshal cloud events as JSON for
|
||||
* HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @return A step to provide the {@link CloudEventImpl} and marshal as JSON
|
||||
* @see BinaryMarshaller
|
||||
*/
|
||||
public static <T> EventStep<AttributesImpl, T, String, String> binary() {
|
||||
return
|
||||
BinaryMarshaller.<AttributesImpl, T, String, String>
|
||||
builder()
|
||||
.map(AttributesImpl::marshal)
|
||||
.map(Accessor::extensionsOf)
|
||||
.map(ExtensionFormat::marshal)
|
||||
.map(HeaderMapper::map)
|
||||
.map(Json.<T, String>marshaller()::marshal)
|
||||
.builder(Wire<String, String, String>::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode marshaller to marshal cloud event as JSON for
|
||||
* HTTP Transport Binding
|
||||
* @param <T> The 'data' type
|
||||
* @return A step to provider the {@link CloudEventImpl} and marshal as JSON
|
||||
* @see StructuredMarshaller
|
||||
*/
|
||||
public static <T> EventStep<AttributesImpl, T, String, String> structured() {
|
||||
return
|
||||
StructuredMarshaller.
|
||||
<AttributesImpl, T, String, String>builder()
|
||||
.mime("Content-Type", "application/cloudevents+json")
|
||||
.map((event) -> {
|
||||
return Json.<CloudEvent<AttributesImpl, T>, String>
|
||||
marshaller().marshal(event, NO_HEADERS);
|
||||
})
|
||||
.map(Accessor::extensionsOf)
|
||||
.map(ExtensionFormat::marshal)
|
||||
.map(HeaderMapper::map);
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v03.http;
|
||||
|
||||
import javax.validation.Validator;
|
||||
|
||||
import io.cloudevents.extensions.DistributedTracingExtension;
|
||||
import io.cloudevents.format.BinaryUnmarshaller;
|
||||
import io.cloudevents.format.StructuredUnmarshaller;
|
||||
import io.cloudevents.format.builder.HeadersStep;
|
||||
import io.cloudevents.json.Json;
|
||||
import io.cloudevents.v03.AttributesImpl;
|
||||
import io.cloudevents.v03.CloudEventBuilder;
|
||||
import io.cloudevents.v03.CloudEventImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 0.3
|
||||
*/
|
||||
public class Unmarshallers {
|
||||
private Unmarshallers() {}
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param type The type reference to use for 'data' unmarshal
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see BinaryUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
binary(Class<T> type) {
|
||||
return binary(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param type The type reference to use for 'data' unmarshal
|
||||
* @param validator Provided instance of a {@link Validator}
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see BinaryUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
binary(Class<T> type, Validator validator) {
|
||||
return
|
||||
BinaryUnmarshaller.<AttributesImpl, T, String>builder()
|
||||
.map(AttributeMapper::map)
|
||||
.map(AttributesImpl::unmarshal)
|
||||
.map("application/json", Json.umarshaller(type)::unmarshal)
|
||||
.next()
|
||||
.map(ExtensionMapper::map)
|
||||
.map(DistributedTracingExtension::unmarshall)
|
||||
.next()
|
||||
.builder(CloudEventBuilder.<T>builder().withValidator(validator)::build);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param typeOfData The type reference to use for 'data' unmarshal
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see StructuredUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
structured(Class<T> typeOfData) {
|
||||
return structured(typeOfData, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param typeOfData The type reference to use for 'data' unmarshal
|
||||
* @param validator Provided instance of a {@link Validator}
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see StructuredUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
structured(Class<T> typeOfData, Validator validator) {
|
||||
|
||||
return
|
||||
StructuredUnmarshaller.<AttributesImpl, T, String>
|
||||
builder()
|
||||
.map(ExtensionMapper::map)
|
||||
.map(DistributedTracingExtension::unmarshall)
|
||||
.next()
|
||||
.map((payload, extensions) -> {
|
||||
CloudEventImpl<T> event =
|
||||
Json.<CloudEventImpl<T>>
|
||||
decodeValue(payload, CloudEventImpl.class, typeOfData);
|
||||
|
||||
CloudEventBuilder<T> builder =
|
||||
CloudEventBuilder.<T>builder(event);
|
||||
|
||||
extensions.get().forEach(extension -> {
|
||||
builder.withExtension(extension);
|
||||
});
|
||||
|
||||
return builder.withValidator(validator).build();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -31,17 +31,11 @@ import java.util.Optional;
|
|||
public class AttributesImpl implements Attributes {
|
||||
|
||||
private final String id;
|
||||
|
||||
private final URI source;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final String datacontenttype;
|
||||
|
||||
private final URI dataschema;
|
||||
|
||||
private final String subject;
|
||||
|
||||
private final ZonedDateTime time;
|
||||
|
||||
public AttributesImpl(String id, URI source,
|
||||
|
@ -91,7 +85,25 @@ public class AttributesImpl implements Attributes {
|
|||
return Optional.ofNullable(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Attributes toV03() {
|
||||
return new io.cloudevents.v03.AttributesImpl(
|
||||
this.id,
|
||||
this.source,
|
||||
this.type,
|
||||
this.time,
|
||||
this.dataschema,
|
||||
this.datacontenttype,
|
||||
this.subject
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attributes toV1() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Attibutes V1.0 [id=" + id + ", source=" + source
|
||||
+ ", type=" + type
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.cloudevents.v1;
|
||||
|
||||
import io.cloudevents.Attributes;
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.impl.BaseCloudEventBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -15,7 +17,6 @@ public final class CloudEventBuilder extends BaseCloudEventBuilder<CloudEventBui
|
|||
|
||||
private String id;
|
||||
private URI source;
|
||||
|
||||
private String type;
|
||||
private String datacontenttype;
|
||||
private URI dataschema;
|
||||
|
@ -26,6 +27,23 @@ public final class CloudEventBuilder extends BaseCloudEventBuilder<CloudEventBui
|
|||
super();
|
||||
}
|
||||
|
||||
public CloudEventBuilder(CloudEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAttributes(Attributes attributes) {
|
||||
AttributesImpl attr = (AttributesImpl) attributes.toV1();
|
||||
this
|
||||
.withId(attr.getId())
|
||||
.withSource(attr.getSource())
|
||||
.withType(attr.getType());
|
||||
attr.getDataContentType().ifPresent(this::withDataContentType);
|
||||
attr.getDataSchema().ifPresent(this::withDataSchema);
|
||||
attr.getSubject().ifPresent(this::withSubject);
|
||||
attr.getTime().ifPresent(this::withTime);
|
||||
}
|
||||
|
||||
public CloudEventBuilder withId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v1.http;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.cloudevents.fun.BinaryFormatAttributeMapper;
|
||||
import io.cloudevents.v1.ContextAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AttributeMapper {
|
||||
private AttributeMapper() {}
|
||||
|
||||
static final String HEADER_PREFIX = "ce-";
|
||||
|
||||
/**
|
||||
* Following the signature of {@link BinaryFormatAttributeMapper#map(Map)}
|
||||
* @param headers Map of HTTP request
|
||||
* @return Map with spec attributes and values without parsing
|
||||
* @see ContextAttributes
|
||||
*/
|
||||
public static Map<String, String> map(final Map<String, Object> headers) {
|
||||
Objects.requireNonNull(headers);
|
||||
|
||||
final AtomicReference<Optional<Entry<String, Object>>> ct =
|
||||
new AtomicReference<>();
|
||||
|
||||
ct.set(Optional.empty());
|
||||
|
||||
Map<String, String> result = headers.entrySet()
|
||||
.stream()
|
||||
.filter(header -> null!= header.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue()))
|
||||
.peek(header -> {
|
||||
if("content-type".equals(header.getKey())) {
|
||||
ct.set(Optional.ofNullable(header));
|
||||
}
|
||||
})
|
||||
.filter(header -> header.getKey().startsWith(HEADER_PREFIX))
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.substring(HEADER_PREFIX.length()), header.getValue()))
|
||||
.map(header -> new SimpleEntry<>(header.getKey(),
|
||||
header.getValue().toString()))
|
||||
.collect(toMap(Entry::getKey, Entry::getValue));
|
||||
|
||||
ct.get().ifPresent(contentType -> {
|
||||
result.put(ContextAttributes.DATACONTENTTYPE.name(),
|
||||
contentType.getValue().toString());
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package io.cloudevents.v1.http;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.cloudevents.fun.FormatExtensionMapper;
|
||||
import io.cloudevents.v1.ContextAttributes;
|
||||
import io.cloudevents.v1.http.AttributeMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ExtensionMapper {
|
||||
private ExtensionMapper() {}
|
||||
|
||||
private static final List<String> RESERVED_HEADERS =
|
||||
ContextAttributes.VALUES.stream()
|
||||
.map(attribute -> AttributeMapper
|
||||
.HEADER_PREFIX + attribute)
|
||||
.collect(Collectors.toList());
|
||||
static {
|
||||
RESERVED_HEADERS.add("content-type");
|
||||
};
|
||||
|
||||
/**
|
||||
* Following the signature of {@link FormatExtensionMapper}
|
||||
* @param headers The HTTP headers
|
||||
* @return The potential extensions without parsing
|
||||
*/
|
||||
public static Map<String, String> map(Map<String, Object> headers) {
|
||||
Objects.requireNonNull(headers);
|
||||
|
||||
// remove all reserved words and the remaining may be extensions
|
||||
return
|
||||
headers.entrySet()
|
||||
.stream()
|
||||
.filter(header -> null!= header.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue().toString()))
|
||||
.filter(header -> !RESERVED_HEADERS.contains(header.getKey()))
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v1.http;
|
||||
|
||||
import static io.cloudevents.v1.http.AttributeMapper.HEADER_PREFIX;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.cloudevents.fun.FormatHeaderMapper;
|
||||
import io.cloudevents.v1.ContextAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
*
|
||||
*/
|
||||
public class HeaderMapper {
|
||||
private HeaderMapper() {}
|
||||
|
||||
private static final String HTTP_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
/**
|
||||
* Following the signature of {@link FormatHeaderMapper}
|
||||
* @param attributes The map of attributes created by {@link AttributeMapper}
|
||||
* @param extensions The map of extensions created by {@link ExtensionMapper}
|
||||
* @return The map of HTTP Headers
|
||||
*/
|
||||
public static Map<String, String> map(Map<String, String> attributes,
|
||||
Map<String, String> extensions) {
|
||||
Objects.requireNonNull(attributes);
|
||||
Objects.requireNonNull(extensions);
|
||||
|
||||
Map<String, String> result = attributes.entrySet()
|
||||
.stream()
|
||||
.filter(attribute -> null!= attribute.getValue())
|
||||
.map(header -> new SimpleEntry<>(header.getKey()
|
||||
.toLowerCase(Locale.US), header.getValue()))
|
||||
.filter(header -> !header.getKey()
|
||||
.equals(ContextAttributes.DATACONTENTTYPE.name()))
|
||||
.map(header -> new SimpleEntry<>(HEADER_PREFIX + header.getKey(),
|
||||
header.getValue()))
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
|
||||
result.putAll(
|
||||
extensions.entrySet()
|
||||
.stream()
|
||||
.filter(extension -> null != extension.getValue())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
|
||||
);
|
||||
|
||||
Optional.ofNullable(attributes
|
||||
.get(ContextAttributes.DATACONTENTTYPE.name()))
|
||||
.ifPresent((dct) -> {
|
||||
result.put(HTTP_CONTENT_TYPE, dct);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package io.cloudevents.v1.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.extensions.ExtensionFormat;
|
||||
import io.cloudevents.format.BinaryMarshaller;
|
||||
import io.cloudevents.format.StructuredMarshaller;
|
||||
import io.cloudevents.format.Wire;
|
||||
import io.cloudevents.format.builder.EventStep;
|
||||
import io.cloudevents.json.Json;
|
||||
import io.cloudevents.v1.Accessor;
|
||||
import io.cloudevents.v1.AttributesImpl;
|
||||
import io.cloudevents.v1.CloudEventImpl;
|
||||
import io.cloudevents.v1.http.HeaderMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 1.0
|
||||
*/
|
||||
public class Marshallers {
|
||||
private Marshallers() {}
|
||||
|
||||
private static final Map<String, String> NO_HEADERS =
|
||||
new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode marshaller to marshal cloud events as JSON for
|
||||
* HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @return A step to provide the {@link CloudEventImpl} and marshal as JSON
|
||||
* @see BinaryMarshaller
|
||||
*/
|
||||
public static <T> EventStep<AttributesImpl, T, String, String> binary() {
|
||||
return
|
||||
BinaryMarshaller.<AttributesImpl, T, String, String>
|
||||
builder()
|
||||
.map(AttributesImpl::marshal)
|
||||
.map(Accessor::extensionsOf)
|
||||
.map(ExtensionFormat::marshal)
|
||||
.map(HeaderMapper::map)
|
||||
.map(Json.<T, String>marshaller()::marshal)
|
||||
.builder(Wire::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode marshaller to marshal cloud event as JSON for
|
||||
* HTTP Transport Binding
|
||||
* @param <T> The 'data' type
|
||||
* @return A step to provider the {@link CloudEventImpl} and marshal as JSON
|
||||
* @see StructuredMarshaller
|
||||
*/
|
||||
public static <T> EventStep<AttributesImpl, T, String, String> structured() {
|
||||
return
|
||||
StructuredMarshaller.
|
||||
<AttributesImpl, T, String, String>builder()
|
||||
.mime("Content-Type", "application/cloudevents+json")
|
||||
.map((event) -> Json.<CloudEvent<AttributesImpl, T>, String>
|
||||
marshaller().marshal(event, NO_HEADERS))
|
||||
.map(Accessor::extensionsOf)
|
||||
.map(ExtensionFormat::marshal)
|
||||
.map(HeaderMapper::map);
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 The CloudEvents Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudevents.v1.http;
|
||||
|
||||
import javax.validation.Validator;
|
||||
|
||||
import io.cloudevents.extensions.DistributedTracingExtension;
|
||||
import io.cloudevents.format.BinaryUnmarshaller;
|
||||
import io.cloudevents.format.StructuredUnmarshaller;
|
||||
import io.cloudevents.format.builder.HeadersStep;
|
||||
import io.cloudevents.json.Json;
|
||||
import io.cloudevents.v1.AttributesImpl;
|
||||
import io.cloudevents.v1.CloudEventBuilder;
|
||||
import io.cloudevents.v1.CloudEventImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fabiojose
|
||||
* @version 1.0
|
||||
*/
|
||||
public class Unmarshallers {
|
||||
private Unmarshallers() {}
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param type The type reference to use for 'data' unmarshal
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see BinaryUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
binary(Class<T> type) {
|
||||
return binary(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Binary Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param type The type reference to use for 'data' unmarshal
|
||||
* @param validator Provided instance of a {@link Validator}
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see BinaryUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
binary(Class<T> type, Validator validator) {
|
||||
return
|
||||
BinaryUnmarshaller.<AttributesImpl, T, String>builder()
|
||||
.map(AttributeMapper::map)
|
||||
.map(AttributesImpl::unmarshal)
|
||||
.map("application/json", Json.umarshaller(type)::unmarshal)
|
||||
.next()
|
||||
.map(ExtensionMapper::map)
|
||||
.map(DistributedTracingExtension::unmarshall)
|
||||
.next()
|
||||
.builder(CloudEventBuilder.<T>builder().withValidator(validator)::build);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param typeOfData The type reference to use for 'data' unmarshal
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see StructuredUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
structured(Class<T> typeOfData) {
|
||||
return structured(typeOfData, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Structured Content Mode unmarshaller to unmarshal JSON as CloudEvents data
|
||||
* for HTTP Transport Binding
|
||||
*
|
||||
* @param <T> The 'data' type
|
||||
* @param typeOfData The type reference to use for 'data' unmarshal
|
||||
* @param validator Provided instance of a {@link Validator}
|
||||
* @return A step to supply the headers, payload and to unmarshal
|
||||
* @see StructuredUnmarshaller
|
||||
*/
|
||||
public static <T> HeadersStep<AttributesImpl, T, String>
|
||||
structured(Class<T> typeOfData, Validator validator) {
|
||||
return
|
||||
StructuredUnmarshaller.<AttributesImpl, T, String>
|
||||
builder()
|
||||
.map(ExtensionMapper::map)
|
||||
.map(DistributedTracingExtension::unmarshall)
|
||||
.next()
|
||||
.map((payload, extensions) -> {
|
||||
CloudEventImpl<T> event =
|
||||
Json.<CloudEventImpl<T>>
|
||||
decodeValue(payload, CloudEventImpl.class, typeOfData);
|
||||
|
||||
CloudEventBuilder<T> builder =
|
||||
CloudEventBuilder.<T>builder(event);
|
||||
|
||||
extensions.get().forEach(extension -> {
|
||||
builder.withExtension(extension);
|
||||
});
|
||||
|
||||
return builder.withValidator(validator).build();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -33,8 +33,7 @@ public class DistributedTracingExtensionTest {
|
|||
tracing.setTraceparent("parent");
|
||||
tracing.setTracestate("state");
|
||||
|
||||
CloudEvent event = CloudEvent.build().build();
|
||||
tracing.writeToEvent(event);
|
||||
CloudEvent event = CloudEvent.buildV1().withExtension(tracing).build();
|
||||
|
||||
assertThat(event.getExtensions())
|
||||
.containsEntry(DistributedTracingExtension.TRACEPARENT, "parent")
|
||||
|
@ -43,7 +42,7 @@ public class DistributedTracingExtensionTest {
|
|||
|
||||
@Test
|
||||
public void parseExtension() {
|
||||
CloudEvent event = CloudEvent.build()
|
||||
CloudEvent event = CloudEvent.buildV1()
|
||||
.withExtension(DistributedTracingExtension.TRACEPARENT, "parent")
|
||||
.withExtension(DistributedTracingExtension.TRACESTATE, "state")
|
||||
.build();
|
||||
|
|
Loading…
Reference in New Issue