http://jira.mfd.msk:8088/browse/CLS-213 добавил словари в мету

This commit is contained in:
ialbert 2022-12-26 20:20:04 +03:00
parent a5320f36f3
commit 1d63a859c6
9 changed files with 158 additions and 23 deletions

View file

@ -9,25 +9,34 @@ import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
@ApiModel(description = "Ответ при получении объектов словаря.") @ApiModel(description = "Ответ при получении объектов словаря.")
public class DictionaryBackendGetAll extends BasicSpcexResponse { public class DictionaryBackendGetAll extends BasicSpcexResponse {
@JsonProperty @JsonProperty
@ApiModelProperty(value = "Полезная нагрузка") @ApiModelProperty(value = "Полезная нагрузка")
private DictionaryBackendPayload payload = new DictionaryBackendPayload(); private IDictionaryPayload payload;
public void fromEntity(Collection<AbstractDictionary> dictionaryValues) { public void fromEntity(Collection<AbstractDictionary> dictionaryValues) {
var payload = this.getPayload(); this.payload = new GeneralDictionaryBackendPayload();
GeneralDictionaryBackendPayload castedPayload = (GeneralDictionaryBackendPayload) payload;
for (AbstractDictionary dictionaryValue : dictionaryValues) { for (AbstractDictionary dictionaryValue : dictionaryValues) {
var singleItem = new DictionaryBackendGetFields(); var singleItem = new DictionaryBackendGetFields();
singleItem.fromEntity(dictionaryValue); singleItem.fromEntity(dictionaryValue);
payload.getItems().add(singleItem); castedPayload.getItems().add(singleItem);
} }
} }
public void addMap(Map<String, Object> m) {
if (this.payload == null) {
this.payload = new SpecificDictionaryBackendPayload();
}
SpecificDictionaryBackendPayload payloadCasted = (SpecificDictionaryBackendPayload) this.payload;
payloadCasted.getItems().add(m);
}
private static class DictionaryBackendPayload { public static class GeneralDictionaryBackendPayload implements IDictionaryPayload {
private List<DictionaryBackendGetFields> items = new ArrayList<>(); private List<DictionaryBackendGetFields> items = new ArrayList<>();
public List<DictionaryBackendGetFields> getItems() { public List<DictionaryBackendGetFields> getItems() {
@ -39,11 +48,24 @@ public class DictionaryBackendGetAll extends BasicSpcexResponse {
} }
} }
public DictionaryBackendPayload getPayload() { public static class SpecificDictionaryBackendPayload implements IDictionaryPayload {
@JsonProperty
private List<Map<String, Object>> items = new ArrayList<>();
public List<Map<String, Object>> getItems() {
return items;
}
public void setItems(List<Map<String, Object>> items) {
this.items = items;
}
}
public IDictionaryPayload getPayload() {
return payload; return payload;
} }
public void setPayload(DictionaryBackendPayload payload) { public void setPayload(IDictionaryPayload payload) {
this.payload = payload; this.payload = payload;
} }
} }

View file

@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import ru.clearing.platform.dictionary.AbstractDictionary; import ru.clearing.platform.dictionary.AbstractDictionary;
public class DictionaryBackendGetFields { public class DictionaryBackendGetFields implements IDictionaryPayload {
@JsonProperty @JsonProperty
@ApiModelProperty(value = "Идентификатор", example = "1234") @ApiModelProperty(value = "Идентификатор", example = "1234")
private Long id; private Long id;

View file

@ -0,0 +1,25 @@
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.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import java.util.HashMap;
import java.util.Map;
@ApiModel(description = "Ответ при получении объекта словаря.")
public class DictionaryBackendGetSingleValueV2 extends BasicSpcexResponse {
@JsonProperty
@ApiModelProperty(value = "Поля объекта")
private Map<String, Object> payload = new HashMap<>();
public Map<String, Object> getPayload() {
return payload;
}
public void setPayload(Map<String, Object> payload) {
this.payload = payload;
}
}

View file

@ -0,0 +1,4 @@
package ru.spcex.clearing.backendapi.controller.response.entity.dictionary;
public interface IDictionaryPayload {
}

View file

@ -13,10 +13,11 @@ import org.springframework.web.bind.annotation.*;
import ru.clearing.platform.dictionary.AbstractDictionary; import ru.clearing.platform.dictionary.AbstractDictionary;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; 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.DictionaryBackendGetAll;
import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValue; import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValueV2;
import ru.spcex.clearing.backendapi.errors.ActionValidationException; import ru.spcex.clearing.backendapi.errors.ActionValidationException;
import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.backendapi.errors.NotFound404Exception; import ru.spcex.clearing.backendapi.errors.NotFound404Exception;
import ru.spcex.clearing.backendapi.meta.GetResponseFactory;
import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
@ -33,10 +34,12 @@ public class DictionaryController {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final Map<String, Imdg<?>> allDictionaryMaps; private final Map<String, Imdg<?>> allDictionaryMaps;
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final GetResponseFactory responseFactory;
@Autowired @Autowired
public DictionaryController(ImdgProvider imdgProvider) { public DictionaryController(ImdgProvider imdgProvider, GetResponseFactory responseFactory) {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.responseFactory = responseFactory;
this.allDictionaryMaps = new ConcurrentHashMap<>(); this.allDictionaryMaps = new ConcurrentHashMap<>();
} }
@ -49,39 +52,42 @@ public class DictionaryController {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
Collection<AbstractDictionary> allValues = dictionary.getAllValues(); Collection<AbstractDictionary> allValues = dictionary.getAllValues();
DictionaryBackendGetAll response = new DictionaryBackendGetAll(); DictionaryBackendGetAll response = new DictionaryBackendGetAll();
response.fromEntity(allValues); for (AbstractDictionary val : allValues) {
Map<String, Object> fromMeta = responseFactory.responseFromDictionary(dictionaryName, val);
response.addMap(fromMeta);
}
return response; return response;
} }
@ApiOperation(value = "get dictionary value by id.") @ApiOperation(value = "get dictionary value by id.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValueV2.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{dictionary-name}/{id}", method = RequestMethod.GET) @RequestMapping(value = "/{dictionary-name}/{id}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public DictionaryBackendGetSingleValue getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") public DictionaryBackendGetSingleValueV2 getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide")
@PathVariable("dictionary-name") String dictionaryName, @PathVariable("dictionary-name") String dictionaryName,
@ApiParam(value = "Идентификатор объекта", required = true, example = "1234") @ApiParam(value = "Идентификатор объекта", required = true, example = "1234")
@PathVariable("id") Long id) { @PathVariable("id") Long id) {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
AbstractDictionary value = dictionary.getSingleObjectByID(id); AbstractDictionary value = dictionary.getSingleObjectByID(id);
if (value == null) throw new NotFound404Exception(dictionaryName + " id='" + id + "'"); if (value == null) throw new NotFound404Exception(dictionaryName + " id='" + id + "'");
DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); DictionaryBackendGetSingleValueV2 response = new DictionaryBackendGetSingleValueV2();
response.fromEntity(value); response.setPayload(responseFactory.responseFromDictionary(dictionaryName, value));
return response; return response;
} }
@ApiOperation(value = "get dictionary value by code.") @ApiOperation(value = "get dictionary value by code.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValueV2.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{dictionary-name}/code/{code}", method = RequestMethod.GET) @RequestMapping(value = "/{dictionary-name}/code/{code}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public DictionaryBackendGetSingleValue getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") public DictionaryBackendGetSingleValueV2 getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide")
@PathVariable("dictionary-name") String dictionaryName, @PathVariable("dictionary-name") String dictionaryName,
@ApiParam(value = "Код словаря", required = true, example = "1234") @ApiParam(value = "Код словаря", required = true, example = "1234")
@PathVariable("code") String code) { @PathVariable("code") String code) {
Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); Imdg<AbstractDictionary> dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class);
AbstractDictionary value = dictionary.getSingleObjectByFieldValues(Map.of("code", code)); AbstractDictionary value = dictionary.getSingleObjectByFieldValues(Map.of("code", code));
if (value == null) throw new NotFound404Exception(dictionaryName + " code='" + code + "'"); if (value == null) throw new NotFound404Exception(dictionaryName + " code='" + code + "'");
DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); DictionaryBackendGetSingleValueV2 response = new DictionaryBackendGetSingleValueV2();
response.fromEntity(value); response.setPayload(responseFactory.responseFromDictionary(dictionaryName, value));
return response; return response;
} }

