From 79dc25de2fb447ef66abfdce857556bc5965e62a Mon Sep 17 00:00:00 2001 From: anirban das Date: Tue, 16 Mar 2021 03:34:54 +0530 Subject: [PATCH] renamed controller in car and polygon service to search specific controller since the client facing apis of the services are read only in nature, implemented end to end flow of polygon service for all search functionalities --- .../CarServiceConfiguration.java | 2 +- .../car/controller/CarSearchController.java | 16 +-- .../sharenow/car/model/entity/CarEntity.java | 9 +- .../sharenow/car/service/CarService.java | 4 +- .../car/service/impl/CarServiceImpl.java | 40 +++---- .../controller/PolygonSearchController.java | 72 ++++++++++++ .../polygon/model/vo/StrategicPolygonVO.java | 3 + .../polygon/repository/PolygonRepository.java | 6 +- .../polygon/service/PolygonService.java | 11 +- .../service/impl/PolygonServiceImpl.java | 105 +++++++++++++++--- 10 files changed, 211 insertions(+), 57 deletions(-) diff --git a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/configuration/CarServiceConfiguration.java b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/configuration/CarServiceConfiguration.java index 3e70931..082e5fb 100644 --- a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/configuration/CarServiceConfiguration.java +++ b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/configuration/CarServiceConfiguration.java @@ -10,7 +10,7 @@ import java.util.Locale; @Configuration -@EnableRedisRepositories +@EnableRedisRepositories(basePackages = "com.teenthofabud.codingchallenge.sharenow.car.repository") public class CarServiceConfiguration { @Bean diff --git a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/controller/CarSearchController.java b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/controller/CarSearchController.java index d8c72f3..e5c4b8b 100644 --- a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/controller/CarSearchController.java +++ b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/controller/CarSearchController.java @@ -25,20 +25,20 @@ public class CarSearchController { private CarService service; @GetMapping("vin/{vin}") - public ResponseEntity getVehicleByVin(@PathVariable String vin) throws CarServiceException { - LOGGER.info("Requesting vehicle with vin: {}", vin); - CarDetailsVO vo = this.service.retrieveVehicleDetailsByVin(vin); + public ResponseEntity getCarByVin(@PathVariable String vin) throws CarServiceException { + LOGGER.info("Requesting car with vin: {}", vin); + CarDetailsVO vo = this.service.retrieveCarDetailsByVin(vin); ResponseEntity response = ResponseEntity.ok(vo); - LOGGER.info("Responding with vehicle of vin: {}", vin); + LOGGER.info("Responding with car of vin: {}", vin); return response; } @GetMapping - public ResponseEntity getAllVehicles() throws CarServiceException { - LOGGER.info("Requesting all vehicles"); - List voList = this.service.retrieveAllVehicles(); + public ResponseEntity getAllCars() throws CarServiceException { + LOGGER.info("Requesting all cars"); + List voList = this.service.retrieveAllCars(); ResponseEntity> response = ResponseEntity.ok(voList); - LOGGER.info("Responding with all available vehicles"); + LOGGER.info("Responding with all available cars"); return response; } diff --git a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/model/entity/CarEntity.java b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/model/entity/CarEntity.java index 00a517d..d4fad02 100644 --- a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/model/entity/CarEntity.java +++ b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/model/entity/CarEntity.java @@ -15,14 +15,15 @@ @Getter @Setter @ToString -@RedisHash("Vehicle") -@TypeAlias("Vehicle") +@RedisHash("Car") +@TypeAlias("Car") @NoArgsConstructor public class CarEntity implements Serializable { - @Id + @Indexed private int id; private int locationId; + @Id @Indexed private String vin; private String numberPlate; @@ -32,7 +33,7 @@ public class CarEntity implements Serializable { private Date updatedAt; public String getCacheKey() { - return "Vehicle:" + id; + return "Car:" + vin; } public CarEntity(String vin) { diff --git a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/CarService.java b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/CarService.java index 7fcbea9..fa1a280 100644 --- a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/CarService.java +++ b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/CarService.java @@ -10,8 +10,8 @@ @Service public interface CarService { - public List retrieveAllVehicles(); + public List retrieveAllCars(); - public CarDetailsVO retrieveVehicleDetailsByVin(String vin) throws CarServiceException; + public CarDetailsVO retrieveCarDetailsByVin(String vin) throws CarServiceException; } diff --git a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/impl/CarServiceImpl.java b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/impl/CarServiceImpl.java index d8ed010..8e5e2a4 100644 --- a/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/impl/CarServiceImpl.java +++ b/car-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/car/service/impl/CarServiceImpl.java @@ -34,7 +34,7 @@ public class CarServiceImpl implements CarService { private CarEntity2DetailedVOConverter complexVOConverter; - private Comparator cmpVehicleByVin; + private Comparator cmpCarByVin; @PostConstruct private void init() { @@ -69,41 +69,41 @@ private void init() { } return vo; }; - this.cmpVehicleByVin = (v1, v2) -> { - return v1.getVin().compareTo(v2.getVin()); + this.cmpCarByVin = (v1, v2) -> { + if(v1 != null && v2 != null) { + return v1.getVin().compareTo(v2.getVin()); + } else { + return 0; + } }; } @Override - public List retrieveAllVehicles() { + public List retrieveAllCars() { List carVOList = new ArrayList<>(); Iterable entityItr = this.repository.findAll(); for(CarEntity entity : entityItr) { - CarVO vo = this.simpleVOConverter.convert(entity); - carVOList.add(vo); + if(entity != null && StringUtils.hasText(entity.getVin())) { + CarVO vo = this.simpleVOConverter.convert(entity); + carVOList.add(vo); + } } - LOGGER.info("Found {} vehicles", carVOList.size()); + LOGGER.info("Found {} cars", carVOList.size()); return carVOList; } @Override - public CarDetailsVO retrieveVehicleDetailsByVin(String vin) throws CarServiceException { + public CarDetailsVO retrieveCarDetailsByVin(String vin) throws CarServiceException { if(StringUtils.hasText(vin)) { - Iterable entityItr = this.repository.findAll(); - List entityList = new ArrayList<>(); - for(CarEntity entity : entityItr) { - entityList.add(entity); - } - Collections.sort(entityList, cmpVehicleByVin); - int idx = Collections.binarySearch(entityList, new CarEntity(vin), cmpVehicleByVin); - if(idx >= 0) { - CarEntity entity = entityList.get(idx); + Optional optEntity = this.repository.findById(vin); + if(optEntity.isPresent()) { + CarEntity entity = optEntity.get(); CarDetailsVO vo = this.complexVOConverter.convert(entity); - LOGGER.info("Found vehicle by vin: {}", vin); + LOGGER.info("Found car by vin: {}", vin); return vo; } else { - LOGGER.error("No vehicle found with vin: {}", vin); - throw new CarServiceException("No vehicle found that matches with vin", CarErrorCode.NOT_FOUND, new Object[] {"vin", vin}); + LOGGER.error("No car found with vin: {}", vin); + throw new CarServiceException("No car found that matches with vin", CarErrorCode.NOT_FOUND, new Object[] {"vin", vin}); } } else { LOGGER.error("Invalid vin: {}", vin); diff --git a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/controller/PolygonSearchController.java b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/controller/PolygonSearchController.java index 1b9d6b2..2f4040e 100644 --- a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/controller/PolygonSearchController.java +++ b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/controller/PolygonSearchController.java @@ -1,9 +1,81 @@ package com.teenthofabud.codingchallenge.sharenow.polygon.controller; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.error.PolygonServiceException; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.StrategicPolygonDetailedVO; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.StrategicPolygonVO; +import com.teenthofabud.codingchallenge.sharenow.polygon.service.PolygonService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController @RequestMapping("search") public class PolygonSearchController { + + private static final Logger LOGGER = LoggerFactory.getLogger(PolygonSearchController.class); + + @Autowired + private PolygonService service; + + @GetMapping + public ResponseEntity getAllPolygons() { + LOGGER.info("Requesting all polygons"); + List voList = this.service.retrieveAll(); + ResponseEntity> response = ResponseEntity.ok(voList); + LOGGER.info("Responding with all available polygons"); + return response; + } + + @GetMapping("cityid/{cityId}") + public ResponseEntity getAllPolygonsByCityId(@PathVariable String cityId) throws PolygonServiceException { + LOGGER.info("Requesting all polygons with cityId: {}", cityId); + List voList = this.service.retrieveByCityId(cityId); + ResponseEntity> response = ResponseEntity.ok(voList); + LOGGER.info("Responding with all available polygons with cityId: {}", cityId); + return response; + } + + @GetMapping("type/{type}") + public ResponseEntity getAllPolygonsByType(@PathVariable String type) throws PolygonServiceException { + LOGGER.info("Requesting all polygons of type: {}", type); + List voList = this.service.retrieveByType(type); + ResponseEntity> response = ResponseEntity.ok(voList); + LOGGER.info("Responding with all available polygons with type: {}", type); + return response; + } + + @GetMapping("name/{name}") + public ResponseEntity getPolygonByName(@PathVariable String name) throws PolygonServiceException { + LOGGER.info("Requesting all polygons with name: {}", name); + List voList = this.service.retrieveByName(name); + ResponseEntity> response = ResponseEntity.ok(voList); + LOGGER.info("Responding with all available polygons with name: {}", name); + return response; + } + + @GetMapping("id/{id}") + public ResponseEntity getPolygonById(@PathVariable String id) throws PolygonServiceException { + LOGGER.info("Requesting polygon with id: {}", id); + StrategicPolygonDetailedVO vo = this.service.retrieveById(id); + ResponseEntity response = ResponseEntity.ok(vo); + LOGGER.info("Responding with polygon of id: {}", id); + return response; + } + + @GetMapping("legacyid/{legacyId}") + public ResponseEntity getPolygonByCityId(@PathVariable String legacyId) throws PolygonServiceException { + LOGGER.info("Requesting polygon with legacyId: {}", legacyId); + StrategicPolygonDetailedVO vo = this.service.retrieveByLegacyId(legacyId); + ResponseEntity response = ResponseEntity.ok(vo); + LOGGER.info("Responding with polygon of legacyId: {}", legacyId); + return response; + } + } diff --git a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/model/vo/StrategicPolygonVO.java b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/model/vo/StrategicPolygonVO.java index 7981ca4..ca24d63 100644 --- a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/model/vo/StrategicPolygonVO.java +++ b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/model/vo/StrategicPolygonVO.java @@ -1,12 +1,14 @@ package com.teenthofabud.codingchallenge.sharenow.polygon.model.vo; import com.fasterxml.jackson.annotation.JsonProperty; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.entity.GeoFeatureEntity; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.io.Serializable; import java.util.Date; +import java.util.List; @Getter @Setter @@ -24,5 +26,6 @@ public class StrategicPolygonVO implements Serializable { private String legacyId; private String type; private int version; + private List geoFeatures; } diff --git a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/repository/PolygonRepository.java b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/repository/PolygonRepository.java index be29b61..d465478 100644 --- a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/repository/PolygonRepository.java +++ b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/repository/PolygonRepository.java @@ -9,12 +9,12 @@ @Repository public interface PolygonRepository extends MongoRepository { - public StrategicPolygonEntity findByName(String name); + public List findAllByName(String name); - public StrategicPolygonEntity findByCityId(String cityId); + public List findAllByCityId(String cityId); public StrategicPolygonEntity findByLegacyId(String legacyId); - public List findByType(String type); + public List findAllByType(String type); } diff --git a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/PolygonService.java b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/PolygonService.java index beb4ad8..3d330f8 100644 --- a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/PolygonService.java +++ b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/PolygonService.java @@ -1,6 +1,7 @@ package com.teenthofabud.codingchallenge.sharenow.polygon.service; import com.teenthofabud.codingchallenge.sharenow.polygon.model.entity.StrategicPolygonEntity; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.error.PolygonServiceException; import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.StrategicPolygonDetailedVO; import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.StrategicPolygonVO; import org.springframework.stereotype.Service; @@ -12,14 +13,14 @@ public interface PolygonService { public List retrieveAll(); - public StrategicPolygonDetailedVO retrieveById(String id); + public StrategicPolygonDetailedVO retrieveById(String id) throws PolygonServiceException; - public StrategicPolygonDetailedVO retrieveByName(String name); + public StrategicPolygonDetailedVO retrieveByLegacyId(String legacyId) throws PolygonServiceException; - public StrategicPolygonDetailedVO retrieveByCityId(String cityId); + public List retrieveByName(String name) throws PolygonServiceException; - public StrategicPolygonDetailedVO retrieveByLegacyId(String legacyId); + public List retrieveByType(String type) throws PolygonServiceException; - public List retrieveByType(String type); + public List retrieveByCityId(String cityId) throws PolygonServiceException; } diff --git a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/impl/PolygonServiceImpl.java b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/impl/PolygonServiceImpl.java index b120c84..182b655 100644 --- a/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/impl/PolygonServiceImpl.java +++ b/polygon-service/src/main/java/com/teenthofabud/codingchallenge/sharenow/polygon/service/impl/PolygonServiceImpl.java @@ -6,6 +6,8 @@ import com.teenthofabud.codingchallenge.sharenow.polygon.model.entity.OptionsEntity; import com.teenthofabud.codingchallenge.sharenow.polygon.model.entity.StrategicPolygonEntity; import com.teenthofabud.codingchallenge.sharenow.polygon.model.entity.TimedOptionsEntity; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.error.PolygonErrorCode; +import com.teenthofabud.codingchallenge.sharenow.polygon.model.error.PolygonServiceException; import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.ActiveTimedOptionsVO; import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.ComputedVO; import com.teenthofabud.codingchallenge.sharenow.polygon.model.vo.GeoFeatureVO; @@ -20,9 +22,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import javax.annotation.PostConstruct; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Component @@ -57,7 +62,7 @@ private void init() { this.computedConverter = computedConverter(this.activeTimedOptionsConverter); this.strategicPolygonComplexConverter = strategicPolygonComplexConverter(this.computedConverter, this.geoFeatureConverter, this.optionsConverter, this.timedOptionsConverter); - this.strategicPolygonSimpleConverter = strategicPolygonSimpleConverter(); + this.strategicPolygonSimpleConverter = strategicPolygonSimpleConverter(this.geoFeatureConverter); } private Converter activeTimedOptionsConverter() { @@ -147,7 +152,7 @@ private Converter strategicP }; } - private Converter strategicPolygonSimpleConverter() { + private Converter strategicPolygonSimpleConverter(Converter geoFeatureConverter) { return (entity) -> { StrategicPolygonVO vo = new StrategicPolygonVO(); if(entity != null) { @@ -160,7 +165,8 @@ private Converter strategicPolygonSi vo.setUpdatedAt(entity.getUpdatedAt()); vo.setV(entity.getV()); vo.setVersion(entity.getVersion()); - + vo.setGeoFeatures(entity.getGeoFeatures().stream() + .map(gf -> geoFeatureConverter.convert(gf)).collect(Collectors.toList())); } return vo; }; @@ -169,31 +175,102 @@ private Converter strategicPolygonSi @Override public List retrieveAll() { - return null; + List voList = new ArrayList<>(); + List entityList = this.repository.findAll(); + for(StrategicPolygonEntity entity : entityList) { + StrategicPolygonVO vo = this.strategicPolygonSimpleConverter.convert(entity); + voList.add(vo); + } + LOGGER.info("Found {} polygons", voList.size()); + return voList; } @Override - public StrategicPolygonDetailedVO retrieveById(String id) { - return null; + public StrategicPolygonDetailedVO retrieveById(String id) throws PolygonServiceException { + if(StringUtils.hasText(id)) { + Optional optEntity = this.repository.findById(id); + if(optEntity.isPresent()) { + StrategicPolygonEntity entity = optEntity.get(); + StrategicPolygonDetailedVO vo = this.strategicPolygonComplexConverter.convert(entity); + LOGGER.info("Found polygon with id: {}", id); + return vo; + } else { + LOGGER.error("No polygon found with id: {}", id); + throw new PolygonServiceException("No polygon found that matches with id", PolygonErrorCode.NOT_FOUND, new Object[] {"id", id}); + } + } else { + LOGGER.error("Invalid id: {}", id); + throw new PolygonServiceException("Invalid id", PolygonErrorCode.INVALID_PARAMETER, new Object[] {"id"}); + } } @Override - public StrategicPolygonDetailedVO retrieveByName(String name) { - return null; + public StrategicPolygonDetailedVO retrieveByLegacyId(String legacyId) throws PolygonServiceException { + if(StringUtils.hasText(legacyId)) { + StrategicPolygonEntity entity = this.repository.findByLegacyId(legacyId); + if(entity != null) { + StrategicPolygonDetailedVO vo = this.strategicPolygonComplexConverter.convert(entity); + LOGGER.info("Found polygon with legacyId: {}", legacyId); + return vo; + } else { + LOGGER.error("No polygon found with legacyId: {}", legacyId); + throw new PolygonServiceException("No polygon found that matches with legacyId", PolygonErrorCode.NOT_FOUND, new Object[] {"legacyId", legacyId}); + } + } else { + LOGGER.error("Invalid legacyId: {}", legacyId); + throw new PolygonServiceException("Invalid legacyId", PolygonErrorCode.INVALID_PARAMETER, new Object[] {"legacyId"}); + } } @Override - public StrategicPolygonDetailedVO retrieveByCityId(String cityId) { - return null; + public List retrieveByType(String type) throws PolygonServiceException { + if(StringUtils.hasText(type)) { + List voList = new ArrayList<>(); + List entityList = this.repository.findAllByType(type); + for(StrategicPolygonEntity entity : entityList) { + StrategicPolygonVO vo = this.strategicPolygonSimpleConverter.convert(entity); + voList.add(vo); + } + LOGGER.info("Found {} polygons of type: {}", voList.size(), type); + return voList; + } else { + LOGGER.error("Invalid type: {}", type); + throw new PolygonServiceException("Invalid type", PolygonErrorCode.INVALID_PARAMETER, new Object[] {"type"}); + } } @Override - public StrategicPolygonDetailedVO retrieveByLegacyId(String legacyId) { - return null; + public List retrieveByCityId(String cityId) throws PolygonServiceException { + if(StringUtils.hasText(cityId)) { + List voList = new ArrayList<>(); + List entityList = this.repository.findAllByCityId(cityId); + for(StrategicPolygonEntity entity : entityList) { + StrategicPolygonVO vo = this.strategicPolygonSimpleConverter.convert(entity); + voList.add(vo); + } + LOGGER.info("Found {} polygons of cityId: {}", voList.size(), cityId); + return voList; + } else { + LOGGER.error("Invalid cityId: {}", cityId); + throw new PolygonServiceException("Invalid cityId", PolygonErrorCode.INVALID_PARAMETER, new Object[] {"cityId"}); + } } @Override - public List retrieveByType(String type) { - return null; + public List retrieveByName(String name) throws PolygonServiceException { + if(StringUtils.hasText(name)) { + List voList = new ArrayList<>(); + List entityList = this.repository.findAllByName(name); + for(StrategicPolygonEntity entity : entityList) { + StrategicPolygonVO vo = this.strategicPolygonSimpleConverter.convert(entity); + voList.add(vo); + } + LOGGER.info("Found {} polygons of name: {}", voList.size(), name); + return voList; + } else { + LOGGER.error("Invalid name: {}", name); + throw new PolygonServiceException("Invalid name", PolygonErrorCode.INVALID_PARAMETER, new Object[] {"name"}); + } } + }