diff --git a/CHANGELOG.md b/CHANGELOG.md index 40f8ac5eb..8f1d88685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +## [0.4.6] - 2023-07-20 + +### Added + +- Adds the `PeriodAndDuration` type to aggregate `Period` and `Duration` serialization + +### Changed + +- Drops the `getPeriodValue` function in favour of `getPeriodAndDurationValue` in the serialization interface. +- Drops the `writePeriodValue` function in favour of `writePeriodAndDurationValue` in the serialization interface. + ## [0.4.5] - 2023-06-27 ### Changed diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/ApiException.java b/components/abstractions/src/main/java/com/microsoft/kiota/ApiException.java index 7885199b9..2f1978b53 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/ApiException.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/ApiException.java @@ -30,13 +30,19 @@ public ApiException(@Nonnull final Throwable cause) { @Nonnull private ResponseHeaders responseHeaders = new ResponseHeaders(); - /** Gets the HTTP response headers for the error response */ + /** + * Gets the HTTP response headers for the error response + * @return The response headers collections from the failed response. + */ @Nonnull public ResponseHeaders getResponseHeaders() { return new ResponseHeaders(responseHeaders); } - /** Sets the HTTP response headers for the error response */ + /** + * Sets the HTTP response headers for the error response + * @param responseHeaders The response headers collections to set. + */ public void setResponseHeaders(@Nonnull ResponseHeaders responseHeaders) { Objects.requireNonNull(responseHeaders); this.responseHeaders = new ResponseHeaders(responseHeaders); diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/CaseInsensitiveMap.java b/components/abstractions/src/main/java/com/microsoft/kiota/CaseInsensitiveMap.java index 17254816b..952f668b4 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/CaseInsensitiveMap.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/CaseInsensitiveMap.java @@ -16,6 +16,11 @@ class CaseInsensitiveMap implements Map>{ private final HashMap> internalMap = new HashMap<>(); + /** + * Formats the string to lower case + * @param key string to normalize to lower case + * @return The normalized string + */ protected String normalizeKey(@Nonnull final String key) { Objects.requireNonNull(key); return key.toLowerCase(Locale.ROOT); diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/NativeResponseHandler.java b/components/abstractions/src/main/java/com/microsoft/kiota/NativeResponseHandler.java index 5e1e81e0f..ac7de2e11 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/NativeResponseHandler.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/NativeResponseHandler.java @@ -9,6 +9,10 @@ import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.ParsableFactory; + +/** + * The {@code ResponseHandler} implementation to handle native response objects + */ public class NativeResponseHandler implements ResponseHandler { private Object value; private HashMap> errorMappings; diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/PeriodAndDuration.java b/components/abstractions/src/main/java/com/microsoft/kiota/PeriodAndDuration.java new file mode 100644 index 000000000..40923c4ec --- /dev/null +++ b/components/abstractions/src/main/java/com/microsoft/kiota/PeriodAndDuration.java @@ -0,0 +1,263 @@ +package com.microsoft.kiota; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.Immutable; +import java.io.Serializable; +import java.time.Duration; +import java.time.Period; +import java.time.temporal.ChronoUnit; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalUnit; +import java.time.temporal.UnsupportedTemporalTypeException; +import java.util.Collections; +import java.util.Objects; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; + +import static java.time.temporal.ChronoUnit.YEARS; +import static java.time.temporal.ChronoUnit.MONTHS; +import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.HOURS; +import static java.time.temporal.ChronoUnit.MINUTES; +import static java.time.temporal.ChronoUnit.SECONDS; +import static java.time.temporal.ChronoUnit.NANOS; + + +/** + * The aggregate type for {@code Period} and {@code Duration } + */ +@Immutable +public final class PeriodAndDuration implements TemporalAmount, Comparable, Serializable { + + /** + * A constant for a duration of zero. + */ + public static final PeriodAndDuration ZERO = new PeriodAndDuration(Period.ZERO, Duration.ZERO); + + /** + * The period. + */ + private final Period period; + + /** + * Gets the period section of the type. + * @return the period section + */ + @Nonnull + public Period getPeriod() { + return period; + } + + /** + * The duration. + */ + private final Duration duration; + /** + * Gets the duration section of the type. + * @return the duration section + */ + @Nonnull + public Duration getDuration() { + return duration; + } + + /** + * Non-public Constructor for PeriodAndDuration + * @param period The {@code Period} component of the aggregate type + * @param duration The {@code Duration } component of the aggregate type + */ + private PeriodAndDuration(@Nonnull Period period, @Nonnull Duration duration) { + Objects.requireNonNull(period, "parameter period cannot be null"); + Objects.requireNonNull(duration, "parameter duration cannot be null"); + this.period = period; + this.duration = duration; + } + + /** + * Creates an instance based on a period and duration. + * @param period the {@code Period}, not null + * @param duration the {@code Duration}, not null + * @return the combined {@code PeriodAndDuration}, not null + */ + @Nonnull + public static PeriodAndDuration of(@Nonnull Period period, @Nonnull Duration duration) { + Objects.requireNonNull(period, "parameter period cannot be null"); + Objects.requireNonNull(duration, "parameter duration cannot be null"); + return new PeriodAndDuration(period, duration); + } + + /** + * Creates an instance based on a period. + * @param period the {@code Period}, not null + * @return the combined {@code PeriodAndDuration}, not null + */ + @Nonnull + public static PeriodAndDuration ofPeriod(@Nonnull Period period) { + Objects.requireNonNull(period, "parameter period cannot be null"); + return new PeriodAndDuration(period, Duration.ZERO); + } + + /** + * Creates an instance based on a duration. + * @param duration the {@code Duration}, not null + * @return the combined {@code PeriodAndDuration}, not null + */ + @Nonnull + public static PeriodAndDuration ofDuration(@Nonnull Duration duration) { + Objects.requireNonNull(duration, "parameter duration cannot be null"); + return new PeriodAndDuration(Period.ZERO, duration); + } + + /** + * @param stringValue the {@code String} parse from. + * @return parsed instance of {@code PeriodAndDuration} + */ + @Nonnull + public static PeriodAndDuration parse(@Nonnull String stringValue) { + Objects.requireNonNull(stringValue, "parameter stringValue cannot be null"); + + if (stringValue.substring(0,3).contains("PT")) {// it is only a duration value as it starts with 'PT', '+PT' or, '-PT' + return PeriodAndDuration.ofDuration(Duration.parse(stringValue)); + } + int timePosition = stringValue.indexOf("T"); + if (timePosition < 0) {// only a period value as there is no time component + return PeriodAndDuration.ofPeriod(Period.parse(stringValue)); + } + + String sign = ""; + if (stringValue.charAt(0) == '-') { + sign = "-"; + }// no need for checking the `+` sign as this is the default + + Period period = Period.parse(stringValue.substring(0, timePosition));//sign will be passed and parsed + Duration duration = Duration.parse(sign + "P" + stringValue.substring(timePosition));// pass the negative if need be + return PeriodAndDuration.of(period, duration); + } + + /** + * @param periodAndDuration the {@code PeriodAndDuration} for which to compare to + * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. + */ + @Override + public int compareTo(@Nonnull PeriodAndDuration periodAndDuration) { + Objects.requireNonNull(periodAndDuration, "parameter periodAndDuration cannot be null"); + + if(this.equals(periodAndDuration)) { + return 0;//they are the same/equal + } + + if(this.period.equals(periodAndDuration.getPeriod())) {// same period so just compare the durations + return this.duration.compareTo(periodAndDuration.getDuration()); + } + + // just check if the difference in the period is negative as this makes the duration moot + if(this.period.minus(periodAndDuration.getPeriod()).isNegative()) { + return -1;//this period is smaller. So duration won't count + }else { + return 1; + } + } + + /** + * @param unit the {@code TemporalUnit} for which to return the value + * @return the long value of the unit + */ + @Override + public long get(@Nonnull TemporalUnit unit) { + Objects.requireNonNull(unit, "parameter unit cannot be null"); + if (unit instanceof ChronoUnit) { + switch ((ChronoUnit) unit) { + case YEARS: + return period.getYears(); + case MONTHS: + return period.getMonths(); + case DAYS: + return period.getDays(); + case HOURS: + return duration.toHours() % 24; + case MINUTES: + return duration.toMinutes() % 60; + case SECONDS: + return duration.getSeconds() % 60; + case NANOS: + return duration.getNano(); + default: + break; + } + } + throw new UnsupportedTemporalTypeException("Unsupported TemporalUnit of type: " + unit); + } + + private static final List UNITS = Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS, HOURS, MINUTES, SECONDS, NANOS)); + /** + * @return the List of TemporalUnits; not null + */ + @Override + public List getUnits() { + return new ArrayList<>(UNITS); + } + + /** + * @param temporal the temporal object to add the amount to, not null + * @return an object of the same observable type with the addition made, not null + */ + @Override + public Temporal addTo(@Nonnull Temporal temporal) { + Objects.requireNonNull(temporal, "parameter temporal cannot be null"); + return temporal.plus(period).plus(duration);//just add everything up + } + + /** + * @param temporal the temporal object to subtract the amount from, not null + * @return an object of the same observable type with the subtraction made, not null + */ + @Override + public Temporal subtractFrom(@Nonnull Temporal temporal) { + Objects.requireNonNull(temporal, "parameter temporal cannot be null"); + return temporal.minus(period).minus(duration);//just subtract everything up + } + + /** + * Returns a string representation of the instance in the ISO-8601 format 'PnYnMnDTnHnMnS'. + * @return the period in ISO-8601 string format + */ + @Override + public String toString() { + if (period.isZero()) { + return duration.toString(); + } + if (duration.isZero()) { + return period.toString(); + } + //simply concatenate and drop the first `P` in the duration + return period + duration.toString().substring(1); + } + + /** + * Gets the hashcode for the object. + * @return The hashCode of the object + */ + @Override + public int hashCode() { + return period.hashCode() + duration.hashCode(); + } + /** + * Checks if this instance is equal to the specified {@code PeriodAndDuration}. + * @param otherPeriodAndDuration the other Object, null returns false + * @return true if the other otherPeriodAndDuration is equal to this one + */ + @Override + public boolean equals(Object otherPeriodAndDuration) { + if(this == otherPeriodAndDuration) { + return true; // same instance + } + + if (otherPeriodAndDuration instanceof PeriodAndDuration) { + PeriodAndDuration otherInstance = (PeriodAndDuration) otherPeriodAndDuration; + return this.period.equals(otherInstance.period) && this.duration.equals(otherInstance.duration); + } + return false; + } +} diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/QueryParameter.java b/components/abstractions/src/main/java/com/microsoft/kiota/QueryParameter.java index 9a9cddabd..a3eafed09 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/QueryParameter.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/QueryParameter.java @@ -5,7 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/* +/** * This annotation allows mapping between the query parameter name in the template and the property name in the class. */ @Retention(RetentionPolicy.RUNTIME) diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/RequestHeaders.java b/components/abstractions/src/main/java/com/microsoft/kiota/RequestHeaders.java index ccb62fd23..4bea13aa8 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/RequestHeaders.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/RequestHeaders.java @@ -10,8 +10,11 @@ public class RequestHeaders extends Headers { public RequestHeaders() { super(); } - - /** Copy constructor */ + + /** + * Copy constructor + * @param requestHeaders The request headers to initialize with. + */ public RequestHeaders(@Nonnull RequestHeaders requestHeaders) { super(requestHeaders); } 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 adfcdcedd..da31f1d53 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java @@ -18,7 +18,6 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import javax.annotation.Nonnull; @@ -305,8 +304,8 @@ else if(valueClass.equals(LocalDate.class)) writer.writeLocalDateValue(null, (LocalDate)value); else if(valueClass.equals(LocalTime.class)) writer.writeLocalTimeValue(null, (LocalTime)value); - else if(valueClass.equals(Period.class)) - writer.writePeriodValue(null, (Period)value); + else if(valueClass.equals(PeriodAndDuration.class)) + writer.writePeriodAndDurationValue(null, (PeriodAndDuration)value); else { final RuntimeException result = new RuntimeException("unknown type to serialize " + valueClass.getName()); span.recordException(result); diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/ResponseHeaders.java b/components/abstractions/src/main/java/com/microsoft/kiota/ResponseHeaders.java index eb497ea97..dd82d864b 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/ResponseHeaders.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/ResponseHeaders.java @@ -11,7 +11,10 @@ public ResponseHeaders() { super(); } - /** Copy constructor */ + /** + * Copy constructor + * @param responseHeaders The response headers to initialize with. + */ public ResponseHeaders(@Nonnull ResponseHeaders responseHeaders) { super(responseHeaders); } diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/ParseNode.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/ParseNode.java index 1302df611..07353c2d6 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/ParseNode.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/ParseNode.java @@ -1,11 +1,12 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.PeriodAndDuration; + import java.lang.Enum; import java.math.BigDecimal; import java.time.OffsetDateTime; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Period; import java.util.EnumSet; import java.util.List; import java.util.UUID; @@ -111,7 +112,7 @@ public interface ParseNode { * @return the Period value of the node. */ @Nullable - Period getPeriodValue(); + PeriodAndDuration getPeriodAndDurationValue(); /** * Gets the Enum value of the node. diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriter.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriter.java index b3734a06f..fa8a17efc 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriter.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriter.java @@ -1,11 +1,12 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.PeriodAndDuration; + import java.io.Closeable; import java.io.InputStream; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.util.Map; import java.util.UUID; import java.util.EnumSet; @@ -98,11 +99,11 @@ public interface SerializationWriter extends Closeable { */ void writeLocalTimeValue(@Nullable final String key, @Nullable final LocalTime value); /** - * Writes the specified Period value to the stream with an optional given key. + * Writes the specified Period/Duration value to the stream with an optional given key. * @param key the key to write the value with. * @param value the value to write to the stream. */ - void writePeriodValue(@Nullable final String key, @Nullable final Period value); + void writePeriodAndDurationValue(@Nullable final String key, @Nullable final PeriodAndDuration value); /** * Writes the specified collection of primitive values to the stream with an optional given key. * @param key the key to write the value with. diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/PeriodAndDurationTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/PeriodAndDurationTest.java new file mode 100644 index 000000000..2c75b0c1f --- /dev/null +++ b/components/abstractions/src/test/java/com/microsoft/kiota/PeriodAndDurationTest.java @@ -0,0 +1,187 @@ +package com.microsoft.kiota; + +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.time.Instant; +import java.time.Period; +import java.time.temporal.ChronoUnit; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PeriodAndDurationTest { + @Test + void Defensive() { + // Assert + var exception = assertThrows(NullPointerException.class, () -> PeriodAndDuration.of(null,null)); + assertTrue(exception.getMessage().contains("period cannot be null")); + + var exception2 = assertThrows(NullPointerException.class, () -> PeriodAndDuration.of(null, Duration.ZERO)); + assertTrue(exception2.getMessage().contains("period cannot be null")); + + var exception3 = assertThrows(NullPointerException.class, () -> PeriodAndDuration.of(Period.ZERO, null)); + assertTrue(exception3.getMessage().contains("duration cannot be null")); + + var exception4 = assertThrows(NullPointerException.class, () -> PeriodAndDuration.ofDuration(null)); + assertTrue(exception4.getMessage().contains("duration cannot be null")); + + var exception5 = assertThrows(NullPointerException.class, () -> PeriodAndDuration.ofPeriod(null)); + assertTrue(exception5.getMessage().contains("period cannot be null")); + + final PeriodAndDuration periodAndDuration = PeriodAndDuration.of(Period.ZERO, Duration.ZERO); + assertNotNull(periodAndDuration); + } + + @Test + void EqualityForZeroValues() { + // Assert + final PeriodAndDuration periodAndDuration = PeriodAndDuration.of(Period.ZERO, Duration.ZERO); + assertTrue(periodAndDuration.equals(periodAndDuration)); + assertTrue(PeriodAndDuration.ZERO.equals(periodAndDuration)); + } + + @Test + void ParsesOnlyDurationString() { + String [] inputs = { "PT6H", "PT1M", "PT1S", "PT6H10M10S","+PT6H10M10S","-PT6H10M10S" }; + for (var durationString :inputs) { + var duration = Duration.parse(durationString); + var periodAndDuration = PeriodAndDuration.parse(durationString); + + // Assert + assertEquals(Period.ZERO, periodAndDuration.getPeriod()); + assertEquals(duration, periodAndDuration.getDuration()); + } + } + + @Test + void SerializesOnlyDurationString() { + String [] inputs = { "PT6H", "PT1M", "PT1S", "PT6H10M10S","+PT6H10M10S" }; + for (var durationString :inputs) { + var duration = Duration.parse(durationString); + var periodAndDuration = PeriodAndDuration.parse(durationString); + + // Assert + assertEquals(Period.ZERO, periodAndDuration.getPeriod()); + assertEquals(duration, periodAndDuration.getDuration()); + + // Assert serialization + if(durationString.startsWith("+")){// character will be removed as its not needed + durationString = durationString.substring(1); + } + + assertEquals(durationString, periodAndDuration.toString()); + } + } + + @Test + void ParsesOnlyPeriodString() { + String [] inputs = { "P6Y", "P10M", "P20D", "P6Y10M10D","+P6Y10M10D","-P6Y10M10D" }; + for (var periodString :inputs) { + var period = Period.parse(periodString); + var periodAndDuration = PeriodAndDuration.parse(periodString); + + // Assert + assertEquals(Duration.ZERO, periodAndDuration.getDuration()); + assertEquals(period, periodAndDuration.getPeriod()); + } + } + + @Test + void SerializesOnlyPeriodString() { + String [] inputs = { "P6Y", "P10M", "P20D", "P6Y10M10D","+P6Y10M10D"}; + for (var periodString :inputs) { + var period = Period.parse(periodString); + var periodAndDuration = PeriodAndDuration.parse(periodString); + + // Assert + assertEquals(Duration.ZERO, periodAndDuration.getDuration()); + assertEquals(period, periodAndDuration.getPeriod()); + + // Assert serialization + if(periodString.startsWith("+")){// character will be removed as its not needed + periodString = periodString.substring(1); + } + + assertEquals(periodString, periodAndDuration.toString()); + } + } + + @Test + void ParsesOnlyPeriodAndDurationString() { + String [] inputs = { "P6YT6H", "P10MT1M", "P20DT1S", "P6Y10M10DT6H10M10S","+P6Y10M10DT6H10M10S","-P6Y10M10DT6H10M10S" }; + for (var periodString :inputs) { + var periodAndDuration = PeriodAndDuration.parse(periodString); + + // Assert + assertNotEquals(Duration.ZERO, periodAndDuration.getDuration()); + assertNotEquals(Period.ZERO, periodAndDuration.getPeriod()); + } + } + + @Test + void SerializesPeriodAndDurationString() { + String [] inputs = { "P6YT6H", "P10MT1M", "P20DT1S", "P6Y10M10DT6H10M10S","+P6Y10M10DT6H10M10S" }; + for (var periodString :inputs) { + var periodAndDuration = PeriodAndDuration.parse(periodString); + + // Assert + assertNotEquals(Duration.ZERO, periodAndDuration.getDuration()); + assertNotEquals(Period.ZERO, periodAndDuration.getPeriod()); + + // Assert serialization + if(periodString.startsWith("+")){// character will be removed as its not needed + periodString = periodString.substring(1); + } + + assertEquals(periodString, periodAndDuration.toString()); + } + } + + @Test + void ParsesOnlyPeriodAndDurationStringAndValue() { + String input = "P7Y9M15DT6H10M11S"; + var periodAndDuration = PeriodAndDuration.parse(input); + var periodAndDurationWithSign = PeriodAndDuration.parse("+"+input); + + assertEquals(periodAndDurationWithSign, periodAndDuration);// sign results in same value + + // Assert + assertNotEquals(Duration.ZERO, periodAndDuration.getDuration()); + assertNotEquals(Period.ZERO, periodAndDuration.getPeriod()); + + assertEquals(7,periodAndDuration.get(ChronoUnit.YEARS));//7 years + assertEquals(9,periodAndDuration.get(ChronoUnit.MONTHS)); // 9 months + assertEquals(15,periodAndDuration.get(ChronoUnit.DAYS)); // 15 days + assertEquals(6,periodAndDuration.get(ChronoUnit.HOURS));// 6 Hours + assertEquals(10,periodAndDuration.get(ChronoUnit.MINUTES)); // 10 minutes + assertEquals(11,periodAndDuration.get(ChronoUnit.SECONDS)); // 11 seconds + } + + @Test + void ComparesPeriodAndDurationObjects() { + + String input = "P7Y9M15DT6H10M11S"; + String inputPlusOneMinute = "P7Y9M15DT6H11M11S"; + String inputMinusOneMinute = "P7Y9M15DT6H9M11S"; + String inputMinusOneMonth = "P7Y8M15DT6H10M11S"; + String inputPlusOneMonth = "P7Y10M15DT6H10M11S"; + var periodAndDuration = PeriodAndDuration.parse(input); + var periodAndDurationWithSign = PeriodAndDuration.parse("+"+input); + + assertEquals(periodAndDurationWithSign, periodAndDuration);// sign results in same value + assertEquals(0, periodAndDuration.compareTo(periodAndDurationWithSign)); // same comparison + + // less than + assertEquals(-1, periodAndDuration.compareTo(PeriodAndDuration.parse(inputPlusOneMinute))); + assertEquals(-1, periodAndDuration.compareTo(PeriodAndDuration.parse(inputPlusOneMonth))); + + + // greater than + assertEquals(1, periodAndDuration.compareTo(PeriodAndDuration.parse(inputMinusOneMinute))); + assertEquals(1, periodAndDuration.compareTo(PeriodAndDuration.parse(inputMinusOneMonth))); + + } + + +} diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java index 668ec0e2b..c3d012d57 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java @@ -9,7 +9,6 @@ import java.time.OffsetDateTime; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Period; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Collection; @@ -22,7 +21,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -35,6 +33,7 @@ import com.microsoft.kiota.ResponseHandlerOption; import com.microsoft.kiota.ResponseHeaders; import com.microsoft.kiota.ResponseHandler; +import com.microsoft.kiota.PeriodAndDuration; import com.microsoft.kiota.authentication.AuthenticationProvider; import com.microsoft.kiota.http.middleware.ParametersNameDecodingHandler; import com.microsoft.kiota.serialization.ParseNodeFactoryRegistry; @@ -367,8 +366,8 @@ public CompletableFuture sendPrimitiveAsync(@Nonnull fina result = rootNode.getLocalDateValue(); } else if(targetClass == LocalTime.class) { result = rootNode.getLocalTimeValue(); - } else if(targetClass == Period.class) { - result = rootNode.getPeriodValue(); + } else if(targetClass == PeriodAndDuration.class) { + result = rootNode.getPeriodAndDurationValue(); } else if(targetClass == byte[].class) { result = rootNode.getByteArrayValue(); } else { diff --git a/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormParseNode.java b/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormParseNode.java index 7ace40118..a721b88fb 100644 --- a/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormParseNode.java +++ b/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormParseNode.java @@ -1,6 +1,7 @@ package com.microsoft.kiota.serialization; import com.google.common.collect.Lists; +import com.microsoft.kiota.PeriodAndDuration; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; @@ -10,7 +11,6 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -175,10 +175,10 @@ public LocalTime getLocalTimeValue() { return LocalTime.parse(stringValue); } @Nullable - public Period getPeriodValue() { + public PeriodAndDuration getPeriodAndDurationValue() { final String stringValue = getStringValue(); if(stringValue == null) return null; - return Period.parse(stringValue); + return PeriodAndDuration.parse(stringValue); } @Nullable public List getCollectionOfPrimitiveValues(@Nonnull final Class targetClass) { @@ -227,8 +227,8 @@ public T next() { return (T)itemNode.getLocalDateValue(); } else if(targetClass == LocalTime.class) { return (T)itemNode.getLocalTimeValue(); - } else if(targetClass == Period.class) { - return (T)itemNode.getPeriodValue(); + } else if(targetClass == PeriodAndDuration.class) { + return (T)itemNode.getPeriodAndDurationValue(); } else { throw new RuntimeException("unknown type to deserialize " + targetClass.getName()); } diff --git a/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormSerializationWriter.java b/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormSerializationWriter.java index ecb84a17d..d7a7dd106 100644 --- a/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormSerializationWriter.java +++ b/components/serialization/form/src/main/java/com/microsoft/kiota/serialization/FormSerializationWriter.java @@ -1,5 +1,7 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.PeriodAndDuration; + import java.lang.Enum; import java.math.BigDecimal; import java.net.URLEncoder; @@ -13,7 +15,6 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.EnumSet; @@ -106,7 +107,7 @@ public void writeLocalTimeValue(@Nullable final String key, @Nullable final Loca if(value != null) writeStringValue(key, value.format(DateTimeFormatter.ISO_LOCAL_TIME)); } - public void writePeriodValue(@Nullable final String key, @Nullable final Period value) { + public void writePeriodAndDurationValue(@Nullable final String key, @Nullable final PeriodAndDuration value) { if(value != null) writeStringValue(key, value.toString()); } @@ -236,8 +237,8 @@ else if(valueClass.equals(LocalDate.class)) this.writeLocalDateValue(key, (LocalDate)value); else if(valueClass.equals(LocalTime.class)) this.writeLocalTimeValue(key, (LocalTime)value); - else if(valueClass.equals(Period.class)) - this.writePeriodValue(key, (Period)value); + else if(valueClass.equals(PeriodAndDuration.class)) + this.writePeriodAndDurationValue(key, (PeriodAndDuration)value); else if(value instanceof Iterable) this.writeCollectionOfPrimitiveValues(key, (Iterable)value); else diff --git a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/FormSerializationWriterTests.java b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/FormSerializationWriterTests.java index 99fe389da..a79e9dfd7 100644 --- a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/FormSerializationWriterTests.java +++ b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/FormSerializationWriterTests.java @@ -10,11 +10,11 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Collectors; +import com.microsoft.kiota.PeriodAndDuration; import org.junit.jupiter.api.Test; import com.microsoft.kiota.serialization.mocks.TestEntity; @@ -24,7 +24,7 @@ public class FormSerializationWriterTests { public void writesSampleObjectValue() throws IOException, UnsupportedEncodingException { final var testEntity = new TestEntity() {{ setId("48d31887-5fad-4d73-a9f5-3c356e68a038"); - setWorkDuration(Period.parse("P1M")); + setWorkDuration(PeriodAndDuration.parse("P1M")); setStartWorkTime(LocalTime.of(8, 0, 0)); setBirthDay(LocalDate.of(2017, 9, 4)); setDeviceNames(Arrays.asList("device1","device2")); @@ -58,7 +58,7 @@ public void writesSampleObjectValue() throws IOException, UnsupportedEncodingExc public void writesSampleCollectionOfObjectValues() throws IOException { final var testEntity = new TestEntity() {{ setId("48d31887-5fad-4d73-a9f5-3c356e68a038"); - setWorkDuration(Period.parse("P1M")); + setWorkDuration(PeriodAndDuration.parse("P1M")); setStartWorkTime(LocalTime.of(8, 0, 0)); setBirthDay(LocalDate.of(2017, 9, 4)); }}; @@ -71,7 +71,7 @@ public void writesSampleCollectionOfObjectValues() throws IOException { public void writesNestedObjectValuesInAdditionalData() throws IOException { final var testEntity = new TestEntity() {{ setId("48d31887-5fad-4d73-a9f5-3c356e68a038"); - setWorkDuration(Period.parse("P1M")); + setWorkDuration(PeriodAndDuration.parse("P1M")); setStartWorkTime(LocalTime.of(8, 0, 0)); setBirthDay(LocalDate.of(2017, 9, 4)); }}; diff --git a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/ParseNodeTests.java b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/ParseNodeTests.java index 6d5d3b28f..6ef8daff3 100644 --- a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/ParseNodeTests.java +++ b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/ParseNodeTests.java @@ -7,10 +7,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.LocalTime; -import java.time.Period; import java.util.List; import java.util.UUID; +import com.microsoft.kiota.PeriodAndDuration; import org.junit.jupiter.api.Test; import com.microsoft.kiota.serialization.mocks.TestEntity; @@ -48,7 +48,7 @@ public void getsEntityValueFromForm() { assertEquals("true", entity.getAdditionalData().get("accountEnabled")); assertEquals("Auditor", entity.getAdditionalData().get("jobTitle")); assertEquals("48d31887-5fad-4d73-a9f5-3c356e68a038", entity.getId()); - assertEquals(Period.parse("P1M"), entity.getWorkDuration()); + assertEquals(PeriodAndDuration.parse("P1M"), entity.getWorkDuration()); assertEquals(LocalTime.of(8, 0, 0, 0), entity.getStartWorkTime()); assertEquals(LocalTime.of(17, 0, 0, 0), entity.getEndWorkTime()); assertEquals("2017-09-04", entity.getBirthDay().toString()); diff --git a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java index 404449807..e2eefbc07 100644 --- a/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java +++ b/components/serialization/form/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java @@ -1,5 +1,6 @@ package com.microsoft.kiota.serialization.mocks; +import com.microsoft.kiota.PeriodAndDuration; import com.microsoft.kiota.serialization.ParseNode; import com.microsoft.kiota.serialization.SerializationWriter; @@ -8,7 +9,6 @@ import java.time.OffsetDateTime; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Period; import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.AdditionalDataHolder; @@ -49,12 +49,12 @@ public List getDeviceNames() { public void setDeviceNames(List value) { this._deviceNames = new ArrayList(value); } - private Period _workDuration; - public Period getWorkDuration() { + private PeriodAndDuration _workDuration; + public PeriodAndDuration getWorkDuration() { return _workDuration; } - public void setWorkDuration(Period value) { + public void setWorkDuration(PeriodAndDuration value) { this._workDuration = value; } @@ -100,7 +100,7 @@ public Map> getFieldDeserializers() { setBirthDay(n.getLocalDateValue()); }); put("workDuration", (n) -> { - setWorkDuration(n.getPeriodValue()); + setWorkDuration(n.getPeriodAndDurationValue()); }); put("startWorkTime", (n) -> { setStartWorkTime(n.getLocalTimeValue()); @@ -123,7 +123,7 @@ public void serialize(SerializationWriter writer) { writer.writeStringValue("id", getId()); writer.writeStringValue("officeLocation", getOfficeLocation()); writer.writeLocalDateValue("birthDay", getBirthDay()); - writer.writePeriodValue("workDuration", getWorkDuration()); + writer.writePeriodAndDurationValue("workDuration", getWorkDuration()); writer.writeLocalTimeValue("startWorkTime", getStartWorkTime()); writer.writeLocalTimeValue("endWorkTime", getEndWorkTime()); writer.writeOffsetDateTimeValue("createdDateTime", getCreatedDateTime()); diff --git a/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNode.java b/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNode.java index 6d9bc18ff..33210ab07 100644 --- a/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNode.java +++ b/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNode.java @@ -4,15 +4,14 @@ import com.google.gson.JsonObject; import com.google.common.collect.Lists; import com.google.gson.JsonArray; -import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; +import com.microsoft.kiota.PeriodAndDuration; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.util.Base64; import java.util.EnumSet; import java.util.Iterator; @@ -110,10 +109,10 @@ public LocalTime getLocalTimeValue() { return LocalTime.parse(stringValue); } @Nullable - public Period getPeriodValue() { + public PeriodAndDuration getPeriodAndDurationValue() { final String stringValue = currentNode.getAsString(); if(stringValue == null) return null; - return Period.parse(stringValue); + return PeriodAndDuration.parse(stringValue); } @Nullable public List getCollectionOfPrimitiveValues(@Nonnull final Class targetClass) { @@ -166,8 +165,8 @@ public T next() { return (T)itemNode.getLocalDateValue(); } else if(targetClass == LocalTime.class) { return (T)itemNode.getLocalTimeValue(); - } else if(targetClass == Period.class) { - return (T)itemNode.getPeriodValue(); + } else if(targetClass == PeriodAndDuration.class) { + return (T)itemNode.getPeriodAndDurationValue(); } else { throw new RuntimeException("unknown type to deserialize " + targetClass.getName()); } diff --git a/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriter.java b/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriter.java index 9e1d78fe5..17b2e6490 100644 --- a/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriter.java +++ b/components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriter.java @@ -1,8 +1,6 @@ package com.microsoft.kiota.serialization; -import com.microsoft.kiota.serialization.SerializationWriter; -import com.microsoft.kiota.serialization.ValuedEnum; -import com.microsoft.kiota.serialization.Parsable; +import com.microsoft.kiota.PeriodAndDuration; import java.lang.Enum; import java.lang.reflect.Field; @@ -12,11 +10,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.EnumSet; @@ -41,11 +38,7 @@ public class JsonSerializationWriter implements SerializationWriter { private final JsonWriter writer; /** Creates a new instance of a json serialization writer */ public JsonSerializationWriter() { - try { - this.writer = new JsonWriter(new OutputStreamWriter(this.stream, "UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("could not create json writer", e); - } + this.writer = new JsonWriter(new OutputStreamWriter(this.stream, StandardCharsets.UTF_8)); } public void writeStringValue(@Nullable final String key, @Nullable final String value) { if(value != null) @@ -190,7 +183,7 @@ public void writeLocalTimeValue(@Nullable final String key, @Nullable final Loca throw new RuntimeException("could not serialize value", ex); } } - public void writePeriodValue(@Nullable final String key, @Nullable final Period value) { + public void writePeriodAndDurationValue(@Nullable final String key, @Nullable final PeriodAndDuration value) { if(value != null) try { if(key != null && !key.isEmpty()) { @@ -386,8 +379,8 @@ else if(valueClass.equals(LocalDate.class)) this.writeLocalDateValue(key, (LocalDate)value); else if(valueClass.equals(LocalTime.class)) this.writeLocalTimeValue(key, (LocalTime)value); - else if(valueClass.equals(Period.class)) - this.writePeriodValue(key, (Period)value); + else if(valueClass.equals(PeriodAndDuration.class)) + this.writePeriodAndDurationValue(key, (PeriodAndDuration)value); else if(value instanceof Iterable) this.writeCollectionOfPrimitiveValues(key, (Iterable)value); else if(!valueClass.isPrimitive()) @@ -420,7 +413,7 @@ public void setOnAfterObjectSerialization(@Nullable final Consumer val public void setOnStartObjectSerialization(@Nullable final BiConsumer value) { this.onStartObjectSerialization = value; } - public void writeByteArrayValue(@Nullable final String key, @Nullable @Nonnull final byte[] value) { + public void writeByteArrayValue(@Nullable final String key, @Nullable final byte[] value) { if(value != null) this.writeStringValue(key, Base64.getEncoder().encodeToString(value)); } diff --git a/components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java b/components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java index 7909653f4..a6e57f682 100644 --- a/components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java +++ b/components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/TestEntity.java @@ -1,5 +1,6 @@ package com.microsoft.kiota.serialization.mocks; +import com.microsoft.kiota.PeriodAndDuration; import com.microsoft.kiota.serialization.ParseNode; import com.microsoft.kiota.serialization.SerializationWriter; @@ -10,7 +11,6 @@ import java.time.OffsetDateTime; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Period; import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.AdditionalDataHolder; @@ -43,12 +43,12 @@ public void setBirthDay(LocalDate value) { this._birthDay = value; } - private Period _workDuration; - public Period getWorkDuration() { + private PeriodAndDuration _workDuration; + public PeriodAndDuration getWorkDuration() { return _workDuration; } - public void setWorkDuration(Period value) { + public void setWorkDuration(PeriodAndDuration value) { this._workDuration = value; } @@ -94,7 +94,7 @@ public Map> getFieldDeserializers() { setBirthDay(n.getLocalDateValue()); }); put("workDuration", (n) -> { - setWorkDuration(n.getPeriodValue()); + setWorkDuration(n.getPeriodAndDurationValue()); }); put("startWorkTime", (n) -> { setStartWorkTime(n.getLocalTimeValue()); @@ -114,7 +114,7 @@ public void serialize(SerializationWriter writer) { writer.writeStringValue("id", getId()); writer.writeStringValue("officeLocation", getOfficeLocation()); writer.writeLocalDateValue("birthDay", getBirthDay()); - writer.writePeriodValue("workDuration", getWorkDuration()); + writer.writePeriodAndDurationValue("workDuration", getWorkDuration()); writer.writeLocalTimeValue("startWorkTime", getStartWorkTime()); writer.writeLocalTimeValue("endWorkTime", getEndWorkTime()); writer.writeOffsetDateTimeValue("createdDateTime", getCreatedDateTime()); diff --git a/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextParseNode.java b/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextParseNode.java index c0e257b17..91a54d2d8 100644 --- a/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextParseNode.java +++ b/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextParseNode.java @@ -1,12 +1,13 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.PeriodAndDuration; + import java.lang.UnsupportedOperationException; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.util.Base64; import java.util.EnumSet; import java.util.List; @@ -86,8 +87,8 @@ public LocalTime getLocalTimeValue() { return LocalTime.parse(this.getStringValue()); } @Nullable - public Period getPeriodValue() { - return Period.parse(this.getStringValue()); + public PeriodAndDuration getPeriodAndDurationValue() { + return PeriodAndDuration.parse(this.getStringValue()); } @Nullable public List getCollectionOfPrimitiveValues(@Nonnull final Class targetClass) { diff --git a/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextSerializationWriter.java b/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextSerializationWriter.java index a1f599981..6c3b08329 100644 --- a/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextSerializationWriter.java +++ b/components/serialization/text/src/main/java/com/microsoft/kiota/serialization/TextSerializationWriter.java @@ -1,5 +1,7 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.PeriodAndDuration; + import java.lang.Enum; import java.lang.UnsupportedOperationException; import java.math.BigDecimal; @@ -12,7 +14,6 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; -import java.time.Period; import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.EnumSet; @@ -103,7 +104,7 @@ public void writeLocalTimeValue(@Nullable final String key, @Nullable final Loca if(value != null) writeStringValue(key, value.format(DateTimeFormatter.ISO_LOCAL_TIME)); } - public void writePeriodValue(@Nullable final String key, @Nullable final Period value) { + public void writePeriodAndDurationValue(@Nullable final String key, @Nullable final PeriodAndDuration value) { if(value != null) writeStringValue(key, value.toString()); } diff --git a/gradle.properties b/gradle.properties index cfd8501bf..66cc48b5f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ org.gradle.caching=true mavenGroupId = com.microsoft.kiota mavenMajorVersion = 0 mavenMinorVersion = 4 -mavenPatchVersion = 5 +mavenPatchVersion = 6 mavenArtifactSuffix = #These values are used to run functional tests