Skip to content

Consider property path root in QuerydslBindings #2422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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
6 changes: 4 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.6.0-SNAPSHOT</version>
<version>2.6.0-2418-SNAPSHOT</version>

<name>Spring Data Core</name>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@
*/
interface PathInformation {

/**
* The root property owner type.
*
* @return
* @since 2.5.4
*/
Class<?> getRootParentType();

/**
* The type of the leaf property.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.13
*/
class PropertyPathInformation implements PathInformation {
Expand Down Expand Up @@ -71,6 +72,15 @@ private static PropertyPathInformation of(PropertyPath path) {
return new PropertyPathInformation(path);
}

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getRootParentType()
*/
@Override
public Class<?> getRootParentType() {
return path.getOwningType().getType();
}

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafType()
Expand Down Expand Up @@ -162,12 +172,13 @@ public boolean equals(Object o) {
return true;
}

if (!(o instanceof PropertyPathInformation)) {
if (!(o instanceof PathInformation)) {
return false;
}

PropertyPathInformation that = (PropertyPathInformation) o;
return ObjectUtils.nullSafeEquals(path, that.path);
PathInformation that = (PathInformation) o;
return ObjectUtils.nullSafeEquals(getRootParentType(), that.getRootParentType())
&& ObjectUtils.nullSafeEquals(toDotPath(), that.toDotPath());
}

/*
Expand All @@ -176,7 +187,9 @@ public boolean equals(Object o) {
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(path);
int result = ObjectUtils.nullSafeHashCode(getRootParentType());
result = 31 * result + ObjectUtils.nullSafeHashCode(toDotPath());
return result;
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
*/
public class QuerydslBindings {

// pathSpecs key format: <class.simpleName>.<pathInformation.toDotPath>
private final Map<String, PathAndBinding<?, ?>> pathSpecs;
private final Map<Class<?>, PathAndBinding<?, ?>> typeSpecs;
private final Set<String> allowList;
Expand Down Expand Up @@ -203,7 +204,7 @@ public <S extends Path<? extends T>, T> Optional<MultiValueBinding<S, T>> getBin

Assert.notNull(path, "PropertyPath must not be null!");

PathAndBinding<S, T> pathAndBinding = (PathAndBinding<S, T>) pathSpecs.get(path.toDotPath());
PathAndBinding<S, T> pathAndBinding = (PathAndBinding<S, T>) pathSpecs.get(createKey(path));

if (pathAndBinding != null) {

Expand All @@ -229,7 +230,7 @@ Optional<Path<?>> getExistingPath(PathInformation path) {

Assert.notNull(path, "PropertyPath must not be null!");

return Optional.ofNullable(pathSpecs.get(path.toDotPath())).flatMap(PathAndBinding::getPath);
return Optional.ofNullable(pathSpecs.get(createKey(path))).flatMap(PathAndBinding::getPath);
}

/**
Expand All @@ -249,6 +250,15 @@ PathInformation getPropertyPath(String path, TypeInformation<?> type) {
return null;
}

// fully-qualified path lookup
String key = createKey(type, path);
if (pathSpecs.containsKey(key)) {
return pathSpecs.get(key).getPath()//
.map(QuerydslPathInformation::of)//
.orElse(null);
}

// alias lookup
if (pathSpecs.containsKey(path)) {
return pathSpecs.get(path).getPath()//
.map(QuerydslPathInformation::of)//
Expand All @@ -263,6 +273,28 @@ PathInformation getPropertyPath(String path, TypeInformation<?> type) {
}
}

/**
* Returns the property path key for the given {@link Path}.
*
* @param path can be {@literal null}.
* @return
*/
private static String createKey(Optional<Path<?>> path) {
return path.map(QuerydslPathInformation::of).map(QuerydslBindings::createKey).orElse("");
}

private static String createKey(PathInformation path) {
return createKey(path.getRootParentType(), path.toDotPath());
}

private static String createKey(TypeInformation<?> type, String path) {
return createKey(type.getType(), path);
}

private static String createKey(Class<?> type, String path) {
return type.getSimpleName() + "." + path;
}

/**
* Checks if a given {@link PropertyPath} should be visible for binding values.
*
Expand Down Expand Up @@ -385,7 +417,7 @@ public void all(MultiValueBinding<P, T> binding) {
}

protected void registerBinding(PathAndBinding<P, T> binding) {
QuerydslBindings.this.pathSpecs.put(toDotPath(binding.getPath()), binding);
QuerydslBindings.this.pathSpecs.put(createKey(binding.getPath()), binding);
}
}

Expand Down Expand Up @@ -455,10 +487,12 @@ protected void registerBinding(PathAndBinding<P, T> binding) {

super.registerBinding(binding);

String dotPath = toDotPath(binding.getPath());

if (alias != null) {
QuerydslBindings.this.pathSpecs.put(alias, binding);
QuerydslBindings.this.aliases.add(alias);
QuerydslBindings.this.denyList.add(toDotPath(binding.getPath()));
QuerydslBindings.this.denyList.add(dotPath);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* {@link PathInformation} based on a Querydsl {@link Path}.
*
* @author Oliver Gierke
* @author Mark Paluch
* @since 1.13
*/
class QuerydslPathInformation implements PathInformation {
Expand All @@ -45,7 +46,16 @@ public static QuerydslPathInformation of(Path<?> path) {

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafType()
* @see org.springframework.data.querydsl.binding.PathInformation#getRootParentType()
*/
@Override
public Class<?> getRootParentType() {
return path.getRoot().getType();
}

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafType()
*/
@Override
public Class<?> getLeafType() {
Expand All @@ -54,7 +64,7 @@ public Class<?> getLeafType() {

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafParentType()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafParentType()
*/
@Override
public Class<?> getLeafParentType() {
Expand All @@ -70,7 +80,7 @@ public Class<?> getLeafParentType() {

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafProperty()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafProperty()
*/
@Override
public String getLeafProperty() {
Expand All @@ -79,7 +89,7 @@ public String getLeafProperty() {

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#getLeafPropertyDescriptor()
* @see org.springframework.data.querydsl.binding.PathInformation#getLeafPropertyDescriptor()
*/
@Nullable
@Override
Expand All @@ -89,7 +99,7 @@ public PropertyDescriptor getLeafPropertyDescriptor() {

/*
* (non-Javadoc)
* @see org.springframework.data.querydsl.binding.MappedPath#toDotPath()
* @see org.springframework.data.querydsl.binding.PathInformation#toDotPath()
*/
@Override
public String toDotPath() {
Expand All @@ -115,12 +125,13 @@ public boolean equals(Object o) {
return true;
}

if (!(o instanceof QuerydslPathInformation)) {
if (!(o instanceof PathInformation)) {
return false;
}

QuerydslPathInformation that = (QuerydslPathInformation) o;
return ObjectUtils.nullSafeEquals(path, that.path);
PathInformation that = (PathInformation) o;
return ObjectUtils.nullSafeEquals(getRootParentType(), that.getRootParentType())
&& ObjectUtils.nullSafeEquals(toDotPath(), that.toDotPath());
}

/*
Expand All @@ -129,7 +140,9 @@ public boolean equals(Object o) {
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(path);
int result = ObjectUtils.nullSafeHashCode(getRootParentType());
result = 31 * result + ObjectUtils.nullSafeHashCode(toDotPath());
return result;
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class Address {

public String street, city;
public Double[] lonLat;
public String description;

public Address(String street, String city) {
this.street = street;
Expand Down
5 changes: 1 addition & 4 deletions src/test/java/org/springframework/data/querydsl/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class User {
public List<Address> addresses;
public List<String> nickNames;
public Long inceptionYear;
public String description;

public User(String firstname, String lastname, Address address) {

Expand All @@ -56,7 +57,3 @@ public SpecialUser(String firstname, String lastname, Address address) {
}
}

@QueryEntity
class UserWrapper {
public User user;
}
23 changes: 23 additions & 0 deletions src/test/java/org/springframework/data/querydsl/UserWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.querydsl;

import com.querydsl.core.annotations.QueryEntity;

@QueryEntity
public final class UserWrapper {
public User user;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.querydsl.binding;

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

import org.junit.jupiter.api.Test;

import org.springframework.data.querydsl.QUser;
import org.springframework.data.querydsl.User;

/**
* Unit tests for {@link PropertyPathInformation}.
*
* @author Mark Paluch
*/
class PropertyPathInformationUnitTests {

@Test // GH-2418
void shouldEqualsCorrectly() {

PropertyPathInformation information = PropertyPathInformation.of("address.description", User.class);

QuerydslPathInformation querydslPathInformation = QuerydslPathInformation.of(QUser.user.address.description);

assertThat(information).isEqualTo(querydslPathInformation);
assertThat(querydslPathInformation).isEqualTo(information);
}

@Test // GH-2418
void shouldHashCodeCorrectly() {

PropertyPathInformation information = PropertyPathInformation.of("address.description", User.class);

QuerydslPathInformation querydslPathInformation = QuerydslPathInformation.of(QUser.user.address.description);

assertThat(information).hasSameHashCodeAs(querydslPathInformation);
assertThat(querydslPathInformation).hasSameHashCodeAs(information);
}
}
Loading