xml-importer xml file processing minor changes

This commit is contained in:
Ivan Nikolaev-Axenov 2024-06-14 18:10:12 +03:00
parent 702cfacad1
commit 0106d58569
No known key found for this signature in database
GPG key ID: 82FFE894BBF6A558
9 changed files with 41 additions and 99 deletions

View file

@ -1,7 +1,5 @@
package ru.spcex.clearing.xml.importer.config; package ru.spcex.clearing.xml.importer.config;
import java.util.HashMap;
import java.util.Map;
import com.ctc.wstx.stax.WstxInputFactory; import com.ctc.wstx.stax.WstxInputFactory;
import com.ctc.wstx.stax.WstxOutputFactory; import com.ctc.wstx.stax.WstxOutputFactory;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
@ -9,6 +7,8 @@ import com.fasterxml.jackson.dataformat.xml.XmlFactory;
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.HashMap;
import java.util.Map;
import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLOutputFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -20,9 +20,15 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.clearing.classes.statics.data.sdf.SDf04;
import ru.clearing.classes.statics.data.sdf.SDf06;
import ru.clearing.classes.statics.data.sdf.SDf52;
import ru.clearing.classes.statics.data.sdf.SDf55;
import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.config.settings.ImportXMLServiceSettings; import ru.spcex.clearing.xml.importer.config.settings.ImportXMLServiceSettings;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
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.iml.hazelcast.service.HazelcastService; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
@ -58,14 +64,14 @@ public class XMLImporterConfig {
} }
@Bean("mapOfTable") @Bean("mapOfTable")
public Map<String, Imdg<?>> getMapOfTables() { public Map<ETable, Imdg<? extends SpcexObjectBase>> getMapOfTables() {
Map<String, Imdg<?>> map = new HashMap<>(); Map<ETable, Imdg<? extends SpcexObjectBase>> map = new HashMap<>();
map.put(ETable.DF_01.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_01, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class));
map.put(ETable.DF_04.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_04, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf04, SDf04.class));
map.put(ETable.DF_06.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_06, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf06, SDf06.class));
map.put(ETable.DF_52.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_52, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf52, SDf52.class));
map.put(ETable.DF_55.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_55, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf55, SDf55.class));
map.put(ETable.DF_57.name(), hazelcastService.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); map.put(ETable.DF_57, hazelcastService.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class));
return map; return map;
} }

View file

