Skip to content

Commit bcfbca0

Browse files
committed
feat: Usar o princípio ISP - Interface Segregation Principle (#8).
1 parent 16a299f commit bcfbca0

40 files changed

+1527
-458
lines changed

lombok.config

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lombok.addLombokGeneratedAnnotation=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package br.com.virtuallibrary.commons.controllers;
2+
3+
import java.io.Serializable;
4+
5+
import org.springframework.data.web.PagedResourcesAssembler;
6+
import org.springframework.hateoas.RepresentationModel;
7+
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
8+
import org.springframework.http.HttpStatus;
9+
import org.springframework.http.ResponseEntity;
10+
import org.springframework.web.bind.annotation.DeleteMapping;
11+
import org.springframework.web.bind.annotation.ResponseStatus;
12+
13+
import br.com.virtuallibrary.commons.IConstants;
14+
import br.com.virtuallibrary.commons.entities.BaseEntity;
15+
import br.com.virtuallibrary.commons.repositories.IBaseRepository;
16+
import br.com.virtuallibrary.commons.services.ICrudService;
17+
import io.swagger.v3.oas.annotations.Operation;
18+
import io.swagger.v3.oas.annotations.Parameter;
19+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
20+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
21+
22+
/**
23+
* Controle básico de delete de registro.
24+
* @author Daniel Oliveira
25+
*
26+
* @param <E> Representa a entidade.
27+
* @param <ID> Representa o tipo identificador da entidade.
28+
* @param <R> Representa o repositório do entidade.
29+
* @param <S> Representa o serviço da entidade.
30+
*/
31+
public interface IDeleteController<
32+
E extends BaseEntity,
33+
ID extends Serializable,
34+
R extends IBaseRepository<E, ID>,
35+
S extends ICrudService<E, ID, R>,
36+
M extends RepresentationModel<M>> {
37+
38+
S getService();
39+
40+
PagedResourcesAssembler<E> getPagedResourcesAssembler();
41+
42+
RepresentationModelAssemblerSupport<E, M> getModelAssembler();
43+
44+
@ResponseStatus(HttpStatus.OK)
45+
@DeleteMapping(value = "/{id}", produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
46+
@Operation(summary = "Deleta um registro.", description = "Remove o registro da base de dados.")
47+
@ApiResponses(value = {
48+
@ApiResponse(responseCode = "200", description = "Registro deletado com sucesso"),
49+
@ApiResponse(responseCode = "404", description = "Registro não encontrado."),
50+
@ApiResponse(responseCode = "500", description = "Erro interno do servidor") })
51+
ResponseEntity<Object> delete(@Parameter(description="Id do registro a ser deletado. Não pode ser vazio.", required=true) ID id);
52+
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package br.com.virtuallibrary.commons.controllers;
2+
3+
import java.io.Serializable;
4+
5+
import org.springframework.data.web.PagedResourcesAssembler;
6+
import org.springframework.hateoas.RepresentationModel;
7+
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
8+
import org.springframework.http.HttpStatus;
9+
import org.springframework.http.ResponseEntity;
10+
import org.springframework.web.bind.annotation.GetMapping;
11+
import org.springframework.web.bind.annotation.ResponseStatus;
12+
13+
import br.com.virtuallibrary.commons.IConstants;
14+
import br.com.virtuallibrary.commons.entities.BaseEntity;
15+
import br.com.virtuallibrary.commons.repositories.IBaseRepository;
16+
import br.com.virtuallibrary.commons.services.ILoadService;
17+
import io.swagger.v3.oas.annotations.Operation;
18+
import io.swagger.v3.oas.annotations.Parameter;
19+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
20+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
21+
22+
/**
23+
* Controle básico de load de registro.
24+
* @author Daniel Oliveira
25+
*
26+
* @param <E> Representa a entidade.
27+
* @param <ID> Representa o tipo identificador da entidade.
28+
* @param <R> Representa o repositório do entidade.
29+
* @param <S> Representa o serviço da entidade.
30+
*/
31+
public interface ILoadController<
32+
E extends BaseEntity,
33+
ID extends Serializable,
34+
R extends IBaseRepository<E, ID>,
35+
S extends ILoadService<E, ID, R>,
36+
M extends RepresentationModel<M>> {
37+
38+
S getService();
39+
40+
PagedResourcesAssembler<E> getPagedResourcesAssembler();
41+
42+
RepresentationModelAssemblerSupport<E, M> getModelAssembler();
43+
44+
@ResponseStatus(HttpStatus.OK)
45+
@GetMapping(value = "/{id}", produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
46+
@Operation(summary = "Obter um registro pelo id.", description = "Retorna um registro.")
47+
@ApiResponses(value = {
48+
@ApiResponse(responseCode = "200", description = "Registro carregado com sucesso."),
49+
@ApiResponse(responseCode = "404", description = "Registro não encontrado."),
50+
@ApiResponse(responseCode = "500", description = "Erro interno do servidor") })
51+
ResponseEntity<M> find(@Parameter(description="O id do registro a ser obtido. Não pode ser vazio.", required=true) ID id);
52+
53+
}

src/main/java/br/com/virtuallibrary/commons/controllers/IBaseController.java renamed to src/main/java/br/com/virtuallibrary/commons/controllers/ISaveAndUpdateController.java

+8-46
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
import javax.validation.Valid;
77

88
import org.springframework.data.web.PagedResourcesAssembler;
9-
import org.springframework.hateoas.CollectionModel;
109
import org.springframework.hateoas.RepresentationModel;
1110
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
1211
import org.springframework.http.HttpStatus;
1312
import org.springframework.http.ResponseEntity;
14-
import org.springframework.web.bind.annotation.DeleteMapping;
15-
import org.springframework.web.bind.annotation.GetMapping;
1613
import org.springframework.web.bind.annotation.PatchMapping;
1714
import org.springframework.web.bind.annotation.PostMapping;
1815
import org.springframework.web.bind.annotation.PutMapping;
@@ -21,60 +18,34 @@
2118
import br.com.virtuallibrary.commons.IConstants;
2219
import br.com.virtuallibrary.commons.entities.BaseEntity;
2320
import br.com.virtuallibrary.commons.repositories.IBaseRepository;
24-
import br.com.virtuallibrary.commons.services.IBaseService;
21+
import br.com.virtuallibrary.commons.services.ISaveAndUpdateService;
2522
import io.swagger.v3.oas.annotations.Operation;
2623
import io.swagger.v3.oas.annotations.Parameter;
2724
import io.swagger.v3.oas.annotations.responses.ApiResponse;
2825
import io.swagger.v3.oas.annotations.responses.ApiResponses;
2926

3027
/**
31-
* Recurso básico com endpoints de CRUD.
28+
* Controle básico de save e update de registro.
3229
* @author Daniel Oliveira
3330
*
3431
* @param <E> Representa a entidade.
3532
* @param <ID> Representa o tipo identificador da entidade.
3633
* @param <R> Representa o repositório do entidade.
3734
* @param <S> Representa o serviço da entidade.
3835
*/
39-
public interface IBaseController<E extends BaseEntity, ID extends Serializable, R extends IBaseRepository<E, ID>, S extends IBaseService<E, ID, R>, M extends RepresentationModel<M>> {
36+
public interface ISaveAndUpdateController<
37+
E extends BaseEntity,
38+
ID extends Serializable,
39+
R extends IBaseRepository<E, ID>,
40+
S extends ISaveAndUpdateService<E, ID, R>,
41+
M extends RepresentationModel<M>> {
4042

4143
S getService();
4244

4345
PagedResourcesAssembler<E> getPagedResourcesAssembler();
4446

4547
RepresentationModelAssemblerSupport<E, M> getModelAssembler();
4648

47-
@ResponseStatus(HttpStatus.OK)
48-
@GetMapping(produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
49-
@Operation(summary = "Retorna a lista de registros paginado.", description =
50-
"O filtro padrão é o igual ($eq), mas você pode utilizar (Exemplo: field=contains:valor):<br/>"
51-
+ "Contém - \"<b>contains</b>:valor\"<br/>"
52-
+ "Igual - \"<b>eq</b>:valor\"<br/>"
53-
+ "Maior que - \"<b>gt</b>:numerico\"<br/>"
54-
+ "Menor que - \"<b>lt</b>:numerico\"<br/>"
55-
+ "Maior ou igual - \"<b>gte</b>:numerico\"<br/>"
56-
+ "Menor ou igual - \"<b>lte</b>:numerico\"<br/>"
57-
+ "Também é possível combinar dois filtros - <b>gt</b>:numerico:<b>lt</b>:numerico<br/>"
58-
+ "Para ordenação, usar no parâmetro: <b>orderby=field1,field2,field3</b><br/>"
59-
+ "Outro exemplo: <b>orderby=field1:asc,field2:desc</b>")
60-
@ApiResponses(value = {
61-
@ApiResponse(responseCode = "200", description = "Registros listados com sucesso"),
62-
@ApiResponse(responseCode = "400", description = "Erro na obtenção dos dados ou filtro"),
63-
@ApiResponse(responseCode = "500", description = "Erro interno do servidor")})
64-
ResponseEntity<CollectionModel<M>> findAll(
65-
@Parameter(description="Número da página.") int page,
66-
@Parameter(description="Quantidade de registros por página.") int size,
67-
@Parameter(description="Filtros de pesquisa conforme campos da entidade.") Map<String, String> filters);
68-
69-
@ResponseStatus(HttpStatus.OK)
70-
@GetMapping(value = "/{id}", produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
71-
@Operation(summary = "Obter um registro pelo id.", description = "Retorna um registro.")
72-
@ApiResponses(value = {
73-
@ApiResponse(responseCode = "200", description = "Registro carregado com sucesso."),
74-
@ApiResponse(responseCode = "404", description = "Registro não encontrado."),
75-
@ApiResponse(responseCode = "500", description = "Erro interno do servidor") })
76-
ResponseEntity<M> find(@Parameter(description="O id do registro a ser obtido. Não pode ser vazio.", required=true) ID id);
77-
7849
@ResponseStatus(HttpStatus.CREATED)
7950
@PostMapping(produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
8051
@Operation(summary = "Adiciona um novo registro.", description = "Será gravado no banco de dados um novo registro.")
@@ -86,15 +57,6 @@ ResponseEntity<M> create(
8657
@Parameter(description="Registro a ser adicionado. Não pode ser nulo ou vazio.", required=true)
8758
@Valid E object);
8859

89-
@ResponseStatus(HttpStatus.OK)
90-
@DeleteMapping(value = "/{id}", produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
91-
@Operation(summary = "Deleta um registro.", description = "Remove o registro da base de dados.")
92-
@ApiResponses(value = {
93-
@ApiResponse(responseCode = "200", description = "Registro deletado com sucesso"),
94-
@ApiResponse(responseCode = "404", description = "Registro não encontrado."),
95-
@ApiResponse(responseCode = "500", description = "Erro interno do servidor") })
96-
ResponseEntity<Object> delete(@Parameter(description="Id do registro a ser deletado. Não pode ser vazio.", required=true) ID id);
97-
9860
@ResponseStatus(HttpStatus.OK)
9961
@PutMapping(value = "/{id}", produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
10062
@Operation(summary = "Atualizar um registro", description = "Atualiza um registro existente.")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package br.com.virtuallibrary.commons.controllers;
2+
3+
import java.io.Serializable;
4+
import java.util.Map;
5+
6+
import org.springframework.data.web.PagedResourcesAssembler;
7+
import org.springframework.hateoas.CollectionModel;
8+
import org.springframework.hateoas.RepresentationModel;
9+
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
10+
import org.springframework.http.HttpStatus;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.web.bind.annotation.GetMapping;
13+
import org.springframework.web.bind.annotation.ResponseStatus;
14+
15+
import br.com.virtuallibrary.commons.IConstants;
16+
import br.com.virtuallibrary.commons.entities.BaseEntity;
17+
import br.com.virtuallibrary.commons.repositories.IBaseRepository;
18+
import br.com.virtuallibrary.commons.services.ISearchService;
19+
import io.swagger.v3.oas.annotations.Operation;
20+
import io.swagger.v3.oas.annotations.Parameter;
21+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
22+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
23+
24+
/**
25+
* Controle básico de pesquisa.
26+
* @author Daniel Oliveira
27+
*
28+
* @param <E> Representa a entidade.
29+
* @param <ID> Representa o tipo identificador da entidade.
30+
* @param <R> Representa o repositório do entidade.
31+
* @param <S> Representa o serviço da entidade.
32+
*/
33+
public interface ISearchController<
34+
E extends BaseEntity,
35+
ID extends Serializable,
36+
R extends IBaseRepository<E, ID>,
37+
S extends ISearchService<E, ID, R>,
38+
M extends RepresentationModel<M>> {
39+
40+
S getService();
41+
42+
PagedResourcesAssembler<E> getPagedResourcesAssembler();
43+
44+
RepresentationModelAssemblerSupport<E, M> getModelAssembler();
45+
46+
@ResponseStatus(HttpStatus.OK)
47+
@GetMapping(produces = { IConstants.APPLICATION_JSON_UTF_8, IConstants.APPLICATION_XML_UTF_8 })
48+
@Operation(summary = "Retorna a lista de registros paginado.", description =
49+
"O filtro padrão é o igual ($eq), mas você pode utilizar (Exemplo: field=contains:valor):<br/>"
50+
+ "Contém - \"<b>contains</b>:valor\"<br/>"
51+
+ "Igual - \"<b>eq</b>:valor\"<br/>"
52+
+ "Maior que - \"<b>gt</b>:numerico\"<br/>"
53+
+ "Menor que - \"<b>lt</b>:numerico\"<br/>"
54+
+ "Maior ou igual - \"<b>gte</b>:numerico\"<br/>"
55+
+ "Menor ou igual - \"<b>lte</b>:numerico\"<br/>"
56+
+ "Também é possível combinar dois filtros - <b>gt</b>:numerico:<b>lt</b>:numerico<br/>"
57+
+ "Para ordenação, usar no parâmetro: <b>orderby=field1,field2,field3</b><br/>"
58+
+ "Outro exemplo: <b>orderby=field1:asc,field2:desc</b>")
59+
@ApiResponses(value = {
60+
@ApiResponse(responseCode = "200", description = "Registros listados com sucesso"),
61+
@ApiResponse(responseCode = "400", description = "Erro na obtenção dos dados ou filtro"),
62+
@ApiResponse(responseCode = "500", description = "Erro interno do servidor")})
63+
ResponseEntity<CollectionModel<M>> findAll(
64+
@Parameter(description="Número da página.") int page,
65+
@Parameter(description="Quantidade de registros por página.") int size,
66+
@Parameter(description="Filtros de pesquisa conforme campos da entidade.") Map<String, String> filters);
67+
68+
}

src/main/java/br/com/virtuallibrary/commons/controllers/impl/BaseController.java renamed to src/main/java/br/com/virtuallibrary/commons/controllers/impl/CompleteController.java

+18-14
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import org.springframework.data.web.PagedResourcesAssembler;
99
import org.springframework.hateoas.CollectionModel;
10-
import org.springframework.hateoas.PagedModel;
1110
import org.springframework.hateoas.RepresentationModel;
1211
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
1312
import org.springframework.http.HttpStatus;
@@ -17,26 +16,33 @@
1716
import org.springframework.web.bind.annotation.RequestParam;
1817

1918
import br.com.virtuallibrary.commons.IConstants;
20-
import br.com.virtuallibrary.commons.controllers.IBaseController;
19+
import br.com.virtuallibrary.commons.controllers.IDeleteController;
20+
import br.com.virtuallibrary.commons.controllers.ILoadController;
21+
import br.com.virtuallibrary.commons.controllers.ISaveAndUpdateController;
22+
import br.com.virtuallibrary.commons.controllers.ISearchController;
2123
import br.com.virtuallibrary.commons.entities.BaseEntity;
2224
import br.com.virtuallibrary.commons.repositories.IBaseRepository;
23-
import br.com.virtuallibrary.commons.services.IBaseService;
25+
import br.com.virtuallibrary.commons.services.ICompleteService;
2426
import lombok.extern.slf4j.Slf4j;
2527

28+
//FIXME: Repetição de código, verificar como usar multipla herança implementada. Code repetition, check how to use multiple inheritance implemented.
2629
@Slf4j
27-
public class BaseController<
30+
public abstract class CompleteController<
2831
E extends BaseEntity,
2932
ID extends Serializable,
3033
R extends IBaseRepository<E, ID>,
31-
S extends IBaseService<E, ID, R>,
34+
S extends ICompleteService<E, ID, R>,
3235
M extends RepresentationModel<M>>
33-
implements IBaseController<E, ID, R, S, M> {
36+
implements ISearchController<E, ID, R, S, M>,
37+
IDeleteController<E, ID, R, S, M>,
38+
ILoadController<E, ID, R, S, M>,
39+
ISaveAndUpdateController<E, ID, R, S, M> {
3440

3541
private final S service;
3642
private final RepresentationModelAssemblerSupport<E, M> modelAssembler;
3743
private final PagedResourcesAssembler<E> pagedResourcesAssembler;
3844

39-
public BaseController(S service, PagedResourcesAssembler<E> pagedResourcesAssembler, RepresentationModelAssemblerSupport<E, M> modelAssembler) {
45+
public CompleteController(S service, PagedResourcesAssembler<E> pagedResourcesAssembler, RepresentationModelAssemblerSupport<E, M> modelAssembler) {
4046
this.service = service;
4147
this.modelAssembler = modelAssembler;
4248
this.pagedResourcesAssembler = pagedResourcesAssembler;
@@ -62,10 +68,7 @@ public ResponseEntity<CollectionModel<M>> findAll(
6268
@RequestParam(value = "page", required = false, defaultValue = IConstants.defaultPage) int page,
6369
@RequestParam(value = "size", required = false, defaultValue = IConstants.defaultSize) int size,
6470
@RequestParam(required = false) Map<String,String> filters) {
65-
66-
PagedModel<M> collModel = getPagedResourcesAssembler().toModel(getService().findPaginated(page, size, filters), getModelAssembler());
67-
68-
return ResponseEntity.ok().body(collModel);
71+
return ResponseEntity.ok().body(getPagedResourcesAssembler().toModel(getService().findPaginated(page, size, filters), getModelAssembler()));
6972
}
7073

7174
@Override
@@ -77,7 +80,6 @@ public ResponseEntity<M> find(@PathVariable ID id) {
7780
}
7881

7982
@Override
80-
8183
public ResponseEntity<M> create(@RequestBody @Valid E object) {
8284
return service.save(object)
8385
.map(modelAssembler::toModel)
@@ -99,13 +101,15 @@ public ResponseEntity<M> update(@RequestBody @Valid E object, @PathVariable ID i
99101
.map(modelAssembler::toModel)
100102
.map(ResponseEntity::ok)
101103
.orElse(ResponseEntity.notFound().build());
102-
103104
}
104105

105106
@Override
106107
public ResponseEntity<M> update(
107108
@RequestBody Map<String, String> updates,
108-
@PathVariable ID id) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
109+
@PathVariable ID id) throws NoSuchFieldException,
110+
SecurityException,
111+
IllegalArgumentException,
112+
IllegalAccessException {
109113
try {
110114
return service.update(updates, id)
111115
.map(modelAssembler::toModel)

0 commit comments

Comments
 (0)