Skip to content

Instantly share code, notes, and snippets.

@medkhelifi
Last active March 26, 2021 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save medkhelifi/ee4f7196e1319f807460d8ec9674a724 to your computer and use it in GitHub Desktop.
Save medkhelifi/ee4f7196e1319f807460d8ec9674a724 to your computer and use it in GitHub Desktop.
package com.medkhelifi.api;
import com.medkhelifi.exceptions.enums.ApiErrNumber;
import com.medkhelifi.api.error.ApiError;
import com.medkhelifi.api.error.ApiValidationError;
import com.medkhelifi.api.error.sub.ApiSubError;
import com.medkhelifi.exceptions.ApiException;
import com.medkhelifi.api.success.ApiSuccess;
import com.medkhelifi.api.success.ApiSuccessType;
import com.medkhelifi.util.Util;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Objects;
/**
* Extension of {@link ResponseEntity} that use {@link Api} to represent the HTTP response.
* CustomResponseEntity use builder design pattern ({@link CustomResponseEntityBuilder}) to construct the {@link Api} response.
*
* <code>
* return new CustomResponseEntity.CustomResponseEntityBuilder(OK)
* .data("Hello World")
* .build();
* </code>
* <p>
* The constructor is private, the only way to instantiate it, is to go through the static nested {@link CustomResponseEntityBuilder} class
* </p>
*
* @param <T> the body type
* @author medKhelifi
* @since 0.1.0
*/
public class CustomResponseEntity<T extends Api> extends ResponseEntity<T> {
/**
* Instantiates a new Custom response entity through {@link CustomResponseEntityBuilder}.
*
* @param customResponseEntityBuilder the custom response entity builder
*/
private CustomResponseEntity(CustomResponseEntityBuilder<T> customResponseEntityBuilder){
super(customResponseEntityBuilder.getApi(), customResponseEntityBuilder.api.getHttpStatus());
}
/**
* The Custom response entity builder.
*
* @param <U> the type parameter
*/
public static class CustomResponseEntityBuilder<U extends Api>{
@Getter
private U api;
/**
* Instantiates a new Custom response entity builder.
*
* @param cls the cls
* @param status the status
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder(Class<U> cls, HttpStatus status) throws ApiException {
try {
this.api = cls.getDeclaredConstructor(HttpStatus.class).newInstance(status);
} catch (NullPointerException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
throw new ApiException(ApiErrNumber.API_0001, e);
}
}
/**
* Debug message custom response entity builder.
*
* @param ex the ex
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> debugMessage(Throwable ex) throws ApiException {
this.validateApi();
try{
( (ApiError ) this.api).setDebugMessage(ex.getCause()!=null? ex.getCause().getMessage(): ex.getLocalizedMessage());
}catch (Exception castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Message custom response entity builder.
*
* @param message the message
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> message(java.lang.String message) throws ApiException {
this.validateApi();
this.api.setMessage(message);
return this;
}
/**
* Err number custom response entity builder.
*
* @param apiErrNumber the Api error number
* @return CustomResponseEntityBuilder custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> errNumber(String apiErrNumber) throws ApiException {
this.validateApi();
try{
( (ApiError) this.api).setErrNumber(apiErrNumber);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Define the api success {@link ApiSuccessType}
*
* @param type the type of success response
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> type (ApiSuccessType type) throws ApiException {
this.validateApi();
try{
((ApiSuccess) this.api).setType(type);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Data custom response entity builder.
*
* @param data the data
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> data (Object data) throws ApiException {
this.validateApi();
try{
((ApiSuccess) this.api).setData(data);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Items list custom response entity builder
*
* @param items the list of items
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> items (List<Object> items) throws ApiException {
this.validateApi();
try{
((ApiSuccess) this.api).setItems(items);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Add sub error custom response entity builder.
*
* @param apiSubError the api sub error
* @return custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> addSubError(ApiSubError apiSubError) throws ApiException {
this.validateApi();
try{
((ApiValidationError) this.api).addValidationError(apiSubError);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* Sub error custom response entity builder.
*
* @param apiSubErrors the api sub errors
* @return the custom response entity builder
* @throws ApiException the api exception
*/
public CustomResponseEntityBuilder<U> subError(List<ApiSubError> apiSubErrors) throws ApiException {
this.validateApi();
try{
((ApiValidationError) this.api).setSubErrors(apiSubErrors);
}catch (ClassCastException castEx){
throw new ApiException(ApiErrNumber.API_0002, castEx);
}
return this;
}
/**
* check the {@link Api} instance if it's valid
*/
private void validateApi() throws ApiException {
if(this.api == null )
throw new ApiException(ApiErrNumber.API_0003);
}
/**
* Return the final constructed {@link CustomResponseEntity}
*
* @return CustomResponseEntity custom response entity
*/
public CustomResponseEntity<U> build(){
return new CustomResponseEntity<>(this);
}
}
/**
* Write the {@link HttpServletResponse} response by passing the CustomResponseEntity {@link Api}
*
* @param res The {@link HttpServletResponse }
* @throws IOException Throw {@link IOException} if some problem occurred when {@link HttpServletResponse} writer.
*/
public void responseWriter(HttpServletResponse res) throws IOException {
res.setStatus(this.getStatusCode().value());
res.setContentType("application/json");
res.getWriter().write(Objects.requireNonNull(Util.convertObjectToJson((this.getBody()) )));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment