diff --git a/CHANGELOG.md b/CHANGELOG.md index df015cbb7..1f5b12924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +## [0.9.1] - 2023-11-13 + +### Changed + +- Fixed a bug where path or query parameters of enum types would not be serialized properly. [microsoft/kiota#3693](https://github.com/microsoft/kiota/issues/3693) + ## [0.9.0] - 2023-11-10 ### Added diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java b/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java index 170705deb..dbd9e73c1 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java @@ -25,6 +25,7 @@ import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.SerializationWriter; +import com.microsoft.kiota.serialization.ValuedEnum; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; @@ -105,9 +106,10 @@ public URI getUri() throws URISyntaxException,IllegalStateException{ throw new IllegalStateException("PathParameters must contain a value for \"baseurl\" for the url to be built."); Map params = new HashMap<>(pathParameters.size() + queryParameters.size()); - params.putAll(pathParameters); + for (final Map.Entry pathParam : pathParameters.entrySet()) { + params.put(pathParam.getKey(), replaceEnumValue(pathParam.getValue())); + } params.putAll(queryParameters); - return new URI(StdUriTemplate.expand(urlTemplate, params)); } @@ -140,7 +142,7 @@ public void addQueryParameters(@Nullable final Object parameters) { final Field[] fields = parameters.getClass().getFields(); for(final Field field : fields) { try { - final Object value = field.get(parameters); + Object value = field.get(parameters); String name = field.getName(); if (field.isAnnotationPresent(QueryParameter.class)) { final String annotationName = field.getAnnotation(QueryParameter.class).name(); @@ -149,6 +151,7 @@ public void addQueryParameters(@Nullable final Object parameters) { } } if(value != null) { + value = replaceEnumValue(value); if(value.getClass().isArray()) { queryParameters.put(name, Arrays.asList((Object[])value)); } else if(!value.toString().isEmpty()){ @@ -160,6 +163,20 @@ public void addQueryParameters(@Nullable final Object parameters) { } } } + private Object replaceEnumValue(@Nonnull final Object source) + { + if (source instanceof ValuedEnum) { + return ((ValuedEnum)source).getValue(); + } else if (source.getClass().isArray() && ((Object[])source).length > 0 && ((Object[])source)[0] instanceof ValuedEnum) { + final ArrayList result = new ArrayList<>(); + for(final Object item : (Object[])source) { + result.add(((ValuedEnum)item).getValue()); + } + return result; + } else { + return source; + } + } /** * Adds query parameters to the request. * @param name The name of the query parameter. diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java index 8182fa448..8eccd7d40 100644 --- a/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java +++ b/components/abstractions/src/test/java/com/microsoft/kiota/RequestInformationTest.java @@ -4,7 +4,10 @@ import com.microsoft.kiota.serialization.SerializationWriter; import com.microsoft.kiota.serialization.SerializationWriterFactory; +import com.microsoft.kiota.serialization.mocks.TestEnum; +import java.net.URI; +import java.net.URISyntaxException; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.ArrayList; @@ -125,7 +128,7 @@ void DoesNotSetQueryParametersParametersIfEmptyCollection() requestInfo.addQueryParameters(queryParameters); // Assert - assertTrue(queryParameters.select.length == 0); + assertEquals(0, queryParameters.select.length); var uriResult = assertDoesNotThrow(() -> requestInfo.getUri()); assertFalse(uriResult.toString().contains("select")); } @@ -230,18 +233,88 @@ void SetsBoundaryOnMultipartBody() { assertFalse(multipartBody.getBoundary().isEmpty()); assertEquals("multipart/form-data; boundary=" + multipartBody.getBoundary(), requestInfo.headers.get("Content-Type").toArray()[0]); } + @Test + void ReplacesEnumSingleValueQueryParameters() throws IllegalStateException, URISyntaxException + { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = "http://localhost/{?dataset}"; + + final GetQueryParameters queryParameters = new GetQueryParameters(); + queryParameters.dataset = TestEnum.First; + // Act + requestInfo.addQueryParameters(queryParameters); + + // Assert + final URI uri = requestInfo.getUri(); + assertEquals("http://localhost/?dataset=1", uri.toString()); + } + @Test + void ReplacesEnumValuesQueryParameters() throws IllegalStateException, URISyntaxException + { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = "http://localhost/{?datasets}"; + + final GetQueryParameters queryParameters = new GetQueryParameters(); + queryParameters.datasets = new TestEnum[] {TestEnum.First, TestEnum.Second}; + // Act + requestInfo.addQueryParameters(queryParameters); + + // Assert + final URI uri = requestInfo.getUri(); + assertEquals("http://localhost/?datasets=1,2", uri.toString()); + } + @Test + void ReplacesEnumSingleValuePathParameters() throws IllegalStateException, URISyntaxException + { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = "http://localhost/{dataset}"; + + // Act + requestInfo.pathParameters.put("dataset", ((Object)(TestEnum.First))); + + // Assert + final URI uri = requestInfo.getUri(); + assertEquals("http://localhost/1", uri.toString()); + } + @Test + void ReplacesEnumValuesPathParameters() throws IllegalStateException, URISyntaxException + { + // Arrange as the request builders would + final RequestInformation requestInfo = new RequestInformation(); + requestInfo.httpMethod = HttpMethod.GET; + requestInfo.urlTemplate = "http://localhost/{datasets}"; + + // Act + requestInfo.pathParameters.put("datasets", ((Object)(new TestEnum[] {TestEnum.First, TestEnum.Second}))); + + // Assert + final URI uri = requestInfo.getUri(); + assertEquals("http://localhost/1,2", uri.toString()); + } } -/// The messages in a mailbox or folder. Read-only. Nullable. +/** The messages in a mailbox or folder. Read-only. Nullable. */ class GetQueryParameters { - /// Select properties to be returned\ + /** Select properties to be returned */ @QueryParameter(name ="%24select") @jakarta.annotation.Nullable public String[] select; - /// Search items by search phrases + /** Search items by search phrases */ @QueryParameter(name ="%24search") @jakarta.annotation.Nullable public String search; + @QueryParameter(name ="dataset") + @jakarta.annotation.Nullable + public TestEnum dataset; + @QueryParameter(name ="datasets") + @jakarta.annotation.Nullable + public TestEnum[] datasets; } \ No newline at end of file diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestEnum.java b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestEnum.java new file mode 100644 index 000000000..375138931 --- /dev/null +++ b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestEnum.java @@ -0,0 +1,24 @@ +package com.microsoft.kiota.serialization.mocks; + +import java.util.Objects; +import com.microsoft.kiota.serialization.ValuedEnum; + +public enum TestEnum implements ValuedEnum { + First("1"), + Second("2"); + public final String value; + TestEnum(final String value) { + this.value = value; + } + @jakarta.annotation.Nonnull + public String getValue() { return this.value; } + @jakarta.annotation.Nullable + public static TestEnum forValue(@jakarta.annotation.Nonnull final String searchValue) { + Objects.requireNonNull(searchValue); + switch(searchValue) { + case "1": return First; + case "2": return Second; + default: return null; + } + } +} diff --git a/gradle.properties b/gradle.properties index 50ae259c3..7cc7749f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ org.gradle.caching=true mavenGroupId = com.microsoft.kiota mavenMajorVersion = 0 mavenMinorVersion = 9 -mavenPatchVersion = 0 +mavenPatchVersion = 1 mavenArtifactSuffix = #These values are used to run functional tests