Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / generators / JerseySpecific.java
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");
	}
}