Skip to content

Commit f216b0d

Browse files
authored
Merge pull request #8 from microsoft/feature/vnd-types
- adds support for vendor specific content types
2 parents 0b0829e + 782b02d commit f216b0d

6 files changed

Lines changed: 63 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Changed
1313

14+
## [1.0.0-preview.2] - 2022-03-29
15+
16+
### Added
17+
18+
- Added support for vendor specific serialization in registries
19+
1420
## [1.0.0-preview.1] - 2022-03-18
1521

1622
### Added

Microsoft.Kiota.Abstractions.Tests/Serialization/ParseNodeFactoryRegistryTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ public void ReturnsExpectedRootNodeForRegisteredContentType()
3939
Assert.NotNull(rootParseNode);
4040
Assert.Equal(mockParseNode.Object, rootParseNode);
4141
}
42+
[Fact]
43+
public void ReturnsExpectedRootNodeForVendorSpecificContentType()
44+
{
45+
// Arrange
46+
var applicationJsonContentType = "application/json";
47+
using var testStream = new MemoryStream(Encoding.UTF8.GetBytes("{\"test\": \"input\"}"));
48+
var mockParseNodeFactory = new Mock<IParseNodeFactory>();
49+
var mockParseNode = new Mock<IParseNode>();
50+
mockParseNodeFactory.Setup(parseNodeFactory => parseNodeFactory.GetRootParseNode(applicationJsonContentType, It.IsAny<Stream>())).Returns(mockParseNode.Object);
51+
_parseNodeFactoryRegistry.ContentTypeAssociatedFactories.Add(applicationJsonContentType, mockParseNodeFactory.Object);
52+
// Act
53+
var rootParseNode = _parseNodeFactoryRegistry.GetRootParseNode("application/vnd+json", testStream);
54+
// Assert
55+
Assert.NotNull(rootParseNode);
56+
Assert.Equal(mockParseNode.Object, rootParseNode);
57+
}
4258

4359
[Fact]
4460
public void ThrowsInvalidOperationExceptionForUnregisteredContentType()

Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationWriterFactoryRegistryTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ public void ReturnsExpectedRootNodeForRegisteredContentType()
3838
Assert.NotNull(serializationWriter);
3939
Assert.Equal(mockSerializationWriter.Object, serializationWriter);
4040
}
41+
[Fact]
42+
public void ReturnsExpectedSerializationWriterForVendorSpecificContentTyp()
43+
{
44+
// Arrange
45+
var applicationJsonContentType = "application/json";
46+
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
47+
var mockSerializationWriter = new Mock<ISerializationWriter>();
48+
mockSerializationWriterFactory.Setup(serializationWriterFactory => serializationWriterFactory.GetSerializationWriter(applicationJsonContentType)).Returns(mockSerializationWriter.Object);
49+
_serializationWriterFactoryRegistry.ContentTypeAssociatedFactories.Add(applicationJsonContentType, mockSerializationWriterFactory.Object);
50+
// Act
51+
var serializationWriter = _serializationWriterFactoryRegistry.GetSerializationWriter("application/vnd+json");
52+
// Assert
53+
Assert.NotNull(serializationWriter);
54+
Assert.Equal(mockSerializationWriter.Object, serializationWriter);
55+
}
4156

4257
[Fact]
4358
public void ThrowsInvalidOperationExceptionForUnregisteredContentType()

src/Microsoft.Kiota.Abstractions.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<EmbedUntrackedSources>true</EmbedUntrackedSources>
1515
<Deterministic>true</Deterministic>
1616
<VersionPrefix>1.0.0</VersionPrefix>
17-
<VersionSuffix>preview.1</VersionSuffix>
17+
<VersionSuffix>preview.2</VersionSuffix>
1818
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1919
<SignAssembly>false</SignAssembly>
2020
<DelaySign>false</DelaySign>
@@ -23,7 +23,7 @@
2323
<!-- Enable this line once we go live to prevent breaking changes -->
2424
<!-- <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion> -->
2525
<PackageReleaseNotes>
26-
- Initial release
26+
- Adds support for vendor specific serialization in registries
2727
</PackageReleaseNotes>
2828
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
2929
<PackageLicenseFile>LICENSE</PackageLicenseFile>

src/serialization/ParseNodeFactoryRegistry.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System;
66
using System.Collections.Generic;
77
using System.IO;
8+
using System.Linq;
9+
using System.Text.RegularExpressions;
810

911
namespace Microsoft.Kiota.Abstractions.Serialization
1012
{
@@ -24,13 +26,14 @@ public string ValidContentType
2426
}
2527
}
2628
/// <summary>
27-
/// Default singleton instance of the registry to be used when registring new factories that should be available by default.
29+
/// Default singleton instance of the registry to be used when registering new factories that should be available by default.
2830
/// </summary>
2931
public static readonly ParseNodeFactoryRegistry DefaultInstance = new();
3032
/// <summary>
3133
/// List of factories that are registered by content type.
3234
/// </summary>
3335
public Dictionary<string, IParseNodeFactory> ContentTypeAssociatedFactories { get; set; } = new Dictionary<string, IParseNodeFactory>();
36+
internal static readonly Regex contentTypeVendorCleanupRegex = new(@"[^/]+\+", RegexOptions.Compiled);
3437
/// <summary>
3538
/// Get the <see cref="IParseNode"/> instance that is the root of the content
3639
/// </summary>
@@ -43,10 +46,15 @@ public IParseNode GetRootParseNode(string contentType, Stream content)
4346
throw new ArgumentNullException(nameof(contentType));
4447
_ = content ?? throw new ArgumentNullException(nameof(content));
4548

46-
if(ContentTypeAssociatedFactories.ContainsKey(contentType))
47-
return ContentTypeAssociatedFactories[contentType].GetRootParseNode(contentType, content);
48-
else
49-
throw new InvalidOperationException($"Content type {contentType} does not have a factory registered to be parsed");
49+
var vendorSpecificContentType = contentType.Split(";", StringSplitOptions.RemoveEmptyEntries).First();
50+
if(ContentTypeAssociatedFactories.ContainsKey(vendorSpecificContentType))
51+
return ContentTypeAssociatedFactories[vendorSpecificContentType].GetRootParseNode(vendorSpecificContentType, content);
52+
53+
var cleanedContentType = contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty);
54+
if(ContentTypeAssociatedFactories.ContainsKey(cleanedContentType))
55+
return ContentTypeAssociatedFactories[cleanedContentType].GetRootParseNode(cleanedContentType, content);
56+
57+
throw new InvalidOperationException($"Content type {cleanedContentType} does not have a factory registered to be parsed");
5058
}
5159
}
5260
}

src/serialization/SerializationWriterFactoryRegistry.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Collections.Generic;
7+
using System.Linq;
78

89
namespace Microsoft.Kiota.Abstractions.Serialization
910
{
@@ -23,7 +24,7 @@ public string ValidContentType
2324
}
2425
}
2526
/// <summary>
26-
/// Default singleton instance of the registry to be used when registring new factories that should be available by default.
27+
/// Default singleton instance of the registry to be used when registering new factories that should be available by default.
2728
/// </summary>
2829
public static readonly SerializationWriterFactoryRegistry DefaultInstance = new();
2930
/// <summary>
@@ -40,10 +41,15 @@ public ISerializationWriter GetSerializationWriter(string contentType)
4041
if(string.IsNullOrEmpty(contentType))
4142
throw new ArgumentNullException(nameof(contentType));
4243

43-
if(ContentTypeAssociatedFactories.ContainsKey(contentType))
44-
return ContentTypeAssociatedFactories[contentType].GetSerializationWriter(contentType);
45-
else
46-
throw new InvalidOperationException($"Content type {contentType} does not have a factory registered to be parsed");
44+
var vendorSpecificContentType = contentType.Split(";", StringSplitOptions.RemoveEmptyEntries).First();
45+
if(ContentTypeAssociatedFactories.ContainsKey(vendorSpecificContentType))
46+
return ContentTypeAssociatedFactories[vendorSpecificContentType].GetSerializationWriter(vendorSpecificContentType);
47+
48+
var cleanedContentType = ParseNodeFactoryRegistry.contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty);
49+
if(ContentTypeAssociatedFactories.ContainsKey(cleanedContentType))
50+
return ContentTypeAssociatedFactories[cleanedContentType].GetSerializationWriter(cleanedContentType);
51+
52+
throw new InvalidOperationException($"Content type {cleanedContentType} does not have a factory registered to be parsed");
4753
}
4854

4955
}

0 commit comments

Comments
 (0)