ialbert 2022-10-12 18:07:50 +03:00
parent ab407edb8c
commit 7eaec47ad3
13 changed files with 313 additions and 15 deletions

View file

@ -53,6 +53,10 @@
<groupId>ru.spcex.clearing</groupId>
<artifactId>classes</artifactId>
</dependency>
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>dictionary</artifactId>
</dependency>
</dependencies>
<dependencyManagement>

View file

@ -0,0 +1,49 @@
package ru.spcex.clearing.backendapi.controller.response.entity.dictionary;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import ru.clearing.platform.dictionary.AbstractDictionary;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ApiModel(description = "Ответ при получении объектов словаря.")
public class DictionaryBackendGetAll extends BasicSpcexResponse {
@JsonProperty
@ApiModelProperty(value = "Полезная нагрузка")
private DictionaryBackendPayload payload = new DictionaryBackendPayload();
public void fromEntity(Collection<AbstractDictionary> dictionaryValues) {
var payload = this.getPayload();
for (AbstractDictionary dictionaryValue : dictionaryValues) {
var singleItem = new DictionaryBackendGetFields();
singleItem.fromEntity(dictionaryValue);
payload.getItems().add(singleItem);
}
}
private static class DictionaryBackendPayload {
private List<DictionaryBackendGetFields> items = new ArrayList<>();
public List<DictionaryBackendGetFields> getItems() {
return items;
}
public void setItems(List<DictionaryBackendGetFields> items) {
this.items = items;
}
}
public DictionaryBackendPayload getPayload() {
return payload;
}
public void setPayload(DictionaryBackendPayload payload) {
this.payload = payload;
}
}

View file

