Skip to content

Commit

Permalink
Merge pull request #545 from eclipse/feature/support-array-field-para…
Browse files Browse the repository at this point in the history
…meter

[FIX] Adding support to embedded array columns onto entities that are implemented using the Java Record feature
  • Loading branch information
otaviojava authored Aug 26, 2024
2 parents 2f4337d + 2f894e4 commit 47b14f7
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 78 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Version
- Include condition to is NUll and is Not Null in the query
- Include pagination with Query annotation
- Add support to array in the fields
- Add support to array in the fields of java record classes

=== Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package org.eclipse.jnosql.mapping.reflection;

import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.BasicRepository;
import org.eclipse.jnosql.mapping.NoSQLRepository;
import org.eclipse.jnosql.mapping.reflection.entities.AnimalRepository;
import org.eclipse.jnosql.mapping.reflection.entities.Contact;
Expand All @@ -40,7 +39,7 @@ class ClassGraphClassScannerTest {
void shouldReturnEntities() {
Set<Class<?>> entities = classScanner.entities();
Assertions.assertNotNull(entities);
assertThat(entities).hasSize(29)
assertThat(entities).hasSize(31)
.contains(Person.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,30 @@
* Contributors:
*
* Otavio Santana
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.reflection;

import org.eclipse.jnosql.mapping.metadata.ArrayParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.ClassConverter;
import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata;
import org.eclipse.jnosql.mapping.metadata.EntityMetadata;
import org.eclipse.jnosql.mapping.reflection.entities.Book;
import org.eclipse.jnosql.mapping.reflection.entities.constructor.BookUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;


class DefaultArrayParameterMetaDataTest {

private ArrayParameterMetaData fieldMetadata;
interface DefaultArrayParameterMetaDataTest {

@BeforeEach
void setUp(){
ClassConverter converter = new ReflectionClassConverter();
EntityMetadata entityMetadata = converter.apply(BookUser.class);
ConstructorMetadata constructor = entityMetadata.constructor();
this.fieldMetadata = (ArrayParameterMetaData)
constructor.parameters().stream().filter(p -> p.name().equals("magazines"))
.findFirst().orElseThrow();
}
ArrayParameterMetaData fieldMetadata();

@Test
void shouldToString() {
assertThat(fieldMetadata.toString()).isNotEmpty().isNotNull();
default void shouldToString() {
assertThat(fieldMetadata().toString()).isNotEmpty().isNotNull();
}

@Test
void shouldGetElementType(){
assertThat(fieldMetadata.elementType()).isEqualTo(Book.class);
}
Class<?> expectedElementType();

@Test
void shouldArrayInstance() {
List<Book> magazines = List.of(Book.builder().build(), Book.builder().build());

Book[] value = (Book[]) fieldMetadata.arrayInstance(magazines);
assertThat(value).containsExactlyElementsOf(magazines);
default void shouldGetElementType() {
assertThat(fieldMetadata().elementType()).isEqualTo(expectedElementType());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2023 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:
*
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.reflection;

import org.eclipse.jnosql.mapping.metadata.ArrayParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.ClassConverter;
import org.eclipse.jnosql.mapping.metadata.EntityMetadata;
import org.eclipse.jnosql.mapping.reflection.entities.constructor.Game;
import org.eclipse.jnosql.mapping.reflection.entities.constructor.Player;

class DefaultArrayParameterMetaDataWhenEntityClassIsRecordTest implements DefaultArrayParameterMetaDataTest {

@Override
public ArrayParameterMetaData fieldMetadata() {
ClassConverter converter = new ReflectionClassConverter();
EntityMetadata entityMetadata = converter.apply(Player.class);
var constructor = entityMetadata.constructor();
return (ArrayParameterMetaData)
constructor.parameters().stream().filter(p -> p.name().equals("games"))
.findFirst().orElseThrow();
}

@Override
public Class<?> expectedElementType() {
return Game.class;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2023 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
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.reflection;

import org.eclipse.jnosql.mapping.metadata.ArrayParameterMetaData;
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.reflection.entities.Book;
import org.eclipse.jnosql.mapping.reflection.entities.constructor.BookUser;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class DefaultArrayParameterMetaDataWhenEntityIsRegularClassTest implements DefaultArrayParameterMetaDataTest {

@Override
public ArrayParameterMetaData fieldMetadata() {
ClassConverter converter = new ReflectionClassConverter();
EntityMetadata entityMetadata = converter.apply(BookUser.class);
ConstructorMetadata constructor = entityMetadata.constructor();
return (ArrayParameterMetaData)
constructor.parameters().stream().filter(p -> p.name().equals("magazines"))
.findFirst().orElseThrow();
}

@Override
public Class<?> expectedElementType() {
return Book.class;
}


@Test
void shouldArrayInstance() {
List<Book> magazines = List.of(Book.builder().build(), Book.builder().build());
Book[] value = (Book[]) fieldMetadata().arrayInstance(magazines);
assertThat(value).containsExactlyElementsOf(magazines);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2022 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
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.reflection.entities.constructor;

import jakarta.nosql.Entity;
import jakarta.nosql.Id;

@Entity
public record Game(@Id String name) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2022 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
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.reflection.entities.constructor;

import jakarta.nosql.Column;
import jakarta.nosql.Entity;
import jakarta.nosql.Id;

@Entity
public record Player(@Id String nickname, @Column Game[] games) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@
* Contributors:
*
* Otavio Santana
* Maximillian Arruda
*/
package org.eclipse.jnosql.mapping.semistructured;

import org.eclipse.jnosql.communication.TypeReference;
import org.eclipse.jnosql.communication.semistructured.Element;
import org.eclipse.jnosql.mapping.metadata.ArrayParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.ConstructorBuilder;
import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata;
import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.MapParameterMetaData;
import org.eclipse.jnosql.mapping.metadata.ParameterMetaData;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -58,7 +61,8 @@ void convert(EntityConverter converter, Element element, ParameterMetaData metaD
builder.add(entity);

} else {
List<Element> columns = element.get(new TypeReference<>() {});
List<Element> columns = element.get(new TypeReference<>() {
});
Object entity = converter.toEntity(metaData.type(), columns);
builder.add(entity);
}
Expand Down Expand Up @@ -86,6 +90,21 @@ void convert(EntityConverter converter, Element element, ParameterMetaData metaD
Object value = mapParameterMetaData.value(element.value());
builder.add(value);
}

}, ARRAY {
@SuppressWarnings("unchecked")
@Override
void convert(EntityConverter converter, Element element, ParameterMetaData metaData, ConstructorBuilder builder) {
var arrayParameterMetaData = (ArrayParameterMetaData) metaData;
List<List<Element>> embeddable = (List<List<Element>>) element.get();
var elements = Array.newInstance(arrayParameterMetaData.elementType(), embeddable.size());
int index = 0;
for (List<Element> elementsList : embeddable) {
Object item = converter.toEntity(arrayParameterMetaData.elementType(), elementsList);
Array.set(elements, index++, item);
}
builder.add(elements);
}
};

abstract void convert(EntityConverter converter,
Expand All @@ -94,19 +113,30 @@ abstract void convert(EntityConverter converter,

static ParameterConverter of(ParameterMetaData parameter, EntitiesMetadata entities) {
return switch (parameter.mappingType()) {
case COLLECTION -> validateCollection(parameter, entities);
case COLLECTION -> collectionConverter(parameter, entities);
case ARRAY -> arrayConverter(parameter, entities);
case MAP -> MAP;
case ENTITY, EMBEDDED_GROUP -> ENTITY;
default -> DEFAULT;
};
}

private static ParameterConverter validateCollection(ParameterMetaData parameter, EntitiesMetadata entities) {
CollectionParameterMetaData genericParameter = (CollectionParameterMetaData) parameter;
private static ParameterConverter collectionConverter(ParameterMetaData parameter, EntitiesMetadata entities) {
var genericParameter = (CollectionParameterMetaData) parameter;
Class<?> type = genericParameter.elementType();
if (entities.findByClassName(type.getName()).isPresent()) {
return COLLECTION;
}
return DEFAULT;
}

private static ParameterConverter arrayConverter(ParameterMetaData parameter, EntitiesMetadata entities) {
var genericParameter = (ArrayParameterMetaData) parameter;
Class<?> type = genericParameter.elementType();
if (entities.findByClassName(type.getName()).isPresent()) {
return ARRAY;
}
return DEFAULT;
}

}
Loading

0 comments on commit 47b14f7

Please sign in to comment.