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"}); + } } + }