Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(specification-storage): implement endpoints to fetch specificati…
Browse files Browse the repository at this point in the history
…on rules and enable/disable it

Closes: MRSPECS-4
psmagin committed May 16, 2024

Verified

This commit was signed with the committer’s verified signature.
marcelstanley Marcel Moura
1 parent 8997289 commit a654e01
Showing 44 changed files with 2,074 additions and 39 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
### Features
#### Server
* Specification Storage: implement endpoint to fetch specifications ([MRSPECS-3](https://folio-org.atlassian.net//browse/MRSPECS-3))
* Specification Storage: implement endpoints to fetch specification rules and enable/disable it ([MRSPECS-4](https://folio-org.atlassian.net//browse/MRSPECS-4))
#### General
* Implement build dependants GitHub workflow on PR creation ([MRSPECS-9](https://folio-org.atlassian.net//browse/MRSPECS-9))

4 changes: 4 additions & 0 deletions api/mod-record-specifications.yaml
Original file line number Diff line number Diff line change
@@ -32,3 +32,7 @@ tags:
paths:
/specification-storage/specifications:
$ref: 'paths/specification-storage/get-specifications-path.yaml'
/specification-storage/specifications/{id}/rules:
$ref: 'paths/specification-storage/get-specification-rules-path.yaml'
/specification-storage/specifications/{id}/rules/{ruleId}:
$ref: 'paths/specification-storage/get-specification-rules-by-id-path.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
patch:
summary: Toggle Specification Rule
description: Enable or disable specification rule.
operationId: toggleSpecificationRule
tags:
- specification-storage
parameters:
- in: path
name: id
description: Specification ID
required: true
schema:
type: string
format: uuid
- in: path
name: ruleId
description: Specification Rule ID
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '../../schemas/toggleSpecificationRuleDto.yaml'
responses:
'204':
description: 'Operation was successful'
'400':
$ref: '../../responses/badRequestResponse.yaml'
'500':
$ref: '../../responses/internalServerErrorResponse.yaml'
25 changes: 25 additions & 0 deletions api/paths/specification-storage/get-specification-rules-path.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
get:
summary: Get Specification Rules
description: Get a collection of specification rules enabled and disabled.
operationId: getSpecificationRules
tags:
- specification-storage
parameters:
- in: path
name: id
description: Specification ID
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Collection of specifications
content:
application/json:
schema:
$ref: '../../schemas/specificationRuleDtoCollection.yaml'
'400':
$ref: '../../responses/badRequestResponse.yaml'
'500':
$ref: '../../responses/internalServerErrorResponse.yaml'
4 changes: 3 additions & 1 deletion api/schemas/includeParam.yaml
Original file line number Diff line number Diff line change
@@ -2,4 +2,6 @@ type: string
description: define what to include in response
enum:
- all
- required-fields
- none
- required-fields
default: none
18 changes: 18 additions & 0 deletions api/schemas/specificationRuleDto.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
type: object
properties:
id:
type: string
format: uuid
specificationId:
type: string
format: uuid
name:
type: string
description:
type: string
code:
type: string
enabled:
type: boolean
metadata:
$ref: 'common/metadataDto.yaml'
8 changes: 8 additions & 0 deletions api/schemas/specificationRuleDtoCollection.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type: object
properties:
rules:
type: array
items:
$ref: specificationRuleDto.yaml
totalRecords:
type: integer
6 changes: 6 additions & 0 deletions api/schemas/toggleSpecificationRuleDto.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type: object
properties:
enabled:
type: boolean
required:
- enabled
32 changes: 31 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
@@ -14,6 +14,24 @@
"permissionsRequired": [
"specification-storage.specifications.collection.get"
]
},
{
"methods": [
"GET"
],
"pathPattern": "/specification-storage/specifications/{id}/rules",
"permissionsRequired": [
"specification-storage.specification.rules.collection.get"
]
},
{
"methods": [
"PATCH"
],
"pathPattern": "/specification-storage/specifications/{id}/rules/{ruleId}",
"permissionsRequired": [
"specification-storage.specification.rules.item.patch"
]
}
]
},
@@ -44,12 +62,24 @@
"displayName": "Specification Storage - Get specification collection",
"description": "Get specification collection"
},
{
"permissionName": "specification-storage.specification.rules.collection.get",
"displayName": "Specification Storage - Get specification rules collection",
"description": "Get specification rules collection"
},
{
"permissionName": "specification-storage.specification.rules.item.patch",
"displayName": "Specification Storage - Toggle rule for specification",
"description": "Toggle rule for specification"
},
{
"permissionName": "specification-storage.all",
"displayName": "Specification Storage - All permissions",
"description": "Entire set of permissions needed to manage specifications",
"subPermissions": [
"specification-storage.specifications.collection.get"
"specification-storage.specifications.collection.get",
"specification-storage.specification.rules.collection.get",
"specification-storage.specification.rules.item.patch"
]
}
],
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.folio.rspec.controller;

import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.folio.rspec.domain.dto.Family;
import org.folio.rspec.domain.dto.FamilyProfile;
import org.folio.rspec.domain.dto.IncludeParam;
import org.folio.rspec.domain.dto.SpecificationDtoCollection;
import org.folio.rspec.domain.dto.SpecificationRuleDtoCollection;
import org.folio.rspec.domain.dto.ToggleSpecificationRuleDto;
import org.folio.rspec.rest.resource.SpecificationStorageApi;
import org.folio.rspec.service.SpecificationService;
import org.springframework.http.HttpStatus;
@@ -23,10 +26,22 @@ public class SpecificationStorageController implements SpecificationStorageApi {
public ResponseEntity<SpecificationDtoCollection> getSpecifications(Family family, FamilyProfile profile,
IncludeParam include, Integer limit,
Integer offset) {
if (include != null) {
if (IncludeParam.REQUIRED_FIELDS == include) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
var specifications = specificationService.findSpecifications(family, profile, include, limit, offset);
return ResponseEntity.ok(specifications);
}

@Override
public ResponseEntity<SpecificationRuleDtoCollection> getSpecificationRules(UUID id) {
return ResponseEntity.ok(specificationService.findSpecificationRules(id));
}

@Override
public ResponseEntity<Void> toggleSpecificationRule(UUID specificationId, UUID ruleId,
ToggleSpecificationRuleDto toggleSpecificationRuleDto) {
specificationService.toggleSpecificationRule(specificationId, ruleId, toggleSpecificationRuleDto);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.folio.rspec.controller.handler;

import static org.folio.rspec.controller.handler.ServiceExceptionHandler.fromErrorCode;
import static org.folio.rspec.domain.dto.ErrorCode.INVALID_REQUEST_PARAMETER;

import org.folio.rspec.domain.dto.ErrorCollection;
import org.folio.rspec.domain.dto.Parameter;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;

@Component
public class MethodArgumentNotValidExceptionHandler implements ServiceExceptionHandler {

@Override
public ResponseEntity<ErrorCollection> handleException(Exception e) {
var exception = (MethodArgumentNotValidException) e;
var errorCollection = new ErrorCollection();
for (FieldError fieldError : exception.getBindingResult().getFieldErrors()) {
var error = fromErrorCode(INVALID_REQUEST_PARAMETER);
error.setMessage(fieldError.getDefaultMessage());
var parameter = new Parameter().key(fieldError.getField()).value(String.valueOf(fieldError.getRejectedValue()));
error.addParametersItem(parameter);
errorCollection.addErrorsItem(error);
}
return ResponseEntity.badRequest().body(errorCollection);
}

@Override
public boolean canHandle(Exception e) {
return e instanceof MethodArgumentNotValidException;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.folio.rspec.controller.handler;

import static org.folio.rspec.controller.handler.ServiceExceptionHandler.errorCollection;
import static org.folio.rspec.controller.handler.ServiceExceptionHandler.fromErrorCode;
import static org.folio.rspec.domain.dto.ErrorCode.RESOURCE_NOT_FOUND;

import org.folio.rspec.domain.dto.ErrorCollection;
import org.folio.rspec.exception.ResourceNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

@Component
public class ResourceNotFoundExceptionHandler implements ServiceExceptionHandler {

@Override
public ResponseEntity<ErrorCollection> handleException(Exception e) {
var error = fromErrorCode(RESOURCE_NOT_FOUND).message(e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorCollection(error));
}

@Override
public boolean canHandle(Exception e) {
return e instanceof ResourceNotFoundException;
}
}
Original file line number Diff line number Diff line change
@@ -21,4 +21,12 @@ static ResponseEntity<ErrorCollection> fallback(Exception e) {
static Error fromErrorCode(ErrorCode errorCode) {
return new Error().code(errorCode.getCode()).type(errorCode.getErrorType());
}

static ErrorCollection errorCollection(Error... errors) {
ErrorCollection errorCollection = new ErrorCollection();
for (Error error : errors) {
errorCollection.addErrorsItem(error);
}
return errorCollection;
}
}
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ public enum ErrorCode {

INVALID_QUERY_VALUE("invalid-query-value", "101"),
INVALID_QUERY_ENUM_VALUE("invalid-query-enum-value", "102"),
INVALID_REQUEST_PARAMETER("invalid-request-parameter", "400"),
RESOURCE_NOT_FOUND("resource-not-found", "404"),
UNEXPECTED("unexpected", "500"),

;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.folio.rspec.domain.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.folio.rspec.domain.entity.support.Metadata;
import org.folio.rspec.domain.entity.support.UuidPersistable;

@Getter
@Setter
@Entity
@Table(name = "rule")
public class Rule extends UuidPersistable {

public static final String NAME_COLUMN = "name";
public static final String DESCRIPTION_COLUMN = "description";
public static final String CODE_COLUMN = "code";

@Column(name = NAME_COLUMN, nullable = false)
private String name;
@Column(name = DESCRIPTION_COLUMN)
private String description;
@Column(name = CODE_COLUMN, nullable = false)
private String code;

@Embedded
private Metadata metadata;

@Override
public int hashCode() {
return super.hashCode();
}

@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
Original file line number Diff line number Diff line change
@@ -5,8 +5,11 @@
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import java.util.LinkedHashSet;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import org.folio.rspec.domain.dto.Family;
@@ -46,6 +49,9 @@ public class Specification extends UuidPersistable {
@Column(name = URL_COLUMN)
private String url;

@OneToMany(mappedBy = "specification", orphanRemoval = true)
private Set<SpecificationRule> specificationRules = new LinkedHashSet<>();

@Embedded
private Metadata metadata;

Loading

0 comments on commit a654e01

Please sign in to comment.