package generators;
import java.util.List;
import java.util.Map;
import algorithms.TypeInference;
import code.ast.Annotation;
import code.ast.CompilationUnit;
import code.ast.FieldDeclaration;
import code.ast.ImportDeclaration;
import code.ast.MethodDeclaration;
import code.ast.TypeDeclaration;
import code.ast.VariableDeclaration;
import models.algebra.Type;
import models.dataConstraintModel.DataConstraintModel;
public class JerseySpecific extends RestApiSpecific {
public static final Type typeClient = new Type("Client", "Client");
public JerseySpecific() {
langSpec = new JavaSpecific();
}
@Override
public void addComponentAnnotations(TypeDeclaration component, String resourcePath) {
component.addAnnotation(new Annotation("Component"));
component.addAnnotation(new Annotation("Path", "\"/" + resourcePath + "\""));
}
@Override
public void addGetAnnotations(MethodDeclaration getMethod) {
getMethod.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON"));
getMethod.addAnnotation(new Annotation("GET"));
}
@Override
public void addPutAnnotations(MethodDeclaration putMethod) {
putMethod.addAnnotation(new Annotation("PUT"));
}
@Override
public void addPostAnnotations(MethodDeclaration postMethod) {
postMethod.addAnnotation(new Annotation("POST"));
}
@Override
public void addDeleteAnnotations(MethodDeclaration deleteMethod) {
deleteMethod.addAnnotation(new Annotation("DELETE"));
}
@Override
public void addPathAnnotation(MethodDeclaration method, String resourcePath) {
method.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\""));
}
@Override
public void addPathParamAnnotation(VariableDeclaration var, String paramName) {
var.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\""));
}
@Override
public void addFormParamAnnotation(VariableDeclaration var, String paramName) {
var.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\""));
}
@Override
public void addPlatformSpecificImports(CompilationUnit cu) {
cu.addImport(new ImportDeclaration("jakarta.ws.rs.*"));
cu.addImport(new ImportDeclaration("jakarta.ws.rs.client.*"));
cu.addImport(new ImportDeclaration("jakarta.ws.rs.core.*"));
// cu.addImport(new ImportDeclaration("javax.ws.rs.*"));
// cu.addImport(new ImportDeclaration("javax.ws.rs.client.*"));
// cu.addImport(new ImportDeclaration("javax.ws.rs.core.*"));
cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component"));
cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper"));
cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException"));
}
@Override
public boolean hasHttpClientFieldDeclaration(TypeDeclaration component) {
for (FieldDeclaration field: component.getFields()) {
if (field.getType().equals(typeClient)) {
return true;
}
}
return false;
}
@Override
public void addHttpClientFieldDeclaration(TypeDeclaration component) {
FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()");
component.addField(clientField);
}
@Override
public String getConversionFromJsonString(String fromStrVarName, String toVarName, String toVarType) {
return toVarType + toVarName + langSpec.getAssignment() + langSpec.getConstructorInvocation("ObjectMapper", null) + ".readValue(" + fromStrVarName + ", HashMap.class)";
}
@Override
public String getHttpMethodParamsConstructionStatement(String callerResourceName, List<Map.Entry<Type, Map.Entry<String, String>>> params, boolean isFirstCall) {
String statements = "";
if (isFirstCall) {
statements += "Form ";
}
statements += "form" + langSpec.getAssignment() + langSpec.getConstructorInvocation("Form", null) + langSpec.getStatementDelimiter() + "\n";
for (Map.Entry<Type, Map.Entry<String, String>> param: params) {
Type paramType = param.getKey();
String paramName = param.getValue().getKey();
String value = param.getValue().getValue();
if (DataConstraintModel.typeList.isAncestorOf(paramType)) {
Type compType = TypeInference.getListComponentType(paramType);
String wrapperType = DataConstraintModel.getWrapperType(compType);
if (wrapperType == null) {
statements += langSpec.getForStatementForCollection("i", compType.getInterfaceTypeName(), value) + "\n";
} else {
statements += langSpec.getForStatementForCollection("i", wrapperType, value) + "\n";
}
if (DataConstraintModel.typeTuple.isAncestorOf(compType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeList.isAncestorOf(compType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) {
statements += "\tform.param(\"" + paramName + "\", " + langSpec.getConstructorInvocation("ObjectMapper", null) + ".writeValueAsString(i))" + langSpec.getStatementDelimiter() + "\n"; // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0}
} else {
statements += "\tform.param(\"" + paramName + "\", i.toString())" + langSpec.getStatementDelimiter() + "\n";
}
statements += langSpec.getEndForStatement("i") + "\n";
// return "Entity<String> entity = Entity.entity(" + paramName + ".toString(), MediaType.APPLICATION_JSON);";
} else if (DataConstraintModel.typeTuple.isAncestorOf(paramType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) {
// typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0}
statements += "form.param(\"" + paramName + "\", " + langSpec.getConstructorInvocation("ObjectMapper", null) + ".writeValueAsString(" + value + "))" + langSpec.getStatementDelimiter() + "\n";
} else {
statements += "form.param(\"" + paramName + "\", " + new JavaSpecific().getValueToStringExp(paramType.getImplementationTypeName(), value) + ")" + langSpec.getStatementDelimiter() + "\n";
}
}
if (isFirstCall) {
statements += "Entity<Form> ";
}
statements += "entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED)" + langSpec.getStatementDelimiter();
return statements;
}
@Override
public String getHttpMethodCallStatement(String baseURL, String resourceName, String senderResName, String httpMethod) {
if (senderResName == null) {
return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(entity, String.class)" + langSpec.getStatementDelimiter();
} else {
// For each source resource, a child resource is defined in the destination resource so that its state can be updated separately.
return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "/" + senderResName + "\").request()." + httpMethod + "(entity, String.class)" + langSpec.getStatementDelimiter();
}
}
@Override
public String getHttpMethodCallWithResponseStatement(String baseURL, String resourceName, String httpMethod, String responseTypeName) {
String responseShortTypeName = responseTypeName;
if (responseTypeName.contains("<")) {
responseShortTypeName = responseTypeName.substring(0, responseTypeName.indexOf("<"));
}
return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class)" + langSpec.getStatementDelimiter();
}
@Override
public void addJsonException(MethodDeclaration method) {
method.addThrow("JsonProcessingException");
}
@Override
public boolean hasJsonException(MethodDeclaration method) {
if (method.getThrows() == null || method.getThrows().getExceptions() == null) return false;
return method.getThrows().getExceptions().contains("JsonProcessingException");
}
}