Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<lombok.version>1.18.38</lombok.version>
<maven.compiler.plugin.version>3.14.0</maven.compiler.plugin.version>
<moshi.version>1.15.2</moshi.version>
<okhttp.version>4.12.0</okhttp.version>
</properties>

<dependencies>
Expand All @@ -69,6 +70,11 @@
<artifactId>moshi</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/dev/resms/core/mapper/IMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.resms.core.mapper;

/** An interface for mapping between JSON representation and Java objects using Moshi. */
public interface IMapper {

/**
* Converts the provided object into its JSON representation.
*
* @param object The object to be converted to JSON.
* @return The JSON representation of the object.
*/
String toJson(Object object);

/**
* Converts the provided JSON value into an instance of the specified class.
*
* @param value The JSON value to be converted.
* @param clazz The class to convert the JSON value to.
* @param <T> The type of the resulting object.
* @return An instance of the specified class with values from the JSON value.
*/
<T> T fromJson(String value, Class<T> clazz);
}
46 changes: 46 additions & 0 deletions src/main/java/dev/resms/core/mapper/ReSMSMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dev.resms.core.mapper;

import com.squareup.moshi.Moshi;
import java.io.IOException;

/**
* Implementation of the IMapper interface for mapping between JSON representation and Java objects
* using Moshi.
*/
public class ReSMSMapper implements IMapper {

private final Moshi moshi;

public ReSMSMapper() {
this.moshi = new Moshi.Builder().build();
}

/**
* Converts the provided object into its JSON representation.
*
* @param object The object to be converted to JSON.
* @return The JSON representation of the object.
*/
@Override
public String toJson(Object object) {
return moshi.adapter(Object.class).toJson(object);
}

/**
* Converts the provided JSON value into an instance of the specified class.
*
* @param value The JSON value to be converted.
* @param clazz The class to convert the JSON value to.
* @param <T> The type of the resulting object.
* @return An instance of the specified class with values from the JSON value.
*/
@Override
public <T> T fromJson(String value, Class<T> clazz) {
try {
return moshi.adapter(clazz).fromJson(value);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
25 changes: 25 additions & 0 deletions src/main/java/dev/resms/core/net/AbstractHttpResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.resms.core.net;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

/**
* Represents an HTTP response containing the response code, body, and success status.
*
* @param <T> The type of the response body.
*/
@Getter
@Setter
@AllArgsConstructor
public class AbstractHttpResponse<T> {

/** The HTTP response code. */
private int code;

/** The response body. */
private T body;

/** Indicates whether the HTTP request was successful. */
private boolean isSuccessful;
}
7 changes: 7 additions & 0 deletions src/main/java/dev/resms/core/net/HttpMethod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.resms.core.net;

/** An enumeration representing common HTTP methods. */
public enum HttpMethod {
GET,
POST,
}
21 changes: 21 additions & 0 deletions src/main/java/dev/resms/core/net/IHttpClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.resms.core.net;

/**
* An interface representing an HTTP client for performing HTTP requests and receiving responses.
*
* @param <T> The type of response data expected.
*/
public interface IHttpClient<T> {

/**
* Perform an HTTP request with the specified path, method, and payload.
*
* @param path The path or endpoint of the request.
* @param apiKey The API Key used to authenticate the request.
* @param method The HTTP method (GET, POST, PUT, DELETE, etc.).
* @param payload The payload or data to send with the request.
* @return An {@link AbstractHttpResponse} representing the response from the server.
*/
AbstractHttpResponse<T> perform(
final String path, final String apiKey, final HttpMethod method, final String payload);
}
64 changes: 64 additions & 0 deletions src/main/java/dev/resms/core/net/impl/HttpClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package dev.resms.core.net.impl;

import dev.resms.core.net.AbstractHttpResponse;
import dev.resms.core.net.HttpMethod;
import dev.resms.core.net.IHttpClient;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
* An implementation of the {@link IHttpClient} interface for performing HTTP requests. This
* implementation uses the OkHttp library for handling HTTP communication.
*/
public class HttpClient implements IHttpClient<Response> {

/** The base URL for the API. */
public static final String BASE_API = "https://api.resms.dev/";

/** The OkHttpClient instance for handling HTTP requests. */
private final OkHttpClient httpClient;

/** Constructs an instance of the HttpClient. */
public HttpClient() {
this.httpClient = new OkHttpClient();
}

/**
* Performs an HTTP request with the specified path, HTTP method, and payload.
*
* @param path The path or endpoint of the request.
* @param apiKey The API Key used to authenticate the request.
* @param method The HTTP method (GET, POST, PUT, DELETE, etc.).
* @param payload The payload or data to send with the request.
* @return An {@link AbstractHttpResponse} representing the response from the server.
*/
@Override
public AbstractHttpResponse<Response> perform(
final String path, final String apiKey, final HttpMethod method, final String payload) {

RequestBody requestBody = null;
if (payload != null) {
requestBody = RequestBody.create(payload, MediaType.get("application/json"));
}

Request request =
new Request.Builder()
.url(BASE_API + path)
.addHeader("Accept", "application/json")
.addHeader("X-Api-Key", apiKey)
.method(method.name(), requestBody)
.build();

try {
Response response = httpClient.newCall(request).execute();
return new AbstractHttpResponse(
response.code(), response.body().string(), response.isSuccessful());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
35 changes: 35 additions & 0 deletions src/main/java/dev/resms/core/service/BaseService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.resms.core.service;

import dev.resms.core.mapper.ReSMSMapper;
import dev.resms.core.net.IHttpClient;
import dev.resms.core.net.impl.HttpClient;
import lombok.Getter;

/**
* An abstract base class for service implementations, providing common functionality such as HTTP
* client, authentication provider, and mapper initialization.
*/
@Getter
public abstract class BaseService {

/** Apikey used for authenticating requests. */
protected final String apiKey;

/** HTTP client for making HTTP requests. */
protected final IHttpClient httpClient;

/** Mapper responsible for mapping data between different representations. */
protected final ReSMSMapper reSMSMapper;

/**
* Constructs a BaseService instance with the specified authentication provider, default HTTP
* client, and mapper.
*
* @param apiKey The apiKey to use.
*/
protected BaseService(final String apiKey) {
this.apiKey = apiKey;
this.httpClient = new HttpClient();
this.reSMSMapper = new ReSMSMapper();
}
}