This leads to two different formatters both called
JsonEventFormatter, just in different namespaces. That probably
wouldn't cause too much ambiguity, as few applications would depend
on both packages. It avoids longer names such as
"SystemTextJsonEventFormatter" which is pretty unwieldy.
Both the implementation and the tests are very much based on the
Newtonsoft.Json implementation.
Fixes#42.
Signed-off-by: Jon Skeet <jonskeet@google.com>
Fixes#103, by always delegating to event formatters. (We'll provide
guidance on how those should handle data.)
Signed-off-by: Jon Skeet <jonskeet@google.com>
Rather than the AMQP code "knowing" how to handle different data
types, delegate that to an event formatter.
There's *still* a little bit of an ugly
not-quite-single-responsibility in terms of event formatters;
CloudEvent formats tend to be specified in terms of structured mode
messages, not binary mode. It's possible that we should really
separate out "data formatting" from everything else... but it does
get intertwined in structured mode formats.
This change fixes#104, but we certainly want more testing and
documentation for this code in general.
Signed-off-by: Jon Skeet <jonskeet@google.com>
It feels like you probably always want to specify a topic when creating a message, hence the parameter - but we should probably get feedback for that.
(The one advantage of using inheritance for this was that you could use an object initializer for the whole thing...)
Signed-off-by: Jon Skeet <jonskeet@google.com>
The naming of the "ToAmqpMessage" extension method is to allow multiple message types to have unambiguous names.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This required a bit of rework for the implementation, but the result
is cleaner, in my view.
There's one skipped test, for when an attribute (other than data) is
populated via an integer/Boolean token. We should discuss what we
want to happen in that case.
The extension tests had to change as JsonEventFormatter now
validates that the event it's parsed is valid (for structured mode),
and the ones we were using didn't have a source attribute.
(We will probably want to pepper lots of places with calls to
CloudEvent.Validate, but most of those can come later.)
Signed-off-by: Jon Skeet <jonskeet@google.com>
Once we've hit 2.0, we won't be able to add new abstract methods to
this class, but for the moment it's okay... and it really does make
sense for these methods to be abstract.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This is largely a matter of clarifying responsibilities and adding
documentation to CloudEventFormatter and our current
implementations. Additionally, the content type of the message is
now passed to structured-mode decoding methods to assist with
aspects such as character encodings.
The methods have been renamed to make it clearer that it's the
message that uses structured or binary mode, not the event itself.
(There's no such thing as a "structured mode CloudEvent" or a
"binary mode CloudEvent".)
Signed-off-by: Jon Skeet <jonskeet@google.com>
The spec version is a required attribute - if it's not present, the message isn't a CloudEvent.
The repetitive code here is somewhat annoying, but that's not the only aspect of structured event decoding that has this issue. We may want to revisit this in the future.
Signed-off-by: Jon Skeet <jonskeet@google.com>
In particular, that gives more flexibility over implementations (e.g. not needing to worry about URI or Date tokens in JObject)
Signed-off-by: Jon Skeet <jonskeet@google.com>
We don't expect users to use CloudEventFormatter directly anyway, so
convenience methods aren't really important. If we later decide we
want them, we can put them in the base class instead.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This allows us to remove the Newtonsoft.Json dependency from the
SDK, and implement another event formatter based on System.Text.Json
later on. That should probably wait until we've iterated on the
design of event formatters though.
This commit moves us closer towards (but doesn't fix) #42.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This still leaves a hole where the user created a Uri instance
manually on Linux and it claims to be absolute, but it would
potentially be confusing to spot this in Validate as well...
Signed-off-by: Jon Skeet <jonskeet@google.com>
Each of these classes has 100% coverage just by running their own tests.
There are still some areas of concern:
- .NET's URI parsing and formatting seems hard to predict, so we're not validating as much as I'd like
- There are some interesting questions about CloudEvent behavior which are tested in a "QuestionableBehavior" nested class in CloudEventTest
There's a fair amount of production code changing in here as well, primarily around validation.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This touches almost file in the repository, because it's hard not to
with such a fundamental change.
There are *lots* of TODOs now, all of which we should chase down
before release. In most cases this isn't a new problem - it's just
one that wasn't noted before,
The two main changes are:
- Spec versions, attributes, and attributes types are now first-class
types. Rather than being able to set attributes to any value you
want, values have to be of the right type and have a valid value
(e.g. for datacontenttype). This centralizes value conversion
for the most part (although transport/format-specific conversions
may still be required) and makes everything more predictable.
- Extensions are now *not* first-class types; instead, the extension
attributes can be registered with the CloudEvent in order to perform
appropriate validation etc, and a pattern around extensions
providing extension methods on CloudEvent allows them to be used
easily.
This work has revealed a lot of smaller problems, such as the HTTP
transports propagating a content of "null" (rather than no content)
when no data was set in the CloudEvent. More testing is certainly
required.
It's worth noting that this is a really big breaking change. The 2.0
release was already going to be breaking, but this is much larger
than the previous changes. I assert that the benefits outweight the
costs though, and even though the package already has many users,
we hope there will be many times more users in the future.
Proposed process for this PR:
- This initial commit does not include nearly as many unit tests for
CloudEvent, CloudEventAttribute or CloudEventAttributeType as I'd
like. Those will come in a follow-up commit (which should be
reviewed before merging) but don't affect the review of the overall
ideas.
- If the general thrust of this PR is acceptable, then I propose we
merge it, only making changes to the most egregious problems, and
leaving further clean-up work (of which there's likely to be a lot)
to later PRs. It's easier to create a clean-up PR in Visual Studio
than to suggest fixes via GitHub.
Style changes:
- Use explicit access modifiers
- Move using directives before the namespace declaration
- Unit tests are generally more separated out to correspond to
production classes, and are in separate directories/namespaces
by project instead of all at the top level.
Currently StyleCop is not installed, but we should probably either
do that or use regular Roslyn analyzers in the long term - along
with turning on XML documentation generation.
Signed-off-by: Jon Skeet <jonskeet@google.com>
This commit includes two WithSpecVersion methods, one in CloudEvent
and the other in CloudEventAttributes, which convert from one
version to another. These are currently internal, but we can expose
them later if we wish.
Fixes#65Fixes#66
Creating this commit has raised more issues to discuss:
- CloudEventSpecVersion.Default is a public enum value; changing that
later would be a breaking change in difficult-to-document ways.
- In general, CloudEventSpecVersion feels like it deserves to be a
class with well-known specific instances, rather than an enum. That
would make various things much simpler.
- Given that attributes other than data have a limited set of types,
I suspect it's worth having a CloudEventAttribute type encapsulating
that.
Signed-off-by: Jon Skeet <jonskeet@google.com>
Also, format those timestamps using the Timestamps class introduced previously.
Fixes#61Fixes#57Fixes#48
Signed-off-by: Jon Skeet <jonskeet@google.com>
We can potentially turn the AppVeyor integration down entirely later
on, but at least for now let's make sure packages are pushed manually.
Signed-off-by: Jon Skeet <jonskeet@google.com>
CloudEventContent now *does* map attributes to HTTP headers in
structured mode, including datacontenttype.
This commit also fixes the format of date/time values to be RFC-3339
compliant.
Signed-off-by: Jon Skeet <jonskeet@google.com>
- For structured mode, we shouldn't map attributes to HTTP headers
- For binary mode, we should default the media content type to application/json
- UrlEncode and UrlDecode headers in binary mode
- Adds more testing of headers
Fixes#67 and #69.
Signed-off-by: Jon Skeet <jonskeet@google.com>