Skip to content

Commit 3e6efa7

Browse files
committed
Introduce TypedPropertyPath support.
1 parent 88b6d90 commit 3e6efa7

File tree

7 files changed

+471
-59
lines changed

7 files changed

+471
-59
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/ColumnName.java

Lines changed: 139 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
import java.util.Optional;
1919

2020
import org.jspecify.annotations.Nullable;
21+
22+
import org.springframework.data.core.PropertyPath;
23+
import org.springframework.data.core.TypedPropertyPath;
2124
import org.springframework.util.Assert;
2225

2326
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -36,6 +39,28 @@
3639
*/
3740
public abstract class ColumnName {
3841

42+
/**
43+
* Create a {@link ColumnName} given a {@link TypedPropertyPath property}.
44+
*
45+
* @param property must not be {@literal null}.
46+
* @return the {@link ColumnName} for {@link PropertyPath}
47+
* @since 5.1
48+
*/
49+
public static <T, P> ColumnName from(TypedPropertyPath<T, P> property) {
50+
return from((PropertyPath) TypedPropertyPath.of(property));
51+
}
52+
53+
/**
54+
* Create a {@link ColumnName} given a {@link PropertyPath property}.
55+
*
56+
* @param propertyPath must not be {@literal null}.
57+
* @return the {@link ColumnName} for {@link PropertyPath}
58+
* @since 5.1
59+
*/
60+
public static ColumnName from(PropertyPath propertyPath) {
61+
return new PropertyPathColumnName(propertyPath);
62+
}
63+
3964
/**
4065
* Create a {@link ColumnName} given {@link CqlIdentifier}. The resulting instance uses CQL identifier rules to
4166
* identify column names (quoting, case-sensitivity).
@@ -45,9 +70,6 @@ public abstract class ColumnName {
4570
* @see CqlIdentifier
4671
*/
4772
public static ColumnName from(CqlIdentifier cqlIdentifier) {
48-
49-
Assert.notNull(cqlIdentifier, "Column name must not be null");
50-
5173
return new CqlIdentifierColumnName(cqlIdentifier);
5274
}
5375

@@ -56,26 +78,79 @@ public static ColumnName from(CqlIdentifier cqlIdentifier) {
5678
* column names (case-sensitivity).
5779
*
5880
* @param columnName must not be {@literal null} or empty.
59-
* @return the {@link ColumnName} for {@link CqlIdentifier}
81+
* @return the {@link ColumnName} for {@code columnName}
6082
*/
6183
public static ColumnName from(String columnName) {
62-
63-
Assert.hasText(columnName, "Column name must not be null or empty");
64-
6584
return new StringColumnName(columnName);
6685
}
6786

6887
/**
6988
* @return the optional column name.
7089
*/
71-
public abstract Optional<String> getColumnName();
90+
public Optional<String> getColumnName() {
91+
return Optional.empty();
92+
}
93+
94+
/**
95+
* Indicates whether a column name is available.
96+
*
97+
* @return {@literal true} if a (string or {@link CqlIdentifier}) column name is available; {@literal false}
98+
* otherwise.
99+
* @since 5.1
100+
*/
101+
public boolean hasColumnName() {
102+
return getColumnName().isPresent();
103+
}
104+
105+
/**
106+
* @return the optional {@link PropertyPath}.
107+
*/
108+
public @Nullable PropertyPath getPropertyPath() {
109+
return null;
110+
}
111+
112+
/**
113+
* Indicates whether a {@link PropertyPath} is available.
114+
*
115+
* @return {@literal true} if a {@link PropertyPath} is available; {@literal false} otherwise.
116+
* @since 5.1
117+
*/
118+
public boolean hasPropertyPath() {
119+
return getPropertyPath() != null;
120+
}
121+
122+
/**
123+
* Returns the required {@link PropertyPath} or throws an {@link IllegalStateException} if not available.
124+
*
125+
* @return the required {@link PropertyPath}.
126+
* @throws IllegalStateException if no {@link PropertyPath} is available.
127+
* @since 5.1
128+
*/
129+
public PropertyPath getRequiredPropertyPath() {
130+
131+
PropertyPath propertyPath = getPropertyPath();
132+
133+
if (propertyPath == null) {
134+
throw new IllegalStateException("No PropertyPath available");
135+
}
136+
137+
return propertyPath;
138+
}
72139

73140
/**
74141
* @return the optional {@link CqlIdentifier}.
75142
*/
76-
public abstract Optional<CqlIdentifier> getCqlIdentifier();
143+
public Optional<CqlIdentifier> getCqlIdentifier() {
144+
return Optional.empty();
145+
}
77146

78-
CqlIdentifier getRequiredCqlIdentifier() {
147+
/**
148+
* Returns the required {@link CqlIdentifier} or constructs one from available information.
149+
*
150+
* @return the required {@link CqlIdentifier}.
151+
* @since 5.1
152+
*/
153+
public CqlIdentifier getRequiredCqlIdentifier() {
79154
return getCqlIdentifier().or(() -> getColumnName().map(CqlIdentifier::fromCql))
80155
.orElseGet(() -> CqlIdentifier.fromCql(toCql()));
81156
}
@@ -110,6 +185,54 @@ public int hashCode() {
110185
return hashValue;
111186
}
112187

188+
/**
189+
* {@link PropertyPath}-based column name representation.
190+
*
191+
* @author Mark Paluch
192+
*/
193+
static class PropertyPathColumnName extends ColumnName {
194+
195+
private final PropertyPath propertyPath;
196+
197+
PropertyPathColumnName(PropertyPath propertyPath) {
198+
199+
Assert.notNull(propertyPath, "Property path must not be null");
200+
201+
this.propertyPath = propertyPath;
202+
}
203+
204+
@Override
205+
public Optional<String> getColumnName() {
206+
return Optional.of(toCql());
207+
}
208+
209+
@Override
210+
public PropertyPath getPropertyPath() {
211+
return propertyPath;
212+
}
213+
214+
@Override
215+
public boolean equals(@Nullable Object obj) {
216+
return super.equals(obj)
217+
&& (obj instanceof PropertyPathColumnName that && this.propertyPath.equals(that.propertyPath));
218+
}
219+
220+
@Override
221+
public String toCql() {
222+
return this.propertyPath.toDotPath();
223+
}
224+
225+
@Override
226+
public String toString() {
227+
228+
if (this.propertyPath.hasNext()) {
229+
return this.propertyPath.toString();
230+
}
231+
232+
return this.propertyPath.toDotPath();
233+
}
234+
}
235+
113236
/**
114237
* {@link String}-based column name representation. Preserves letter casing.
115238
*
@@ -120,6 +243,9 @@ static class StringColumnName extends ColumnName {
120243
private final String columnName;
121244

122245
StringColumnName(String columnName) {
246+
247+
Assert.hasText(columnName, "Column name must not be null or empty");
248+
123249
this.columnName = columnName;
124250
}
125251

@@ -128,11 +254,6 @@ public Optional<String> getColumnName() {
128254
return Optional.of(columnName);
129255
}
130256

131-
@Override
132-
public Optional<CqlIdentifier> getCqlIdentifier() {
133-
return Optional.empty();
134-
}
135-
136257
@Override
137258
public String toCql() {
138259
return this.columnName;
@@ -154,12 +275,10 @@ static class CqlIdentifierColumnName extends ColumnName {
154275
private final CqlIdentifier cqlIdentifier;
155276

156277
CqlIdentifierColumnName(CqlIdentifier cqlIdentifier) {
157-
this.cqlIdentifier = cqlIdentifier;
158-
}
159278

160-
@Override
161-
public Optional<String> getColumnName() {
162-
return Optional.empty();
279+
Assert.notNull(cqlIdentifier, "Column name must not be null");
280+
281+
this.cqlIdentifier = cqlIdentifier;
163282
}
164283

165284
@Override

0 commit comments

Comments
 (0)