Skip to content

Commit 13fa7c4

Browse files
committed
Data Repo Aot Optimizations
Signed-off-by: BoykoAlex <alex.boyko@broadcom.com>
1 parent ee4b29a commit 13fa7c4

File tree

12 files changed

+293
-199
lines changed

12 files changed

+293
-199
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Broadcom, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Broadcom, Inc. - initial API and implementation
10+
*******************************************************************************/
11+
package org.springframework.ide.vscode.boot.java.data;
12+
13+
abstract class AbstractDataRepositoryAotMethodMetadata implements IDataRepositoryAotMethodMetadata {
14+
15+
private String name;
16+
17+
private String signature;
18+
19+
public AbstractDataRepositoryAotMethodMetadata(String name, String signature) {
20+
this.name = name;
21+
this.signature = signature;
22+
}
23+
24+
public String getName() {
25+
return name;
26+
}
27+
28+
public String getSignature() {
29+
return signature;
30+
}
31+
32+
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositoryAotMetadata.java

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,51 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.data;
1212

13-
public record DataRepositoryAotMetadata (String name, String type, String module, DataRepositoryAotMetadataMethod[] methods) {
13+
import org.eclipse.jdt.core.dom.IMethodBinding;
14+
import org.eclipse.jdt.core.dom.ITypeBinding;
15+
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser;
16+
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser.JLRMethod;
17+
18+
public record DataRepositoryAotMetadata (String name, String type, DataRepositoryModule module, IDataRepositoryAotMethodMetadata[] methods) {
1419

15-
public boolean isJPA() {
16-
return module != null && module.toLowerCase().equals("jpa");
20+
public IDataRepositoryAotMethodMetadata findMethod(IMethodBinding method) {
21+
String name = method.getName();
22+
23+
for (IDataRepositoryAotMethodMetadata methodMetadata : methods()) {
24+
25+
if (methodMetadata.getName() != null && methodMetadata.getName().equals(name)) {
26+
27+
String signature = methodMetadata.getSignature();
28+
JLRMethod parsedMethodSignature = JLRMethodParser.parse(signature);
29+
30+
if (parsedMethodSignature.getFQClassName().equals(name())
31+
&& parsedMethodSignature.getMethodName().equals(method.getName())
32+
&& parsedMethodSignature.getReturnType().equals(method.getReturnType().getQualifiedName())
33+
&& parameterMatches(parsedMethodSignature, method)) {
34+
return methodMetadata;
35+
}
36+
}
37+
}
38+
39+
return null;
1740
}
18-
19-
public boolean isMongoDb() {
20-
return module != null && module.toLowerCase().equals("mongodb");
41+
42+
private boolean parameterMatches(JLRMethod parsedMethodSignature, IMethodBinding method) {
43+
String[] parsedParameeterTypes = parsedMethodSignature.getParameters();
44+
ITypeBinding[] methodParameters = method.getParameterTypes();
45+
46+
if (parsedParameeterTypes == null || methodParameters == null || parsedParameeterTypes.length != methodParameters.length) {
47+
return false;
48+
}
49+
50+
for (int i = 0; i < parsedParameeterTypes.length; i++) {
51+
String qualifiedName = methodParameters[i].getQualifiedName();
52+
if (qualifiedName != null && !qualifiedName.equals(parsedParameeterTypes[i])) {
53+
return false;
54+
}
55+
}
56+
57+
return true;
2158
}
59+
2260
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositoryAotMetadataCodeLensProvider.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ static Optional<DataRepositoryAotMetadata> getMetadata(DataRepositoryAotMetadata
108108
return Optional.ofNullable(dataRepositoryAotMetadataService.getRepositoryMetadata(project, repositoryClass));
109109
}
110110

111-
static Optional<DataRepositoryAotMetadataMethod> getMethodMetadata(DataRepositoryAotMetadataService dataRepositoryAotMetadataService, DataRepositoryAotMetadata metadata, IMethodBinding methodBinding) {
111+
static Optional<IDataRepositoryAotMethodMetadata> getMethodMetadata(DataRepositoryAotMetadataService dataRepositoryAotMetadataService, DataRepositoryAotMetadata metadata, IMethodBinding methodBinding) {
112112
final IMethodBinding method = methodBinding.getMethodDeclaration();
113113

114-
return Optional.ofNullable(dataRepositoryAotMetadataService.findMethod(metadata, method));
114+
return Optional.ofNullable(metadata.findMethod(method));
115115
}
116116

117117
protected void provideCodeLens(CancelChecker cancelToken, MethodDeclaration node, TextDocument document, List<CodeLens> resultAccumulator) {
@@ -143,7 +143,7 @@ private List<CodeLens> createCodeLenses(MethodDeclaration node, TextDocument doc
143143
Range range = new Range(startPos, endPos);
144144
AnnotationHierarchies hierarchyAnnot = AnnotationHierarchies.get(node);
145145

146-
Optional<DataRepositoryAotMetadataMethod> methodMetadata = getMethodMetadata(repositoryMetadataService, metadata, mb);
146+
Optional<IDataRepositoryAotMethodMetadata> methodMetadata = getMethodMetadata(repositoryMetadataService, metadata, mb);
147147

148148
if (mb != null && hierarchyAnnot != null && methodMetadata.isPresent()) {
149149

@@ -165,7 +165,7 @@ private List<CodeLens> createCodeLenses(MethodDeclaration node, TextDocument doc
165165
codeLenses.add(new CodeLens(range, impl, null));
166166

167167
if (!isQueryAnnotated) {
168-
String queryStatement = methodMetadata.get().getQueryStatement(metadata);
168+
String queryStatement = methodMetadata.get().getQueryStatement();
169169
if (queryStatement != null) {
170170
Command queryTitle = new Command();
171171
queryTitle.setTitle(queryStatement);
@@ -179,18 +179,18 @@ private List<CodeLens> createCodeLenses(MethodDeclaration node, TextDocument doc
179179
return codeLenses;
180180
}
181181

182-
static FixDescriptor createFixDescriptor(IMethodBinding mb, String docUri, DataRepositoryAotMetadata metadata, DataRepositoryAotMetadataMethod methodMetadata) {
182+
static FixDescriptor createFixDescriptor(IMethodBinding mb, String docUri, DataRepositoryAotMetadata metadata, IDataRepositoryAotMethodMetadata methodMetadata) {
183183
return new FixDescriptor(AddAnnotationOverMethod.class.getName(), List.of(docUri), "Turn into `@Query`")
184184

185185
.withRecipeScope(RecipeScope.FILE)
186186

187187
.withParameters(Map.of(
188-
"annotationType", metadata.isJPA() ? Annotations.DATA_JPA_QUERY : Annotations.DATA_MONGODB_QUERY,
188+
"annotationType", metadata.module() == DataRepositoryModule.JPA ? Annotations.DATA_JPA_QUERY : Annotations.DATA_MONGODB_QUERY,
189189
"method", "%s %s(%s)".formatted(mb.getDeclaringClass().getQualifiedName(), mb.getName(),
190190
Arrays.stream(mb.getParameterTypes())
191191
.map(pt -> pt.getQualifiedName())
192192
.collect(Collectors.joining(", "))),
193-
"attributes", createAttributeList(methodMetadata.getAttributesMap(metadata))));
193+
"attributes", createAttributeList(methodMetadata.getAttributesMap())));
194194
}
195195

196196
private static List<AddAnnotationOverMethod.Attribute> createAttributeList(Map<String, String> attributes) {

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositoryAotMetadataMethod.java

Lines changed: 0 additions & 108 deletions
This file was deleted.

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositoryAotMetadataService.java

Lines changed: 31 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,52 @@
1313
import java.io.File;
1414
import java.io.FileReader;
1515
import java.io.IOException;
16+
import java.lang.reflect.Type;
1617
import java.util.Optional;
1718

18-
import org.eclipse.jdt.core.dom.IMethodBinding;
19-
import org.eclipse.jdt.core.dom.ITypeBinding;
2019
import org.slf4j.Logger;
2120
import org.slf4j.LoggerFactory;
2221
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
2322
import org.springframework.ide.vscode.commons.java.IJavaProject;
24-
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser;
25-
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser.JLRMethod;
2623

2724
import com.google.gson.Gson;
25+
import com.google.gson.GsonBuilder;
26+
import com.google.gson.JsonDeserializationContext;
27+
import com.google.gson.JsonDeserializer;
28+
import com.google.gson.JsonElement;
29+
import com.google.gson.JsonObject;
30+
import com.google.gson.JsonParseException;
2831

2932
/**
3033
* @author Martin Lippert
3134
*/
3235
public class DataRepositoryAotMetadataService {
3336

3437
private static final Logger log = LoggerFactory.getLogger(DataRepositoryAotMetadataService.class);
38+
39+
final private Gson gson = new GsonBuilder().registerTypeAdapter(DataRepositoryAotMetadata.class, new JsonDeserializer<DataRepositoryAotMetadata>() {
40+
41+
@Override
42+
public DataRepositoryAotMetadata deserialize(JsonElement json, Type typeOfT,
43+
JsonDeserializationContext context) throws JsonParseException {
44+
JsonObject o = json.getAsJsonObject();
45+
JsonElement e = o.get("module");
46+
if (e.isJsonPrimitive()) {
47+
String module = e.getAsString();
48+
String name = context.deserialize(o.get("name"), String.class);
49+
String type = context.deserialize(o.get("type"), String.class);
50+
DataRepositoryModule moduleType = DataRepositoryModule.valueOf(module.toUpperCase());
51+
switch (moduleType) {
52+
case MONGODB:
53+
return new DataRepositoryAotMetadata(name, type, moduleType, context.deserialize(o.get("methods"), MongoAotMethodMetadata[].class));
54+
case JPA:
55+
return new DataRepositoryAotMetadata(name, type, moduleType, context.deserialize(o.get("methods"), JpaAotMethodMetadata[].class));
56+
}
57+
}
58+
return null;
59+
}
60+
61+
}).create();
3562

3663
public DataRepositoryAotMetadata getRepositoryMetadata(IJavaProject project, String repositoryType) {
3764
try {
@@ -56,60 +83,12 @@ public DataRepositoryAotMetadata getRepositoryMetadata(IJavaProject project, Str
5683
private DataRepositoryAotMetadata readMetadataFile(File file) {
5784

5885
try (FileReader reader = new FileReader(file)) {
59-
Gson gson = new Gson();
6086
DataRepositoryAotMetadata result = gson.fromJson(reader, DataRepositoryAotMetadata.class);
61-
6287
return result;
6388
}
6489
catch (IOException e) {
6590
return null;
6691
}
6792
}
68-
69-
public String getQueryStatement(DataRepositoryAotMetadata metadata, IMethodBinding method) {
70-
DataRepositoryAotMetadataMethod methodMetadata = findMethod(metadata, method);
71-
return methodMetadata.getQueryStatement(metadata);
72-
}
7393

74-
public DataRepositoryAotMetadataMethod findMethod(DataRepositoryAotMetadata metadata, IMethodBinding method) {
75-
String name = method.getName();
76-
77-
for (DataRepositoryAotMetadataMethod methodMetadata : metadata.methods()) {
78-
79-
if (methodMetadata.name() != null && methodMetadata.name().equals(name)) {
80-
81-
String signature = methodMetadata.signature();
82-
JLRMethod parsedMethodSignature = JLRMethodParser.parse(signature);
83-
84-
if (parsedMethodSignature.getFQClassName().equals(metadata.name())
85-
&& parsedMethodSignature.getMethodName().equals(method.getName())
86-
&& parsedMethodSignature.getReturnType().equals(method.getReturnType().getQualifiedName())
87-
&& parameterMatches(parsedMethodSignature, method)) {
88-
return methodMetadata;
89-
}
90-
}
91-
}
92-
93-
return null;
94-
}
95-
96-
private boolean parameterMatches(JLRMethod parsedMethodSignature, IMethodBinding method) {
97-
String[] parsedParameeterTypes = parsedMethodSignature.getParameters();
98-
ITypeBinding[] methodParameters = method.getParameterTypes();
99-
100-
if (parsedParameeterTypes == null || methodParameters == null || parsedParameeterTypes.length != methodParameters.length) {
101-
return false;
102-
}
103-
104-
for (int i = 0; i < parsedParameeterTypes.length; i++) {
105-
String qualifiedName = methodParameters[i].getQualifiedName();
106-
if (qualifiedName != null && !qualifiedName.equals(parsedParameeterTypes[i])) {
107-
return false;
108-
}
109-
}
110-
111-
return true;
112-
}
113-
114-
11594
}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
/*******************************************************************************
2-
* Copyright (c) 2025 Broadcom
2+
* Copyright (c) 2025 Broadcom, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
66
* https://www.eclipse.org/legal/epl-v10.html
77
*
88
* Contributors:
9-
* Broadcom - initial API and implementation
9+
* Broadcom, Inc. - initial API and implementation
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.data;
1212

13-
/**
14-
* Details about the AOT generated query.
15-
*
16-
* query: For JPA-based repositories, this field contains the generated SQL query statememt for the query method
17-
* filter, sort, projection, pipeline: Query details for MongoDB-based repository query methods
18-
*/
19-
public record DataRepositoryAotMetadataQuery(String query, String filter, String sort, String projection, String pipeline, String fields) {
13+
public enum DataRepositoryModule {
14+
15+
JPA,
16+
MONGODB
17+
2018
}

0 commit comments

Comments
 (0)