@ -0,0 +1,48 @@
package ru.spcex.clearing.backendapi.controller.response.entity.dictionary;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import ru.clearing.platform.dictionary.AbstractDictionary;
public class DictionaryBackendGetFields {
@JsonProperty
@ApiModelProperty(value = "Идентификатор", example = "1234")
private Long id;
@JsonProperty
@ApiModelProperty(value = "", example = "")
private String code;
@JsonProperty
@ApiModelProperty(value = "Имя банка", example = "Сбербанк")
private String name;
public void fromEntity(AbstractDictionary dictionaryValue) {
this.id = dictionaryValue.getId();
this.code = dictionaryValue.getCode();
this.name = dictionaryValue.getName();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View file

@ -0,0 +1,30 @@
package ru.spcex.clearing.backendapi.controller.response.entity.dictionary;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import ru.clearing.platform.dictionary.AbstractDictionary;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
@ApiModel(description = "Ответ при получении объекта BankAccount.")
public class DictionaryBackendGetSingleValue extends BasicSpcexResponse {
@JsonProperty
@ApiModelProperty(value = "Поля объекта")
private DictionaryBackendGetFields payload;
public DictionaryBackendGetFields getPayload() {
return payload;
}
public void fromEntity(AbstractDictionary dictionaryValue) {
var payload = new DictionaryBackendGetFields();
this.setPayload(payload);
payload.fromEntity(dictionaryValue);
}
public void setPayload(DictionaryBackendGetFields payload) {
this.payload = payload;
}
}

View file

@ -0,0 +1,139 @@
package ru.spcex.clearing.backendapi.controller.system;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import ru.clearing.platform.dictionary.AbstractDictionary;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetAll;
import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValue;
import ru.spcex.clearing.backendapi.errors.ActionValidationException;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.backendapi.errors.NotFound404Exception;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Controller
@RequestMapping("/dictionary")
public class DictionaryController {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Map<String, Imdg<?>> allDictionaryMaps;
private final ImdgProvider imdgProvider;
@Autowired
public DictionaryController(ImdgProvider imdgProvider) {
this.imdgProvider = imdgProvider;
this.allDictionaryMaps = new ConcurrentHashMap<>();
}
@ApiOperation(value = "get all dictionary value.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetAll.class)})
@RequestMapping(value = "/{dictionary-name}", method = RequestMethod.GET)
@ResponseBody
public DictionaryBackendGetAll getAll(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide")
@PathVariable("dictionary-name") String dictionaryName) {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
Collection<AbstractDictionary> allValues = dictionary.getAllValues();
DictionaryBackendGetAll response = new DictionaryBackendGetAll();
response.fromEntity(allValues);
return response;
}
@ApiOperation(value = "get dictionary value by id.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{dictionary-name}/{id}", method = RequestMethod.GET)
@ResponseBody
public DictionaryBackendGetSingleValue getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide")
@PathVariable("dictionary-name") String dictionaryName,
@ApiParam(value = "Идентификатор объекта", required = true, example = "1234")
@PathVariable("id") Long id) {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
AbstractDictionary value = dictionary.getSingleObjectByID(id);
if (value == null) throw new NotFound404Exception(dictionaryName + " id='" + id + "'");
DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue();
response.fromEntity(value);
return response;
}
@ApiOperation(value = "get dictionary value by code.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{dictionary-name}/{code}", method = RequestMethod.GET)
@ResponseBody
public DictionaryBackendGetSingleValue getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide")
@PathVariable("dictionary-name") String dictionaryName,
@ApiParam(value = "Код словаря", required = true, example = "1234")
@PathVariable("code") String code) {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
AbstractDictionary value = dictionary.getSingleObjectByFieldValues(Map.of("code", code));
if (value == null) throw new NotFound404Exception(dictionaryName + " code='" + code + "'");
DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue();
response.fromEntity(value);
return response;
}
@SuppressWarnings("unchecked")
private <T extends SpcexObjectBase> Imdg<T> extractDictionaryImdgFromUrlParameter(String dictionaryNameFromUrl, Class<T> clazz) {
if (dictionaryNameFromUrl == null || dictionaryNameFromUrl.length() < 1) {
throw new ActionValidationException(BackEndError.ValidationError, "dictionary-name");
}
String actualDictionaryName = "Map_"
+ dictionaryNameFromUrl.substring(0, 1).toUpperCase()
+ dictionaryNameFromUrl.substring(1)
+ "Dictionary";
Imdg<T> dictionary = (Imdg<T>) allDictionaryMaps.computeIfAbsent(actualDictionaryName, (mapName1) -> {
Imdg<T> potentialImdg = imdgProvider.getImdg(actualDictionaryName, clazz);
if (potentialImdg.size() == 0) {
log.warn("coudln't find dictionary {}", actualDictionaryName);
return null;
}
return potentialImdg;
});
if (dictionary == null) {
throw new ActionValidationException(BackEndError.DictionaryNotFound, dictionaryNameFromUrl);
}
return dictionary;
}
@Autowired
private IMessageResolver errorResolver;
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
@ExceptionHandler(ActionValidationException.class)
public BasicSpcexResponse conflict(ActionValidationException ex) {
BasicSpcexResponse response = new BasicSpcexResponse();
EnumMessage message = ex.getErrors().stream().findFirst().orElseThrow();
response.setCode(message.getSubject().getId());
response.setMessage(errorResolver.resolve(message));
return response;
}
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@ResponseBody
@ExceptionHandler(NotFound404Exception.class)
public BasicSpcexResponse conflict(NotFound404Exception ex) {
BasicSpcexResponse response = new BasicSpcexResponse();
EnumMessage message = ex.getError();
response.setCode(message.getSubject().getId());
response.setMessage(errorResolver.resolve(message));
return response;
}
}

View file

@ -1,6 +1,7 @@
package ru.spcex.clearing.backendapi.errors;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import java.util.Collection;
import java.util.List;
@ -16,6 +17,10 @@ public class ActionValidationException extends RuntimeException {
this.errors = List.of(error);
}
public ActionValidationException(IEnumId subject, Object... args) {
this.errors = List.of(new EnumMessage(subject, args));
}
public Collection<EnumMessage> getErrors() {
return errors;
}

View file

@ -6,7 +6,10 @@ public enum BackEndError implements IEnumId {
ValidationError(3000L),
UnknownJsonProperty(3001L),
FailedToReadHttpMessage(3002L),
KeycloakRepeatedRoles(3003L);
KeycloakRepeatedRoles(3003L),
DictionaryNotFound(3004L),
ResourceNotFound(404L)
;
private final Long id;
BackEndError(Long id) {

View file

@ -0,0 +1,16 @@
package ru.spcex.clearing.backendapi.errors;
import ru.spcex.platform.utils.enumeration.EnumMessage;
public class NotFound404Exception extends RuntimeException {
private final EnumMessage error;
public NotFound404Exception(String comment) {
this.error = new EnumMessage(BackEndError.ResourceNotFound, comment);
}
public EnumMessage getError() {
return error;
}
}

View file

@ -1,4 +1,5 @@
1=This is error example 1.
3000=validation error field '%s'
3001=unrecognized json property '%s'
3002=failed to read http message
3002=failed to read http message
3004=couldn't find dictionary '%s'

View file

@ -55,6 +55,10 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-classes-base</artifactId>
</dependency>
</dependencies>
<build>

View file

@ -1,22 +1,12 @@
package ru.clearing.platform.dictionary;
public abstract class AbstractDictionary implements Dictionary {
static final long serialVersionUID = ConstDictionarySerializable.serialVersionUID;
import ru.spcex.platform.classes.base.SpcexObjectBase;
protected Long id;
public abstract class AbstractDictionary extends SpcexObjectBase implements Dictionary {
static final long serialVersionUID = ConstDictionarySerializable.serialVersionUID;
protected String code;
protected String name;
@Override
public Long getId() {
return id;
}
@Override
public void setId(Long id) {
this.id = id;
}
@Override
public String getCode() {
return code;

View file

@ -29,6 +29,11 @@ public class ImdgHazelcast<T extends SpcexObjectBase> implements Imdg<T> {
return map.values();
}
@Override
public Integer size() {
return map.size();
}
@Override
public void insert(T paramT) {
if (paramT.getId() == null) {

View file

@ -57,4 +57,8 @@ public interface Imdg<T extends SpcexObjectBase> {
default <A> Collection<A> projectionsAttributeBySql(String paramString, String... paramVarArgs) {
throw new UnsupportedOperationException("not implemented projectionsAttributeBySql");
}
default Integer size() {
throw new UnsupportedOperationException("not implemented size");
}
}