@ -2,17 +2,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF01ObjectTag extends ObjectTag<SDf01> { public class DF01ObjectTag extends ObjectTag<SDf01> {
private static final String PREFIX = ETable.DF_01.name(); private static final ETable PREFIX = ETable.DF_01;
private static final Class<SDf01> CLAZZ = SDf01.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf01;
@JacksonXmlProperty(isAttribute = true, localName = "CURR_CODE") @JacksonXmlProperty(isAttribute = true, localName = "CURR_CODE")
private String currCode; private String currCode;
@ -52,7 +48,7 @@ public class DF01ObjectTag extends ObjectTag<SDf01> {
private String fileType; private String fileType;
public DF01ObjectTag() { public DF01ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -71,9 +67,6 @@ public class DF01ObjectTag extends ObjectTag<SDf01> {
result.setSumengage(this.getSumengage()); result.setSumengage(this.getSumengage());
result.setSumunblock(this.getSumunblock()); result.setSumunblock(this.getSumunblock());
result.setFile_type(this.getFileType()); result.setFile_type(this.getFileType());
result.setFileName(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -2,17 +2,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf04; import ru.clearing.classes.statics.data.sdf.SDf04;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF04ObjectTag extends ObjectTag<SDf04> { public class DF04ObjectTag extends ObjectTag<SDf04> {
private static final String PREFIX = ETable.DF_04.name(); private static final ETable PREFIX = ETable.DF_04;
private static final Class<SDf04> CLAZZ = SDf04.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf04;
@JacksonXmlProperty(isAttribute = true, localName = "SEG_TYPE") @JacksonXmlProperty(isAttribute = true, localName = "SEG_TYPE")
private String segType; private String segType;
@ -63,7 +59,7 @@ public class DF04ObjectTag extends ObjectTag<SDf04> {
private String impResult; private String impResult;
public DF04ObjectTag() { public DF04ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -91,9 +87,6 @@ public class DF04ObjectTag extends ObjectTag<SDf04> {
result.setSum_deb(this.getSumDeb()); result.setSum_deb(this.getSumDeb());
result.setSpecif_1(this.getSpecif1()); result.setSpecif_1(this.getSpecif1());
result.setImp_result(this.getImpResult()); result.setImp_result(this.getImpResult());
result.setFile_name(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -3,17 +3,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf06; import ru.clearing.classes.statics.data.sdf.SDf06;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF06ObjectTag extends ObjectTag<SDf06> { public class DF06ObjectTag extends ObjectTag<SDf06> {
private static final String PREFIX = ETable.DF_06.name(); private static final ETable PREFIX = ETable.DF_06;
private static final Class<SDf06> CLAZZ = SDf06.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf06;
@JacksonXmlProperty(isAttribute = true, localName = "ACCOUNT") @JacksonXmlProperty(isAttribute = true, localName = "ACCOUNT")
private String account; private String account;
@ -56,7 +52,7 @@ public class DF06ObjectTag extends ObjectTag<SDf06> {
private String payVal; private String payVal;
public DF06ObjectTag() { public DF06ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -76,9 +72,6 @@ public class DF06ObjectTag extends ObjectTag<SDf06> {
result.setDoc_Num(this.getDocNum()); result.setDoc_Num(this.getDocNum());
result.setDoc_Date(this.getDocDate().toString()); result.setDoc_Date(this.getDocDate().toString());
result.setPay_val(this.getPayVal()); result.setPay_val(this.getPayVal());
result.setFileName(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -2,17 +2,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf52; import ru.clearing.classes.statics.data.sdf.SDf52;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF52ObjectTag extends ObjectTag<SDf52> { public class DF52ObjectTag extends ObjectTag<SDf52> {
private static final String PREFIX = ETable.DF_52.name(); private static final ETable PREFIX = ETable.DF_52;
private static final Class<SDf52> CLAZZ = SDf52.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf52;
@JacksonXmlProperty(isAttribute = true, localName = "ACCOUNT") @JacksonXmlProperty(isAttribute = true, localName = "ACCOUNT")
private String account; private String account;
@ -34,7 +30,7 @@ public class DF52ObjectTag extends ObjectTag<SDf52> {
private String accType; private String accType;
public DF52ObjectTag() { public DF52ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -47,9 +43,6 @@ public class DF52ObjectTag extends ObjectTag<SDf52> {
result.setDate(this.getDate().toString()); result.setDate(this.getDate().toString());
result.setAcc_type(this.getAccType()); result.setAcc_type(this.getAccType());
result.setStatus(this.getStatus()); result.setStatus(this.getStatus());
result.setFileName(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -2,17 +2,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf55; import ru.clearing.classes.statics.data.sdf.SDf55;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF55ObjectTag extends ObjectTag<SDf55> { public class DF55ObjectTag extends ObjectTag<SDf55> {
private static final String PREFIX = ETable.DF_55.name(); private static final ETable PREFIX = ETable.DF_55;
private static final Class<SDf55> CLAZZ = SDf55.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf55;
@JacksonXmlProperty(isAttribute = true, localName = "SEG_TYPE") @JacksonXmlProperty(isAttribute = true, localName = "SEG_TYPE")
private String segType; private String segType;
@ -125,7 +121,7 @@ public class DF55ObjectTag extends ObjectTag<SDf55> {
private String swiftInt; private String swiftInt;
public DF55ObjectTag() { public DF55ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -177,9 +173,6 @@ public class DF55ObjectTag extends ObjectTag<SDf55> {
result.setValue_date(this.getValueDate().toString()); result.setValue_date(this.getValueDate().toString());
result.setSwift_ben(this.getSwiftBen()); result.setSwift_ben(this.getSwiftBen());
result.setSwift_int(this.getSwiftInt()); result.setSwift_int(this.getSwiftInt());
result.setFileName(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -2,17 +2,13 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Objects; import java.util.Objects;
import ru.clearing.classes.statics.data.sdf.SDf57; import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable; import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
public class DF57ObjectTag extends ObjectTag<SDf57> { public class DF57ObjectTag extends ObjectTag<SDf57> {
private static final String PREFIX = ETable.DF_57.name(); private static final ETable PREFIX = ETable.DF_57;
private static final Class<SDf57> CLAZZ = SDf57.class;
private static final String NAME_OF_HZ_MAP = IMDGDistributedNames.Map_SDf57;
@JacksonXmlProperty(isAttribute = true, localName = "ID") @JacksonXmlProperty(isAttribute = true, localName = "ID")
private Long id; private Long id;
@ -118,7 +114,7 @@ public class DF57ObjectTag extends ObjectTag<SDf57> {
private String ktOut; private String ktOut;
public DF57ObjectTag() { public DF57ObjectTag() {
super(PREFIX, CLAZZ, NAME_OF_HZ_MAP); super(PREFIX);
} }
@Override @Override
@ -168,9 +164,6 @@ public class DF57ObjectTag extends ObjectTag<SDf57> {
result.setKt_in(this.getKtIn()); result.setKt_in(this.getKtIn());
result.setDt_out(this.getDtOut()); result.setDt_out(this.getDtOut());
result.setKt_out(this.getKtOut()); result.setKt_out(this.getKtOut());
result.setFileName(filename);
result.setGenerationTime(Instant.now());
result.setGenerationId(fileId);
return result; return result;
} }

View file

@ -2,6 +2,7 @@ package ru.spcex.clearing.xml.importer.logic.data.tags.objects;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
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;
@ -15,50 +16,26 @@ import ru.spcex.platform.imdg.api.Imdg;
@JsonSubTypes.Type(DF57ObjectTag.class) @JsonSubTypes.Type(DF57ObjectTag.class)
}) })
public abstract class ObjectTag<T1 extends SpcexObjectBase> { public abstract class ObjectTag<T1 extends SpcexObjectBase> {
private final String prefix; private final ETable prefix;
private final Class<T1> clazz;
private final String nameOfMap;
// protected HazelcastService hazelcastService;
protected String filename; public ObjectTag(ETable prefix) {
protected Long fileId;
public ObjectTag(String prefix, Class<T1> clazz, String nameOfMap) {
this.prefix = prefix; this.prefix = prefix;
this.clazz = clazz;
this.nameOfMap = nameOfMap;
} }
public abstract T1 getSDfEntity(); public abstract T1 getSDfEntity();
public String getPrefix() { public ETable getPrefix() {
return prefix; return prefix;
} }
public void insertEntity(Imdg<?> map) { public void insertEntity(Imdg<T1> map) {
T1 obj = getSDfEntity(); T1 obj = getSDfEntity();
if (checkOnExisting(obj)) { if (checkOnExisting(obj)) {
// map.insert(obj); map.insert(obj);
} }
} }
protected boolean checkOnExisting(T1 obj) { protected boolean checkOnExisting(T1 obj) {
return true; return true;
} }
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public Long getFileId() {
return fileId;
}
public void setFileId(Long fileId) {
this.fileId = fileId;
}
} }

View file

@ -1,9 +1,9 @@
package ru.spcex.clearing.xml.importer.logic.steps; package ru.spcex.clearing.xml.importer.logic.steps;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -13,6 +13,7 @@ import ru.spcex.clearing.xml.importer.logic.data.enums.ETable;
import ru.spcex.clearing.xml.importer.logic.data.enums.StageResult; import ru.spcex.clearing.xml.importer.logic.data.enums.StageResult;
import ru.spcex.clearing.xml.importer.logic.data.tags.DocumentTag; import ru.spcex.clearing.xml.importer.logic.data.tags.DocumentTag;
import ru.spcex.clearing.xml.importer.logic.data.tags.objects.ObjectTag; import ru.spcex.clearing.xml.importer.logic.data.tags.objects.ObjectTag;
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.iml.hazelcast.service.HazelcastService; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.log.ExceptionUtils;
@ -23,12 +24,12 @@ public class ImportToDB {
private final XmlMapper xmlMapper; private final XmlMapper xmlMapper;
private final HazelcastService hazelcastService; private final HazelcastService hazelcastService;
private final XmlImportKafkaMessenger kafkaMessenger; private final XmlImportKafkaMessenger kafkaMessenger;
private final Map<String, Imdg<?>> mapOfTable; private final Map<ETable, Imdg<?>> mapOfTable;
public ImportToDB(@Qualifier("xmlMapper") XmlMapper xmlMapper, public ImportToDB(@Qualifier("xmlMapper") XmlMapper xmlMapper,
HazelcastService hazelcastService, HazelcastService hazelcastService,
XmlImportKafkaMessenger kafkaMessenger, XmlImportKafkaMessenger kafkaMessenger,
@Qualifier("mapOfTable") Map<String, Imdg<?>> mapOfTable) { @Qualifier("mapOfTable") Map<ETable, Imdg<?>> mapOfTable) {
this.xmlMapper = xmlMapper; this.xmlMapper = xmlMapper;
this.hazelcastService = hazelcastService; this.hazelcastService = hazelcastService;
this.kafkaMessenger = kafkaMessenger; this.kafkaMessenger = kafkaMessenger;
@ -52,8 +53,8 @@ public class ImportToDB {
String fileName = resultContainer.getXmlFile().getName(); String fileName = resultContainer.getXmlFile().getName();
Long fileId = hazelcastService.getImdgIdGenerator().nextId(); Long fileId = hazelcastService.getImdgIdGenerator().nextId();
for (ObjectTag<?> o : documentTag.getObjects()) { for (ObjectTag o : documentTag.getObjects()) {
Imdg<?> imdgMap = mapOfTable.get(o.getPrefix()); Imdg<? extends SpcexObjectBase> imdgMap = mapOfTable.get(o.getPrefix());
o.insertEntity(imdgMap); o.insertEntity(imdgMap);
} }