meta parsing
This commit is contained in:
parent
15f42c96b8
commit
47b0e6d6c4
16 changed files with 937 additions and 0 deletions
|
|
@ -82,6 +82,11 @@
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.reflections</groupId>
|
||||||
|
<artifactId>reflections</artifactId>
|
||||||
|
<version>0.9.11</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DefaultAnnotationParam", "unused"})
|
||||||
|
public class ActionElement {
|
||||||
|
@JsonProperty(value = "class")
|
||||||
|
private String clazz = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "name", required = true)
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "destination", required = false)
|
||||||
|
private String destination = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "array", required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Boolean isArray = null;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "fields", required = true)
|
||||||
|
// private List<Map<String, ActionField>> fields = new LinkedList<>();
|
||||||
|
@JsonProperty(value = "fields", required = true)
|
||||||
|
private List<ActionField> fields = new LinkedList<>();
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActionField> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getArray() {
|
||||||
|
return isArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ActionField {
|
||||||
|
@JsonProperty(value = "code")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@JsonProperty(value = "name")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JsonProperty(value = "shortname")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String shortname;
|
||||||
|
|
||||||
|
@JsonProperty(value = "linkCode")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String linkcode;
|
||||||
|
|
||||||
|
@JsonProperty(value = "link")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
@JsonProperty(value = "field")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String field;
|
||||||
|
|
||||||
|
@JsonProperty(value = "length")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private Integer length;
|
||||||
|
|
||||||
|
@JsonProperty(value = "required")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private Boolean required;
|
||||||
|
|
||||||
|
@JsonProperty(value = "table")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private String table;
|
||||||
|
|
||||||
|
@JsonProperty(value = "type")
|
||||||
|
@JsonDeserialize(using = MetaDataTypeDeserializer.class)
|
||||||
|
@JsonSerialize(using = MetaDataTypeSerializer.class, include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private MetaDataTypes type;
|
||||||
|
|
||||||
|
@JsonProperty(value = "virtual")
|
||||||
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
|
||||||
|
private Boolean virtual;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private Map<String, Object> additionalProperties = new HashMap<>();
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isRequired() {
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetaDataTypes getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLink() {
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortname() {
|
||||||
|
return shortname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLinkcode() {
|
||||||
|
return linkcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonAnyGetter
|
||||||
|
public Map<String, Object> getAdditionalProperties() {
|
||||||
|
return this.additionalProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonAnySetter
|
||||||
|
public void setAdditionalProperty(String name, Object value) {
|
||||||
|
this.additionalProperties.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isVirtual(){
|
||||||
|
return virtual;
|
||||||
|
}
|
||||||
|
public Boolean getVirtual() {
|
||||||
|
return virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVirtual(Boolean virtual) {
|
||||||
|
this.virtual = virtual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
|
||||||
|
public class ClearingMetaServerValidationException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
public ClearingMetaServerValidationException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClearingMetaServerValidationException(String s, Throwable throwable) {
|
||||||
|
super(s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClearingMetaServerValidationException(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class FieldExtracted {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private ActionField field;
|
||||||
|
private String memberName;
|
||||||
|
private Collection<String> getterNames;
|
||||||
|
|
||||||
|
public FieldExtracted(ActionField field) {
|
||||||
|
this.field = field;
|
||||||
|
this.memberName = field.getField() != null ? field.getField() : field.getCode();
|
||||||
|
this.getterNames = gettersForField(this.memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<String> gettersForField(String fieldName) {
|
||||||
|
String[] fieldParts = fieldName.split("\\.");
|
||||||
|
List<String> getters = new LinkedList<>();
|
||||||
|
for (String partName : fieldParts) {
|
||||||
|
getters.add(String.format("%s%s%s",
|
||||||
|
RfHelper.GETTER_NAME_PREFIX,
|
||||||
|
partName.substring(0, 1).toUpperCase(),
|
||||||
|
partName.substring(1, partName.length())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return getters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s (%s) (getters=%d)", field.getCode(), memberName, getterNames.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Object getObjectRef(Object o);
|
||||||
|
|
||||||
|
public Object extractValue(Object from)
|
||||||
|
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
Object result = from;
|
||||||
|
for (String getterName : getGetterNames()) {
|
||||||
|
if (RfHelper.BUSINESS_OBJECT_REF.equals(result.getClass().getSimpleName()) && !RfHelper.GETTER_NAME_ID.equals(getterName)) {
|
||||||
|
Object resultNew = getObjectRef(result);
|
||||||
|
if (resultNew == null) {
|
||||||
|
log.warn("BusinessObject by referenceId does not exists!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = resultNew;
|
||||||
|
}
|
||||||
|
Method m = result.getClass().getMethod(getterName);
|
||||||
|
result = m.invoke(result);
|
||||||
|
if (result == null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// тут нужно вернуть список id объектов а не список самих объектов для случая
|
||||||
|
// - add(r, "addresseeId", o.getAddressee() == null ? null : o.getAddressee().stream().map(OtcObjectBase::getId).collect(Collectors.toSet()), fieldFilter);
|
||||||
|
if (result instanceof Set && ((Set) result).size() > 0) {
|
||||||
|
try {
|
||||||
|
Set t = new HashSet();
|
||||||
|
Class citem = (((Set) result).iterator().next()).getClass();
|
||||||
|
for (Object item : (Set) result) {
|
||||||
|
t.add(citem.getMethod(RfHelper.GETTER_NAME_ID).invoke(item));
|
||||||
|
}
|
||||||
|
result = t;
|
||||||
|
} catch (Throwable ignored) {// вернем сами объекты
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionField getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setField(ActionField field) {
|
||||||
|
this.field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberName(String memberName) {
|
||||||
|
this.memberName = memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGetterNames(Collection<String> getterNames) {
|
||||||
|
this.getterNames = getterNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemberName() {
|
||||||
|
return memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getGetterNames() {
|
||||||
|
return getterNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MetaBase {
|
||||||
|
|
||||||
|
@JsonProperty(required = true, defaultValue = "unknown")
|
||||||
|
private String version = null;
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty(required = true)
|
||||||
|
private Map<String, ObjectEnumElement> enums = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = true)
|
||||||
|
private Map<String, ObjectElement> objects = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = true)
|
||||||
|
private List<Map<String, String>> types = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Map<String, Object> views = new HashMap<>();
|
||||||
|
|
||||||
|
public Map<String, ObjectEnumElement> getEnums() {
|
||||||
|
return enums;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ObjectElement> getObjects() {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Map<String, String>> getTypes() {
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getViews() {
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViews(Map<String, Object> views) {
|
||||||
|
this.views = views;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
|
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class MetaDataTypeDeserializer extends JsonDeserializer<MetaDataTypes> {
|
||||||
|
@Override
|
||||||
|
public MetaDataTypes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||||
|
if (p.getText() != null && p.getText().length() > 0) {
|
||||||
|
if (!"0".equals(p.getText()) && !p.getText().matches("[1-9]+[0-9]*")) return null;
|
||||||
|
Long metaDataType = new Long(p.getText());
|
||||||
|
return IEnumId.getEnumById(MetaDataTypes.class, metaDataType);
|
||||||
|
} else return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class MetaDataTypeSerializer extends JsonSerializer<MetaDataTypes> {
|
||||||
|
@Override
|
||||||
|
public void serialize(MetaDataTypes metaDataTypes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
|
||||||
|
jsonGenerator.writeNumber(metaDataTypes.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||||
|
|
||||||
|
public enum MetaDataTypes implements IEnumId {
|
||||||
|
Identity(1L),
|
||||||
|
String(2L),
|
||||||
|
Long(3L),
|
||||||
|
DateTime(4L),
|
||||||
|
Time(5L),
|
||||||
|
Date(6L),
|
||||||
|
Array(7L),
|
||||||
|
Object(8L),
|
||||||
|
Boolean(9L),
|
||||||
|
Double(10L),
|
||||||
|
UID(11L);
|
||||||
|
|
||||||
|
private final Long id;
|
||||||
|
|
||||||
|
MetaDataTypes(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.lang.Long getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeSize() {
|
||||||
|
switch (this) {
|
||||||
|
case Long:
|
||||||
|
return java.lang.String.valueOf(java.lang.Long.MAX_VALUE).length();
|
||||||
|
case Identity:
|
||||||
|
return java.lang.String.valueOf(java.lang.Long.MAX_VALUE).length();
|
||||||
|
case DateTime:
|
||||||
|
return 25;
|
||||||
|
case Time:
|
||||||
|
return 25;
|
||||||
|
case Date:
|
||||||
|
return 25;
|
||||||
|
case Array:
|
||||||
|
return java.lang.String.valueOf(java.lang.Long.MAX_VALUE).length() * 400;
|
||||||
|
case Boolean:
|
||||||
|
return java.lang.Boolean.TRUE.toString().length();
|
||||||
|
case Double:
|
||||||
|
return 18;
|
||||||
|
case UID:
|
||||||
|
return 36;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public abstract class MetaServer extends MetaBase {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private Collection<ObjectExtracted> objectsExtracted;
|
||||||
|
private Map<String, ObjectExtracted> objectsExtractedByClazz;
|
||||||
|
private Map<String, ObjectExtracted> objectsExtractedByDestination;
|
||||||
|
private Map<String, ObjectExtracted> actionObjectsExtracted;
|
||||||
|
private Map<String, ObjectElement> objectElementByDestination;
|
||||||
|
|
||||||
|
protected abstract ObjectExtracted getImplInstanceObjectExtracted(String clazz, List<ActionField> actionFields);
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
public void initAndValidate() throws ClearingMetaServerValidationException, OtcMetaServerGetterNotFoundException {
|
||||||
|
if (objectsExtracted == null) {
|
||||||
|
objectsExtracted = new LinkedList<>();
|
||||||
|
actionObjectsExtracted = new ConcurrentHashMap<>();
|
||||||
|
objectsExtractedByClazz = new ConcurrentHashMap<>();
|
||||||
|
objectsExtractedByDestination = new ConcurrentHashMap<>();
|
||||||
|
objectElementByDestination = new ConcurrentHashMap<>();
|
||||||
|
try {
|
||||||
|
Map<String, ObjectElement> objects = getObjects();
|
||||||
|
log.info("Meta objects:\n{}",
|
||||||
|
objects.values()
|
||||||
|
.stream()
|
||||||
|
.map(ObjectElement::getName)
|
||||||
|
.collect(Collectors.joining(";", "[", "]")));
|
||||||
|
for (String key : objects.keySet()) {
|
||||||
|
ObjectExtracted oe;
|
||||||
|
ObjectElement objectElement = objects.get(key);
|
||||||
|
if (objectElement.getSubscription() != null) {
|
||||||
|
objectElementByDestination.put(objectElement.getSubscription().destination, objectElement);
|
||||||
|
if (objectElement.getSubscriptionHistory() != null) {
|
||||||
|
objectElementByDestination.put(objectElement.getSubscriptionHistory().destination, objectElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
oe = getImplInstanceObjectExtracted(objectElement.getClazz(), objectElement.getFields());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.warn("META SERVER >>> Класс {} не найден!", objects.get(key).getClazz());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
objectsExtracted.add(oe);
|
||||||
|
objectsExtractedByClazz.put(oe.getClassName(), oe);
|
||||||
|
if (objectElement.getSubscription() != null && objectElement.getSubscription().destination != null) {
|
||||||
|
objectsExtractedByDestination.put(objectElement.getSubscription().destination, oe);
|
||||||
|
}
|
||||||
|
for (ActionElement actionElement : objectElement.getActions()) {
|
||||||
|
if (actionElement.getClazz() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
oe = getImplInstanceObjectExtracted(actionElement.getClazz(), actionElement.getFields());
|
||||||
|
if (actionElement.getArray() != null) {
|
||||||
|
oe.setArray(actionElement.getArray());
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.warn("META SERVER >>> {}", e.getLocalizedMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
actionObjectsExtracted.put(actionElement.getDestination(), oe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new ClearingMetaServerValidationException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ObjectExtracted o : this.objectsExtracted) {
|
||||||
|
try {
|
||||||
|
if (!RfHelper.isAbstract(o.getClazz())) {
|
||||||
|
try {
|
||||||
|
Object instance = newInstance(o.getClassName());
|
||||||
|
// создается успешно.
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.warn("META SERVER >>> Не удается создать класс {} !", o.getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validateGetterForObject(o);
|
||||||
|
} catch (OtcMetaServerGetterNotFoundException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new ClearingMetaServerValidationException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ObjectExtracted o : this.actionObjectsExtracted.values()) {
|
||||||
|
try {
|
||||||
|
if (!RfHelper.isAbstract(o.getClazz())) {
|
||||||
|
try {
|
||||||
|
Object instance = newInstance(o.getClassName());
|
||||||
|
// создается успешно.
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.warn("META SERVER ACTION >>> Не удается создать класс {} !", o.getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validateGetterForObject(o);
|
||||||
|
} catch (OtcMetaServerGetterNotFoundException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new ClearingMetaServerValidationException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* проверим наличие геттеров к полям
|
||||||
|
*
|
||||||
|
* @param o
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
private void validateGetterForObject(ObjectExtracted o) throws ClassNotFoundException {
|
||||||
|
for (FieldExtracted field : o.getFields()) {
|
||||||
|
Class<?> c = o.getClazz();
|
||||||
|
for (String getterName : field.getGetterNames()) {
|
||||||
|
try {
|
||||||
|
Method m = RfHelper.searchGetter(c, getterName);
|
||||||
|
if (m == null) {
|
||||||
|
for (Class<?> sub : RfHelper.getSubclasses(c)) {
|
||||||
|
m = RfHelper.searchGetter(sub, getterName);
|
||||||
|
if (m != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m == null) {
|
||||||
|
throw new OtcMetaServerGetterNotFoundException(c, getterName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c = RfHelper.getMetodReturnClazz(m);
|
||||||
|
} catch (OtcMetaServerGetterNotFoundException e) {
|
||||||
|
log.warn("META SERVER >>> Геттер {}.{} не найден!", o.getClassName(), getterName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object newInstance(String className, Object... args) throws Exception {
|
||||||
|
Class<?> clazz = Class.forName(className);
|
||||||
|
if (args == null || args.length == 0) {
|
||||||
|
return clazz.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Class<?>> argTypes = new ArrayList<Class<?>>();
|
||||||
|
for (Object object : args) {
|
||||||
|
argTypes.add(object.getClass());
|
||||||
|
}
|
||||||
|
Constructor<?> explicitConstructor = clazz.getConstructor(argTypes.toArray(new Class[argTypes.size()]));
|
||||||
|
return explicitConstructor.newInstance(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ObjectExtracted> getObjectsExtracted() {
|
||||||
|
return objectsExtracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ObjectExtracted> getActionObjectsExtracted() {
|
||||||
|
return actionObjectsExtracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ObjectExtracted> getObjectsExtractedByClazz() {
|
||||||
|
return objectsExtractedByClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ObjectElement> getObjectElementByDestination() {
|
||||||
|
return objectElementByDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ObjectExtracted> getObjectsExtractedByDestination() {
|
||||||
|
return objectsExtractedByDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPartSizeValueByDestination(String destination) {
|
||||||
|
ObjectElement objectElementByDestination = getObjectElementByDestination().get(destination);
|
||||||
|
Integer partSize = null;
|
||||||
|
if (objectElementByDestination == null) {
|
||||||
|
log.warn("Null objectElement for destination: {}", destination);
|
||||||
|
} else {
|
||||||
|
partSize = objectElementByDestination.getSubscription().getPartSize();
|
||||||
|
}
|
||||||
|
return partSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DefaultAnnotationParam", "unused"})
|
||||||
|
public class ObjectElement {
|
||||||
|
@JsonProperty(required = true)
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "class", required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String clazz = null;
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String table = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "fields", required = true)
|
||||||
|
private List<ActionField> fields = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Map<String, Object> query = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Subscription subscription;
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Subscription subscriptionHistory;
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private List<ActionElement> actions = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private List<Map<String, String>> values = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Map<String, Object> views = new HashMap<>();
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getQuery() {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subscription getSubscription() {
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActionElement> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Map<String, String>> getValues() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActionField> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subscription getSubscriptionHistory() {
|
||||||
|
return subscriptionHistory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DefaultAnnotationParam", "unused"})
|
||||||
|
public class ObjectEnumElement {
|
||||||
|
@JsonProperty(required = true)
|
||||||
|
private String name = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "class", required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String clazz = null;
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String table = null;
|
||||||
|
|
||||||
|
@JsonProperty(value = "fields", required = true)
|
||||||
|
private List<ActionField> fields = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Map<String, Object> query = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private List<ActionElement> actions = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private List<Map<String, Object>> values = new LinkedList<>();
|
||||||
|
|
||||||
|
@JsonProperty(required = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private Map<String, Object> views = new HashMap<>();
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getQuery() {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActionElement> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Map<String, Object>> getValues() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActionField> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public abstract class ObjectExtracted {
|
||||||
|
private String className;
|
||||||
|
private Class<?> clazz;
|
||||||
|
private List<FieldExtracted> fields = new LinkedList<>();
|
||||||
|
private Map<String, FieldExtracted> fieldByCode = new ConcurrentHashMap<>();
|
||||||
|
private boolean isArray = false;
|
||||||
|
|
||||||
|
|
||||||
|
public ObjectExtracted(String clazz, List<ActionField> actionFields) {
|
||||||
|
this.className = clazz;
|
||||||
|
try {
|
||||||
|
this.clazz = Class.forName(this.className);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new ClearingMetaServerValidationException(String.format("Class not found [%s]", this.className));
|
||||||
|
}
|
||||||
|
for (ActionField field : actionFields) {
|
||||||
|
if (field.getVirtual() != null && field.isVirtual()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FieldExtracted fe = getImplFieldExtracted(field);
|
||||||
|
fields.add(fe);
|
||||||
|
fieldByCode.put(field.getCode(), fe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract FieldExtracted getImplFieldExtracted(ActionField field);
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s (fields=%d)", className, fields.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FieldExtracted> getFields() {
|
||||||
|
return new ArrayList<>(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, FieldExtracted> getFieldByCode() {
|
||||||
|
return new HashMap<>(fieldByCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArray() {
|
||||||
|
return isArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArray(boolean array) {
|
||||||
|
isArray = array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
|
||||||
|
public class OtcMetaServerGetterNotFoundException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
public OtcMetaServerGetterNotFoundException(Class clazz, String getterName) {
|
||||||
|
super(
|
||||||
|
String.format(
|
||||||
|
"Method %s() not found for class %s and subclasses!",
|
||||||
|
getterName, clazz
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class RfHelper {
|
||||||
|
|
||||||
|
private static Map<String, Reflections> REFLECTION_CACHE = new HashMap<>();
|
||||||
|
public static final String BUSINESS_OBJECT_REF = "BusinessObjectRef";
|
||||||
|
public static final String OTC_CLASSES_PACKAGE = "com.moex.otc.classes";
|
||||||
|
public static final String GETTER_NAME_PREFIX = "get";
|
||||||
|
public static final String GETTER_NAME_ID = GETTER_NAME_PREFIX + "Id";
|
||||||
|
|
||||||
|
public static Method searchGetter(Class<?> methodOwner, String name) {
|
||||||
|
for (Method m : methodOwner.getMethods()) {
|
||||||
|
if (m.getName().equals(name)) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Class<?>[] getSubclasses(Class<T> clazz) {
|
||||||
|
return getSubclasses(clazz, OTC_CLASSES_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Class<?>[] getSubclasses(Class<T> clazz, String packageName) {
|
||||||
|
Reflections reflections = REFLECTION_CACHE.computeIfAbsent(packageName, k -> new Reflections(packageName));
|
||||||
|
Set<Class<? extends T>> classes = reflections.getSubTypesOf(clazz);
|
||||||
|
return classes.toArray(new Class<?>[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAbstract(Class<?> clazz) {
|
||||||
|
return Modifier.isAbstract(clazz.getModifiers());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class getMetodReturnClazz(Method m) throws ClassNotFoundException {
|
||||||
|
Type t = m.getAnnotatedReturnType().getType();
|
||||||
|
if (t instanceof ParameterizedType) {
|
||||||
|
Class<?> raw = Class.forName(((ParameterizedType) t).getRawType().getTypeName());
|
||||||
|
if (BUSINESS_OBJECT_REF.equals(raw.getSimpleName())) {
|
||||||
|
return Class.forName(((ParameterizedType) t).getActualTypeArguments()[0].getTypeName());
|
||||||
|
} else if ("Set".equals(raw.getSimpleName())) { // множества пока не распаковываем
|
||||||
|
return Class.forName(raw.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Class.forName(t.getTypeName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package ru.spcex.clearing.backendapi.meta;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class Subscription {
|
||||||
|
@JsonProperty
|
||||||
|
public String destination;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public boolean enabled;
|
||||||
|
|
||||||
|
@JsonProperty(value = "partSize")
|
||||||
|
private Integer partSize;
|
||||||
|
|
||||||
|
public String getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(String destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPartSize() {
|
||||||
|
return partSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPartSize(Integer partSize) {
|
||||||
|
this.partSize = partSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue