diff --git a/components/abstractions/android/build.gradle b/components/abstractions/android/build.gradle index 818e02384..63ed0cd21 100644 --- a/components/abstractions/android/build.gradle +++ b/components/abstractions/android/build.gradle @@ -57,6 +57,7 @@ android { disable "GradleDependency" disable "NewerVersionAvailable" disable "DuplicatePlatformClasses" // xpp3 added by azure-identity + disable "LambdaLast" // Wrongly enforced in KiotaJsonSerialization helpers } sourceSets { main { diff --git a/components/abstractions/gradle/dependencies.gradle b/components/abstractions/gradle/dependencies.gradle index 63a4ce8b0..8f63f9354 100644 --- a/components/abstractions/gradle/dependencies.gradle +++ b/components/abstractions/gradle/dependencies.gradle @@ -3,6 +3,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.2' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.2' testImplementation 'org.mockito:mockito-core:5.14.1' + testImplementation project(':components:serialization:json') // Use JUnit Jupiter Engine for testing. testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' diff --git a/components/abstractions/spotBugsExcludeFilter.xml b/components/abstractions/spotBugsExcludeFilter.xml index e2dbb38ce..68e65df88 100644 --- a/components/abstractions/spotBugsExcludeFilter.xml +++ b/components/abstractions/spotBugsExcludeFilter.xml @@ -46,13 +46,11 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu - - - - + + diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java index 046c81019..ddf229f88 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java @@ -26,6 +26,20 @@ private KiotaJsonSerialization() {} return KiotaSerialization.serializeAsStream(CONTENT_TYPE, value); } + /** + * Serializes the given value to a stream + * @param the type of the value to serialize + * @param value the value to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a stream + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static InputStream serializeAsStream( + @Nonnull final T value, final boolean serializeOnlyChangedValues) throws IOException { + return KiotaSerialization.serializeAsStream( + CONTENT_TYPE, value, serializeOnlyChangedValues); + } + /** * Serializes the given value to a string * @param the type of the value to serialize @@ -38,6 +52,20 @@ private KiotaJsonSerialization() {} return KiotaSerialization.serializeAsString(CONTENT_TYPE, value); } + /** + * Serializes the given value to a string + * @param the type of the value to serialize + * @param value the value to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a string + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static String serializeAsString( + @Nonnull final T value, final boolean serializeOnlyChangedValues) throws IOException { + return KiotaSerialization.serializeAsString( + CONTENT_TYPE, value, serializeOnlyChangedValues); + } + /** * Serializes the given value to a stream * @param the type of the value to serialize @@ -50,6 +78,21 @@ private KiotaJsonSerialization() {} return KiotaSerialization.serializeAsStream(CONTENT_TYPE, values); } + /** + * Serializes the given value to a stream + * @param the type of the value to serialize + * @param values the values to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a stream + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static InputStream serializeAsStream( + @Nonnull final Iterable values, final boolean serializeOnlyChangedValues) + throws IOException { + return KiotaSerialization.serializeAsStream( + CONTENT_TYPE, values, serializeOnlyChangedValues); + } + /** * Serializes the given value to a string * @param the type of the value to serialize @@ -62,6 +105,21 @@ private KiotaJsonSerialization() {} return KiotaSerialization.serializeAsString(CONTENT_TYPE, values); } + /** + * Serializes the given value to a string + * @param the type of the value to serialize + * @param values the values to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a string + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static String serializeAsString( + @Nonnull final Iterable values, final boolean serializeOnlyChangedValues) + throws IOException { + return KiotaSerialization.serializeAsString( + CONTENT_TYPE, values, serializeOnlyChangedValues); + } + /** * Deserializes the given stream to a model object * @param the type of the value to deserialize diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java index e7b06eb13..a9c0a9e0e 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java @@ -16,6 +16,7 @@ */ public final class KiotaSerialization { private static final String CHARSET_NAME = "UTF-8"; + private static final boolean DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES = true; private KiotaSerialization() {} @@ -29,7 +30,26 @@ private KiotaSerialization() {} */ @Nonnull public static InputStream serializeAsStream( @Nonnull final String contentType, @Nonnull final T value) throws IOException { - try (final SerializationWriter writer = getSerializationWriter(contentType, value)) { + return serializeAsStream(contentType, value, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES); + } + + /** + * Serializes the given value to a stream and configures returned values by the backing store if available + * @param the type of the value to serialize + * @param contentType the content type to use for serialization + * @param value the value to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a stream + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static InputStream serializeAsStream( + @Nonnull final String contentType, + @Nonnull final T value, + final boolean serializeOnlyChangedValues) + throws IOException { + Objects.requireNonNull(value); + try (final SerializationWriter writer = + getSerializationWriter(contentType, serializeOnlyChangedValues)) { writer.writeObjectValue("", value); return writer.getSerializedContent(); } @@ -45,7 +65,27 @@ private KiotaSerialization() {} */ @Nonnull public static String serializeAsString( @Nonnull final String contentType, @Nonnull final T value) throws IOException { - try (final InputStream stream = serializeAsStream(contentType, value)) { + Objects.requireNonNull(value); + return serializeAsString(contentType, value, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES); + } + + /** + * Serializes the given value to a string + * @param the type of the value to serialize + * @param contentType the content type to use for serialization + * @param value the value to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a string + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static String serializeAsString( + @Nonnull final String contentType, + @Nonnull final T value, + final boolean serializeOnlyChangedValues) + throws IOException { + Objects.requireNonNull(value); + try (final InputStream stream = + serializeAsStream(contentType, value, serializeOnlyChangedValues)) { return new String(Compatibility.readAllBytes(stream), CHARSET_NAME); } } @@ -61,7 +101,27 @@ private KiotaSerialization() {} @Nonnull public static InputStream serializeAsStream( @Nonnull final String contentType, @Nonnull final Iterable values) throws IOException { - try (final SerializationWriter writer = getSerializationWriter(contentType, values)) { + Objects.requireNonNull(values); + return serializeAsStream(contentType, values, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES); + } + + /** + * Serializes the given value to a stream + * @param the type of the value to serialize + * @param contentType the content type to use for serialization + * @param values the values to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a stream + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static InputStream serializeAsStream( + @Nonnull final String contentType, + @Nonnull final Iterable values, + final boolean serializeOnlyChangedValues) + throws IOException { + Objects.requireNonNull(values); + try (final SerializationWriter writer = + getSerializationWriter(contentType, serializeOnlyChangedValues)) { writer.writeCollectionOfObjectValues("", values); return writer.getSerializedContent(); } @@ -78,20 +138,39 @@ private KiotaSerialization() {} @Nonnull public static String serializeAsString( @Nonnull final String contentType, @Nonnull final Iterable values) throws IOException { - try (final InputStream stream = serializeAsStream(contentType, values)) { + Objects.requireNonNull(values); + return serializeAsString(contentType, values, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES); + } + + /** + * Serializes the given value to a string + * @param the type of the value to serialize + * @param contentType the content type to use for serialization + * @param values the values to serialize + * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel + * @return the serialized value as a string + * @throws IOException when the stream cannot be closed or read. + */ + @Nonnull public static String serializeAsString( + @Nonnull final String contentType, + @Nonnull final Iterable values, + final boolean serializeOnlyChangedValues) + throws IOException { + Objects.requireNonNull(values); + try (final InputStream stream = + serializeAsStream(contentType, values, serializeOnlyChangedValues)) { return new String(Compatibility.readAllBytes(stream), CHARSET_NAME); } } private static SerializationWriter getSerializationWriter( - @Nonnull final String contentType, @Nonnull final Object value) { + @Nonnull final String contentType, final boolean serializeOnlyChangedValues) { Objects.requireNonNull(contentType); - Objects.requireNonNull(value); if (contentType.isEmpty()) { throw new NullPointerException("content type cannot be empty"); } return SerializationWriterFactoryRegistry.defaultInstance.getSerializationWriter( - contentType); + contentType, serializeOnlyChangedValues); } /** diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java index 0c4b5879c..9fcb2cb23 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java @@ -1,6 +1,9 @@ package com.microsoft.kiota.serialization; +import com.microsoft.kiota.store.BackingStoreSerializationWriterProxyFactory; + import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.util.HashMap; import java.util.Objects; @@ -32,24 +35,77 @@ public SerializationWriterFactoryRegistry() { @Override @Nonnull public SerializationWriter getSerializationWriter(@Nonnull final String contentType) { + return getSerializationWriter(contentType, true); + } + + /** + * Get a Serialization Writer with backing store configured with serializeOnlyChangedValues + * @param contentType + * @param serializeOnlyChangedValues control backing store functionality + * @return the serialization writer + * @throws RuntimeException when no factory is found for content type + */ + @Nonnull public SerializationWriter getSerializationWriter( + @Nonnull final String contentType, final boolean serializeOnlyChangedValues) { Objects.requireNonNull(contentType, "parameter contentType cannot be null"); if (contentType.isEmpty()) { throw new NullPointerException("contentType cannot be empty"); } - final String vendorSpecificContentType = contentType.split(";")[0]; - if (contentTypeAssociatedFactories.containsKey(vendorSpecificContentType)) { - return contentTypeAssociatedFactories - .get(vendorSpecificContentType) - .getSerializationWriter(vendorSpecificContentType); + String cleanedContentType = getVendorSpecificContentType(contentType); + SerializationWriterFactory factory = getSerializationWriterFactory(cleanedContentType); + if (factory == null) { + cleanedContentType = getCleanedVendorSpecificContentType(cleanedContentType); + factory = + getSerializationWriterFactory( + getCleanedVendorSpecificContentType(cleanedContentType)); + if (factory == null) { + throw new RuntimeException( + "Content type " + + contentType + + " does not have a factory to be serialized"); + } } - final String cleanedContentType = - contentTypeVendorCleanupPattern.matcher(vendorSpecificContentType).replaceAll(""); - if (contentTypeAssociatedFactories.containsKey(cleanedContentType)) { - return contentTypeAssociatedFactories - .get(cleanedContentType) - .getSerializationWriter(cleanedContentType); + if (!serializeOnlyChangedValues) { + if (factory instanceof BackingStoreSerializationWriterProxyFactory) { + return ((BackingStoreSerializationWriterProxyFactory) factory) + .getSerializationWriter(cleanedContentType, serializeOnlyChangedValues); + } + } + return factory.getSerializationWriter(cleanedContentType); + } + + /** + * Gets a SerializationWriterFactory that is mapped to a cleaned content type string + * @param contentType wrapper object carrying initial content type and result of parsing it + * @return the serialization writer factory or null if no mapped factory is found + */ + @Nullable private SerializationWriterFactory getSerializationWriterFactory( + @Nonnull final String contentType) { + if (contentTypeAssociatedFactories.containsKey(contentType)) { + return contentTypeAssociatedFactories.get(contentType); } - throw new RuntimeException( - "Content type " + contentType + " does not have a factory to be serialized"); + return null; + } + + /** + * Splits content type by ; and returns first segment or original contentType + * @param contentType + * @return vendor specific content type + */ + @Nonnull private String getVendorSpecificContentType(@Nonnull final String contentType) { + String[] split = contentType.split(";"); + if (split.length >= 1) { + return split[0]; + } + return contentType; + } + + /** + * Does a regex match on the content type replacing special characters + * @param contentType + * @return cleaned content type + */ + @Nonnull private String getCleanedVendorSpecificContentType(@Nonnull final String contentType) { + return contentTypeVendorCleanupPattern.matcher(contentType).replaceAll(""); } } diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java index d45d80f89..fe3d34c99 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java @@ -10,10 +10,10 @@ /** Proxy factory that allows the composition of before and after callbacks on existing factories. */ public abstract class SerializationWriterProxyFactory implements SerializationWriterFactory { @Nonnull public String getValidContentType() { - return _concrete.getValidContentType(); + return proxiedFactory.getValidContentType(); } - private final SerializationWriterFactory _concrete; + protected final SerializationWriterFactory proxiedFactory; private final Consumer _onBefore; private final Consumer _onAfter; private final BiConsumer _onStart; @@ -30,14 +30,14 @@ public SerializationWriterProxyFactory( @Nullable final Consumer onBeforeSerialization, @Nullable final Consumer onAfterSerialization, @Nullable final BiConsumer onStartObjectSerialization) { - _concrete = Objects.requireNonNull(concrete); + proxiedFactory = Objects.requireNonNull(concrete); _onBefore = onBeforeSerialization; _onAfter = onAfterSerialization; _onStart = onStartObjectSerialization; } @Nonnull public SerializationWriter getSerializationWriter(@Nonnull final String contentType) { - final SerializationWriter writer = _concrete.getSerializationWriter(contentType); + final SerializationWriter writer = proxiedFactory.getSerializationWriter(contentType); final Consumer originalBefore = writer.getOnBeforeObjectSerialization(); final Consumer originalAfter = writer.getOnAfterObjectSerialization(); final BiConsumer originalStart = diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java b/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java index a4681cb2a..b3d0d1fd1 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java @@ -1,5 +1,6 @@ package com.microsoft.kiota.store; +import com.microsoft.kiota.serialization.SerializationWriter; import com.microsoft.kiota.serialization.SerializationWriterFactory; import com.microsoft.kiota.serialization.SerializationWriterProxyFactory; @@ -48,4 +49,21 @@ public BackingStoreSerializationWriterProxyFactory( } }); } + + /** + * Returns a SerializationWriter that overrides the default serialization of only changed values if serializeOnlyChangedValues="true" + * Gets the previously proxied serialization writer without any backing store configuration to prevent overwriting the registry affecting + * future serialization requests + * + * @param contentType HTTP content type header value + * @param serializeOnlyChangedValues alter backing store default behavior + * @return the SerializationWriter + */ + @Nonnull public SerializationWriter getSerializationWriter( + @Nonnull final String contentType, final boolean serializeOnlyChangedValues) { + if (!serializeOnlyChangedValues) { + return proxiedFactory.getSerializationWriter(contentType); + } + return getSerializationWriter(contentType); + } } diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java index 427605cef..320050a7c 100644 --- a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java +++ b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java @@ -1,6 +1,7 @@ package com.microsoft.kiota.serialization; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -9,13 +10,16 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.microsoft.kiota.serialization.mocks.TestBackedModelEntity; import com.microsoft.kiota.serialization.mocks.TestEntity; +import com.microsoft.kiota.store.BackingStoreSerializationWriterProxyFactory; import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; class SerializationHelpersTest { private static final String _jsonContentType = "application/json"; @@ -91,4 +95,83 @@ void serializesObjectCollection() throws IOException { assertEquals("[{'id':'123'}]", result); verify(mockSerializationWriter, times(1)).writeCollectionOfObjectValues(eq(""), any()); } + + @Test + void serializesAllValuesInBackedModel() throws IOException { + final BackingStoreSerializationWriterProxyFactory + backingStoreSerializationWriterProxyFactory = + new BackingStoreSerializationWriterProxyFactory( + new JsonSerializationWriterFactory()); + SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put( + _jsonContentType, backingStoreSerializationWriterProxyFactory); + + final TestBackedModelEntity entity = new TestBackedModelEntity(); + entity.setId("123"); + entity.setOfficeLocation("Nairobi"); + + // Sets the backing store to be initialized. No properties are dirty + entity.getBackingStore().setIsInitializationCompleted(true); + + final String result = KiotaJsonSerialization.serializeAsString(entity, false); + + assertFalse(entity.getBackingStore().getReturnOnlyChangedValues()); + assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", result); + + final String collectionResult = + KiotaJsonSerialization.serializeAsString( + new ArrayList<>(Arrays.asList(entity)), false); + + assertEquals("[{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}]", collectionResult); + } + + @Test + void serializesChangedValuesInBackedModel() throws IOException { + final BackingStoreSerializationWriterProxyFactory + backingStoreSerializationWriterProxyFactory = + new BackingStoreSerializationWriterProxyFactory( + new JsonSerializationWriterFactory()); + SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put( + _jsonContentType, backingStoreSerializationWriterProxyFactory); + + final TestBackedModelEntity entity = new TestBackedModelEntity(); + entity.setId("123"); + entity.setOfficeLocation("Nairobi"); + entity.getBackingStore().setIsInitializationCompleted(true); + + final String result = KiotaJsonSerialization.serializeAsString(entity, true); + + assertFalse(entity.getBackingStore().getReturnOnlyChangedValues()); + assertEquals("{}", result); + + final String collectionResult = + KiotaJsonSerialization.serializeAsString( + new ArrayList<>(Arrays.asList(entity)), true); + assertEquals("[{}]", collectionResult); + } + + @Test + void cleansContentType() throws IOException { + final BackingStoreSerializationWriterProxyFactory + backingStoreSerializationWriterProxyFactory = + new BackingStoreSerializationWriterProxyFactory( + new JsonSerializationWriterFactory()); + SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put( + _jsonContentType, backingStoreSerializationWriterProxyFactory); + + final TestBackedModelEntity entity = new TestBackedModelEntity(); + entity.setId("123"); + entity.setOfficeLocation("Nairobi"); + + final String result = + KiotaSerialization.serializeAsString( + "application/json;odata.metadata=minimal", entity); + assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", result); + + // Because onAfterObjectSerialization, returnOnlyChangedValues is set to false & + // initialization is completed + entity.getBackingStore().setIsInitializationCompleted(false); + final String otherResult = + KiotaSerialization.serializeAsString("application/vnd.github.raw+json", entity); + assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", otherResult); + } } diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java new file mode 100644 index 000000000..cadacf5b0 --- /dev/null +++ b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java @@ -0,0 +1,168 @@ +package com.microsoft.kiota.serialization.mocks; + +import com.microsoft.kiota.PeriodAndDuration; +import com.microsoft.kiota.serialization.AdditionalDataHolder; +import com.microsoft.kiota.serialization.Parsable; +import com.microsoft.kiota.serialization.ParseNode; +import com.microsoft.kiota.serialization.SerializationWriter; +import com.microsoft.kiota.store.BackedModel; +import com.microsoft.kiota.store.BackingStore; +import com.microsoft.kiota.store.BackingStoreFactorySingleton; + +import jakarta.annotation.Nonnull; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +public class TestBackedModelEntity implements Parsable, AdditionalDataHolder, BackedModel { + private BackingStore backingStore; + + public TestBackedModelEntity() { + backingStore = BackingStoreFactorySingleton.instance.createBackingStore(); + } + + public String getId() { + return this.backingStore.get("id"); + } + + public void setId(String id) { + this.backingStore.set("id", id); + } + + public String getOfficeLocation() { + return this.backingStore.get("officeLocation"); + } + + public void setOfficeLocation(String officeLocation) { + this.backingStore.set("officeLocation", officeLocation); + } + + public LocalDate getBirthDay() { + return this.backingStore.get("birthDay"); + } + + public void setBirthDay(LocalDate value) { + this.backingStore.set("birthDay", value); + } + + public PeriodAndDuration getWorkDuration() { + return this.backingStore.get("workDuration"); + } + + public void setWorkDuration(PeriodAndDuration value) { + this.backingStore.set("workDuration", PeriodAndDuration.ofPeriodAndDuration(value)); + } + + public LocalTime getStartWorkTime() { + return this.backingStore.get("startWorkTime"); + } + + public void setStartWorkTime(LocalTime value) { + this.backingStore.set("startWorkTime", value); + } + + public LocalTime getEndWorkTime() { + return this.backingStore.get("endWorkTime"); + } + + public void setEndWorkTime(LocalTime value) { + this.backingStore.set("endWorkTime", value); + } + + public OffsetDateTime getCreatedDateTime() { + return this.backingStore.get("createdDateTime"); + } + + public void setCreatedDateTime(OffsetDateTime value) { + this.backingStore.set("createdDateTime", value); + } + + @Nonnull @Override + public Map> getFieldDeserializers() { + return new HashMap<>() { + { + put( + "id", + n -> { + setId(n.getStringValue()); + }); + put( + "officeLocation", + n -> { + setOfficeLocation(n.getStringValue()); + }); + put( + "birthDay", + n -> { + setBirthDay(n.getLocalDateValue()); + }); + put( + "workDuration", + n -> { + setWorkDuration(n.getPeriodAndDurationValue()); + }); + put( + "startWorkTime", + n -> { + setStartWorkTime(n.getLocalTimeValue()); + }); + put( + "endWorkTime", + n -> { + setEndWorkTime(n.getLocalTimeValue()); + }); + put( + "createdDateTime", + n -> { + setCreatedDateTime(n.getOffsetDateTimeValue()); + }); + } + }; + } + + @Override + public void serialize(@Nonnull SerializationWriter writer) { + Objects.requireNonNull(writer); + writer.writeStringValue("id", getId()); + writer.writeStringValue("officeLocation", getOfficeLocation()); + writer.writeLocalDateValue("birthDay", getBirthDay()); + writer.writePeriodAndDurationValue("workDuration", getWorkDuration()); + writer.writeLocalTimeValue("startWorkTime", getStartWorkTime()); + writer.writeLocalTimeValue("endWorkTime", getEndWorkTime()); + writer.writeOffsetDateTimeValue("createdDateTime", getCreatedDateTime()); + writer.writeAdditionalData(getAdditionalData()); + } + + @Nonnull @Override + public Map getAdditionalData() { + Map value = this.backingStore.get("additionalData"); + if (value == null) { + value = new HashMap<>(); + this.setAdditionalData(value); + } + return value; + } + + /** + * Sets the AdditionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + * @param value Value to set for the AdditionalData property. + */ + public void setAdditionalData(@jakarta.annotation.Nullable final Map value) { + this.backingStore.set("additionalData", value); + } + + @jakarta.annotation.Nonnull public static TestEntity createFromDiscriminatorValue( + @jakarta.annotation.Nonnull final ParseNode parseNode) { + return new TestEntity(); + } + + @Override + public BackingStore getBackingStore() { + return backingStore; + } +}