diff --git a/pom.xml b/pom.xml index cf7c56d..f7b6bbf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.umutayb Utilities - 1.7.6 + 1.7.7 jar Java-Utilities @@ -59,7 +59,7 @@ 1.9.12 2.22.1 3.8.0 - 1.0.0 + 1.0.3 1.8 1.8 4.8.0 @@ -86,65 +86,6 @@ ${context.store.version} - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - - com.squareup.okhttp3 - logging-interceptor - ${okhttp.version} - - - - - com.squareup.retrofit2 - adapter-rxjava - ${retrofit.version} - - - com.squareup.retrofit2 - converter-gson - ${retrofit.version} - - - com.squareup.retrofit2 - retrofit - ${retrofit.version} - - - com.squareup.retrofit2 - converter-jackson - ${retrofit.version} - - - com.squareup.retrofit2 - converter-scalars - ${retrofit.version} - - - com.squareup.retrofit2 - converter-simplexml - ${retrofit.version} - - - com.squareup.retrofit2 - converter-moshi - ${retrofit.version} - - - com.squareup.retrofit2 - converter-protobuf - ${retrofit.version} - - - com.squareup.retrofit2 - converter-wire - ${retrofit.version} - - org.apache.poi @@ -314,7 +255,7 @@ --pinentry-mode loopback - false + true diff --git a/src/main/java/api_assured/ApiUtilities.java b/src/main/java/api_assured/ApiUtilities.java deleted file mode 100644 index 3a10ed4..0000000 --- a/src/main/java/api_assured/ApiUtilities.java +++ /dev/null @@ -1,279 +0,0 @@ -package api_assured; - -import context.ContextStore; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.RequestBody; -import org.junit.Assert; -import retrofit2.Call; -import retrofit2.Response; -import utils.*; -import utils.mapping.MappingUtilities; -import utils.reflection.ReflectionUtilities; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import static utils.StringUtilities.*; -import static utils.reflection.ReflectionUtilities.getPreviousMethodName; -import static utils.reflection.ReflectionUtilities.iterativeConditionalInvocation; - -@SuppressWarnings("unused") -@Deprecated(since = "1.7.4") -public abstract class ApiUtilities extends Caller { - - public static Printer log = new Printer(ApiUtilities.class); - - /** - * Converts file to multipart - * - * @param file target file - * @param name desired name for the multipart - * @return returns the multipart - */ - public static MultipartBody.Part getMultipartFromFile(File file, String name) { - RequestBody body = getRequestBodyFromFile(file); - log.info("Creating multipart from " + file.getName() + " file"); - return MultipartBody.Part.createFormData(name, file.getName(), body); - } - - /** - * Converts file to multipart - * - * @param file target file - * @param name desired name for the multipart - * @param mediaType desired media type - * @return returns the multipart - */ - public static MultipartBody.Part getMultipartFromFile(File file, String name, String mediaType) { - RequestBody body = getRequestBodyFromFile(file, mediaType); - log.info("Creating multipart from " + file.getName() + " file"); - return MultipartBody.Part.createFormData(name, file.getName(), body); - } - - /** - * Converts file to RequestBody - * - * @param file target file - * @return returns the RequestBody - */ - public static RequestBody getRequestBodyFromFile(File file) { - String mediaType; - try { - mediaType = Files.probeContentType(file.toPath()); - } catch (IOException e) { - throw new RuntimeException(e); - } - return getRequestBodyFromFile(file, mediaType); - } - - /** - * Converts file to RequestBody - * - * @param file target file - * @param mediaType desired media type - * @return returns the RequestBody - */ - public static RequestBody getRequestBodyFromFile(File file, String mediaType) { - log.info("Generating request body from " + file.getName() + " file"); - return RequestBody.create(file, MediaType.parse(mediaType)); - } - - /** - * Monitors the response code of a network call within a specified time limit. - * - * @param timeoutInSeconds The time limit (in seconds) for monitoring the response code. - * @param expectedCode The expected HTTP response code to be matched. - * @param call The network call to monitor. - * @param The type of the expected response model. - */ - public void monitorResponseCode( - int timeoutInSeconds, - int expectedCode, - Call call - ) { - String serviceName = getPreviousMethodName(); - iterativeConditionalInvocation( - timeoutInSeconds, - () -> { - boolean condition; - Call callClone = call.clone(); - Response response = getResponse(serviceName, callClone, false, false); - condition = response.code() == expectedCode; - if (condition) { - log.success("Status code verified as " + expectedCode + "!"); - ContextStore.put("monitorResponseCodeResponse", response); - } - return condition; - } - ); - } - - /** - * Monitors the response code of a network call within a specified time limit, print the response body of the last successful call. - * - * @param timeoutInSeconds The time limit (in seconds) for monitoring the response code. - * @param expectedCode The expected HTTP response code to be matched. - * @param call The network call to monitor. - * @param The type of the expected response model. - * @param printLastCallBody If true, print the response body for successful call. - */ - public Response getResponseForCode( - int timeoutInSeconds, - int expectedCode, - Call call, - boolean printLastCallBody - ) { - String serviceName = getPreviousMethodName(); - boolean codeMatch = iterativeConditionalInvocation( - timeoutInSeconds, - () -> responseCodeMatch( - serviceName, - expectedCode, - call, - false, - false, - printLastCallBody - ) - ); - Assert.assertTrue("Response code did not match the expected code " + expectedCode + " within " + timeoutInSeconds + " seconds!", codeMatch); - return ContextStore.get("monitorResponseCodeResponse"); - } - - /** - * Monitors the response code of a network call within a specified time limit, not print the response body. - * - * @param timeoutInSeconds The time limit (in seconds) for monitoring the response code. - * @param expectedCode The expected HTTP response code to be matched. - * @param call The network call to monitor. - * @param The type of the expected response model. - */ - public Response getResponseForCode( - int timeoutInSeconds, - int expectedCode, - Call call - ) { - String serviceName = getPreviousMethodName(); - boolean codeMatch = iterativeConditionalInvocation( - timeoutInSeconds, - () -> responseCodeMatch( - serviceName, - expectedCode, - call, - false, - false, - false - ) - ); - Assert.assertTrue("Response code did not match the expected code " + expectedCode + " within " + timeoutInSeconds + " seconds!", codeMatch); - return ContextStore.get("monitorResponseCodeResponse"); - } - - /** - * Monitors the response field value for compliance with the expected value, print the response body of the last successful call. - * - * @param timeoutInSeconds The time limit (in seconds) for monitoring the response code. - * @param expectedValue The expected value to be matched. - * @param call The network call to monitor. - * @param The type of the expected response model. - * @param printLastCallBody If true, print the response body for successful call - */ - public Response monitorFieldValueFromResponse( - int timeoutInSeconds, - String expectedValue, - Call call, - String fieldName, - boolean printLastCallBody - ) { - String serviceName = getPreviousMethodName(); - boolean codeMatch = iterativeConditionalInvocation( - timeoutInSeconds, - () -> fieldValueMatch( - serviceName, - call, - false, - false, - fieldName, - expectedValue, - printLastCallBody - ) - ); - Assert.assertTrue(highlighted(Color.BLUE, fieldName) + " did not match the expected value " - + highlighted(Color.BLUE, expectedValue) + " within " - + highlighted(Color.BLUE, String.valueOf(timeoutInSeconds)) + " seconds!", codeMatch); - return ContextStore.get("monitorFieldValueResponse"); - } - - /** - * Checks if the HTTP response code of a network call matches the expected code. - * - * @param The type of the expected response model. - * @param serviceName The name of the service for identification purposes. - * @param expectedCode The expected HTTP response code. - * @param call The network call to inspect. - * @param strict If true, performs strict checking of the response code. - * @param printBody If true, prints the response body. - * @param printLastCallBody If true, prints the response body of the last call. - * @return True if the response code matches the expected code; otherwise, false. - */ - - public static boolean responseCodeMatch(String serviceName, - int expectedCode, - Call call, - Boolean strict, - Boolean printBody, - Boolean printLastCallBody) { - Printer log = new Printer(ApiUtilities.class); - boolean condition; - Call callClone = call.clone(); - Response response = getResponse(serviceName, callClone, strict, printBody); - condition = response.code() == expectedCode; - if (condition) { - if (printLastCallBody) { - log.info("Response body: " + MappingUtilities.Json.getJsonStringFor(response.body())); - } - log.success("Status code verified as " + expectedCode + "!"); - ContextStore.put("monitorResponseCodeResponse", response); - } - return condition; - } - - /** - * Checks if the field value of the response body matches the expected value. - * - * @param The type of the expected response model. - * @param serviceName The name of the service for identification purposes. - * @param call The network call to inspect. - * @param strict If true, performs strict checking of the response code. - * @param printBody If true, prints the response body. - * @param fieldName The name of the field to inspect. - * @param expectedValue The expected field value to match. - * @param printLastCallBody If true, prints the response body of the last call. - * @return True if the field value matches the expected value; otherwise, false. - */ - public static boolean fieldValueMatch( - String serviceName, - Call call, - boolean strict, - boolean printBody, - String fieldName, - String expectedValue, - boolean printLastCallBody - ) { - Printer log = new Printer(ApiUtilities.class); - boolean condition; - Call callClone = call.clone(); - Response response = getResponse(serviceName, callClone, strict, printBody); - SuccessModel responseBody = response.body(); - if (responseBody == null) return false; - condition = ReflectionUtilities.getField(fieldName, responseBody).toString().equals(expectedValue); - if (condition) { - if (printLastCallBody) { - log.info("Response body: " + MappingUtilities.Json.getJsonStringFor(response.body())); - } - log.success(fieldName + " is verified as " + expectedValue + "!"); - ContextStore.put("monitorFieldValueResponse", response); - } - return condition; - } -} \ No newline at end of file diff --git a/src/main/java/api_assured/Caller.java b/src/main/java/api_assured/Caller.java deleted file mode 100644 index ab2caf6..0000000 --- a/src/main/java/api_assured/Caller.java +++ /dev/null @@ -1,290 +0,0 @@ -package api_assured; - -import api_assured.exceptions.FailedCallException; -import com.fasterxml.jackson.core.JsonProcessingException; -import okhttp3.ResponseBody; -import okio.Buffer; -import properties.PropertyUtilities; -import retrofit2.Call; -import retrofit2.Response; -import utils.*; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Objects; -import static utils.mapping.MappingUtilities.Json.fromJsonString; -import static utils.mapping.MappingUtilities.Json.getJsonString; -import static utils.reflection.ReflectionUtilities.getPreviousMethodName; -import static utils.StringUtilities.Color.*; -import static utils.reflection.ReflectionUtilities.isOfType; - -/** - * This abstract class represents a caller that performs API calls, logs the results and returns objects in response bodies. - * It contains methods for performing and getting responses from API calls, as well as a method for printing the response body. - * It also has a static boolean variable for keeping logs, an ObjectMapper for JSON serialization and deserialization, - * a StringUtilities object for string manipulation, and a Printer object for logging. - * - * @author Umut Ay Bora - * @version 1.4.0 (Documented in 1.4.0, released in an earlier version) - */ -@SuppressWarnings("unused") -@Deprecated(since = "1.7.4") -public abstract class Caller { - - /** - * A static boolean variable that determines whether logs should be kept for API calls. - */ - protected static boolean keepLogs; - - /** - * A Printer object for logging. - */ - private static final Printer log = new Printer(Caller.class); - - /** - * Constructs a Caller object and initializes the ObjectMapper object and the keepLogs variable. - */ - public Caller(){ - keepLogs = Boolean.parseBoolean(PropertyUtilities.getProperty("keep-api-logs", "true")); - } - - /** - * Performs the given call and processes the response. This method provides advanced error handling capabilities. - * - * @param call The call to be executed. This is a retrofit2.Call object, which represents a request that has been prepared for execution. - * @param strict If true, throws a FailedCallException when the call fails or the response is not successful. If false, returns null in these cases. - * @param printBody If true, prints the body of the response. This may be useful for debugging purposes. - * @param errorModels Varargs parameter. Each ErrorModel class is used to try to parse the error response if the call was not successful. - * - * @return A ResponseType object. If the call was successful, this is the body of the response. If the call was not successful and strict is false, this may be a parsed error response, or null if parsing the error response failed. - * - * @throws FailedCallException If strict is true, and the call failed or the response was not successful. - * - * @param The type of the successful response body. - * @param The type of the return value in this method. This is either SuccessModel or ErrorModel. - */ - @SuppressWarnings("unchecked") - protected static ReturnType perform( - Call call, - Boolean strict, - Boolean printBody, - Class... errorModels){ - Response response = call(call, strict, printBody, getPreviousMethodName()); - return response.isSuccessful() ? (ReturnType) response.body() : getErrorBody(response, errorModels); - } - - /** - * Gets the response from an API call and logs the results. - * - * @param call the Call object representing the API call - * @param strict a boolean indicating whether the call should be strict (i.e. throw an exception if the response is not successful) - * @param printBody a boolean indicating whether the response body should be printed - * @return the Response object representing the API response - * @throws FailedCallException if the call is strict and the response is not successful - */ - protected static Response getResponse(Call call, Boolean strict, Boolean printBody){ - return call(call, strict, printBody, getPreviousMethodName()); - } - - /** - * Gets the response from an API call and logs the results. - * - * @param call the Call object representing the API call - * @param strict a boolean indicating whether the call should be strict (i.e. throw an exception if the response is not successful) - * @param printBody a boolean indicating whether the response body should be printed - * @return the Response object representing the API response - * @throws FailedCallException if the call is strict and the response is not successful - */ - protected static Response getResponse(String serviceName, Call call, Boolean strict, Boolean printBody){ - return call(call, strict, printBody, serviceName); - } - - /** - * Executes the given call and returns a Pair containing the response and potential error model. - * This method provides advanced error handling capabilities. - * - * @param call The call to be executed. This is a retrofit2.Call object, which represents a request that has been prepared for execution. - * @param strict If true, throws a FailedCallException when the call fails or the response is not successful. If false, returns null in these cases. - * @param printBody If true, prints the body of the response. This may be useful for debugging purposes. - * @param errorModels Varargs parameter. Each ErrorModel class is used to try to parse the error response if the call was not successful. - * - * @return A Pair object with the SuccessModel response as the first element and ErrorModel as the second element. If the call was successful, the second element is null. - * If the call was not successful and strict is false, the second element may be a parsed error response, or null if parsing the error response failed. - * - * @throws FailedCallException If strict is true and the call failed or the response was not successful. - * - * @param The type of the successful response body. - * @param The type of the error response body. - */ - protected static ResponsePair, ErrorModel> getResponse( - Call call, - Boolean strict, - Boolean printBody, - Class... errorModels - ){ - Response response = call(call, strict, printBody, getPreviousMethodName()); - return response.isSuccessful() ? - new ResponsePair<>(response, null) : - new ResponsePair<>(response, getErrorBody(response, errorModels)); - } - - /** - * Clones and logs the given response. - * - * @param The type of the response body. - * @param call The original call to execute and log. - * @param printBody Flag to indicate whether the response body should be logged. - * @return A new cloned response object. - */ - private static Response getResponse(Call call, boolean printBody) throws IOException { - Response response = call.execute(); - if (response.isSuccessful()) { - String contentType = response.headers().get("content-type"); - boolean printableResponse = contentType != null && contentType.contains("application/json"); - T body = response.body(); - if (keepLogs) log.success("The response code is: " + response.code()); - if (keepLogs && !response.message().isEmpty()) log.info(response.message()); - if (printBody && printableResponse) log.info("The response body is: \n" + getJsonString(body)); - return Response.success(body, response.raw()); - } - else { - log.warning("The response code is: " + response.code()); - if (response.message().length()>0) log.warning(response.message()); - if (response.errorBody() != null && printBody) { - Object errorBody = isOfType(response, Object.class) ? - getJsonString(getErrorObject(response, Object.class)) : - response.raw(); - String errorLog = errorBody.equals("null") ? - "The error body is empty." : - "The error body is: \n" + errorBody; - log.warning(errorLog); - } - return Response.error(response.errorBody(), response.raw()); - } - } - - /** - * Extracts the error object from the given response and attempts to deserialize it into the specified model. - *

- * The method tries to read the error content from the response and then deserialize it into a generic model type. - * If the deserialization fails or other issues occur while processing the error content, a runtime exception is thrown. - *

- * - * @param The generic type representing the desired structure of the error object. - * @param response The response containing the potential error data. - * @return A deserialized error object instance of type {@code Model}. - * @throws RuntimeException if there's an issue processing the error content or deserializing it. - * - * @see utils.mapping.MappingUtilities.Json#fromJsonString(String, Class) - */ - @SuppressWarnings("unchecked") - private static ErrorModel getErrorObject(Response response, Class errorModel) throws JsonProcessingException { - assert response.errorBody() != null; - if (errorModel.isAssignableFrom(ResponseBody.class)) - return (ErrorModel) response.errorBody(); - try (Buffer errorBuffer = response.errorBody().source().getBuffer().clone()) { - String bodyString = errorBuffer.readString(StandardCharsets.UTF_8); - if (!StringUtilities.isBlank(bodyString)) { - if (errorModel.isAssignableFrom(String.class)) - return (ErrorModel) bodyString; - else return fromJsonString(bodyString, errorModel); - } - else - return null; - } - } - - /** - * Logs the HTTP method, service name, and URL for a given call if logging is enabled. - * - * @param The type of the response body. - * @param call The call object containing request details. - * @param serviceName The name of the service being called. - */ - private static void printCallSpecifications(Call call, String serviceName){ - if (keepLogs) - log.info("Performing " + - StringUtilities.markup(PALE, call.request().method()) + - " call for '" + - StringUtilities.markup(PALE, serviceName) + - "' service on url: " + call.request().url() - ); - } - - /** - * Executes the given call, logs the response or error, and optionally throws an exception for non-successful responses. - * - * @param call The call object to execute. - * @param strict Flag to indicate whether an exception should be thrown for non-successful responses. - * @param printBody Flag to indicate whether the response body should be logged. - * @param serviceName The name of the service being called. - * @return The response object from the executed call. - * @throws RuntimeException If there's an I/O error during call execution. - * @throws FailedCallException If the call is strict and the response is not successful. - */ - private static Response call( - Call call, - boolean strict, - boolean printBody, - String serviceName){ - try { - printCallSpecifications(call, serviceName); - Response response = getResponse(call, printBody); - if (strict && !Objects.requireNonNull(response).isSuccessful()) - throw new FailedCallException( - "The strict call performed for " + serviceName + " service returned response code " + response.code() - ); - else return response; - } - catch (IOException e) {throw new RuntimeException(e);} - } - - /** - * Attempts to extract and deserialize the error model from the given response using the specified error models. - *

- * The method iterates through the provided error models, trying to deserialize the error content of the response - * to each one until a successful deserialization is found or all error models have been tested. - * If none of the error models match, a runtime exception is thrown. - *

- * - * @param The generic type representing the expected error model structure. - * @param response The response containing the potential error data. - * @param errorModels Varargs array of error model classes to attempt deserialization. - * @return A deserialized error model instance of type {@code ErrorModel} if a match is found. - * @throws RuntimeException if none of the provided error models match the error content of the response. - * - * @see utils.mapping.MappingUtilities.Json#fromJsonString(String, Class) - * @see utils.mapping.MappingUtilities.Json#getJsonStringFor(Object) - * @see #getErrorObject(Response, Class) - */ - @SuppressWarnings("unchecked") - private static ErrorModel getErrorBody(Response response, Class... errorModels){ - for (Class errorClass:errorModels){ - try { - ErrorModel errorModel = (ErrorModel) getErrorObject(response, errorClass); - assert errorModel != null; - if (errorClass.isAssignableFrom(errorModel.getClass())) - return errorModel; - } - catch (JsonProcessingException ignored) {} - } - throw new RuntimeException("Error model(s) did not match the error body!"); - } - - /** - * Returns whether logs are being kept for API calls. - * - * @return a boolean indicating whether logs are being kept for API calls - */ - public static boolean keepsLogs() { - return keepLogs; - } - - /** - * Sets whether logs should be kept for API calls. - * - * @param keepLogs a boolean indicating whether logs should be kept for API calls - */ - public static void keepLogs(boolean keepLogs) { - Caller.keepLogs = keepLogs; - } -} \ No newline at end of file diff --git a/src/main/java/api_assured/ResponsePair.java b/src/main/java/api_assured/ResponsePair.java deleted file mode 100644 index 10fbb70..0000000 --- a/src/main/java/api_assured/ResponsePair.java +++ /dev/null @@ -1,10 +0,0 @@ -package api_assured; - -/** - * A record that represents a response and its errorBody. - * - * @param expected Response-SuccessModel- - * @param potential error body - */ -@Deprecated(since = "1.7.4") -public record ResponsePair(Response response, ErrorBody errorBody) { } diff --git a/src/main/java/api_assured/ServiceGenerator.java b/src/main/java/api_assured/ServiceGenerator.java deleted file mode 100644 index f888c26..0000000 --- a/src/main/java/api_assured/ServiceGenerator.java +++ /dev/null @@ -1,512 +0,0 @@ -package api_assured; - -import context.ContextStore; -import okhttp3.Headers; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.logging.HttpLoggingInterceptor; -import okio.Buffer; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.converter.jackson.JacksonConverterFactory; -import retrofit2.converter.moshi.MoshiConverterFactory; -import retrofit2.converter.protobuf.ProtoConverterFactory; -import retrofit2.converter.scalars.ScalarsConverterFactory; -import retrofit2.converter.simplexml.SimpleXmlConverterFactory; -import retrofit2.converter.wire.WireConverterFactory; -import utils.*; -import utils.reflection.ReflectionUtilities; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static utils.mapping.MappingUtilities.Json.getJsonString; -import static utils.mapping.MappingUtilities.Json.mapper; - -/** - * The ServiceGenerator class is responsible for generating Retrofit Service based on the provided service class - * and configurations. It also provides methods to set and get different configurations like headers, timeouts, - * and base URL. - * - * @author Umut Ay Bora - * @version 1.4.0 (Documented in 1.4.0, released in version 1.0.0) - */ -@SuppressWarnings({"unused", "UnusedReturnValue"}) -@Deprecated(since = "1.7.4") -public class ServiceGenerator { - - OkHttpClient client; - - /** - * The header object containing the headers to be added to the requests. - */ - Headers headers = new Headers.Builder().build(); - - /** - * A boolean indicating whether to log the headers in the requests. - */ - boolean printHeaders = Boolean.parseBoolean(ContextStore.get("log-headers", "true")); - - /** - * A boolean indicating whether to log detailed information in the requests. - */ - boolean detailedLogging = Boolean.parseBoolean(ContextStore.get("detailed-logging", "false")); - - /** - * A boolean indicating whether to verify the hostname in the requests. - */ - boolean hostnameVerification = Boolean.parseBoolean(ContextStore.get("verify-hostname", "true")); - - /** - * A boolean indicating whether to print request body in the outgoing requests. - */ - boolean printRequestBody = Boolean.parseBoolean(ContextStore.get("print-request-body", "false")); - - /** - * Connection timeout in seconds. - */ - int connectionTimeout = Integer.parseInt(ContextStore.get("connection-timeout", "60")); - - /** - * Read timeout in seconds. - */ - int readTimeout = Integer.parseInt(ContextStore.get("connection-read-timeout", "30")); - - /** - * Write timeout in seconds. - */ - int writeTimeout = Integer.parseInt(ContextStore.get("connection-write-timeout", "30")); - - /** - * Proxy host. (default: null) - */ - String proxyHost = ContextStore.get("proxy-host", null); - - /** - * Proxy port (default: 8888) - */ - int proxyPort = Integer.parseInt(ContextStore.get("proxy-port", "8888")); - - /** - * Follow redirects? - */ - boolean followRedirects = Boolean.parseBoolean(ContextStore.get("request-follows-redirects", "false")); - - /** - * Use proxy? - */ - boolean useProxy = proxyHost != null; - - /** - * The base URL for the service. - */ - String BASE_URL = ""; - - /** - * The logger object for logging information. - */ - private static final Printer log = new Printer(ServiceGenerator.class); - - /** - * Constructor for the ServiceGenerator class with headers and base URL. - * - * @param headers The headers to be added to the requests. - * @param BASE_URL The base URL for the service. - */ // TODO: Constructor should reference each other - public ServiceGenerator(Headers headers, String BASE_URL) { - this(BASE_URL); - setHeaders(headers); - } - - /** - * Constructor for the ServiceGenerator class with headers. - * - * @param headers The headers to be added to the requests. - */ - public ServiceGenerator(Headers headers) {setHeaders(headers);} - - /** - * Constructor for the ServiceGenerator class with base URL. - * - * @param BASE_URL The base URL for the service. - */ - public ServiceGenerator(String BASE_URL) {this.BASE_URL = BASE_URL;} - - /** - * Default constructor for the ServiceGenerator class. - */ - public ServiceGenerator(){} - - /** - * Creates Retrofit Service based on the provided service class and configurations. - * - * @param serviceClass The service class (api data store) to be used when creating Retrofit Service. - * @return The created Retrofit Service. - */ - public static S generate( - Class serviceClass, - String BASE_URL, - boolean detailedLogging, - int connectionTimeout, - int readTimeout, - int writeTimeout, - Headers headers, - boolean printRequestBody, - boolean printHeaders, - boolean hostnameVerification, - String proxyHost - ) { - return new ServiceGenerator(headers, BASE_URL) - .setRequestLogging(printRequestBody) - .hostnameVerification(hostnameVerification) - .detailedLogging(detailedLogging) - .setPoxyHost(proxyHost) - .printHeaders(printHeaders) - .setReadTimeout(readTimeout) - .setWriteTimeout(writeTimeout) - .setConnectionTimeout(connectionTimeout) - .generate(serviceClass); - } - - /** - * Creates Retrofit Service based on the provided service class and configurations. - * - * @param serviceClass The service class (api data store) to be used when creating Retrofit Service. - * @return The created Retrofit Service. - */ - public static S generate(Class serviceClass, String BASE_URL) { - return new ServiceGenerator(BASE_URL).generate(serviceClass); - } - - /** - * Creates Retrofit Service based on the provided service class and configurations. - * - * @param serviceClass The service class (api data store) to be used when creating Retrofit Service. - * @return The created Retrofit Service. - */ - public S generate(Class serviceClass) { - - if (BASE_URL.isEmpty()) BASE_URL = (String) ReflectionUtilities.getFieldValue("BASE_URL", serviceClass); - - client = client == null ? getDefaultHttpClient() : client; - - assert BASE_URL != null; - @SuppressWarnings("deprecation") - Retrofit retrofit = new Retrofit.Builder() - .baseUrl(BASE_URL) - .addConverterFactory(JacksonConverterFactory.create(mapper)) - .addConverterFactory(GsonConverterFactory.create()) - .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(SimpleXmlConverterFactory.create()) //Deprecated - .addConverterFactory(MoshiConverterFactory.create()) - .addConverterFactory(WireConverterFactory.create()) - .addConverterFactory(ProtoConverterFactory.create()) - .client(client) - .build(); - return retrofit.create(serviceClass); - } - - /** - * Sets the OkHttpClient instance to be used by the ServiceGenerator. - * - * @param client the OkHttpClient instance to be set - * @return the current instance of ServiceGenerator for method chaining - */ - public ServiceGenerator setHttpClient(OkHttpClient client){ - this.client = client; - return this; - } - - /** - * Creates and returns a default OkHttpClient instance with predefined configurations. - *

- * This client includes: - *

    - *
  • Logging interceptors for both body and headers.
  • - *
  • Connection, read, and write timeouts.
  • - *
  • Redirect handling.
  • - *
  • A network interceptor for modifying requests before execution.
  • - *
- * The interceptor ensures headers are set, logs the request body if enabled, - * and prints headers when required. - * - * @return a configured OkHttpClient instance - */ - public OkHttpClient getDefaultHttpClient(){ - OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(connectionTimeout, TimeUnit.SECONDS) - .readTimeout(readTimeout, TimeUnit.SECONDS) - .writeTimeout(writeTimeout, TimeUnit.SECONDS) - .followRedirects(followRedirects) - .addNetworkInterceptor(chain -> { - Request request = chain.request().newBuilder().build(); - request = request.newBuilder() - .header("Host", request.url().host()) - .method(request.method(), request.body()) - .build(); - for (String header: headers.names()) { - if (!request.headers().names().contains(header)){ - request = request.newBuilder() - .addHeader(header, Objects.requireNonNull(headers.get(header))) - .build(); - } - } - if (request.body() != null) { - Boolean contentLength = Objects.requireNonNull(request.body()).contentLength()!=0; - Boolean contentType = Objects.requireNonNull(request.body()).contentType() != null; - - if (contentLength && contentType) - request = request.newBuilder() - .header( - "Content-Length", - String.valueOf(Objects.requireNonNull(request.body()).contentLength())) - .header( - "Content-Type", - String.valueOf(Objects.requireNonNull(request.body()).contentType())) - .build(); - - if (printRequestBody) { - Request cloneRequest = request.newBuilder().build(); - if (cloneRequest.body()!= null){ - Buffer buffer = new Buffer(); - cloneRequest.body().writeTo(buffer); - String bodyString = buffer.readString(UTF_8); - try { - Object jsonObject = mapper.readValue(bodyString, Object.class); - String outgoingRequestLog = "The request body is: \n" + getJsonString(jsonObject); - log.info(outgoingRequestLog); - } - catch (IOException ignored) { - log.warning("Could not log request body!\nBody: " + bodyString); - } - } - else log.warning("Request body is null!"); - } - } - if (printHeaders) - log.info(("Headers(" + request.headers().size() + "): \n" + request.headers()).trim()); - return chain.proceed(request); - }).build(); - - if (detailedLogging) - client = new OkHttpClient.Builder(client) - .addInterceptor(getLogginInterceptor(HttpLoggingInterceptor.Level.BODY)) - .addInterceptor(getLogginInterceptor(HttpLoggingInterceptor.Level.HEADERS)) - .build(); - - if (!hostnameVerification) - client = new OkHttpClient.Builder(client).hostnameVerifier((hostname, session) -> true).build(); - - if (useProxy) - client = new OkHttpClient.Builder(client) - .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort))) - .build(); - - return client; - } - - /** - * Creates and returns an {@link HttpLoggingInterceptor} with the specified logging level. - *

- * This interceptor is used to log HTTP request and response details, - * such as headers, body, and metadata, depending on the provided level. - * - * @param level the logging level to set for the interceptor (e.g., BODY, HEADERS, BASIC, NONE) - * @return an {@link HttpLoggingInterceptor} instance configured with the specified level - */ - public HttpLoggingInterceptor getLogginInterceptor(HttpLoggingInterceptor.Level level){ - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); - interceptor.setLevel(level); - return interceptor; - } - - /** - * Sets whether to log the headers in the requests. - * - * @param printHeaders A boolean indicating whether to log the headers in the requests. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator printHeaders(boolean printHeaders) { - this.printHeaders = printHeaders; - return this; - } - - /** - * Sets whether to log detailed information in the requests. - * - * @param detailedLogging A boolean indicating whether to log detailed information in the requests. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator detailedLogging(boolean detailedLogging) { - this.detailedLogging = detailedLogging; - return this; - } - - /** - * Sets whether to verify the hostname in the requests. - * - * @param hostnameVerification A boolean indicating whether to verify the hostname in the requests. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator hostnameVerification(boolean hostnameVerification) { - this.hostnameVerification = hostnameVerification; - return this; - } - - /** - * Sets whether to print request bodies in the outgoing requests. - * - * @param logRequestBody A boolean indicating whether to print request bodies in the outgoing requests. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setRequestLogging(boolean logRequestBody) { - this.printRequestBody = logRequestBody; - return this; - } - - /** - * Sets the headers to be added to the requests. - * - * @param headers The headers to be added to the requests. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setHeaders(Headers headers){ - this.headers = headers; - return this; - } - - /** - * Gets the headers to be added to the requests. - * - * @return The headers to be added to the requests. - */ - public Headers getHeaders() { - return headers; - } - - /** - * Gets whether to log the headers in the requests. - * - * @return A boolean indicating whether to log the headers in the requests. - */ - public boolean printHeaders() { - return printHeaders; - } - - /** - * Gets whether to log detailed information in the requests. - * - * @return A boolean indicating whether to log detailed information in the requests. - */ - public boolean detailedLogs() { - return detailedLogging; - } - - /** - * Gets whether to verify the hostname in the requests. - * - * @return A boolean indicating whether to verify the hostname in the requests. - */ - public boolean isHostnameVerification() { - return hostnameVerification; - } - - /** - * Sets the connection timeout in seconds. - * - * @param connectionTimeout The connection timeout in seconds. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - return this; - } - - /** - * Sets the read timeout in seconds. - * - * @param readTimeout The read timeout in seconds. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - /** - * Sets write timeout in seconds. - * - * @param writeTimeout write timeout in seconds. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setWriteTimeout(int writeTimeout) { - this.writeTimeout = writeTimeout; - return this; - } - - /** - * Sets write timeout in seconds. - * - * @param proxyHost proxy host. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setPoxyHost(String proxyHost) { - this.proxyHost = proxyHost; - return this; - } - - /** - * Sets write timeout in seconds. - * - * @param proxyPort proxy host. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setPoxyPort(int proxyPort) { - this.proxyPort = proxyPort; - return this; - } - - /** - * Sets the base URL for the service. - * - * @param BASE_URL The base URL for the service. - * @return The updated ServiceGenerator object. - */ - public ServiceGenerator setBASE_URL(String BASE_URL) { - this.BASE_URL = BASE_URL; - return this; - } - - /** - * Gets connection timeout in seconds. - * - * @return connection timeout in seconds. - */ - public int getConnectionTimeout() { - return connectionTimeout; - } - - /** - * Gets read timeout in seconds. - * - * @return read timeout in seconds. - */ - public int getReadTimeout() { - return readTimeout; - } - - /** - * Gets write timeout in seconds. - * - * @return write timeout in seconds. - */ - public int getWriteTimeout() { - return writeTimeout; - } -} \ No newline at end of file diff --git a/src/main/java/api_assured/exceptions/FailedCallException.java b/src/main/java/api_assured/exceptions/FailedCallException.java deleted file mode 100644 index 507c63c..0000000 --- a/src/main/java/api_assured/exceptions/FailedCallException.java +++ /dev/null @@ -1,16 +0,0 @@ -package api_assured.exceptions; - -/** - * This class represents an exception that is thrown when a call fails. - */ -@Deprecated(since = "1.7.4") -public class FailedCallException extends RuntimeException { - - /** - * Constructs a FailedCallException with the specified runtime exception. - * @param errorMessage The runtime exception to be associated with this exception. - */ - public FailedCallException(String errorMessage) {super(errorMessage);} - - public FailedCallException(RuntimeException errorMessage) {super(errorMessage);} -} diff --git a/src/main/java/api_assured/exceptions/JavaUtilitiesException.java b/src/main/java/exceptions/JavaUtilitiesException.java similarity index 89% rename from src/main/java/api_assured/exceptions/JavaUtilitiesException.java rename to src/main/java/exceptions/JavaUtilitiesException.java index 3d1b94d..db9e65f 100644 --- a/src/main/java/api_assured/exceptions/JavaUtilitiesException.java +++ b/src/main/java/exceptions/JavaUtilitiesException.java @@ -1,9 +1,8 @@ -package api_assured.exceptions; +package exceptions; /** * This class represents an exception that is thrown when an error occurs in JavaUtilities. */ -@Deprecated(since = "1.7.4") public class JavaUtilitiesException extends RuntimeException { /** diff --git a/src/main/java/utils/FileUtilities.java b/src/main/java/utils/FileUtilities.java index c502bf9..405afbe 100644 --- a/src/main/java/utils/FileUtilities.java +++ b/src/main/java/utils/FileUtilities.java @@ -1,6 +1,6 @@ package utils; -import api_assured.exceptions.JavaUtilitiesException; +import exceptions.JavaUtilitiesException; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/utils/StringUtilities.java b/src/main/java/utils/StringUtilities.java index 507267d..6301c05 100644 --- a/src/main/java/utils/StringUtilities.java +++ b/src/main/java/utils/StringUtilities.java @@ -3,7 +3,6 @@ import com.google.gson.JsonObject; import context.ContextStore; import org.apache.commons.lang3.RandomStringUtils; -import org.jetbrains.annotations.NotNull; import properties.PropertyUtilities; import java.text.Normalizer; import java.util.*; @@ -223,7 +222,7 @@ else if (keyValue[0] == null) * @param input string that is to be context checked * @return value depending on the context (could be from ContextStore, Properties, Random etc) */ - public static String contextCheck(@NotNull String input){ + public static String contextCheck(String input){ if (input.contains("CONTEXT-")) input = ContextStore.get(TextParser.parse("CONTEXT-", null, input)); else if (input.contains("PROPERTY-")){ diff --git a/src/test/java/AppTest.java b/src/test/java/AppTest.java index ca73ec5..3f19fd7 100644 --- a/src/test/java/AppTest.java +++ b/src/test/java/AppTest.java @@ -1,14 +1,10 @@ import collections.Pair; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonObject; import context.ContextStore; import enums.ZoneIds; import org.junit.Assert; import org.junit.Before; -import petstore.PetStore; -import petstore.PetStoreServices; -import petstore.models.Pet; import org.junit.Test; import utils.*; import utils.arrays.ArrayUtilities; @@ -17,14 +13,12 @@ import utils.reflection.ReflectionUtilities; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import static utils.arrays.ArrayUtilities.*; import static utils.email.EmailUtilities.Inbox.EmailField.CONTENT; import static utils.email.EmailUtilities.Inbox.EmailField.SUBJECT; -import static utils.mapping.MappingUtilities.Json.*; import static utils.StringUtilities.contextCheck; public class AppTest { @@ -49,82 +43,6 @@ public void dataGeneratorPetTest() { printer.info("Test!"); } - @Test - public void stringToObjectTest() throws JsonProcessingException { - Pet pet = fromJsonString("{\"id\" : null, \"category\" : {\"id\" : null, \"name\" : \"Cats\"},\"name\" : \"Whiskers\", \"photoUrls\" : [ \"https://example.com/cat.jpg\" ],\"tags\" : [ {\"id\" : 123456789, \"name\" : \"Furry\"}, {\"id\" : 987654321, \"name\" : \"Playful\"} ],\"status\" : \"Available\"}", Pet.class); - printer.success("The stringToObjectTest() test passed!"); - } - - @Test - public void petStatusTest() { - PetStore petStore = new PetStore(); - petStore.getPetsByStatus(PetStoreServices.PetStatus.pending); - printer.success("The petStatusTest() test passed!"); - } - - @Test - public void petPostTest() { - PetStore petStore = new PetStore(); - Pet pet = new Pet(); - pet.setName("doggie"); - List photoUrls = List.of("string"); - pet.setPhotoUrls(photoUrls); - pet.setStatus("available"); - petStore.postPet(pet); - printer.success("The petPostTest() test passed!"); - } - - @Test - public void petCompareJsonTest() { - PetStore petStore = new PetStore(); - List photoUrls = List.of("string1", "string2"); - List tags = new ArrayList<>(); - Pet.DataModel dataModel = new Pet.DataModel(111222L, "dataModel1"); - tags.add(dataModel); - Pet.DataModel category = new Pet.DataModel(3333L, "category"); - Pet pet = new Pet(category, "Puppy", photoUrls, tags, "available"); - Pet createdPet = petStore.postPet(pet); - Pet actualPet = petStore.getPetById(createdPet.getId()); - createdPet.setId(actualPet.getId()); - ReflectionUtilities.objectsMatch(createdPet, actualPet); - printer.success("The petCompareJsonTest() test passed!"); - } - - @Test - public void compareJsonPetWithEmptyArrayNegativeTest() { - PetStore petStore = new PetStore(); - List photoUrls = List.of("string1", "string2"); - List tags = new ArrayList<>(); - Pet.DataModel dataModel = new Pet.DataModel(111222L, "dataModel1"); - tags.add(dataModel); - Pet.DataModel category = new Pet.DataModel(3333L, "category"); - Pet pet = new Pet(category, "Puppy", photoUrls, tags, "available"); - Pet createdPet = petStore.postPet(pet); - Pet actualPet = petStore.getPetById(createdPet.getId()); - createdPet.setId(actualPet.getId()); - createdPet.setPhotoUrls(new ArrayList<>()); - Assert.assertFalse("The compareJsonPetWithEmptyArrayNegativeTest() negative test fails!", ReflectionUtilities.objectsMatch(createdPet, actualPet)); - printer.success("The compareJsonPetWithEmptyArrayNegativeTest() negative test passes!"); - } - - @Test - public void compareJsonPetWithNullFieldValueInObjectNegativeTest() { - PetStore petStore = new PetStore(); - List photoUrls = List.of("string1", "string2"); - List tags = new ArrayList<>(); - Pet.DataModel dataModel = new Pet.DataModel(111222L, "dataModel1"); - tags.add(dataModel); - Pet.DataModel category = new Pet.DataModel(3333L, "category"); - Pet pet = new Pet(category, "Puppy", photoUrls, tags, "available"); - Pet createdPet = petStore.postPet(pet); - Pet actualPet = petStore.getPetById(createdPet.getId()); - createdPet.setId(actualPet.getId()); - Pet.DataModel expectedCategory = new Pet.DataModel(3333L, null); - createdPet.setCategory(expectedCategory); - Assert.assertFalse("The compareJsonPetWithNullFieldValueInObjectNegativeTest() negative test fails!", ReflectionUtilities.objectsMatch(createdPet, actualPet)); - printer.success("The compareJsonPetWithNullFieldValueInObjectNegativeTest() negative test passes!"); - } - @Test public void localisationCapabilityTest() { JsonObject localisationJson = FileUtilities.Json.parseJsonFile("src/test/resources/localisation.json"); @@ -277,20 +195,6 @@ public void filterEmailTest() { printer.success("Sending and receiving emails tests are successful!"); } - @Test - public void setFieldTest() { - Pet pet = new Pet(); - String expectedFieldName = "name"; - String expectedFieldValue = "Bella"; - ReflectionUtilities.setField(pet, expectedFieldName, expectedFieldValue); - Assert.assertEquals( - "Value of field " + expectedFieldName + " does not match!", - expectedFieldValue, - pet.getName() - ); - printer.success("The setFieldTest() test pass!"); - } - @Test public void lastItemOfTest() { List integers = List.of(1, 2, 3, 4, 5); @@ -328,17 +232,6 @@ public void partitionCountTest() { printer.success("The partitionCountTest() test pass!"); } - @Test - public void jsonSchemaTest() { - JsonNode petSchema = MappingUtilities.Json.Schema.getJsonNodeFor(Pet.class); - Assert.assertEquals( - "Generated json schema did not match the expected one!", - "{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"integer\"},\"category\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"integer\"},\"name\":{\"type\":\"string\"}}},\"name\":{\"type\":\"string\"},\"photoUrls\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"tags\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"integer\"},\"name\":{\"type\":\"string\"}}}},\"status\":{\"type\":\"string\"}}}", - petSchema.toString() - ); - printer.success("The jsonSchemaTest() test pass!"); - } - @Test public void dateFormatTest() { String date = "2025-6-20"; diff --git a/src/test/java/petstore/PetStore.java b/src/test/java/petstore/PetStore.java deleted file mode 100644 index 0e8c496..0000000 --- a/src/test/java/petstore/PetStore.java +++ /dev/null @@ -1,36 +0,0 @@ -package petstore; - -import api_assured.ApiUtilities; -import api_assured.ServiceGenerator; -import petstore.models.Pet; -import retrofit2.Call; -import utils.StringUtilities; -import java.util.List; - -import static utils.StringUtilities.*; - -public class PetStore extends ApiUtilities { - - PetStoreServices petStoreServices = new ServiceGenerator() - .setRequestLogging(true) - .printHeaders(true) - .generate(PetStoreServices.class); - - public List getPetsByStatus(PetStoreServices.PetStatus status){ - log.info("Getting pets by status: " + highlighted(StringUtilities.Color.BLUE, status.name())); - Call> petByStatusCall = petStoreServices.getPet(status); - return getResponseForCode(30, 200, petByStatusCall, true).body(); - } - - public Pet postPet(Pet pet){ - log.info("Post pet"); - Call postPetCall = petStoreServices.postPet(pet); - return monitorFieldValueFromResponse(30, "available", postPetCall, "status", true).body(); - } - - public Pet getPetById(Long petId){ - log.info("Getting pet by petId: " + highlighted(StringUtilities.Color.BLUE, String.valueOf(petId))); - Call petByIdCall = petStoreServices.getPetById(petId); - return getResponseForCode(30, 200, petByIdCall, true).body(); - } -} diff --git a/src/test/java/petstore/PetStoreServices.java b/src/test/java/petstore/PetStoreServices.java deleted file mode 100644 index 6c7989c..0000000 --- a/src/test/java/petstore/PetStoreServices.java +++ /dev/null @@ -1,27 +0,0 @@ -package petstore; - -import petstore.models.Pet; -import retrofit2.Call; -import retrofit2.http.*; - -import java.util.List; - -public interface PetStoreServices { - - enum PetStatus { - available, - pending, - sold - } - - String BASE_URL = "https://petstore.swagger.io/v2/"; - - @GET("pet/findByStatus") - Call> getPet(@Query("status") PetStatus status); - - @GET("pet/{petId}") - Call getPetById(@Path("petId") Long petId); - - @POST("pet") - Call postPet(@Body Pet pet); -} diff --git a/src/test/java/petstore/models/Pet.java b/src/test/java/petstore/models/Pet.java deleted file mode 100644 index fb9b034..0000000 --- a/src/test/java/petstore/models/Pet.java +++ /dev/null @@ -1,94 +0,0 @@ -package petstore.models; - -import java.util.List; - -public class Pet { - Long id; - DataModel category; - String name; - List photoUrls; - List tags; - String status; - - public Pet(DataModel category, String name, List photoUrls, List tags, String status) { - this.category = category; - this.name = name; - this.photoUrls = photoUrls; - this.tags = tags; - this.status = status; - } - - public Pet() { - } - - public Pet(Long id, DataModel category, String name, List photoUrls, List tags, String status) { - this.id = id; - this.category = category; - this.name = name; - this.photoUrls = photoUrls; - this.tags = tags; - this.status = status; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public DataModel getCategory() { - return category; - } - - public void setCategory(DataModel category) { - this.category = category; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getPhotoUrls() { - return photoUrls; - } - - public void setPhotoUrls(List photoUrls) { - this.photoUrls = photoUrls; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public static class DataModel { - Long id; - String name; - - public DataModel(Long id, String name) { - this.id = id; - this.name = name; - } - - public DataModel() { - } - } -} -