Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
18 changes: 17 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zoomcare</groupId>
Expand All @@ -16,6 +16,7 @@

<properties>
<java.version>1.8</java.version>
<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -49,6 +50,21 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<EmployeeModel> getEmployeeById(@PathVariable Long id){
EmployeeModel model = service.getEmployee(id);
return new ResponseEntity<>(model, HttpStatus.OK);
}

@GetMapping("/")
public ResponseEntity<List<EmployeeModel>> getTopEmployees(){
List<EmployeeModel> topEmployees = service.getTopEmployees();
return new ResponseEntity<>(topEmployees, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -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<EmployeeEntity> reports = new ArrayList<>();

@OneToMany(mappedBy = "employee", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<PropertyEntity> properties = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<Long> reports = new ArrayList<>();
private List<PropertyModel> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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<EmployeeEntity, Long> {
List<EmployeeEntity> findBySupervisorIsNull();
}
Original file line number Diff line number Diff line change
@@ -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<EmployeeEntity> employee = employeeRepository.findById(id);
if (employee.isPresent()) {
EmployeeEntity e = employee.get();
EmployeeModel model = EmployeeModel.parseFrom(e);
return model;
} else {
return EmployeeModel.EMPTY;
}
}

public List<EmployeeModel> getTopEmployees(){
List<EmployeeModel> topEmployees = new ArrayList<>();
List<EmployeeEntity> topEntityEmployees = employeeRepository.findBySupervisorIsNull();

if(topEntityEmployees!=null && !topEntityEmployees.isEmpty()){
for(EmployeeEntity entity : topEntityEmployees){
topEmployees.add(EmployeeModel.parseFrom(entity));
}
}
return topEmployees;
}
}
16 changes: 16 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -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
12 changes: 0 additions & 12 deletions src/main/resources/application.yml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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<EmployeeEntity> entities = new ArrayList<>();
entities.add(employeeEntity);

when(repository.findBySupervisorIsNull()).thenReturn(entities);
List<EmployeeModel> 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);
}
}