Monday, February 21, 2022

Other Utilities

File checker


public interface AbcFileValidationService {
  boolean isFileExists(@NotBlank String absolutePathToFile);
}

@ValidatedService
public class AbcFileValidationServiceImpl implements AbcFileValidationService {

  @Override
  public boolean isFileExists(@NotBlank final String absolutePathToFile) {
    final FileSystemResource fileResource = new FileSystemResource(absolutePathToFile);
    return fileResource.exists();
  }
}

Thursday, February 17, 2022

JSON Mapper - Adaptor Pattern Approach to hide Jackson API

An example to hide the dependency on Jackson directly:


public interface AbcJsonMapper<K, E> {
  E getEntity(@NotBlank String json, @NotNull Class<E> entityType);

  String getJsonString(@NotNull E entity);

  List<E> getList(@NotBlank String jsonList, @NotNull Class<E> elementClass);

  Map<K, E> getMap(
      @NotBlank String jsonMap,
      @NotNull Class<? extends Map<K, E>> mapClass,
      @NotNull Class<K> keyClass,
      @NotNull Class<E> valueClass);
}

@Value
public class Car {

  private final String color;
  private final String type;

  @JsonCreator
  public Car(@JsonProperty("color") String color, @JsonProperty("type") String type) {
    this.color = color;
    this.type = type;
  }
}

@Service
@RequiredArgsConstructor
@Slf4j
public class AbcJsonMapperImpl<K, E> implements AbcJsonMapper<K, E> {

  @SuppressWarnings("squid:S3749")
  private final ObjectMapper jacksonObjectMapper;

  @Override
  public List<E> getList(@NotBlank final String jsonList, Class<E> elementClass) {
    log.info("jsonListAsString:{}", jsonList);
    List<E> result = Collections.emptyList();
    try {
      result =
          jacksonObjectMapper.readValue(
              jsonList,
              TypeFactory.defaultInstance().constructCollectionType(List.class, elementClass));
    } catch (JsonProcessingException e) {
      throw new AbcApplicationException(
          AbcAlertMessage.ABC_APP_JSON_MSG_PARSING_EXCEPTION
              + " ### ### ### Failed to transfer to a list of"
              + elementClass
              + " from:"
              + jsonList,
          e);
    }
    log.info("result:{}", result);
    return result;
  }

  @Override
  public E getEntity(@NotBlank String json, Class<E> entityType) {
    try {
      return this.jacksonObjectMapper.readValue(json, entityType);
    } catch (JsonProcessingException e) {
      throw new AbcApplicationException(
          AbcAlertMessage.ABC_APP_JSON_MSG_PARSING_EXCEPTION
              + " ### ### ### Failed to map to "
              + entityType
              + "  from:"
              + json,
          e);
    }
  }

  @Override
  public String getJsonString(@NotNull E entity) {
    try {
      return this.jacksonObjectMapper.writeValueAsString(entity);
    } catch (JsonProcessingException e) {
      throw new AbcApplicationException(
          AbcAlertMessage.ABC_APP_JSON_MSG_PARSING_EXCEPTION
              + " ### ### ### Failed to map to Json String from entity:"
              + entity,
          e);
    }
  }

  @Override
  public Map<K, E> getMap(
      @NotBlank String jsonMap,
      @NotNull Class<? extends Map<K, E>> mapClass,
      @NotNull Class<K> keyClass,
      @NotNull Class<E> valueClass) {
    log.info("jsonMap:{}", jsonMap);
    Map<K, E> result = Collections.emptyMap();
    try {
      result =
          jacksonObjectMapper.readValue(
              jsonMap,
              TypeFactory.defaultInstance().constructMapLikeType(mapClass, keyClass, valueClass));
    } catch (JsonProcessingException e) {
      throw new AbcApplicationException(
          AbcAlertMessage.ABC_APP_JSON_MSG_PARSING_EXCEPTION
              + " ### ### ### Failed to transfer to a map of key class: "
              + keyClass
              + ", value class:"
              + valueClass
              + " from:"
              + jsonMap,
          e);
    }
    log.info("result:{}", result);
    return result;
  }
}


@Slf4j
class JsonMapperImplTest {
  private final ObjectMapper objectMapper = new ObjectMapper();

  @Test
  void testStringList() {
    AbcJson<String, String> mapper = new AbcJsonImpl<>(this.objectMapper);
    List<String> list = mapper.getList("[\"A\", \"B\"]", String.class);
    log.info("list:{}", list);
    assertEquals(2, list.size());
  }

  @Test
  void testIntegerList() {
    AbcJson<String, Integer> mapper = new AbcJsonImpl<>(this.objectMapper);
    List<Integer> list = mapper.getList("[1, 2]", Integer.class);
    log.info("list:{}", list);
    assertEquals(2, list.size());
  }

  @Test
  void testCarList() {
    AbcJson<String, Car> mapper = new AbcJsonImpl<>(this.objectMapper);
    String jsonCarListAsString =
        "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
    List<Car> list = mapper.getList(jsonCarListAsString, Car.class);
    log.info("list:{}", list);
    assertEquals(2, list.size());
  }

  @Test
  void testCarMap() {
    AbcJson<String, String> mapper = new AbcJsonImpl<>(this.objectMapper);
    String jsonCarMapAsString = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
    @SuppressWarnings("unchecked")
Map<String, String> map =
        mapper.getMap(
            jsonCarMapAsString,
            (@NotNull Class<? extends Map<String, String>>) (new HashMap<>().getClass()),
            String.class,
            String.class);
    log.info("map:{}", map);
    assertEquals(2, map.keySet().size());
  }

  @Test
  void testGetEntity() {
    AbcJson<String, Car> mapper = new AbcJsonImpl<>(this.objectMapper);
    String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
    Car car = mapper.getEntity(json, Car.class);
    log.info("car:{}", car);
    assertEquals("Black", car.getColor());
    assertEquals("BMW", car.getType());
  }

  @Test
  void testgetJsonString() {
    AbcJson<String, Car> mapper = new AbcJsonImpl<>(this.objectMapper);
    Car car = new Car("Yellow", "BMW");
    String json = mapper.getJsonString(car);
    log.info("json:{}", json);
    assertEquals("{\"color\":\"Yellow\",\"type\":\"BMW\"}", json);
  }
}