Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Implementation of XML Format #448

Merged
merged 13 commits into from
Jan 10, 2023
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Javadocs are available on [javadoc.io](https://www.javadoc.io):
- [cloudevents-core](https://www.javadoc.io/doc/io.cloudevents/cloudevents-core)
- [cloudevents-json-jackson](https://www.javadoc.io/doc/io.cloudevents/cloudevents-json-jackson)
- [cloudevents-protobuf](https://www.javadoc.io/doc/io.cloudevents/cloudevents-protobuf)
- [cloudevents-xml](https://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)
- [cloudevents-http-basic](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-basic)
- [cloudevents-http-restful-ws](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
- [cloudevents-http-vertx](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-vertx)
Expand Down
11 changes: 11 additions & 0 deletions api/src/main/java/io/cloudevents/rw/CloudEventRWException.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,15 @@ public static CloudEventRWException newOther(Throwable cause) {
cause
);
}

/**
* An exception for use where none of the other variants are
* appropriate.
*
* @param msg A description error message.
* @return a new {@link CloudEventRWException}
*/
public static CloudEventRWException newOther(String msg){
return new CloudEventRWException(CloudEventRWExceptionKind.OTHER, msg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ public SELF withExtension(@Nonnull String key, @Nonnull String value) {
return self;
}

// @TODO - I think this method should be removed/deprecated
// **Number** Is NOT a valid CE Context atrribute type.

JemDay marked this conversation as resolved.
Show resolved Hide resolved
public SELF withExtension(@Nonnull String key, @Nonnull Number value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
Expand All @@ -132,6 +135,14 @@ public SELF withExtension(@Nonnull String key, @Nonnull Number value) {
return self;
}

public SELF withExtension(@Nonnull String key, @Nonnull Integer value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
}
this.extensions.put(key, value);
return self;
}

public SELF withExtension(@Nonnull String key, @Nonnull Boolean value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
Expand Down
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Using the Java SDK you can:
| - [Jackson](json-jackson.md) | :heavy_check_mark: | :heavy_check_mark: |
| Protobuf Event Format | :heavy_check_mark: | :heavy_check_mark: |
| - [Proto](protobuf.md) | :heavy_check_mark: | :heavy_check_mark: |
| XML Event Format | :heavy_check_mark: | :heavy_check_mark: |
| - [XML](xml.md) | :heavy_check_mark: | :heavy_check_mark: |
| [Kafka Protocol Binding](kafka.md) | :heavy_check_mark: | :heavy_check_mark: |
| MQTT Protocol Binding | :x: | :x: |
| NATS Protocol Binding | :x: | :x: |
Expand Down Expand Up @@ -96,6 +98,7 @@ a different feature from the different sub specs of
[Jackson](https://github.com/FasterXML/jackson)
- [`cloudevents-protobuf`] Implementation of [Protobuf Event format] using code generated
from the standard [protoc](https://github.com/protocolbuffers/protobuf) compiler.
- [`cloudevents-xml`] Implementation of the XML Event Format.
- [`cloudevents-http-vertx`] Implementation of [HTTP Protocol Binding] with
[Vert.x Core](https://vertx.io/)
- [`cloudevents-http-restful-ws`] Implementation of [HTTP Protocol Binding]
Expand Down Expand Up @@ -123,6 +126,7 @@ You can look at the latest published artifacts on
[`cloudevents-core`]: https://github.com/cloudevents/sdk-java/tree/master/core
[`cloudevents-json-jackson`]: https://github.com/cloudevents/sdk-java/tree/master/formats/json-jackson
[`cloudevents-protobuf`]: https://github.com/cloudevents/sdk-java/tree/master/formats/protobuf
[`cloudevents-xml`]: https://github.com/cloudevents/sdk-java/tree/master/formats/xml
[`cloudevents-http-vertx`]: https://github.com/cloudevents/sdk-java/tree/master/http/vertx
[`cloudevents-http-basic`]: https://github.com/cloudevents/sdk-java/tree/master/http/basic
[`cloudevents-http-restful-ws`]: https://github.com/cloudevents/sdk-java/tree/master/http/restful-ws
Expand Down
77 changes: 77 additions & 0 deletions docs/xml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: CloudEvents XML Format
nav_order: 4
---

# CloudEvents XML Format

[![Javadocs](http://www.javadoc.io/badge/io.cloudevents/cloudevents-xml.svg?color=green)](http://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)

This module provides and `EventFormat` implementation that adheres
to the CloudEvent XML Format specification.

This format also supports specialized handling for XML CloudEvent `data`.

For Maven based projects, use the following dependency:

```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-xml</artifactId>
<version>2.4.0</version>
</dependency>
```

## Using the XML Event Format

You don't need to perform any operation to configure the module, more than
adding the dependency to your project:

```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.format.EventFormatProvider;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.xml.XMLFormat;

CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.xml")
.withSource(URI.create("http://localhost"))
.build();

byte[] serialized = EventFormatProvider
.getInstance()
.resolveFormat(XMLFormat.CONTENT_TYPE)
.serialize(event);
```

The `EventFormatProvider` will resolve automatically the `XMLFormat` using the
`ServiceLoader` APIs.

XML Document data handling is supported via the `XMLCloudEventData`
facility. This convenience wrapper can be used with `any` other supported
format.

```java
import org.w3c.dom.Document;
JemDay marked this conversation as resolved.
Show resolved Hide resolved
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.xml.XMLCloudEventData;

// Create the business event data.
Document xmlDoc = .... ;

// Wrap it into CloudEventData
CloudEventData myData = XMLCloudEventData.wrap(xmlDoc);

// Construct the event
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.xml")
.withSource(URI.create("http://localhost"))
.withData(myData)
.build();
```



87 changes: 87 additions & 0 deletions formats/xml/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2021-Present The CloudEvents Authors
~ <p>
~ 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
~ <p>
~ http://www.apache.org/licenses/LICENSE-2.0
~ <p>
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.5.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

<artifactId>cloudevents-xml</artifactId>
<name>CloudEvents - XML Format</name>
<packaging>jar</packaging>

<properties>
<module-name>io.cloudevents.formats.xml</module-name>
<xmlunit.version>2.9.0</xmlunit.version>
<javax.xml.version>2.3.1</javax.xml.version>
</properties>

<dependencies>

<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${javax.xml.version}</version>
</dependency>

<!-- Test deps -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<classifier>tests</classifier>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
<version>${xmlunit.version}</version>
<scope>test</scope>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.xml;

import java.util.HashSet;
import java.util.Set;

/**
* Tracks the occurrences of a key to ensure only a single
* instance is allowed.
*
* Used to help ensure that each CloudEvent context attribute
* only occurs once in each CloudEvent element instance.
*
*/
class OccurrenceTracker {

private final Set<String> keySet;

OccurrenceTracker() {
keySet = new HashSet<>(10);
}

/**
* Record an occurrence of attribute name.
* @param name The name to track.
* @return boolean true => accepted, false => duplicate name.
*/
boolean trackOccurrence(String name) {

return keySet.add(name);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.xml;

import io.cloudevents.CloudEventData;
import org.w3c.dom.Document;

/**
* A variant of {@link CloudEventData} that supports direct access
* to data as an XML {@link Document}
*/
public interface XMLCloudEventData extends CloudEventData {

/**
* Get an XML Document representation of the
* CloudEvent data.
*
* @return The {@link Document} representation.
*/
Document getDocument();

/**
* Wraps an XML {@link Document}
*
* @param xmlDoc {@link Document}
* @return The wrapping {@link XMLCloudEventData}
*/
static CloudEventData wrap(Document xmlDoc) {
return new XMLDataWrapper(xmlDoc);
}
}
Loading