diff --git a/api/src/main/java/io/cloudevents/format/BinaryMarshaller.java b/api/src/main/java/io/cloudevents/format/BinaryMarshaller.java index 709b900b..0f4132ad 100644 --- a/api/src/main/java/io/cloudevents/format/BinaryMarshaller.java +++ b/api/src/main/java/io/cloudevents/format/BinaryMarshaller.java @@ -1,10 +1,24 @@ +/** + * 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.format; import java.net.URI; +import java.util.Collection; import java.util.Map; -import java.util.Map.Entry; import java.util.function.Supplier; -import java.util.stream.Collectors; import io.cloudevents.Attributes; import io.cloudevents.CloudEvent; @@ -13,8 +27,9 @@ import io.cloudevents.extensions.ExtensionFormat; import io.cloudevents.fun.AttributeMarshaller; import io.cloudevents.fun.BinaryFormatHeaderMapper; import io.cloudevents.fun.DataMarshaller; +import io.cloudevents.fun.ExtensionFormatAccessor; import io.cloudevents.fun.ExtensionMarshaller; -import io.cloudevents.fun.FormatBuilder; +import io.cloudevents.fun.WireBuilder; import io.cloudevents.json.Json; import io.cloudevents.v02.Accessor; import io.cloudevents.v02.AttributesImpl; @@ -27,131 +42,216 @@ import io.cloudevents.v02.http.BinaryFormatHeaderMapperImpl; * @author fabiojose * */ -public class BinaryMarshaller { - - public static EventStep builder() { - return new Builder<>(); - } +public final class BinaryMarshaller { + private BinaryMarshaller() {} - public static interface EventStep { - AttributeMarshalStep - withEvent(Supplier> event); + /** + * Gets a new builder instance + * @param The attributes type + * @param The 'data' type + * @param

The payload type + * @return + */ + public static + AttributeMarshalStep builder() { + + return new Builder(); } - public static interface AttributeMarshalStep { - ExtensionsStep attributes(AttributeMarshaller marshaller); + public static interface AttributeMarshalStep { + /** + * Marshals the {@link Attributes} instance into a + * {@code Map} + * @param marshaller + * @return + */ + ExtensionsAccessorStep map(AttributeMarshaller marshaller); } - public static interface ExtensionsStep { - HeaderMapStep extensions(ExtensionMarshaller marshaller); + public static interface ExtensionsAccessorStep { + + /** + * To get access of internal collection of {@link ExtensionFormat} + * @param accessor + * @return + */ + ExtensionsStep map(ExtensionFormatAccessor accessor); + } - public static interface HeaderMapStep { - PayloadStep headers(BinaryFormatHeaderMapper mapper); + public static interface ExtensionsStep { + /** + * Marshals the collection of {@link ExtensionFormat} into a + * {@code Map} + * @param marshaller + * @return + */ + HeaderMapStep map(ExtensionMarshaller marshaller); } - public static interface PayloadStep { - Build payload(DataMarshaller marshaller); + public static interface HeaderMapStep { + /** + * Marshals the map of attributes and extensions into a map of headers + * @param mapper + * @return + */ + PayloadStep map(BinaryFormatHeaderMapper mapper); } - public static interface Build { - Format

build(FormatBuilder

builder); + public static interface PayloadStep { + /** + * Marshals the 'data' into payload + * @param marshaller + * @return + */ + BuilderStep map(DataMarshaller marshaller); } - public static class Builder implements - EventStep, AttributeMarshalStep, - ExtensionsStep, HeaderMapStep, - PayloadStep, Build { - - private CloudEvent event; - - private Map attributesMap; - - private Map headers; - - private P payload; - - private Map extensionsMap; + public static interface BuilderStep { + /** + * Builds the {@link Wire} to use for wire transfer + * @param builder + * @return + */ + EventStep builder(WireBuilder

builder); + } + + public static interface EventStep { + /** + * Takes the {@link CloudEvent} instance to marshal + * @param event + * @return + */ + Marshaller

withEvent(Supplier> event); + } + + public static interface Marshaller

{ + /** + * Builds an instance of {@link Wire}, doing all the computation at + * this method call. + * @return + */ + Wire

marshal(); + } + + private static final class Builder implements + AttributeMarshalStep, + ExtensionsAccessorStep, + ExtensionsStep, + PayloadStep, + HeaderMapStep, + BuilderStep, + EventStep, + Marshaller

{ + private AttributeMarshaller attributeMarshaller; + private ExtensionFormatAccessor extensionsAccessor; + private ExtensionMarshaller extensionMarshaller; + private BinaryFormatHeaderMapper headerMapper; + private DataMarshaller dataMarshaller; + private WireBuilder

wireBuilder; + private Supplier> eventSupplier; + @Override - public AttributeMarshalStep - withEvent(Supplier> event) { - this.event = event.get(); + public ExtensionsAccessorStep map(AttributeMarshaller marshaller) { + this.attributeMarshaller = marshaller; return this; } @Override - public ExtensionsStep attributes(AttributeMarshaller marshaller) { - this.attributesMap = marshaller.marshal(event.getAttributes()); - return this; - } - - @Override - public HeaderMapStep extensions(ExtensionMarshaller marshaller) { - this.extensionsMap = marshaller.marshal(Accessor.extensionsOf(event)); + public ExtensionsStep map(ExtensionFormatAccessor accessor) { + this.extensionsAccessor = accessor; return this; } @Override - public PayloadStep headers(BinaryFormatHeaderMapper mapper) { - this.headers = mapper.map(attributesMap, extensionsMap); + public HeaderMapStep map(ExtensionMarshaller marshaller) { + this.extensionMarshaller = marshaller; + return this; + } + + @Override + public PayloadStep map(BinaryFormatHeaderMapper mapper) { + this.headerMapper = mapper; + return this; + } + + @Override + public BuilderStep map(DataMarshaller marshaller) { + this.dataMarshaller = marshaller; + return this; + } + + @Override + public EventStep builder(WireBuilder

builder) { + this.wireBuilder = builder; return this; } @Override - public Build payload(DataMarshaller marshaller) { - event.getData().ifPresent((data) -> { - try { - payload = marshaller.marshal(data, headers); - }catch(Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - }); + public Marshaller

withEvent(Supplier> event) { + this.eventSupplier = event; return this; } @Override - public Format

build(FormatBuilder

builder) { - return builder.build(payload, headers); + public Wire

marshal() { + CloudEvent event = eventSupplier.get(); + + Map attributesMap = + attributeMarshaller.marshal(event.getAttributes()); + + Collection extensionsFormat = + extensionsAccessor.extensionsOf(event); + + Map extensionsMap = + extensionMarshaller.marshal(extensionsFormat); + + Map headers = + headerMapper.map(attributesMap, extensionsMap); + + P payload = null; + if(event.getData().isPresent()) { + payload = dataMarshaller.marshal(event.getData().get(), + headers); + } + + return wireBuilder.build(payload, headers); } } public static void main(String[] args) { - - final DistributedTracingExtension dt = new DistributedTracingExtension(); + final DistributedTracingExtension dt = + new DistributedTracingExtension(); dt.setTraceparent("0"); dt.setTracestate("congo=4"); - final ExtensionFormat tracing = new DistributedTracingExtension.Format(dt); - + final ExtensionFormat tracing = + new DistributedTracingExtension.Format(dt); + final CloudEventImpl ce = - CloudEventBuilder.builder() - .withId("x10") - .withSource(URI.create("/source")) - .withType("event-type") - .withSchemaurl(URI.create("/schema")) - .withContenttype("text/plain") - .withExtension(tracing) - .withData("my-data") - .build(); + CloudEventBuilder.builder() + .withId("x10") + .withSource(URI.create("/source")) + .withType("event-type") + .withSchemaurl(URI.create("/schema")) + .withContenttype("text/plain") + .withData("my-data") + .withExtension(tracing) + .build(); - Format format = - BinaryMarshaller.builder() + Wire wire = + BinaryMarshaller.builder() + .map(AttributesImpl::marshal) + .map(Accessor::extensionsOf) + .map(ExtensionFormat::marshal) + .map(BinaryFormatHeaderMapperImpl::map) + .map(Json.marshaller()::marshal) + .builder(Wire::new) .withEvent(() -> ce) - .attributes(AttributesImpl.marshaller()::marshal) - .extensions((extensions) -> { - return extensions.stream() - .map(ExtensionFormat::transport) - .flatMap(t -> t.entrySet().stream()) - .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - }) - .headers(BinaryFormatHeaderMapperImpl.mapper()::map) - .payload(Json.marshaller()::marshal) - .build((payload, headers) -> { - return new Format<>(payload, headers); - }); + .marshal(); - System.out.println(format.getPayload()); - System.out.print(format.getHeaders()); + System.out.println(wire.getPayload()); + System.out.println(wire.getHeaders()); } }