Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.perplexhub.rsql.model.account;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
@Entity
public class AccountEntity {

@Id
private String ident;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "account")
private List<AddressHistoryEntity> addressHistory = new ArrayList<>();

public AccountEntity(String ident) {
this.ident = ident;
}

public AccountEntity() {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.github.perplexhub.rsql.model.account;

import jakarta.persistence.Embeddable;
import lombok.Getter;
import lombok.Setter;


@Setter
@Getter
@Embeddable
public class AddressEntity {

private String name;
private String address;

public AddressEntity(String name, String address) {
this.name = name;
this.address = address;
}

public AddressEntity() {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.github.perplexhub.rsql.model.account;

import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;

import java.time.OffsetDateTime;

@Entity
public class AddressHistoryEntity {

@Setter
@Getter
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", nullable = false)
private Long id;

@Setter
@Getter
@ManyToOne
@JoinColumn(name = "account_ident")
AccountEntity account;

OffsetDateTime activeSince;

@Embedded
@AttributeOverride(name = "name", column = @Column(name = "invoice_name"))
@AttributeOverride(name = "address", column = @Column(name = "invoice_address"))
AddressEntity invoiceAddress;

@Embedded
@AttributeOverride(name = "name", column = @Column(name = "shipping_name"))
@AttributeOverride(name = "address", column = @Column(name = "shipping_address"))
AddressEntity shippingAddress;

public AddressHistoryEntity() {
}

public AddressHistoryEntity(
AccountEntity account,
OffsetDateTime activeSince,
AddressEntity invoiceAddress,
AddressEntity shippingAddress) {
this.account = account;
this.activeSince = activeSince;
this.invoiceAddress = invoiceAddress;
this.shippingAddress = shippingAddress;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.perplexhub.rsql.repository.jpa;

import io.github.perplexhub.rsql.model.account.AccountEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;


public interface AccountRepository extends JpaRepository<AccountEntity, String>, JpaSpecificationExecutor<AccountEntity> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import jakarta.persistence.criteria.Path;
import jakarta.persistence.metamodel.Attribute;

import jakarta.persistence.metamodel.ManagedType;
import lombok.Value;

@Value(staticConstructor = "of")
class RSQLJPAContext {

private Path<?> path;
private Attribute<?, ?> attribute;
Path<?> path;
Attribute<?, ?> attribute;
ManagedType<?> managedType;

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ private RSQLJPAContext findPropertyPathInternal(String propertyPath, Path startR
RSQLJPAContext context = findPropertyPathInternal(mappedProperty, root, firstTry);
root = context.getPath();
attribute = context.getAttribute();
classMetadata = context.getManagedType();
} else {
if (!hasPropertyName(mappedProperty, classMetadata)) {
Optional<String> mayBeJSonPath = PathUtils
Expand Down Expand Up @@ -165,7 +166,7 @@ private RSQLJPAContext findPropertyPathInternal(String propertyPath, Path startR
accessControl(type, attribute.getName());
}

return RSQLJPAContext.of(root, attribute);
return RSQLJPAContext.of(root, attribute, classMetadata);
}

private String getKeyJoin(Path<?> root, String mappedProperty) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.*;

import io.github.perplexhub.rsql.custom.CustomType;
import io.github.perplexhub.rsql.model.account.AccountEntity;
import io.github.perplexhub.rsql.model.account.AddressEntity;
import io.github.perplexhub.rsql.model.account.AddressHistoryEntity;
import io.github.perplexhub.rsql.repository.jpa.AccountRepository;
import io.github.perplexhub.rsql.repository.jpa.custom.CustomTypeRepository;
import io.github.perplexhub.rsql.custom.EntityWithCustomType;
import jakarta.persistence.criteria.Expression;
Expand All @@ -23,10 +29,8 @@
import io.github.perplexhub.rsql.model.Status;
import org.assertj.core.api.Assertions;
import org.assertj.core.groups.Tuple;
import org.junit.Ignore;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
Expand Down Expand Up @@ -64,6 +68,9 @@ class RSQLJPASupportTest {
@Autowired
private CustomTypeRepository customTypeRepository;

@Autowired
AccountRepository accountRepository;

@BeforeAll
static void beforeAll() {
RSQLCommonSupport.addConverter(CustomType.class, CustomType::new);
Expand Down Expand Up @@ -1362,11 +1369,82 @@ void resetDBBeforeTest() {
assertEquals(0, size);
}

@Test
void testSearchForActiveSince() { // this is only a simple query test
// Given
AccountEntity account1 = new AccountEntity("account-ident-0");
account1.setAddressHistory(
List.of(
new AddressHistoryEntity(
account1,
OffsetDateTime.of(2024, 7, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "some address 1"),
new AddressEntity("Name 1", "some other address 2")),
new AddressHistoryEntity(
account1,
OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "old address 1"),
new AddressEntity("Name 1", "old address 1"))));
accountRepository.save(account1);
// When
List<AccountEntity> result = accountRepository.findAll(RSQLJPASupport.rsql("addressHistory.activeSince=ge=2024-06-01T00:00:00Z"));
// Then
Assertions.assertThat(result).hasSize(1);
}

@Test
void testSearchInListWhichContainEmbeddedClass() {
// Given
AccountEntity account1 = new AccountEntity("account-ident-1");
account1.setAddressHistory(
List.of(
new AddressHistoryEntity(
account1,
OffsetDateTime.of(2024, 7, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "some address 1"),
new AddressEntity("Name 1", "some other address 2")),
new AddressHistoryEntity(
account1,
OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "old address 1"),
new AddressEntity("Name 1", "old address 1"))));
accountRepository.save(account1);
// When
List<AccountEntity> result = accountRepository.findAll(RSQLJPASupport.rsql("addressHistory.invoiceAddress.name=='Name 1'"));
// Then
Assertions.assertThat(result).hasSize(1);
}

@Test
void testSearchWithReducedPathUsingRSQLMapping() {
// Given
RSQLCommonSupport.addMapping(AccountEntity.class, "invoiceAddress", "addressHistory.invoiceAddress");
AccountEntity account1 = new AccountEntity("account-ident-2");
account1.setAddressHistory(
List.of(
new AddressHistoryEntity(
account1,
OffsetDateTime.of(2024, 7, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "some address 1"),
new AddressEntity("Name 1", "some other address 2")),
new AddressHistoryEntity(
account1,
OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC),
new AddressEntity("Name 1", "old address 1"),
new AddressEntity("Name 1", "old address 1"))));
accountRepository.save(account1);
// When
List<AccountEntity> result = accountRepository.findAll(RSQLJPASupport.rsql("invoiceAddress.name=='Name 1'"));
// Then
Assertions.assertThat(result).hasSize(1);
}

@BeforeEach
void setUp() {
getPropertyWhitelist().clear();
getPropertyBlacklist().clear();
customTypeRepository.deleteAll();
accountRepository.deleteAll();
}

}