View file

@ -0,0 +1,22 @@
package ru.spcex.clearing.backendapi.meta;
import java.util.List;
public class ClearingDictionaryExtracted extends ObjectExtracted {
public ClearingDictionaryExtracted(String clazz, List<ActionField> actionFields) {
for (ActionField field : actionFields) {
if (field.getVirtual() != null && field.isVirtual()){
continue;
}
FieldExtracted fe = getImplFieldExtracted(field);
fields.add(fe);
fieldByCode.put(field.getCode(), fe);
}
}
@Override
public FieldExtracted getImplFieldExtracted(ActionField field) {
return new ClearingFieldExtracted(field);
}
}

View file

@ -31,11 +31,26 @@ public class GetResponseFactory {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
/**
* dictionaryName - это имя тэга внутри <enum>
*/
public Map<String, Object> responseFromDictionary(String dictionaryName, Object o) {
ObjectExtracted objectExtracted = meta.getEnumsExtractedByTagName().get(dictionaryName);
if (objectExtracted == null) {
throw new RuntimeException("cannot find dictionary in meta for " + dictionaryName);
}
return responseFromObjectExtracted(o, objectExtracted);
}
public Map<String, Object> responseFromObject(Object o) { public Map<String, Object> responseFromObject(Object o) {
ObjectExtracted objExtr = meta.getObjectsExtractedByClazz().get(o.getClass().getCanonicalName()); ObjectExtracted objExtr = meta.getObjectsExtractedByClazz().get(o.getClass().getCanonicalName());
if (objExtr == null) { if (objExtr == null) {
throw new RuntimeException("cannot find object in meta for " + o.getClass().getCanonicalName()); throw new RuntimeException("cannot find object in meta for " + o.getClass().getCanonicalName());
} }
return responseFromObjectExtracted(o, objExtr);
}
private Map<String, Object> responseFromObjectExtracted(Object o, ObjectExtracted objExtr) {
Map<String, Object> r = new LinkedHashMap<>(); Map<String, Object> r = new LinkedHashMap<>();
FieldExtracted currentField = null; FieldExtracted currentField = null;
try { try {

View file

@ -2,6 +2,7 @@ package ru.spcex.clearing.backendapi.meta;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.spcex.platform.utils.log.ExceptionUtils;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -17,6 +18,8 @@ public class MetaServer extends MetaBase {
private Map<String, ObjectExtracted> objectsExtractedByDestination; private Map<String, ObjectExtracted> objectsExtractedByDestination;
private Map<String, ObjectExtracted> actionObjectsExtracted; private Map<String, ObjectExtracted> actionObjectsExtracted;
private Map<String, ObjectElement> objectElementByDestination; private Map<String, ObjectElement> objectElementByDestination;
private Map<String, ObjectExtracted> enumsExtractedByTagName;
private final static Set<String> dictionaryDefaultFields = Set.of("id", "code", "name");
protected ObjectExtracted getImplInstanceObjectExtracted(String clazz, List<ActionField> actionFields) { protected ObjectExtracted getImplInstanceObjectExtracted(String clazz, List<ActionField> actionFields) {
return new ClearingObjectExtracted(clazz, actionFields); return new ClearingObjectExtracted(clazz, actionFields);
@ -31,6 +34,7 @@ public class MetaServer extends MetaBase {
objectsExtractedByClazz = new ConcurrentHashMap<>(); objectsExtractedByClazz = new ConcurrentHashMap<>();
objectsExtractedByDestination = new ConcurrentHashMap<>(); objectsExtractedByDestination = new ConcurrentHashMap<>();
objectElementByDestination = new ConcurrentHashMap<>(); objectElementByDestination = new ConcurrentHashMap<>();
enumsExtractedByTagName = new ConcurrentHashMap<>();
try { try {
Map<String, ObjectElement> objects = getObjects(); Map<String, ObjectElement> objects = getObjects();
log.info("Meta objects:\n{}", log.info("Meta objects:\n{}",
@ -84,6 +88,37 @@ public class MetaServer extends MetaBase {
} catch (Throwable e) { } catch (Throwable e) {
throw new ClearingMetaServerValidationException(e.getLocalizedMessage()); throw new ClearingMetaServerValidationException(e.getLocalizedMessage());
} }
try {
Map<String, ObjectEnumElement> enums = getEnums();
for (String key : enums.keySet()) {
ObjectExtracted oe;
ObjectEnumElement objectElement = enums.get(key);
try {
oe = new ClearingDictionaryExtracted(objectElement.getClazz(), objectElement.getFields());
} catch (Throwable e) {
log.warn("{} {}", key, ExceptionUtils.getStackTrace(e));
continue;
}
/**
* можно было бы хранить только для нестандартных словарей (где не только id, name, code)
*/
// List<FieldExtracted> dictFields = oe.getFields();
// boolean add = false;
// for (FieldExtracted dictField : dictFields) {
// if (!dictionaryDefaultFields.contains(dictField.getMemberName())) {
// add = true;
// break;
// }
// }
// if (add) {
// enumsExtractedByTagName.put(key, oe);
// }
enumsExtractedByTagName.put(key, oe);
}
} catch (Throwable e) {
throw new ClearingMetaServerValidationException(e.getLocalizedMessage());
}
} }
for (ObjectExtracted o : this.objectsExtracted) { for (ObjectExtracted o : this.objectsExtracted) {
try { try {
@ -196,4 +231,8 @@ public class MetaServer extends MetaBase {
} }
return partSize; return partSize;
} }
public Map<String, ObjectExtracted> getEnumsExtractedByTagName() {
return enumsExtractedByTagName;
}
} }

View file

@ -5,12 +5,14 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public abstract class ObjectExtracted { public abstract class ObjectExtracted {
private String className; protected String className;
private Class<?> clazz; protected Class<?> clazz;
private List<FieldExtracted> fields = new LinkedList<>(); protected List<FieldExtracted> fields = new LinkedList<>();
private Map<String, FieldExtracted> fieldByCode = new ConcurrentHashMap<>(); protected Map<String, FieldExtracted> fieldByCode = new ConcurrentHashMap<>();
private boolean isArray = false; protected boolean isArray = false;
public ObjectExtracted() {
}
public ObjectExtracted(String clazz, List<ActionField> actionFields) { public ObjectExtracted(String clazz, List<ActionField> actionFields) {
this.className = clazz; this.className = clazz;