diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0c996be41..c60830a1a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -20,6 +20,8 @@ and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Version - Fix the `Orderby` annotation in the Repository - Make the JDQL return the correct type when the select is by field +- Invalid deserialization of maps with generic values +- Make sure at the serialization to the field, the API does not return any communication layer, but standard Java types === Removed diff --git a/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReader.java b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReader.java index a5fd34979..57b4b1dc8 100644 --- a/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReader.java +++ b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReader.java @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. @@ -88,22 +88,46 @@ private Map getMap(Class keyClass, Class valueClass, Object v return map; } } + if (Entry.class.isInstance(value)) { + Map map = new HashMap<>(); + convertEntryToMap(value, map); + return map; + } throw new UnsupportedOperationException("There is not supported convert" + value + " a not Map type."); } private void convertEntryToMap(Object value, Map map) { - Entry entry = Entry.class.cast(value); + Entry entry = (Entry) value; Object entryValue = entry.value().get(); - if (entryValue instanceof Entry) { - Map subMap = new HashMap<>(); - Entry subEntry = Entry.class.cast(entryValue); - convertEntryToMap(subEntry, subMap); - map.put((K) entry.name(), (V) subMap); + if (entryValue instanceof Entry subEntry) { + feedEntryValue(map, subEntry, entry); + } else if(entryValue instanceof Iterable iterable) { + feedIterable(map, iterable, entry); } else { map.put((K) entry.name(), (V) entryValue); } } + private void feedIterable(Map map, Iterable iterable, Entry entry) { + List collection = new ArrayList<>(); + iterable.forEach(collection::add); + if (collection.isEmpty()) { + map.put((K) entry.name(), (V) Collections.emptyList()); + } else if (collection.stream().allMatch(Entry.class::isInstance)) { + Map subMap = new HashMap<>(); + collection.forEach(e -> convertEntryToMap(e, subMap)); + map.put((K) entry.name(), (V) subMap); + } else { + map.put((K) entry.name(), (V) collection); + } + } + + private void feedEntryValue(Map map, Entry subEntry, Entry entry) { + Map subMap = new HashMap<>(); + convertEntryToMap(subEntry, subMap); + map.put((K) entry.name(), (V) subMap); + } + private Map convertToMap(Class keyClass, Class valueClass, Object value) { Map mapValue = Map.class.cast(value); return (Map) mapValue.keySet().stream() diff --git a/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReaderTest.java b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReaderTest.java index 3a785e80c..7352014e4 100644 --- a/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReaderTest.java +++ b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/MapTypeReferenceReaderTest.java @@ -150,6 +150,67 @@ void shouldConvertSubEntryToMap() { }); } + @SuppressWarnings("unchecked") + @Test + void shouldConvertUsingObject() { + Entry subEntry = new EntryTest("key", Value.of("value")); + Entry entry = new EntryTest("key", Value.of(subEntry)); + + Map map = referenceReader.convert(new TypeReference<>() { + }, Collections.singletonList(entry)); + + Map subMap = (Map) map.get("key"); + + assertSoftly(softly -> { + softly.assertThat(map).as("Map is correctly converted").hasSize(1).contains(entry("key", Map.of("key", "value"))); + softly.assertThat(subMap).as("SubMap is correctly converted").hasSize(1).contains(entry("key", "value")); + }); + } + + @Test + void shouldConvertEntry() { + Entry entry = new EntryTest("key", Value.of("value")); + + Map map = referenceReader.convert(new TypeReference<>() { + }, entry); + + assertSoftly(softly -> softly.assertThat(map).as("Map is correctly converted").hasSize(1).contains(entry("key", "value"))); + } + + @Test + void shouldConvertEntryWithSubEntry() { + Entry subEntry = new EntryTest("key", Value.of("value")); + Entry entry = new EntryTest("key", Value.of(subEntry)); + + Map map = referenceReader.convert(new TypeReference<>() { + }, Collections.singletonList(entry)); + + Map subMap = (Map) map.get("key"); + + assertSoftly(softly -> { + softly.assertThat(map).as("Map is correctly converted").hasSize(1).contains(entry("key", Map.of("key", "value"))); + softly.assertThat(subMap).as("SubMap is correctly converted").hasSize(1).contains(entry("key", "value")); + }); + } + + @Test + void shouldConvertEntryWithSubEntryAsList() { + Entry subEntry = new EntryTest("key3", Value.of("value")); + Entry subEntry2 = new EntryTest("key2", Value.of("value2")); + Entry entry = new EntryTest("key", Value.of(List.of(subEntry, subEntry2))); + + Map map = referenceReader.convert(new TypeReference<>() { + }, Collections.singletonList(entry)); + + Map subMap = (Map) map.get("key"); + + assertSoftly(softly -> { + softly.assertThat(map).as("Map is correctly converted").hasSize(1).containsKey("key"); + softly.assertThat(subMap).as("SubMap is correctly converted").hasSize(2).contains(entry("key2", "value2"), + entry("key3", "value")); + }); + } + static Stream compatibleTypeReferences() { return Stream.of( arguments(new TypeReference>() { diff --git a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericFieldMetadata.java b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionFieldMetadata.java similarity index 96% rename from jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericFieldMetadata.java rename to jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionFieldMetadata.java index 2c674e5bc..499a3fb1b 100644 --- a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericFieldMetadata.java +++ b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionFieldMetadata.java @@ -27,7 +27,7 @@ * * @see ParameterMetaData */ -public interface GenericFieldMetadata extends FieldMetadata { +public interface CollectionFieldMetadata extends FieldMetadata { /** * Returns true if it is the element has either Entity or Embeddable annotations * @return true if the element has Entity or Embeddable annotations diff --git a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericParameterMetaData.java b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionParameterMetaData.java similarity index 83% rename from jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericParameterMetaData.java rename to jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionParameterMetaData.java index ec4856197..366f7512b 100644 --- a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/GenericParameterMetaData.java +++ b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/CollectionParameterMetaData.java @@ -17,15 +17,15 @@ import java.util.Collection; /** - * The GenericParameterMetaData interface extends the {@link ParameterMetaData} interface and provides - * additional information about a parameter with a generic type. + * The CollectionParameterMetaData interface extends the {@link ParameterMetaData} interface and provides + * additional information about a parameter with a generic type for collections. * *

This interface is used to represent parameters of generic types, where the type may be a collection * or array containing elements of a specific type.

* * @see ParameterMetaData */ -public interface GenericParameterMetaData extends ParameterMetaData { +public interface CollectionParameterMetaData extends ParameterMetaData { /** * Returns the {@link Class} representing the type of elements in the collection or array. diff --git a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapFieldMetadata.java b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapFieldMetadata.java new file mode 100644 index 000000000..e89624fba --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapFieldMetadata.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.metadata; + +/** + * The MapFieldMetadata interface extends the {@link FieldMetadata} interface and provides + * additional information about a parameter with a map type. + * + *

This interface is used to represent parameters of map types, where the type may be a map + * containing keys and values of specific types.

+ * + * @see ParameterMetaData + */ +public interface MapFieldMetadata extends FieldMetadata { + /** + * Returns true if either the key or value has Entity or Embeddable annotations + * @return true if the key or value has Entity or Embeddable annotations + */ + boolean isEmbeddable(); + + /** + * Returns the {@link Class} representing the type of keys in the map. + * + * @return the key type of the map parameter + */ + Class keyType(); + + /** + * Returns the {@link Class} representing the type of values in the map. + * + * @return the value type of the map parameter + */ + Class valueType(); +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapParameterMetaData.java b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapParameterMetaData.java new file mode 100644 index 000000000..69a1b17b7 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-api-core/src/main/java/org/eclipse/jnosql/mapping/metadata/MapParameterMetaData.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.metadata; + + +import org.eclipse.jnosql.communication.Value; + +/** + * The MapParameterMetaData interface extends the {@link ParameterMetaData} interface and provides + * additional information about a parameter with a generic type for maps. + * + *

This interface is used to represent parameters of generic types, where the type may be a map + * containing keys and values of specific types.

+ * + * @see ParameterMetaData + */ +public interface MapParameterMetaData extends ParameterMetaData { + + /** + * Returns the {@link Class} representing the type of keys in the map. + * + * @return the key type of the map parameter + */ + Class keyType(); + + /** + * Returns the {@link Class} representing the type of values in the map. + * + * @return the value type of the map parameter + */ + Class valueType(); + + /** + * Returns the object from the field type. + * + * @param value the value {@link Value} + * @return the instance from the field type + */ + Object value(Value value); +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetadata.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadata.java similarity index 87% rename from jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetadata.java rename to jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadata.java index 219b06ae1..eb639b4ef 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetadata.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadata.java @@ -20,7 +20,7 @@ import jakarta.nosql.AttributeConverter; import jakarta.nosql.Embeddable; import org.eclipse.jnosql.mapping.metadata.CollectionSupplier; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; import org.eclipse.jnosql.mapping.metadata.MappingType; import java.lang.reflect.Field; @@ -30,13 +30,13 @@ import java.util.Objects; import java.util.ServiceLoader; -final class DefaultGenericFieldMetadata extends AbstractFieldMetadata implements GenericFieldMetadata { +final class DefaultCollectionFieldMetadata extends AbstractFieldMetadata implements CollectionFieldMetadata { private final TypeSupplier typeSupplier; - DefaultGenericFieldMetadata(MappingType type, Field field, String name, TypeSupplier typeSupplier, - Class> converter, - FieldReader reader, FieldWriter writer, String udt) { + DefaultCollectionFieldMetadata(MappingType type, Field field, String name, TypeSupplier typeSupplier, + Class> converter, + FieldReader reader, FieldWriter writer, String udt) { super(type, field, name, converter, reader, writer, udt); this.typeSupplier = typeSupplier; } @@ -63,7 +63,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - DefaultGenericFieldMetadata that = (DefaultGenericFieldMetadata) o; + DefaultCollectionFieldMetadata that = (DefaultCollectionFieldMetadata) o; return mappingType == that.mappingType && Objects.equals(field, that.field) && Objects.equals(typeSupplier, that.typeSupplier) && diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaData.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaData.java similarity index 78% rename from jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaData.java rename to jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaData.java index d0970b9e1..b8e2843ab 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaData.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaData.java @@ -17,29 +17,31 @@ import org.eclipse.jnosql.communication.TypeSupplier; import jakarta.nosql.AttributeConverter; import org.eclipse.jnosql.mapping.metadata.CollectionSupplier; -import org.eclipse.jnosql.mapping.metadata.GenericParameterMetaData; +import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData; import org.eclipse.jnosql.mapping.metadata.MappingType; import java.lang.reflect.ParameterizedType; import java.util.Collection; import java.util.ServiceLoader; -class DefaultGenericParameterMetaData extends DefaultParameterMetaData implements GenericParameterMetaData { +class DefaultCollectionParameterMetaData extends DefaultParameterMetaData implements CollectionParameterMetaData { private final TypeSupplier typeSupplier; - DefaultGenericParameterMetaData(String name, Class type, boolean id, - Class> converter, - MappingType mappingType, TypeSupplier typeSupplier) { + DefaultCollectionParameterMetaData(String name, Class type, boolean id, + Class> converter, + MappingType mappingType, TypeSupplier typeSupplier) { super(name, type, id, converter, mappingType); this.typeSupplier = typeSupplier; } + @Override public Class elementType() { return (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[0]; } + @Override public Collection collectionInstance() { Class type = type(); final CollectionSupplier supplier = ServiceLoader.load(CollectionSupplier.class) diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadata.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadata.java new file mode 100644 index 000000000..5dd1b2a9d --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadata.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection; + +import jakarta.nosql.AttributeConverter; +import org.eclipse.jnosql.communication.TypeSupplier; +import org.eclipse.jnosql.communication.Value; +import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.MappingType; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.Objects; + +final class DefaultMapFieldMetadata extends AbstractFieldMetadata implements MapFieldMetadata { + + private final TypeSupplier typeSupplier; + + private final Class keyType; + + private final Class valueType; + + DefaultMapFieldMetadata(MappingType type, Field field, String name, TypeSupplier typeSupplier, + Class> converter, + FieldReader reader, FieldWriter writer, String udt) { + super(type, field, name, converter, reader, writer, udt); + this.typeSupplier = typeSupplier; + this.keyType = (Class) ((ParameterizedType) this.field + .getGenericType()) + .getActualTypeArguments()[0]; + this.valueType = (Class) ((ParameterizedType) this.field + .getGenericType()) + .getActualTypeArguments()[1]; + } + + @Override + public Object value(Value value) { + return value.get(typeSupplier); + } + + @Override + public boolean isId() { + return false; + } + + + @Override + public boolean isEmbeddable() { + return false; + } + + @Override + public Class keyType() { + return keyType; + } + + @Override + public Class valueType() { + return valueType; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DefaultMapFieldMetadata that = (DefaultMapFieldMetadata) o; + return Objects.equals(typeSupplier, that.typeSupplier) && Objects.equals(keyType, that.keyType) && Objects.equals(valueType, that.valueType); + } + + @Override + public int hashCode() { + return Objects.hash(typeSupplier, keyType, valueType); + } +} diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaData.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaData.java new file mode 100644 index 000000000..9df31d630 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaData.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection; + +import jakarta.nosql.AttributeConverter; +import org.eclipse.jnosql.communication.TypeSupplier; +import org.eclipse.jnosql.communication.Value; +import org.eclipse.jnosql.mapping.metadata.MapParameterMetaData; +import org.eclipse.jnosql.mapping.metadata.MappingType; + +import java.lang.reflect.ParameterizedType; + +class DefaultMapParameterMetaData extends DefaultParameterMetaData implements MapParameterMetaData { + + private final TypeSupplier typeSupplier; + private final Class keyType; + private final Class valueType; + + DefaultMapParameterMetaData(String name, Class type, boolean id, + Class> converter, + MappingType mappingType, TypeSupplier typeSupplier) { + super(name, type, id, converter, mappingType); + this.typeSupplier = typeSupplier; + this.keyType = (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[0]; + this.valueType = (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[1]; + } + + @Override + public Class keyType() { + return this.keyType; + } + + @Override + public Class valueType() { + return this.valueType; + } + + @Override + public Object value(Value value) { + return value.get(typeSupplier); + } + +} diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/FieldMappingBuilder.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/FieldMappingBuilder.java index fe368f107..f4378f2c7 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/FieldMappingBuilder.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/FieldMappingBuilder.java @@ -16,7 +16,8 @@ import org.eclipse.jnosql.communication.TypeSupplier; import jakarta.nosql.AttributeConverter; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; import org.eclipse.jnosql.mapping.metadata.MappingType; import java.lang.reflect.Field; @@ -98,8 +99,12 @@ public DefaultFieldMetadata buildDefault() { return new DefaultFieldMetadata(type, field, name, converter, id, reader, writer, udt); } - public GenericFieldMetadata buildGeneric() { - return new DefaultGenericFieldMetadata(type, field, name, typeSupplier, converter, reader, writer, udt); + public CollectionFieldMetadata buildCollection() { + return new DefaultCollectionFieldMetadata(type, field, name, typeSupplier, converter, reader, writer, udt); + } + + public MapFieldMetadata buildMap() { + return new DefaultMapFieldMetadata(type, field, name, typeSupplier, converter, reader, writer, udt); } public EmbeddedFieldMetadata buildEmbedded() { diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilder.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilder.java index d1e901186..a9191f60f 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilder.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilder.java @@ -47,7 +47,11 @@ ParameterMetaData build() { } MappingType mappingType = MappingType.of(parameter.getType()); return switch (mappingType) { - case COLLECTION, MAP -> new DefaultGenericParameterMetaData(name, type, + case COLLECTION -> new DefaultCollectionParameterMetaData(name, type, + id != null, + Optional.ofNullable(convert).map(Convert::value).orElse(null), + mappingType, parameter::getParameterizedType); + case MAP -> new DefaultMapParameterMetaData(name, type, id != null, Optional.ofNullable(convert).map(Convert::value).orElse(null), mappingType, parameter::getParameterizedType); diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ReflectionClassConverter.java b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ReflectionClassConverter.java index 025433662..b5d8d4281 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ReflectionClassConverter.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/main/java/org/eclipse/jnosql/mapping/reflection/ReflectionClassConverter.java @@ -18,7 +18,7 @@ import org.eclipse.jnosql.mapping.metadata.ClassConverter; import org.eclipse.jnosql.mapping.metadata.EntityMetadata; import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; import org.eclipse.jnosql.mapping.metadata.MappingType; @@ -112,8 +112,8 @@ private void appendValue(Map nativeFieldGroupByJavaField, appendPreparePrefix(nativeField, field.name())); case EMBEDDED -> appendFields(nativeFieldGroupByJavaField, field, javaField, nativeField); case COLLECTION -> { - if (((GenericFieldMetadata) field).isEmbeddable()) { - Class type = ((GenericFieldMetadata) field).elementType(); + if (((CollectionFieldMetadata) field).isEmbeddable()) { + Class type = ((CollectionFieldMetadata) field).elementType(); String nativeFieldAppended = appendPreparePrefix(nativeField, field.name()); appendFields(nativeFieldGroupByJavaField, field, javaField, nativeFieldAppended, type); return; @@ -185,9 +185,12 @@ private FieldMetadata to(Field field) { builder.converter(convert.value()); } switch (mappingType) { - case COLLECTION, MAP -> { + case COLLECTION -> { + builder.typeSupplier(field::getGenericType); + return builder.buildCollection(); + }case MAP -> { builder.typeSupplier(field::getGenericType); - return builder.buildGeneric(); + return builder.buildMap(); } case EMBEDDED -> { return builder.entityName(reflections.getEntityName(field.getType())).buildEmbedded(); diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ClassGraphClassScannerTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ClassGraphClassScannerTest.java index 5777291a5..88fcd6257 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ClassGraphClassScannerTest.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ClassGraphClassScannerTest.java @@ -40,7 +40,7 @@ class ClassGraphClassScannerTest { void shouldReturnEntities() { Set> entities = classScanner.entities(); Assertions.assertNotNull(entities); - assertThat(entities).hasSize(28) + assertThat(entities).hasSize(29) .contains(Person.class); } diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetaDataTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadataTest.java similarity index 91% rename from jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetaDataTest.java rename to jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadataTest.java index f050964dd..e9bcdc9ea 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericFieldMetaDataTest.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionFieldMetadataTest.java @@ -19,7 +19,7 @@ import org.eclipse.jnosql.mapping.metadata.ClassConverter; import org.eclipse.jnosql.mapping.metadata.EntityMetadata; import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; import org.eclipse.jnosql.mapping.reflection.entities.Person; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,16 +30,16 @@ import static org.assertj.core.api.Assertions.assertThat; -class DefaultGenericFieldMetaDataTest { +class DefaultCollectionFieldMetadataTest { - private GenericFieldMetadata fieldMetadata; + private CollectionFieldMetadata fieldMetadata; @BeforeEach void setUp(){ ClassConverter converter = new ReflectionClassConverter(); EntityMetadata entityMetadata = converter.apply(Person.class); FieldMetadata phones = entityMetadata.fieldMapping("phones").orElseThrow(); - this.fieldMetadata = (GenericFieldMetadata) phones; + this.fieldMetadata = (CollectionFieldMetadata) phones; } @Test void shouldToString() { diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaDataTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaDataTest.java similarity index 89% rename from jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaDataTest.java rename to jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaDataTest.java index 40ba8c0df..c7fa37d2c 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultGenericParameterMetaDataTest.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultCollectionParameterMetaDataTest.java @@ -17,7 +17,7 @@ import org.eclipse.jnosql.mapping.metadata.ClassConverter; import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.GenericParameterMetaData; +import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData; import org.eclipse.jnosql.mapping.reflection.entities.Book; import org.eclipse.jnosql.mapping.reflection.entities.constructor.BookUser; import org.junit.jupiter.api.BeforeEach; @@ -29,16 +29,16 @@ import static org.assertj.core.api.Assertions.assertThat; -class DefaultGenericParameterMetaDataTest { +class DefaultCollectionParameterMetaDataTest { - private GenericParameterMetaData fieldMetadata; + private CollectionParameterMetaData fieldMetadata; @BeforeEach void setUp(){ ClassConverter converter = new ReflectionClassConverter(); EntityMetadata entityMetadata = converter.apply(BookUser.class); ConstructorMetadata constructor = entityMetadata.constructor(); - this.fieldMetadata = (GenericParameterMetaData) + this.fieldMetadata = (CollectionParameterMetaData) constructor.parameters().stream().filter(p -> p.name().equals("books")) .findFirst().orElseThrow(); } diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadataTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadataTest.java new file mode 100644 index 000000000..e14cd94d3 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapFieldMetadataTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection; + +import org.assertj.core.api.Assertions; +import org.eclipse.jnosql.communication.Entry; +import org.eclipse.jnosql.communication.Value; +import org.eclipse.jnosql.mapping.metadata.ClassConverter; +import org.eclipse.jnosql.mapping.metadata.EntityMetadata; +import org.eclipse.jnosql.mapping.metadata.FieldMetadata; +import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; +import org.eclipse.jnosql.mapping.reflection.entities.Actor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class DefaultMapFieldMetadataTest { + + private MapFieldMetadata fieldMetadata; + + @BeforeEach + void setUp() { + ClassConverter converter = new ReflectionClassConverter(); + EntityMetadata entityMetadata = converter.apply(Actor.class); + FieldMetadata movieRating = entityMetadata.fieldMapping("movieRating").orElseThrow(); + this.fieldMetadata = (MapFieldMetadata) movieRating; + } + + @Test + void shouldToString() { + assertThat(fieldMetadata.toString()).isNotEmpty().isNotNull(); + } + + @Test + void shouldGetValueType() { + assertThat(fieldMetadata.valueType()).isEqualTo(Integer.class); + } + + @Test + void shouldGetKeyType() { + assertThat(fieldMetadata.keyType()).isEqualTo(String.class); + } + + @Test + void shouldEqualsHashCode() { + Assertions.assertThat(fieldMetadata).isEqualTo(fieldMetadata); + Assertions.assertThat(fieldMetadata).hasSameHashCodeAs(fieldMetadata); + } + + @Test + void shouldValue() { + Map phones = Map.of("Ada", 5); + Object value = fieldMetadata.value(Value.of(phones)); + assertThat(value).isNotNull().isInstanceOf(Map.class); + } + + @Test + void shouldValueEntry() { + Entry entry = new ReflectionEntry("Ada", Value.of(12)); + Object value = fieldMetadata.value(Value.of(entry)); + assertThat(value).isNotNull().isInstanceOf(Map.class); + } + + @Test + void shouldConverter() { + assertThat(fieldMetadata.converter()).isNotNull().isEmpty(); + } + + @Test + void shouldNewConverter() { + assertThat(fieldMetadata.newConverter()).isNotNull().isEmpty(); + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaDataTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaDataTest.java new file mode 100644 index 000000000..7eab92faf --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/DefaultMapParameterMetaDataTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection; + +import org.eclipse.jnosql.communication.Value; +import org.eclipse.jnosql.mapping.metadata.ClassConverter; +import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; +import org.eclipse.jnosql.mapping.metadata.EntityMetadata; +import org.eclipse.jnosql.mapping.metadata.MapParameterMetaData; +import org.eclipse.jnosql.mapping.reflection.entities.constructor.Form; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class DefaultMapParameterMetaDataTest { + + private MapParameterMetaData fieldMetadata; + + @BeforeEach + void setUp(){ + ClassConverter converter = new ReflectionClassConverter(); + EntityMetadata entityMetadata = converter.apply(Form.class); + ConstructorMetadata constructor = entityMetadata.constructor(); + this.fieldMetadata = (MapParameterMetaData) + constructor.parameters().stream().filter(p -> p.name().equals("questions")) + .findFirst().orElseThrow(); + } + @Test + void shouldToString() { + assertThat(fieldMetadata.toString()).isNotEmpty().isNotNull(); + } + + @Test + void shouldKeyType(){ + assertThat(fieldMetadata.keyType()).isEqualTo(String.class); + } + + @Test + void shouldValueType(){ + Class value = this.fieldMetadata.valueType(); + assertThat(value).isInstanceOf(Object.class); + } + + @Test + void shouldValueClass(){ + Map value = Map.of("name", "name"); + assertThat(fieldMetadata.value(Value.of(value))).isInstanceOf(Map.class); + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilderTest.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilderTest.java index 4ea722d56..92949f816 100644 --- a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilderTest.java +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ParameterMetaDataBuilderTest.java @@ -113,7 +113,7 @@ void shouldConvertCollectionParameter() { Assertions.assertEquals(List.class, books.type()); Assertions.assertEquals(MappingType.COLLECTION, books.mappingType()); Assertions.assertTrue(books.converter().isEmpty()); - assertEquals(DefaultGenericParameterMetaData.class, books.getClass()); + assertEquals(DefaultCollectionParameterMetaData.class, books.getClass()); } @@ -127,7 +127,7 @@ void shouldConvertMapParameter() { Assertions.assertEquals(Map.class, map.type()); Assertions.assertEquals(MappingType.MAP, map.mappingType()); Assertions.assertTrue(map.converter().isEmpty()); - assertEquals(DefaultGenericParameterMetaData.class, map.getClass()); + assertEquals(DefaultMapParameterMetaData.class, map.getClass()); } @Test @@ -140,7 +140,7 @@ void shouldConvertListParameter() { Assertions.assertEquals(List.class, powers.type()); Assertions.assertEquals(MappingType.COLLECTION, powers.mappingType()); Assertions.assertTrue(powers.converter().isEmpty()); - assertEquals(DefaultGenericParameterMetaData.class, powers.getClass()); + assertEquals(DefaultCollectionParameterMetaData.class, powers.getClass()); } diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ReflectionEntry.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ReflectionEntry.java new file mode 100644 index 000000000..87d0d7890 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/ReflectionEntry.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection; + +import org.eclipse.jnosql.communication.Entry; +import org.eclipse.jnosql.communication.Value; + +public record ReflectionEntry(String name, Value value) implements Entry { +} diff --git a/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/entities/constructor/Form.java b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/entities/constructor/Form.java new file mode 100644 index 000000000..5d229c68b --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-reflection/src/test/java/org/eclipse/jnosql/mapping/reflection/entities/constructor/Form.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.reflection.entities.constructor; + +import jakarta.nosql.Column; +import jakarta.nosql.Entity; +import jakarta.nosql.Id; + +import java.util.Map; + +@Entity +public record Form(@Id String name, @Column Map questions) { +} diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/DefaultAttributeFieldValue.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/DefaultAttributeFieldValue.java index b1140e2ca..a6665ddf5 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/DefaultAttributeFieldValue.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/DefaultAttributeFieldValue.java @@ -21,7 +21,7 @@ import org.eclipse.jnosql.mapping.metadata.MappingType; import org.eclipse.jnosql.mapping.metadata.FieldValue; import org.eclipse.jnosql.mapping.metadata.DefaultFieldValue; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; import java.util.ArrayList; import java.util.List; @@ -98,7 +98,7 @@ private String getName() { } private boolean isEmbeddableElement() { - return ((GenericFieldMetadata) field()).isEmbeddable(); + return ((CollectionFieldMetadata) field()).isEmbeddable(); } @Override diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/FieldConverter.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/FieldConverter.java index b7e6752db..0db1ff5d1 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/FieldConverter.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/FieldConverter.java @@ -20,7 +20,8 @@ import jakarta.nosql.AttributeConverter; import org.eclipse.jnosql.mapping.metadata.EntityMetadata; import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.GenericFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; +import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; import org.eclipse.jnosql.mapping.metadata.MappingType; import java.util.ArrayList; @@ -83,21 +84,39 @@ public void convert(T instance, List columns, Element element EntityConverter converter) { if (Objects.nonNull(element)) { - GenericFieldMetadata genericField = (GenericFieldMetadata) field; - Collection elements = genericField.collectionInstance(); + var collectionFieldMetadata = (CollectionFieldMetadata) field; + Collection elements = collectionFieldMetadata.collectionInstance(); List> embeddable = (List>) element.get(); - if(Objects.isNull(embeddable)) { + if (Objects.isNull(embeddable)) { return; } for (List elementList : embeddable) { - Object item = converter.toEntity(genericField.elementType(), elementList); + var item = converter.toEntity(collectionFieldMetadata.elementType(), elementList); elements.add(item); } field.write(instance, elements); } } - }, DEFAULT{ + }, + MAP { @SuppressWarnings("unchecked") + @Override + void convert(T instance, List elements, Element element, FieldMetadata field, EntityConverter converter) { + if (Objects.nonNull(element)) { + var mapFieldMetadata = (MapFieldMetadata) field; + Y value = (Y) mapFieldMetadata.value(element.value()); + var optionalConverter = field.converter(); + if (optionalConverter.isPresent()) { + AttributeConverter attributeConverter = converter.converters().get(field); + attributeConverter.convertToEntityAttribute(value); + Object attributeConverted = attributeConverter.convertToEntityAttribute(value); + field.write(instance, attributeConverted); + } else { + field.write(instance, value); + } + } + } + }, DEFAULT { @Override public void convert(T instance, List elements, Element element, FieldMetadata field, EntityConverter converter) { @@ -105,31 +124,48 @@ public void convert(T instance, List elements, Element elemen Value value = element.value(); Optional>> optionalConverter = field.converter(); if (optionalConverter.isPresent()) { - AttributeConverter attributeConverter = converter.converters().get(field); - Y attr = (Y)(value.isInstanceOf(List.class) ? element : value.get()); - Object attributeConverted = attributeConverter.convertToEntityAttribute(attr); - field.write(instance, field.value(Value.of(attributeConverted))); + executeConverter(instance, element, field, converter, value); } else { field.write(instance, field.value(value)); } } } + + @SuppressWarnings("unchecked") + private void executeConverter(T instance, Element element, FieldMetadata field, EntityConverter converter, Value value) { + AttributeConverter attributeConverter = converter.converters().get(field); + Y attr = (Y) (value.isInstanceOf(List.class) ? element : value.get()); + if (isElement(attr)) { + var mapValue = value.get(new TypeReference>() {}); + Object attributeConverted = attributeConverter.convertToEntityAttribute((Y) mapValue); + field.write(instance, field.value(Value.of(attributeConverted))); + } else { + Object attributeConverted = attributeConverter.convertToEntityAttribute(attr); + field.write(instance, field.value(Value.of(attributeConverted))); + } + } + + private boolean isElement(Y attr) { + return attr instanceof Element; + } }; static FieldConverter get(FieldMetadata field) { if (MappingType.EMBEDDED.equals(field.mappingType())) { return EMBEDDED; - } else if (MappingType.ENTITY.equals(field.mappingType())|| MappingType.EMBEDDED_GROUP.equals(field.mappingType())) { + } else if (MappingType.ENTITY.equals(field.mappingType()) || MappingType.EMBEDDED_GROUP.equals(field.mappingType())) { return ENTITY; } else if (isCollectionEmbeddable(field)) { return COLLECTION; + } else if (MappingType.MAP.equals(field.mappingType())) { + return MAP; } else { return DEFAULT; } } private static boolean isCollectionEmbeddable(FieldMetadata field) { - return MappingType.COLLECTION.equals(field.mappingType()) && ((GenericFieldMetadata) field).isEmbeddable(); + return MappingType.COLLECTION.equals(field.mappingType()) && ((CollectionFieldMetadata) field).isEmbeddable(); } abstract void convert(T instance, List elements, Element element, FieldMetadata field, diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/ParameterConverter.java b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/ParameterConverter.java index e345cbce6..d850f98db 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/ParameterConverter.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/ParameterConverter.java @@ -18,7 +18,8 @@ import org.eclipse.jnosql.communication.semistructured.Element; import org.eclipse.jnosql.mapping.metadata.ConstructorBuilder; import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata; -import org.eclipse.jnosql.mapping.metadata.GenericParameterMetaData; +import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData; +import org.eclipse.jnosql.mapping.metadata.MapParameterMetaData; import org.eclipse.jnosql.mapping.metadata.ParameterMetaData; import java.util.ArrayList; @@ -68,17 +69,23 @@ void convert(EntityConverter converter, Element element, ParameterMetaData metaD void convert(EntityConverter converter, Element element, ParameterMetaData metaData, ConstructorBuilder builder) { - GenericParameterMetaData genericParameter = (GenericParameterMetaData) metaData; - Collection elements = genericParameter.collectionInstance(); + var collectionParameterMetaData = (CollectionParameterMetaData) metaData; + Collection elements = collectionParameterMetaData.collectionInstance(); List> embeddable = (List>) element.get(); for (List elementsList : embeddable) { - Object item = converter.toEntity(genericParameter.elementType(), elementsList); + Object item = converter.toEntity(collectionParameterMetaData.elementType(), elementsList); elements.add(item); } builder.add(elements); - } + }, MAP { + @Override + void convert(EntityConverter converter, Element element, ParameterMetaData metaData, ConstructorBuilder builder) { + var mapParameterMetaData = (MapParameterMetaData) metaData; + Object value = mapParameterMetaData.value(element.value()); + builder.add(value); + } }; abstract void convert(EntityConverter converter, @@ -88,13 +95,14 @@ abstract void convert(EntityConverter converter, static ParameterConverter of(ParameterMetaData parameter, EntitiesMetadata entities) { return switch (parameter.mappingType()) { case COLLECTION -> validateCollection(parameter, entities); + case MAP -> MAP; case ENTITY, EMBEDDED_GROUP -> ENTITY; default -> DEFAULT; }; } private static ParameterConverter validateCollection(ParameterMetaData parameter, EntitiesMetadata entities) { - GenericParameterMetaData genericParameter = (GenericParameterMetaData) parameter; + CollectionParameterMetaData genericParameter = (CollectionParameterMetaData) parameter; Class type = genericParameter.elementType(); if (entities.findByClassName(type.getName()).isPresent()) { return COLLECTION; diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterConstructorTest.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterConstructorTest.java index 141e1723c..5bf65be75 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterConstructorTest.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterConstructorTest.java @@ -23,6 +23,7 @@ import org.eclipse.jnosql.mapping.semistructured.entities.Animal; import org.eclipse.jnosql.mapping.semistructured.entities.Book; import org.eclipse.jnosql.mapping.semistructured.entities.BookRelease; +import org.eclipse.jnosql.mapping.semistructured.entities.Form; import org.eclipse.jnosql.mapping.semistructured.entities.Money; import org.eclipse.jnosql.mapping.semistructured.entities.SocialMediaContact; import org.eclipse.jnosql.mapping.semistructured.entities.Wine; @@ -37,6 +38,7 @@ import org.eclipse.jnosql.mapping.semistructured.entities.constructor.SuperHero; import org.eclipse.jnosql.mapping.reflection.Reflections; import org.eclipse.jnosql.mapping.core.spi.EntityMetadataExtension; +import org.eclipse.jnosql.mapping.semistructured.entities.constructor.Survey; import org.jboss.weld.junit5.auto.AddExtensions; import org.jboss.weld.junit5.auto.AddPackages; import org.jboss.weld.junit5.auto.EnableAutoWeld; @@ -46,6 +48,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -278,4 +281,26 @@ void shouldConvertGroupEmbeddableToCommunication(){ }); } + @Test + void shouldConvertGenericTypes() { + CommunicationEntity communication = CommunicationEntity.of("Survey"); + communication.add("_id", "form"); + communication.add("questions", Arrays.asList( + Element.of("question1", true), + Element.of("question2", false), + Element.of("question3", List.of(Element.of("advanced", true), + Element.of("visible", "true"))) + )); + + Survey survey = converter.toEntity(communication); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(survey.id()).isEqualTo("form"); + softly.assertThat(survey.questions()).containsEntry("question1", true); + softly.assertThat(survey.questions()).containsEntry("question2", false); + softly.assertThat(survey.questions()).containsEntry("question3", Map.of("advanced", true, "visible", "true")); + }); + + } + } diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterInheritanceTest.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterInheritanceTest.java index d9c8fa386..7cefaccbe 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterInheritanceTest.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterInheritanceTest.java @@ -426,6 +426,6 @@ void shouldConvertConvertCommunicationProjectManager() { assertNotNull(large); assertEquals("large-project", large.getName()); assertEquals(BigDecimal.TEN, large.getBudget()); - } + } diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterTest.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterTest.java index 4df262fdd..74ecb9eae 100644 --- a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterTest.java +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/EntityConverterTest.java @@ -29,7 +29,11 @@ import org.eclipse.jnosql.mapping.semistructured.entities.ContactType; import org.eclipse.jnosql.mapping.semistructured.entities.Director; import org.eclipse.jnosql.mapping.semistructured.entities.Download; +import org.eclipse.jnosql.mapping.semistructured.entities.ElectricEngine; +import org.eclipse.jnosql.mapping.semistructured.entities.Form; +import org.eclipse.jnosql.mapping.semistructured.entities.GasEngine; import org.eclipse.jnosql.mapping.semistructured.entities.Job; +import org.eclipse.jnosql.mapping.semistructured.entities.Machine; import org.eclipse.jnosql.mapping.semistructured.entities.MainStepType; import org.eclipse.jnosql.mapping.semistructured.entities.Money; import org.eclipse.jnosql.mapping.semistructured.entities.Movie; @@ -60,6 +64,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.UUID; import java.util.stream.Stream; import static java.util.Arrays.asList; @@ -661,6 +666,74 @@ void shouldConvertGroupEmbeddableToCommunication(){ } + @Test + void shouldConvertGenericTypes() { + CommunicationEntity communication = CommunicationEntity.of("Form"); + communication.add("_id", "form"); + communication.add("questions", Arrays.asList( + Element.of("question1", true), + Element.of("question2", false), + Element.of("question3", List.of(Element.of("advanced", true), + Element.of("visible", "true"))) + )); + + Form form = converter.toEntity(communication); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(form.getId()).isEqualTo("form"); + softly.assertThat(form.getQuestions()).containsEntry("question1", true); + softly.assertThat(form.getQuestions()).containsEntry("question2", false); + softly.assertThat(form.getQuestions()).containsEntry("question3", Map.of("advanced", true, "visible", "true")); + }); + } + + @Test + void shouldConvertGenericTypesWithConverterAsElectric() { + var communication = CommunicationEntity.of("Machine"); + communication.add("_id", UUID.randomUUID().toString()); + communication.add("manufacturer", "Tesla"); + communication.add("year", 2022); + communication.add("engine", Arrays.asList( + Element.of("type", "electric"), + Element.of("horsepower", 300) + )); + + Machine machine = converter.toEntity(communication); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(machine.getId()).isNotNull(); + softly.assertThat(machine.getManufacturer()).isEqualTo("Tesla"); + softly.assertThat(machine.getYear()).isEqualTo(2022); + softly.assertThat(machine.getEngine()).isNotNull(); + softly.assertThat(machine.getEngine().getHorsepower()).isEqualTo(300); + softly.assertThat(machine.getEngine()).isInstanceOf(ElectricEngine.class); + }); + } + + @Test + void shouldConvertGenericTypesWithConverterGas() { + var communication = CommunicationEntity.of("Machine"); + communication.add("_id", UUID.randomUUID().toString()); + communication.add("manufacturer", "Mustang"); + communication.add("year", 2021); + communication.add("engine", Arrays.asList( + Element.of("type", "gas"), + Element.of("horsepower", 450) + )); + + Machine machine = converter.toEntity(communication); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(machine.getId()).isNotNull(); + softly.assertThat(machine.getManufacturer()).isEqualTo("Mustang"); + softly.assertThat(machine.getYear()).isEqualTo(2021); + softly.assertThat(machine.getEngine()).isNotNull(); + softly.assertThat(machine.getEngine().getHorsepower()).isEqualTo(450); + softly.assertThat(machine.getEngine()).isInstanceOf(GasEngine.class); + }); + } + + private Object getValue(Optional column) { return column.map(Element::value).map(Value::get).orElse(null); } diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/ElectricEngine.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/ElectricEngine.java new file mode 100644 index 000000000..b5f06e9fa --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/ElectricEngine.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + + +import jakarta.json.bind.annotation.JsonbVisibility; + +@JsonbVisibility(FieldAccessStrategy.class) +public class ElectricEngine extends Engine { + + public ElectricEngine() { + } + + public ElectricEngine(int horsepower) { + super(horsepower); + } + + @Override + public String getFuelType() { + return "Electric"; + } + + @Override + public String toString() { + return "ElectricEngine{" + + "horsepower=" + horsepower + + '}'; + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Engine.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Engine.java new file mode 100644 index 000000000..068c0a5b4 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Engine.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.json.bind.annotation.JsonbSubtype; +import jakarta.json.bind.annotation.JsonbTypeInfo; +import jakarta.json.bind.annotation.JsonbVisibility; + +import java.util.Objects; + +@JsonbTypeInfo( + key = "type", + value = { + @JsonbSubtype(alias = "gas", type = GasEngine.class), + @JsonbSubtype(alias = "electric", type = ElectricEngine.class) + } +) +@JsonbVisibility(FieldAccessStrategy.class) +public abstract class Engine { + + public Engine() { + } + + public Engine(int horsepower) { + this.horsepower = horsepower; + } + + protected int horsepower; + + public int getHorsepower() { + return horsepower; + } + + public abstract String getFuelType(); + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Engine engine = (Engine) o; + return horsepower == engine.horsepower && + getFuelType().equals(engine.getFuelType()); + } + + @Override + public int hashCode() { + return Objects.hash(horsepower, getFuelType()); + } + + @Override + public String toString() { + return "Engine{" + + "horsepower=" + horsepower + + '}'; + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/EngineConverter.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/EngineConverter.java new file mode 100644 index 000000000..ae1146375 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/EngineConverter.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.nosql.AttributeConverter; +import org.eclipse.jnosql.communication.TypeReference; +import org.eclipse.jnosql.communication.semistructured.Element; + +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Collectors; + + +public class EngineConverter implements AttributeConverter { + + private static final Logger LOGGER = Logger.getLogger(EngineConverter.class.getName()); + + private static final Jsonb JSONB = JsonbBuilder.create(); + + @Override + public Object convertToDatabaseColumn(Engine attribute) { + LOGGER.info("Converting to database column: " + attribute); + if (attribute == null) { + return null; + } + return JSONB.fromJson(JSONB.toJson(attribute), Map.class); + } + + @Override + public Engine convertToEntityAttribute(Object dbData) { + + if(dbData == null) { + return null; + } + if(dbData instanceof Map) { + return JSONB.fromJson(JSONB.toJson(dbData), Engine.class); + } + throw new IllegalArgumentException("The dbData is not a valid type: " + dbData.getClass()); + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/FieldAccessStrategy.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/FieldAccessStrategy.java new file mode 100644 index 000000000..c5c39216e --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/FieldAccessStrategy.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.json.bind.config.PropertyVisibilityStrategy; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class FieldAccessStrategy implements PropertyVisibilityStrategy { + @Override + public boolean isVisible(Field field) { + return true; + } + + @Override + public boolean isVisible(Method method) { + return true; + } +} diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Form.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Form.java new file mode 100644 index 000000000..047d76873 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Form.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.nosql.Column; +import jakarta.nosql.Entity; +import jakarta.nosql.Id; + +import java.util.Map; + +@Entity +public class Form { + + @Id + private String id; + + @Column + private Map questions; + + public String getId() { + return id; + } + + public Map getQuestions() { + return questions; + } +} diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/GasEngine.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/GasEngine.java new file mode 100644 index 000000000..20efe0b42 --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/GasEngine.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.json.bind.annotation.JsonbVisibility; + +@JsonbVisibility(FieldAccessStrategy.class) +public class GasEngine extends Engine { + + public GasEngine() { + } + + public GasEngine(int horsepower) { + super(horsepower); + } + + @Override + public String getFuelType() { + return "Gasoline"; + } + + + @Override + public String toString() { + return "GasEngine{" + + "horsepower=" + horsepower + + '}'; + } +} \ No newline at end of file diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Machine.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Machine.java new file mode 100644 index 000000000..57dfd7d5f --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/Machine.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities; + +import jakarta.json.bind.annotation.JsonbVisibility; +import jakarta.nosql.Column; +import jakarta.nosql.Convert; +import jakarta.nosql.Entity; +import jakarta.nosql.Id; + +import java.util.Objects; + +@Entity +@JsonbVisibility(FieldAccessStrategy.class) +public class Machine { + + @Id + private String id; + + @Column + @Convert(EngineConverter.class) + private Engine engine; + + @Column + private String manufacturer; + + @Column + private int year; + + public String getId() { + return id; + } + + public Engine getEngine() { + return engine; + } + + public String getManufacturer() { + return manufacturer; + } + + public int getYear() { + return year; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Machine machine = (Machine) o; + return Objects.equals(id, machine.id); + } + + @Override + public int hashCode() { + return Objects.hashCode(id); + } + + @Override + public String toString() { + return "Machine{" + + "id='" + id + '\'' + + ", engine=" + engine + + ", manufacturer='" + manufacturer + '\'' + + ", year=" + year + + '}'; + } +} diff --git a/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/constructor/Survey.java b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/constructor/Survey.java new file mode 100644 index 000000000..7e30345ac --- /dev/null +++ b/jnosql-mapping/jnosql-mapping-semistructured/src/test/java/org/eclipse/jnosql/mapping/semistructured/entities/constructor/Survey.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + */ +package org.eclipse.jnosql.mapping.semistructured.entities.constructor; + +import jakarta.nosql.Column; +import jakarta.nosql.Entity; +import jakarta.nosql.Id; + +import java.util.Map; + +@Entity +public record Survey(@Id String id, @Column Map questions) { +}