diff --git a/pom.xml b/pom.xml
index 17fd7ad..83b4779 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,13 +25,18 @@
org.springframework.boot
- spring-boot-starter-data-jdbc
+ spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
-
+
+ org.projectlombok
+ lombok
+ 1.18.24
+ provided
+
org.flywaydb
flyway-core
@@ -49,6 +54,18 @@
spring-boot-starter-test
test
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
diff --git a/src/main/java/com/zoomcare/candidatechallenge/config/SwaggerConfig.java b/src/main/java/com/zoomcare/candidatechallenge/config/SwaggerConfig.java
new file mode 100644
index 0000000..0643b51
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/config/SwaggerConfig.java
@@ -0,0 +1,28 @@
+package com.zoomcare.candidatechallenge.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+ @Bean
+ public Docket challengeApi() {
+ return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName("Candidate Challenge").select()
+ .apis(RequestHandlerSelectors.basePackage("com.zoomcare.candidatechallenge.controllers")).build();
+
+ }
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder().title("Challenge Api").description("The resulting services should allow users to get a list of all top-level employees or to specify an employee by id to return just that employee.")
+ .contact(new Contact("Gabriel Leoni","","")).version("1.0").build();
+ }
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/controllers/EmployeeController.java b/src/main/java/com/zoomcare/candidatechallenge/controllers/EmployeeController.java
new file mode 100644
index 0000000..0e99bf2
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/controllers/EmployeeController.java
@@ -0,0 +1,35 @@
+package com.zoomcare.candidatechallenge.controllers;
+
+import java.math.BigInteger;
+import java.util.List;
+
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.zoomcare.candidatechallenge.map.EmployeeData;
+import com.zoomcare.candidatechallenge.service.EmployeeService;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@RestController
+@RequestMapping("/employee")
+public class EmployeeController {
+
+ @Autowired
+ private EmployeeService employeeService;
+
+ @GetMapping
+ public ResponseEntity getEmployee(BigInteger id) {
+ return employeeService.getEmployeeData(id);
+ }
+
+ @GetMapping("/topLevel")
+ public ResponseEntity> getTopLevelEmployee() {
+ return employeeService.getTopLevelEmployee();
+ }
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/entities/Employee.java b/src/main/java/com/zoomcare/candidatechallenge/entities/Employee.java
new file mode 100644
index 0000000..7fc6dbc
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/entities/Employee.java
@@ -0,0 +1,28 @@
+package com.zoomcare.candidatechallenge.entities;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+import lombok.Data;
+
+@Entity
+@Data
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private BigInteger id;
+
+ @Column(name = "supervisor_id")
+ private BigInteger supervisorid;
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/entities/Property.java b/src/main/java/com/zoomcare/candidatechallenge/entities/Property.java
new file mode 100644
index 0000000..7f1e403
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/entities/Property.java
@@ -0,0 +1,32 @@
+package com.zoomcare.candidatechallenge.entities;
+
+import java.math.BigInteger;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.zoomcare.candidatechallenge.repositories.CompositeKey;
+
+import lombok.Data;
+
+@Data
+@Entity
+@IdClass(CompositeKey.class)
+public class Property {
+
+ @Id
+ @JsonIgnore
+ @Column(name = "employee_id")
+ private BigInteger employeeId;
+
+ @Id
+ private String key;
+
+ @Id
+ private String value;
+
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/map/EmployeeData.java b/src/main/java/com/zoomcare/candidatechallenge/map/EmployeeData.java
new file mode 100644
index 0000000..190dfc7
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/map/EmployeeData.java
@@ -0,0 +1,19 @@
+package com.zoomcare.candidatechallenge.map;
+
+import java.util.List;
+
+import com.zoomcare.candidatechallenge.entities.Employee;
+import com.zoomcare.candidatechallenge.entities.Property;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class EmployeeData {
+
+ private Employee employee;
+
+ private List properties;
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/repositories/CompositeKey.java b/src/main/java/com/zoomcare/candidatechallenge/repositories/CompositeKey.java
new file mode 100644
index 0000000..e444d37
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/repositories/CompositeKey.java
@@ -0,0 +1,14 @@
+package com.zoomcare.candidatechallenge.repositories;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+
+public class CompositeKey implements Serializable {
+
+ private BigInteger employeeId;
+
+ private String key;
+
+ private String value;
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/repositories/EmployeeRepository.java b/src/main/java/com/zoomcare/candidatechallenge/repositories/EmployeeRepository.java
new file mode 100644
index 0000000..1b02c62
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/repositories/EmployeeRepository.java
@@ -0,0 +1,19 @@
+package com.zoomcare.candidatechallenge.repositories;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import com.zoomcare.candidatechallenge.entities.Employee;
+
+@Repository
+public interface EmployeeRepository extends JpaRepository{
+
+ Optional findById(BigInteger id);
+
+ Optional> findAllBySupervisoridIsNull();
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/repositories/PropertyRepository.java b/src/main/java/com/zoomcare/candidatechallenge/repositories/PropertyRepository.java
new file mode 100644
index 0000000..8d794cd
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/repositories/PropertyRepository.java
@@ -0,0 +1,19 @@
+package com.zoomcare.candidatechallenge.repositories;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.zoomcare.candidatechallenge.entities.Property;
+
+@Repository
+public interface PropertyRepository extends JpaRepository{
+
+ Optional findByEmployeeId(BigInteger employeeId);
+
+ Optional> findAllByEmployeeId(BigInteger employeeId);
+
+}
diff --git a/src/main/java/com/zoomcare/candidatechallenge/service/EmployeeService.java b/src/main/java/com/zoomcare/candidatechallenge/service/EmployeeService.java
new file mode 100644
index 0000000..d3c2976
--- /dev/null
+++ b/src/main/java/com/zoomcare/candidatechallenge/service/EmployeeService.java
@@ -0,0 +1,69 @@
+package com.zoomcare.candidatechallenge.service;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import com.zoomcare.candidatechallenge.entities.Employee;
+import com.zoomcare.candidatechallenge.entities.Property;
+import com.zoomcare.candidatechallenge.map.EmployeeData;
+import com.zoomcare.candidatechallenge.repositories.EmployeeRepository;
+import com.zoomcare.candidatechallenge.repositories.PropertyRepository;
+
+import lombok.extern.log4j.Log4j2;
+
+@Service
+@Log4j2
+public class EmployeeService {
+
+ @Autowired
+ private EmployeeRepository empRepo;
+
+ @Autowired
+ private PropertyRepository propRepo;
+
+ public ResponseEntity getEmployeeData(BigInteger id) {
+
+ Optional emp = empRepo.findById(id);
+
+ if(emp.isPresent()) {
+ Optional> props = propRepo.findAllByEmployeeId(id);
+
+ return new ResponseEntity(EmployeeData.builder().employee(emp.get()).properties(props.get()).build(), HttpStatus.OK);
+ }else {
+ log.error("The emploee with id {} does not exist.", id);
+ return new ResponseEntity(HttpStatus.NOT_FOUND);
+ }
+
+ }
+
+ public ResponseEntity> getTopLevelEmployee() {
+
+ Optional> topEmpList = empRepo.findAllBySupervisoridIsNull();
+
+ if(topEmpList.isPresent()) {
+ List finalList = new ArrayList<>();
+
+ topEmpList.get().forEach(employee -> {
+ Optional> props = propRepo.findAllByEmployeeId(employee.getId());
+
+ finalList.add(EmployeeData.builder().employee(employee).properties(props.get()).build());
+ });
+
+ return new ResponseEntity>(finalList, HttpStatus.OK);
+ }else {
+
+ log.error("There are no top-level employees");
+ return new ResponseEntity>(HttpStatus.NOT_FOUND);
+ }
+
+ }
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 4408d17..9a4c36e 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -2,6 +2,12 @@ spring:
h2:
console:
enabled: true
+ datasource:
+ url: jdbc:h2:mem:testdb
+ username: sa
+ password: sa
+ driverClassName: org.h2.Driver
+
management:
endpoints:
web: