Skip to content

Commit 433ec5b

Browse files
authored
Initial Implementation of XML Format (#448)
Signed-off-by: Day, Jeremy(jday) <[email protected]> Signed-off-by: Jem Day <[email protected]>
1 parent 40fe91a commit 433ec5b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2137
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Javadocs are available on [javadoc.io](https://www.javadoc.io):
6565
- [cloudevents-core](https://www.javadoc.io/doc/io.cloudevents/cloudevents-core)
6666
- [cloudevents-json-jackson](https://www.javadoc.io/doc/io.cloudevents/cloudevents-json-jackson)
6767
- [cloudevents-protobuf](https://www.javadoc.io/doc/io.cloudevents/cloudevents-protobuf)
68+
- [cloudevents-xml](https://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)
6869
- [cloudevents-http-basic](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-basic)
6970
- [cloudevents-http-restful-ws](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
7071
- [cloudevents-http-vertx](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-vertx)

api/src/main/java/io/cloudevents/rw/CloudEventRWException.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,15 @@ public static CloudEventRWException newOther(Throwable cause) {
216216
cause
217217
);
218218
}
219+
220+
/**
221+
* An exception for use where none of the other variants are
222+
* appropriate.
223+
*
224+
* @param msg A description error message.
225+
* @return a new {@link CloudEventRWException}
226+
*/
227+
public static CloudEventRWException newOther(String msg){
228+
return new CloudEventRWException(CloudEventRWExceptionKind.OTHER, msg);
229+
}
219230
}

core/src/main/java/io/cloudevents/core/impl/BaseCloudEventBuilder.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public SELF withExtension(@Nonnull String key, @Nonnull String value) {
124124
return self;
125125
}
126126

127+
// @TODO - I think this method should be removed/deprecated
128+
// **Number** Is NOT a valid CE Context atrribute type.
129+
127130
public SELF withExtension(@Nonnull String key, @Nonnull Number value) {
128131
if (!isValidExtensionName(key)) {
129132
throw CloudEventRWException.newInvalidExtensionName(key);
@@ -132,6 +135,14 @@ public SELF withExtension(@Nonnull String key, @Nonnull Number value) {
132135
return self;
133136
}
134137

138+
public SELF withExtension(@Nonnull String key, @Nonnull Integer value) {
139+
if (!isValidExtensionName(key)) {
140+
throw CloudEventRWException.newInvalidExtensionName(key);
141+
}
142+
this.extensions.put(key, value);
143+
return self;
144+
}
145+
135146
public SELF withExtension(@Nonnull String key, @Nonnull Boolean value) {
136147
if (!isValidExtensionName(key)) {
137148
throw CloudEventRWException.newInvalidExtensionName(key);

docs/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Using the Java SDK you can:
4242
| - [Jackson](json-jackson.md) | :heavy_check_mark: | :heavy_check_mark: |
4343
| Protobuf Event Format | :heavy_check_mark: | :heavy_check_mark: |
4444
| - [Proto](protobuf.md) | :heavy_check_mark: | :heavy_check_mark: |
45+
| XML Event Format | :heavy_check_mark: | :heavy_check_mark: |
46+
| - [XML](xml.md) | :heavy_check_mark: | :heavy_check_mark: |
4547
| [Kafka Protocol Binding](kafka.md) | :heavy_check_mark: | :heavy_check_mark: |
4648
| MQTT Protocol Binding | :x: | :x: |
4749
| NATS Protocol Binding | :x: | :x: |
@@ -96,6 +98,7 @@ a different feature from the different sub specs of
9698
[Jackson](https://github.com/FasterXML/jackson)
9799
- [`cloudevents-protobuf`] Implementation of [Protobuf Event format] using code generated
98100
from the standard [protoc](https://github.com/protocolbuffers/protobuf) compiler.
101+
- [`cloudevents-xml`] Implementation of the XML Event Format.
99102
- [`cloudevents-http-vertx`] Implementation of [HTTP Protocol Binding] with
100103
[Vert.x Core](https://vertx.io/)
101104
- [`cloudevents-http-restful-ws`] Implementation of [HTTP Protocol Binding]
@@ -123,6 +126,7 @@ You can look at the latest published artifacts on
123126
[`cloudevents-core`]: https://github.com/cloudevents/sdk-java/tree/master/core
124127
[`cloudevents-json-jackson`]: https://github.com/cloudevents/sdk-java/tree/master/formats/json-jackson
125128
[`cloudevents-protobuf`]: https://github.com/cloudevents/sdk-java/tree/master/formats/protobuf
129+
[`cloudevents-xml`]: https://github.com/cloudevents/sdk-java/tree/master/formats/xml
126130
[`cloudevents-http-vertx`]: https://github.com/cloudevents/sdk-java/tree/master/http/vertx
127131
[`cloudevents-http-basic`]: https://github.com/cloudevents/sdk-java/tree/master/http/basic
128132
[`cloudevents-http-restful-ws`]: https://github.com/cloudevents/sdk-java/tree/master/http/restful-ws

docs/xml.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: CloudEvents XML Format
3+
nav_order: 4
4+
---
5+
6+
# CloudEvents XML Format
7+
8+
[![Javadocs](http://www.javadoc.io/badge/io.cloudevents/cloudevents-xml.svg?color=green)](http://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)
9+
10+
This module provides and `EventFormat` implementation that adheres
11+
to the CloudEvent XML Format specification.
12+
13+
This format also supports specialized handling for XML CloudEvent `data`.
14+
15+
For Maven based projects, use the following dependency:
16+
17+
```xml
18+
<dependency>
19+
<groupId>io.cloudevents</groupId>
20+
<artifactId>cloudevents-xml</artifactId>
21+
<version>2.4.0</version>
22+
</dependency>
23+
```
24+
25+
## Using the XML Event Format
26+
27+
You don't need to perform any operation to configure the module, more than
28+
adding the dependency to your project:
29+
30+
```java
31+
import io.cloudevents.CloudEvent;
32+
import io.cloudevents.core.format.EventFormatProvider;
33+
import io.cloudevents.core.builder.CloudEventBuilder;
34+
import io.cloudevents.xml.XMLFormat;
35+
36+
CloudEvent event = CloudEventBuilder.v1()
37+
.withId("hello")
38+
.withType("example.xml")
39+
.withSource(URI.create("http://localhost"))
40+
.build();
41+
42+
byte[] serialized = EventFormatProvider
43+
.getInstance()
44+
.resolveFormat(XMLFormat.CONTENT_TYPE)
45+
.serialize(event);
46+
```
47+
48+
The `EventFormatProvider` will resolve automatically the `XMLFormat` using the
49+
`ServiceLoader` APIs.
50+
51+
XML Document data handling is supported via the `XMLCloudEventData`
52+
facility. This convenience wrapper can be used with `any` other supported
53+
format.
54+
55+
```java
56+
import org.w3c.dom.Document;
57+
import io.cloudevents.CloudEvent;
58+
import io.cloudevents.core.builder.CloudEventBuilder;
59+
import io.cloudevents.xml.XMLCloudEventData;
60+
61+
// Create the business event data.
62+
Document xmlDoc = .... ;
63+
64+
// Wrap it into CloudEventData
65+
CloudEventData myData = XMLCloudEventData.wrap(xmlDoc);
66+
67+
// Construct the event
68+
CloudEvent event = CloudEventBuilder.v1()
69+
.withId("hello")
70+
.withType("example.xml")
71+
.withSource(URI.create("http://localhost"))
72+
.withData(myData)
73+
.build();
74+
```
75+
76+
77+

formats/xml/pom.xml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2021-Present The CloudEvents Authors
4+
~ <p>
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~ <p>
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~ <p>
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
~
17+
-->
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<parent>
24+
<groupId>io.cloudevents</groupId>
25+
<artifactId>cloudevents-parent</artifactId>
26+
<version>2.5.0-SNAPSHOT</version>
27+
<relativePath>../../pom.xml</relativePath>
28+
</parent>
29+
30+
<artifactId>cloudevents-xml</artifactId>
31+
<name>CloudEvents - XML Format</name>
32+
<packaging>jar</packaging>
33+
34+
<properties>
35+
<module-name>io.cloudevents.formats.xml</module-name>
36+
<xmlunit.version>2.9.0</xmlunit.version>
37+
<javax.xml.version>2.3.1</javax.xml.version>
38+
</properties>
39+
40+
<dependencies>
41+
42+
<dependency>
43+
<groupId>io.cloudevents</groupId>
44+
<artifactId>cloudevents-core</artifactId>
45+
<version>${project.version}</version>
46+
</dependency>
47+
48+
<dependency>
49+
<groupId>javax.xml.bind</groupId>
50+
<artifactId>jaxb-api</artifactId>
51+
<version>${javax.xml.version}</version>
52+
</dependency>
53+
54+
<!-- Test deps -->
55+
<dependency>
56+
<groupId>org.junit.jupiter</groupId>
57+
<artifactId>junit-jupiter</artifactId>
58+
<version>${junit-jupiter.version}</version>
59+
<scope>test</scope>
60+
</dependency>
61+
62+
<dependency>
63+
<groupId>org.assertj</groupId>
64+
<artifactId>assertj-core</artifactId>
65+
<version>${assertj-core.version}</version>
66+
<scope>test</scope>
67+
</dependency>
68+
69+
<dependency>
70+
<groupId>io.cloudevents</groupId>
71+
<artifactId>cloudevents-core</artifactId>
72+
<classifier>tests</classifier>
73+
<type>test-jar</type>
74+
<version>${project.version}</version>
75+
<scope>test</scope>
76+
</dependency>
77+
78+
<dependency>
79+
<groupId>org.xmlunit</groupId>
80+
<artifactId>xmlunit-core</artifactId>
81+
<version>${xmlunit.version}</version>
82+
<scope>test</scope>
83+
</dependency>
84+
85+
</dependencies>
86+
87+
</project>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2018-Present The CloudEvents Authors
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package io.cloudevents.xml;
19+
20+
import java.util.HashSet;
21+
import java.util.Set;
22+
23+
/**
24+
* Tracks the occurrences of a key to ensure only a single
25+
* instance is allowed.
26+
*
27+
* Used to help ensure that each CloudEvent context attribute
28+
* only occurs once in each CloudEvent element instance.
29+
*
30+
*/
31+
class OccurrenceTracker {
32+
33+
private final Set<String> keySet;
34+
35+
OccurrenceTracker() {
36+
keySet = new HashSet<>(10);
37+
}
38+
39+
/**
40+
* Record an occurrence of attribute name.
41+
* @param name The name to track.
42+
* @return boolean true => accepted, false => duplicate name.
43+
*/
44+
boolean trackOccurrence(String name) {
45+
46+
return keySet.add(name);
47+
48+
}
49+
50+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2018-Present The CloudEvents Authors
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package io.cloudevents.xml;
19+
20+
import io.cloudevents.CloudEventData;
21+
import org.w3c.dom.Document;
22+
23+
/**
24+
* A variant of {@link CloudEventData} that supports direct access
25+
* to data as an XML {@link Document}
26+
*/
27+
public interface XMLCloudEventData extends CloudEventData {
28+
29+
/**
30+
* Get an XML Document representation of the
31+
* CloudEvent data.
32+
*
33+
* @return The {@link Document} representation.
34+
*/
35+
Document getDocument();
36+
37+
/**
38+
* Wraps an XML {@link Document}
39+
*
40+
* @param xmlDoc {@link Document}
41+
* @return The wrapping {@link XMLCloudEventData}
42+
*/
43+
static CloudEventData wrap(Document xmlDoc) {
44+
return new XMLDataWrapper(xmlDoc);
45+
}
46+
}

0 commit comments

Comments
 (0)