From de4defe5748971fa6bc0c3d4a685a0f247585da8 Mon Sep 17 00:00:00 2001 From: dgil Date: Tue, 9 May 2023 14:14:34 -0600 Subject: [PATCH] first commit --- .DS_Store | Bin 0 -> 6148 bytes pom.xml | 18 +++++- .../controller/EmployeeController.java | 33 ++++++++++ .../entity/EmployeeEntity.java | 29 +++++++++ .../entity/PropertyEntity.java | 24 +++++++ .../entity/PropertyIdEntity.java | 20 ++++++ .../model/EmployeeModel.java | 45 +++++++++++++ .../model/PropertyModel.java | 22 +++++++ .../repository/EmployeeRepository.java | 12 ++++ .../service/EmployeeService.java | 40 ++++++++++++ src/main/resources/application.properties | 16 +++++ src/main/resources/application.yml | 12 ---- .../ApplicationContextTest.java | 19 ++++++ .../service/EmployeeServiceTest.java | 60 ++++++++++++++++++ 14 files changed, 337 insertions(+), 13 deletions(-) create mode 100644 .DS_Store create mode 100644 src/main/java/com/zoomcare/candidatechallenge/controller/EmployeeController.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/entity/EmployeeEntity.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/entity/PropertyEntity.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/entity/PropertyIdEntity.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/model/EmployeeModel.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/model/PropertyModel.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java create mode 100644 src/main/java/com/zoomcare/candidatechallenge/service/EmployeeService.java create mode 100644 src/main/resources/application.properties delete mode 100644 src/main/resources/application.yml create mode 100644 src/main/test/com/zoomcare/candidatechallenge/ApplicationContextTest.java create mode 100644 src/main/test/com/zoomcare/candidatechallenge/service/EmployeeServiceTest.java diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 org.springframework.boot spring-boot-starter-parent - 2.1.3.RELEASE + 2.3.0.RELEASE com.zoomcare @@ -16,6 +16,7 @@ 1.8 + 1.5.5.Final @@ -49,6 +50,21 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.projectlombok + lombok + 1.18.26 + provided + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + diff --git a/src/main/java/com/zoomcare/candidatechallenge/controller/EmployeeController.java b/src/main/java/com/zoomcare/candidatechallenge/controller/EmployeeController.java new file mode 100644 index 0000000..073c16c --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/controller/EmployeeController.java @@ -0,0 +1,33 @@ +package com.zoomcare.candidatechallenge.controller; + +import com.zoomcare.candidatechallenge.entity.EmployeeEntity; +import com.zoomcare.candidatechallenge.model.EmployeeModel; +import com.zoomcare.candidatechallenge.service.EmployeeService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +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 +@RequiredArgsConstructor +@RequestMapping("/employees") +public class EmployeeController { + private EmployeeService service; + + @GetMapping("/{id}") + public ResponseEntity getEmployeeById(@PathVariable Long id){ + EmployeeModel model = service.getEmployee(id); + return new ResponseEntity<>(model, HttpStatus.OK); + } + + @GetMapping("/") + public ResponseEntity> getTopEmployees(){ + List topEmployees = service.getTopEmployees(); + return new ResponseEntity<>(topEmployees, HttpStatus.OK); + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/entity/EmployeeEntity.java b/src/main/java/com/zoomcare/candidatechallenge/entity/EmployeeEntity.java new file mode 100644 index 0000000..27f61f6 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/entity/EmployeeEntity.java @@ -0,0 +1,29 @@ +package com.zoomcare.candidatechallenge.entity; + +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name="EMPLOYEE") +public class EmployeeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "SUPERVISOR_ID") + private EmployeeEntity supervisor; + + @OneToMany(mappedBy = "supervisor", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private List reports = new ArrayList<>(); + + @OneToMany(mappedBy = "employee", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private List properties = new ArrayList<>(); +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyEntity.java b/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyEntity.java new file mode 100644 index 0000000..78480ce --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyEntity.java @@ -0,0 +1,24 @@ +package com.zoomcare.candidatechallenge.entity; + +import lombok.*; + +import javax.persistence.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name="PROPERTY") +public class PropertyEntity { + + @EmbeddedId + private PropertyIdEntity id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "EMPLOYEE_ID", insertable = false, updatable = false) + private EmployeeEntity employee; + + @Column(name = "VALUE") + private String value; +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyIdEntity.java b/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyIdEntity.java new file mode 100644 index 0000000..f7ae984 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/entity/PropertyIdEntity.java @@ -0,0 +1,20 @@ +package com.zoomcare.candidatechallenge.entity; + +import lombok.*; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.io.Serializable; + +@Getter +@Setter +@NoArgsConstructor +@EqualsAndHashCode +@AllArgsConstructor +@Embeddable +public class PropertyIdEntity implements Serializable { + @Column(name = "EMPLOYEE_ID") + private Long id; + @Column(name = "KEY") + private String key; +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/model/EmployeeModel.java b/src/main/java/com/zoomcare/candidatechallenge/model/EmployeeModel.java new file mode 100644 index 0000000..ac28a83 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/model/EmployeeModel.java @@ -0,0 +1,45 @@ +package com.zoomcare.candidatechallenge.model; + +import com.zoomcare.candidatechallenge.entity.EmployeeEntity; +import com.zoomcare.candidatechallenge.entity.PropertyEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EmployeeModel { + private Long id; + private Long supervisor; + + private List reports = new ArrayList<>(); + private List properties = new ArrayList<>(); + + public static final EmployeeModel EMPTY = new EmployeeModel(); + + public static final EmployeeModel parseFrom(EmployeeEntity entity){ + EmployeeModel model = new EmployeeModel(); + model.setId(entity.getId()); + + if(entity.getSupervisor()!= null && entity.getSupervisor().getId()!=null){ + model.setSupervisor(entity.getSupervisor().getId()); + } + + if(entity.getReports()!=null && !entity.getReports().isEmpty()){ + for(EmployeeEntity report : entity.getReports()){ + model.getReports().add(report.getId()); + } + } + + if(entity.getProperties()!=null && !entity.getProperties().isEmpty()){ + for(PropertyEntity property : entity.getProperties()){ + model.getProperties().add(PropertyModel.parseFrom(property)); + } + } + return model; + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/model/PropertyModel.java b/src/main/java/com/zoomcare/candidatechallenge/model/PropertyModel.java new file mode 100644 index 0000000..abd9176 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/model/PropertyModel.java @@ -0,0 +1,22 @@ +package com.zoomcare.candidatechallenge.model; + +import com.zoomcare.candidatechallenge.entity.PropertyEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PropertyModel { + + private String key; + private String value; + + public static PropertyModel parseFrom(PropertyEntity entity){ + PropertyModel model = new PropertyModel(); + model.setKey(entity.getId().getKey()); + model.setValue(entity.getValue()); + return model; + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java b/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java new file mode 100644 index 0000000..d668f79 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java @@ -0,0 +1,12 @@ +package com.zoomcare.candidatechallenge.repository; + +import com.zoomcare.candidatechallenge.entity.EmployeeEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface EmployeeRepository extends JpaRepository { + List findBySupervisorIsNull(); +} 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..fc0165c --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/service/EmployeeService.java @@ -0,0 +1,40 @@ +package com.zoomcare.candidatechallenge.service; + +import com.zoomcare.candidatechallenge.entity.EmployeeEntity; +import com.zoomcare.candidatechallenge.model.EmployeeModel; +import com.zoomcare.candidatechallenge.repository.EmployeeRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class EmployeeService { + private final EmployeeRepository employeeRepository; + + public EmployeeModel getEmployee(Long id) { + Optional employee = employeeRepository.findById(id); + if (employee.isPresent()) { + EmployeeEntity e = employee.get(); + EmployeeModel model = EmployeeModel.parseFrom(e); + return model; + } else { + return EmployeeModel.EMPTY; + } + } + + public List getTopEmployees(){ + List topEmployees = new ArrayList<>(); + List topEntityEmployees = employeeRepository.findBySupervisorIsNull(); + + if(topEntityEmployees!=null && !topEntityEmployees.isEmpty()){ + for(EmployeeEntity entity : topEntityEmployees){ + topEmployees.add(EmployeeModel.parseFrom(entity)); + } + } + return topEmployees; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..4d9ef04 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,16 @@ +server.port=8890 +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.defer-datasource-initialization=true + +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console + +#http://localhost:8080/h2-console +#http://127.0.0.1:8080/h2-console \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index 4408d17..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - h2: - console: - enabled: true -management: - endpoints: - web: - exposure: - include: "*" - endpoint: - health: - show-details: always \ No newline at end of file diff --git a/src/main/test/com/zoomcare/candidatechallenge/ApplicationContextTest.java b/src/main/test/com/zoomcare/candidatechallenge/ApplicationContextTest.java new file mode 100644 index 0000000..72c946c --- /dev/null +++ b/src/main/test/com/zoomcare/candidatechallenge/ApplicationContextTest.java @@ -0,0 +1,19 @@ +package com.zoomcare.candidatechallenge; + +import com.zoomcare.candidatechallenge.controller.EmployeeController; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +public class ApplicationContextTest { + @Autowired + private EmployeeController controller; + + @Test + public void testContext_whenApplicationRuns_thenContextLoads(){ + assertThat(controller).isNull(); + } +} diff --git a/src/main/test/com/zoomcare/candidatechallenge/service/EmployeeServiceTest.java b/src/main/test/com/zoomcare/candidatechallenge/service/EmployeeServiceTest.java new file mode 100644 index 0000000..79830f7 --- /dev/null +++ b/src/main/test/com/zoomcare/candidatechallenge/service/EmployeeServiceTest.java @@ -0,0 +1,60 @@ +package com.zoomcare.candidatechallenge.service; + + +import com.zoomcare.candidatechallenge.entity.EmployeeEntity; +import com.zoomcare.candidatechallenge.model.EmployeeModel; +import com.zoomcare.candidatechallenge.repository.EmployeeRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.when; + +public class EmployeeServiceTest { + + @Mock + private EmployeeRepository repository; + + private EmployeeService service; + + @BeforeEach + public void setup(){ + MockitoAnnotations.initMocks(this); + service = new EmployeeService(repository); + } + + @Test + public void testTopEmployees_whenTopRequired_thenReturnTop(){ + + EmployeeEntity employeeEntity = new EmployeeEntity(); + employeeEntity.setId(Long.valueOf(1)); + employeeEntity.setSupervisor(null); + List entities = new ArrayList<>(); + entities.add(employeeEntity); + + when(repository.findBySupervisorIsNull()).thenReturn(entities); + List topEmployees = service.getTopEmployees(); + assertEquals(1,topEmployees.size()); + assertEquals(EmployeeModel.parseFrom(employeeEntity),topEmployees.get(0)); + } + + @Test + public void testEmployee_whenEmployeeIdIsGiven_thenEmployeeReturned(){ + EmployeeEntity employeeEntity = new EmployeeEntity(); + employeeEntity.setId(Long.valueOf(5)); + + when(repository.findById(Long.valueOf(5))).thenReturn(Optional.of(employeeEntity)); + EmployeeModel employeeModel = service.getEmployee(Long.valueOf(5)); + + assertNotNull(employeeModel); + assertEquals(employeeEntity.getId(),employeeModel.getId()); + assertEquals(EmployeeModel.parseFrom(employeeEntity),employeeModel); + } +}