Skip to content

Commit

Permalink
Initial Implementation of XML Format (#448)
Browse files Browse the repository at this point in the history
Signed-off-by: Day, Jeremy(jday) <[email protected]>
Signed-off-by: Jem Day <[email protected]>
  • Loading branch information
JemDay authored Jan 10, 2023
1 parent 40fe91a commit 433ec5b
Show file tree
Hide file tree
Showing 45 changed files with 2,137 additions and 0 deletions.
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.

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;
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

0 comments on commit 433ec5b

Please sign in to comment.