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

fix: make optional properties of bindings nullable #89

Merged
merged 25 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
366a2f3
Make optional fields in the Pulsar binding nullable
ullebe1 Feb 7, 2023
8acd340
Make optional field in the Kafka binding nullable
ullebe1 Feb 7, 2023
37daddb
Make optional fields in the HTTP binding nullable
ullebe1 Feb 7, 2023
b503883
Make optional fields in the Websockets binding nullable
ullebe1 Feb 7, 2023
438d2ee
AsyncApiReference is already nullable
ullebe1 Feb 9, 2023
ef0e8a0
TopicConfigurationObject is WriteOptional
ullebe1 Feb 9, 2023
ea5f862
IEnumerable is already nullable
ullebe1 Feb 9, 2023
9b3f44a
RetentionDefinition is WriteOptional
ullebe1 Feb 9, 2023
f32ba66
String is already nullable, and we will be setting a default instead …
ullebe1 Feb 9, 2023
5afa4ef
Add GetScalarValueOrDefault(string defaultValue)
ullebe1 Feb 9, 2023
6eb7278
Parse bindingVersion with a default of "latest" for all bindings
ullebe1 Feb 9, 2023
80e7258
Revert accidental bumping of target framework
ullebe1 Feb 9, 2023
97abe32
add OrDefault versions of scalar value fetching
VisualBean Feb 14, 2023
9eed15c
retract "Default" reading of binding version
VisualBean Feb 14, 2023
9c6d5aa
Bump AsyncApi version
ullebe1 Feb 22, 2023
cf37e51
Put versions in quotes as they're strings per the spec
ullebe1 Feb 22, 2023
973ba60
Add default null tests for Pulsar server bindings
ullebe1 Feb 22, 2023
0ec6026
Add default value tests for Pulsar Bindings
ullebe1 Feb 22, 2023
b936835
Remove "Nullable" from csproj
ullebe1 Feb 27, 2023
b7e0caa
Remove ? from types that are already nullable
ullebe1 Feb 27, 2023
c360285
Revert "Put versions in quotes as they're strings per the spec"
ullebe1 Feb 28, 2023
e6b623a
Since Persistence is an Enum it has to be explicitly nullable or it d…
ullebe1 Feb 28, 2023
acb6913
Merge branch 'main' into ullebe1/optionals_nullable
VisualBean Feb 28, 2023
669017b
Use a shared reference to the binding in the test, rather than findin…
ullebe1 Feb 28, 2023
ff004f8
Merge remote-tracking branch 'origin/ullebe1/optionals_nullable' into…
ullebe1 Feb 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/LEGO.AsyncAPI.Readers/ParseNodes/ParseNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,41 @@ public virtual string GetScalarValue()
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual string GetScalarValueOrDefault(string defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual bool GetBooleanValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual bool? GetBooleanValueOrDefault(bool? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual int GetIntegerValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual int? GetIntegerValueOrDefault(int? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual long GetLongValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual long? GetLongValueOrDefault(long? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual List<IAsyncApiAny> CreateListOfAny()
{
throw new AsyncApiReaderException("Cannot create a list from this type of node.", this.Context);
Expand Down
40 changes: 40 additions & 0 deletions src/LEGO.AsyncAPI.Readers/ParseNodes/ValueNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public override string GetScalarValue()
return this.node.Value;
}

public override string GetScalarValueOrDefault(string defaultValue)
{
if (this.node.Value is not null)
{
return this.node.Value;
}

return defaultValue;
}

public override int GetIntegerValue()
{
if (int.TryParse(this.node.Value, out int value))
Expand All @@ -39,6 +49,16 @@ public override int GetIntegerValue()
throw new AsyncApiReaderException("Value could not parse to integer", this.node);
}

public override int? GetIntegerValueOrDefault(int? defaultValue)
{
if (int.TryParse(this.node.Value, out int value))
{
return value;
}

return defaultValue;
}

public override long GetLongValue()
{
if (long.TryParse(this.node.Value, out long value))
Expand All @@ -49,6 +69,16 @@ public override long GetLongValue()
throw new AsyncApiReaderException("Value could not parse to long", this.node);
}

public override long? GetLongValueOrDefault(long? defaultValue)
{
if (long.TryParse(this.node.Value, out long value))
{
return value;
}

return defaultValue;
}

public override bool GetBooleanValue()
{
if (bool.TryParse(this.node.Value, out bool value))
Expand All @@ -59,6 +89,16 @@ public override bool GetBooleanValue()
throw new AsyncApiReaderException("Value could not parse to bool", this.node);
}

public override bool? GetBooleanValueOrDefault(bool? defaultValue)
{
if (bool.TryParse(this.node.Value, out bool value))
{
return value;
}

return defaultValue;
}

public override IAsyncApiAny CreateAny()
{
var value = this.GetScalarValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal static partial class AsyncApiV2Deserializer
{
private static FixedFieldMap<AsyncApiDocument> asyncApiFixedFields = new()
{
{ "asyncapi", (a, n) => { a.Asyncapi = "2.5.0"; } },
{ "asyncapi", (a, n) => { a.Asyncapi = "2.6.0"; } },
{ "id", (a, n) => a.Id = n.GetScalarValue() },
{ "info", (a, n) => a.Info = LoadInfo(n) },
{ "servers", (a, n) => a.Servers = n.CreateMap(LoadServer) },
Expand Down
1 change: 1 addition & 0 deletions src/LEGO.AsyncAPI/LEGO.AsyncAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<AssemblyName>LEGO.AsyncAPI</AssemblyName>
<RootNamespace>LEGO.AsyncAPI</RootNamespace>
<RepositoryUrl>https://github.com/LEGO/AsyncAPI.NET</RepositoryUrl>
<Nullable>enable</Nullable>
VisualBean marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void SerializeV2(IAsyncApiWriter writer)
writer.WriteStartObject();

// asyncApi
writer.WriteRequiredProperty(AsyncApiConstants.AsyncApi, "2.5.0");
writer.WriteRequiredProperty(AsyncApiConstants.AsyncApi, "2.6.0");

// info
writer.WriteRequiredObject(AsyncApiConstants.Info, this.Info, (w, i) => i.SerializeV2(w));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class HttpMessageBinding : IMessageBinding
/// <summary>
/// A Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type object and have a properties key.
/// </summary>
public AsyncApiSchema Headers { get; set; }
public AsyncApiSchema? Headers { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding. If omitted, "latest" MUST be assumed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public class HttpOperationBinding : IOperationBinding
/// <summary>
/// When type is request, this is the HTTP method, otherwise it MUST be ignored. Its value MUST be one of GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, CONNECT, and TRACE.
/// </summary>
public string Method { get; set; }
public string? Method { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// A Schema object containing the definitions for each query parameter. This schema MUST be of type object and have a properties key.
/// </summary>
public AsyncApiSchema Query { get; set; }
public AsyncApiSchema? Query { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding. If omitted, "latest" MUST be assumed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ public class KafkaChannelBinding : IChannelBinding
/// <summary>
/// Kafka topic name if different from channel name.
/// </summary>
public string Topic { get; set; }
public string? Topic { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Number of partitions configured on this topic (useful to know how many parallel consumers you may run).
/// </summary>
public int Partitions { get; set; }
public int? Partitions { get; set; }

/// <summary>
/// Number of replicas configured on this topic.
/// </summary>
public int Replicas { get; set; }
public int? Replicas { get; set; }

/// <summary>
/// Topic configuration properties that are relevant for the API.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ public class KafkaMessageBinding : IMessageBinding
/// <summary>
/// The message key. NOTE: You can also use the <a href="https://www.asyncapi.com/docs/reference/specification/v2.4.0#referenceObject">reference object</a> way.
/// </summary>
public AsyncApiSchema Key { get; set; }
public AsyncApiSchema? Key { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// If a Schema Registry is used when performing this operation, tells where the id of schema is stored (e.g. header or payload).
/// </summary>
public string SchemaIdLocation { get; set; }
public string? SchemaIdLocation { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Number of bytes or vendor specific values when schema id is encoded in payload (e.g confluent/ apicurio-legacy / apicurio-new).
/// </summary>
public string SchemaIdPayloadEncoding { get; set; }
public string? SchemaIdPayloadEncoding { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied.
/// </summary>
public string SchemaLookupStrategy { get; set; }
public string? SchemaLookupStrategy { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding. If omitted, "latest" MUST be assumed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ public class KafkaOperationBinding : IOperationBinding
/// <summary>
/// Id of the consumer group.
/// </summary>
public AsyncApiSchema GroupId { get; set; }
public AsyncApiSchema? GroupId { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Id of the consumer inside a consumer group.
/// </summary>
public AsyncApiSchema ClientId { get; set; }
public AsyncApiSchema? ClientId { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding. If omitted, "latest" MUST be assumed.
Expand Down
4 changes: 2 additions & 2 deletions src/LEGO.AsyncAPI/Models/Bindings/Kafka/KafkaServerBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ public class KafkaServerBinding : IServerBinding
/// <summary>
/// API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)
/// </summary>
public string SchemaRegistryUrl { get; set; }
public string? SchemaRegistryUrl { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The vendor of Schema Registry and Kafka serdes library that should be used (e.g. apicurio, confluent, ibm, or karapace)
/// </summary>
public string SchemaRegistryVendor { get; set; }
public string? SchemaRegistryVendor { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,27 @@ public class TopicConfigurationObject : IAsyncApiElement
/// <summary>
/// The cleanup.policy configuration option.
/// </summary>
public List<string> CleanupPolicy { get; set; }
public List<string>? CleanupPolicy { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The retention.ms configuration option.
/// </summary>
public int RetentionMiliseconds { get; set; }
public int? RetentionMiliseconds { get; set; }

/// <summary>
/// The retention.bytes configuration option.
/// </summary>
public int RetentionBytes { get; set; }
public int? RetentionBytes { get; set; }

/// <summary>
/// The delete.retention.ms configuration option.
/// </summary>
public int DeleteRetentionMiliseconds { get; set; }
public int? DeleteRetentionMiliseconds { get; set; }

/// <summary>
/// The max.message.bytes configuration option.
/// </summary>
public int MaxMessageBytes { get; set; }
public int? MaxMessageBytes { get; set; }

public void Serialize(IAsyncApiWriter writer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class PulsarChannelBinding : IChannelBinding
/// <summary>
/// Topic compaction threshold given in bytes.
/// </summary>
public int Compaction { get; set; }
public int? Compaction { get; set; }

/// <summary>
/// A list of clusters the topic is replicated to.
Expand All @@ -40,12 +40,12 @@ public class PulsarChannelBinding : IChannelBinding
/// <summary>
/// Message Time-to-live in seconds.
/// </summary>
public int TTL { get; set; }
public int? TTL { get; set; }

/// <summary>
/// When Message deduplication is enabled, it ensures that each message produced on Pulsar topics is persisted to disk only once.
/// </summary>
public bool Deduplication { get; set; }
public bool? Deduplication { get; set; }

/// <summary>
/// The version of this binding.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class PulsarServerBinding : IServerBinding
/// <summary>
/// The pulsar tenant. If omitted, "public" must be assumed.
/// </summary>
public string Tenant { get; set; }
public string? Tenant { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The version of this binding.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ public class WebSocketsChannelBinding : IChannelBinding
/// <summary>
/// The HTTP method t use when establishing the connection. Its value MUST be either 'GET' or 'POST'.
/// </summary>
public string Method { get; set; }
public string? Method { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a 'properties' key.
/// </summary>
public AsyncApiSchema Query { get; set; }
public AsyncApiSchema? Query { get; set; }
VisualBean marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schma MUST be of type 'object' and have a 'properties' key.
/// </summary>
public AsyncApiSchema Headers { get; set; }
public AsyncApiSchema? Headers { get; set; }

public string BindingVersion { get; set; }

Expand Down
8 changes: 4 additions & 4 deletions test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public void AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserializes()
{
// Arrange
var expected =
@"asyncapi: '2.5.0'
@"asyncapi: '2.6.0'
info:
title: Streetlights Kafka API
version: 1.0.0
version: '1.0.0'
description: The Smartylighting Streetlights API allows you to remotely manage the city lights.
license:
name: Apache 2.0
Expand Down Expand Up @@ -699,7 +699,7 @@ public void AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserializes()
public void SerializeV2_WithFullSpec_Serializes()
{
var expected =
@"asyncapi: '2.5.0'
@"asyncapi: '2.6.0'
info:
title: apiTitle
version: apiVersion
Expand Down Expand Up @@ -1129,7 +1129,7 @@ public void SerializeV2_WithFullSpec_Serializes()
[Test]
public void Serializev2_WithBindings_Serializes()
{
var expected = @"asyncapi: '2.5.0'
var expected = @"asyncapi: '2.6.0'
info:
description: test description
servers:
Expand Down
Loading