package ee.esutoniagodesu.service;
import ee.esutoniagodesu.bean.EGDAssets;
import ee.esutoniagodesu.bean.ProjectDAO;
import ee.esutoniagodesu.domain.heisig.view.VHeisig6Custom;
import ee.esutoniagodesu.pojo.cf.ECfReportType;
import ee.esutoniagodesu.repository.domain.kanjidic2.KanjiRepository;
import ee.esutoniagodesu.repository.project.KanjiDB;
import ee.esutoniagodesu.repository.project.ReportDB;
import ee.esutoniagodesu.security.SecurityUtils;
import ee.esutoniagodesu.util.JCDateTime;
import ee.esutoniagodesu.util.JCString;
import ee.esutoniagodesu.util.commons.JCIOUtils;
import ee.esutoniagodesu.util.commons.JCText;
import ee.esutoniagodesu.util.jasperreports.CSVGenerator;
import ee.esutoniagodesu.util.jasperreports.JSGeneratorType;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.*;
import java.util.zip.ZipOutputStream;
@Service
@Transactional
public class JasperService {
private static final Logger log = LoggerFactory.getLogger(JasperService.class);
@Inject
private ProjectDAO dao;
@Inject
private KanjiDB kanjiDB;
@Inject
private KanjiRepository kanjiRepository;
@Inject
private ReportDB reportDB;
private static final CSVGenerator _csvGenerator = new CSVGenerator("\t");
private int _exampleWordsCount = 20;
private List<VHeisig6Custom> findAllVHeisig6Custom() throws UnsupportedEncodingException {
return findVHeisig6Custom(1, 2200);
}
/**
* 1) Leiab kõik 2200 Heisig 6 kaarti
* 2) Lisab näidissõnad
* 3) Koostab html'i
*/
private List<VHeisig6Custom> findVHeisig6Custom(int from, int to) throws UnsupportedEncodingException {
Assert.isTrue(from > 0 && to > from && to <= 2200);
List<VHeisig6Custom> result = dao.findAll(VHeisig6Custom.class);
Assert.isTrue(2200 == result.size());
result = result.subList(from - 1, to);
StringBuilder words = new StringBuilder();
for (VHeisig6Custom p : result) {
kanjiRepository.findByLiteral(p.getKanji()).ifPresent(item -> {
p.setJlpt(item.getJlpt());
if (item.getJouyou() != null) {
p.setJouyou(item.getJouyou().getJouyouId());
}
});
if (_exampleWordsCount > 0) {
p.setExampleWords(kanjiDB.getExampleWords(p.getKanji(), _exampleWordsCount));
}
if (p.getImageSha() != null) {
String diagram = "<img src=\"" + JCText.toHex(p.getKanji()).toUpperCase() + ".png" + "\" />";
p.setStrokeImageHtml(diagram);
}
p.setJpWordAudioHtml("[sound:" + jpFilename(p) + "]");
p.setKeywordEnAudioFileName("[sound:" + enFilename(p) + "]");
if (p.getExampleWords() != null) {
words.setLength(0);
for (String[] q : p.getExampleWords()) {
if (words.length() > 0) words.append("<br/>");
words.append(q[1]).append("【").append(q[0]).append("】").append(q[2]);
}
p.setExampleWordsHtml(words.length() > 0 ? words.toString() : null);
}
}
return result;
}
private List<Map<String, ?>> findAllVHeisig4() {
return reportDB.findAllVHeisig4();
}
private List<Map<String, ?>> findAllVKanji() {
return reportDB.findAllVKanji();
}
private List<Map<String, ?>> findTofuTranslated() {
return reportDB.getTofuTranslatedByUser(SecurityUtils.getUserUuid());
}
private List<?> getData(ECfReportType reportType) throws UnsupportedEncodingException {
List data = null;
switch (reportType) {
case HEISIG6_CUSTOM: {
data = findAllVHeisig6Custom();
break;
}
case HEISIG4: {
data = findAllVHeisig4();
break;
}
case KANJI: {
data = findAllVKanji();
break;
}
case TOFU_TRANSLATIONS: {
data = findTofuTranslated();
break;
}
}
if (data == null) throw new IllegalStateException("getData: data == null");
return data;
}
private byte[] compileToBytes(ECfReportType reportType, JSGeneratorType format, Collection data) throws IOException, JRException, IllegalArgumentException, IllegalStateException, SQLException {
if (reportType == null || format == null)
throw new IllegalArgumentException("reportType == null || format == null");
log.info("getFileAsBytes: reportType=" + reportType + ", format=" + format);
InputStream istream = null;
JRDataSource dataSource = null;
Map<String, Object> staticParams = new HashMap<>();
switch (reportType) {
case HEISIG6_CUSTOM: {
dataSource = new JRBeanCollectionDataSource(data);
istream = assets.getVHeisig6Custom().getInputStream();
break;
}
case HEISIG4: {
dataSource = new JRBeanCollectionDataSource(data);
staticParams.put("dtnow", JCDateTime.now());
staticParams.put("elementCount", data.size());
istream = assets.getVHeisig4().getInputStream();
break;
}
case KANJI: {
dataSource = new JRBeanCollectionDataSource(data);
staticParams.put("dtnow", JCDateTime.now());
staticParams.put("elementCount", data.size());
istream = assets.getVKanji().getInputStream();
break;
}
case TOFU_TRANSLATIONS: {
dataSource = new JRBeanCollectionDataSource(data);
istream = assets.getTofuSentenceTranslations().getInputStream();
break;
}
}
if (istream == null) throw new IllegalStateException("istream == null || dataSource == null");
//paneb ka istreami ise kinni
byte[] result;
if (format == JSGeneratorType.CSV) {
result = JSGeneratorType.export(istream, dataSource, staticParams, _csvGenerator.getExporter());
} else {
result = format.export(istream, dataSource, staticParams);
}
log.info("getFileAsBytes: result.length=" + result.length);
return result;
}
public Map.Entry<String, byte[]> getReport(String entityName, String formatName) throws IOException, JRException, SQLException {
ECfReportType reportType = ECfReportType.valueOf(entityName.toUpperCase());
JSGeneratorType format = JSGeneratorType.findByExtension(formatName);
return getReport(reportType, format);
}
public Map.Entry<String, byte[]> getReport(ECfReportType reportType, JSGeneratorType format) throws IOException, JRException, SQLException {
List data = getData(reportType);
return getReport(reportType, format, data);
}
private static String toFileName(ECfReportType reportType, JSGeneratorType format) {
String stamp = JCDateTime.nowIncludingSec();
return reportType.name().toLowerCase() + " " + stamp + "." + format.extension();
}
private Map.Entry<String, byte[]> getReport(ECfReportType reportType, JSGeneratorType format, Collection data) throws IOException, JRException, SQLException {
StringBuilder msg = new StringBuilder("getReport: reportType=" + reportType + ", format=" + format);
byte[] fileAsBytes = compileToBytes(reportType, format, data);
if (fileAsBytes == null) throw new IllegalStateException(msg.append(", fileAsBytes == null").toString());
String fileName = toFileName(reportType, format);
if (fileName == null) throw new IllegalStateException(msg.append(", fileName == null").toString());
return new AbstractMap.SimpleEntry<>(fileName, fileAsBytes);
}
@Inject
protected EGDAssets assets;
//------------------------------ cache management ------------------------------
private static String jpFilename(VHeisig6Custom item) {
String ext = JCString.getExtension(item.getJpWordAudioFileName());
if (ext == null || ext.length() < 1) ext = "mp3";
return "RTK1_keyword_jp_" + item.getId() + "." + ext;
}
private static String enFilename(VHeisig6Custom item) {
return "RTK1_keyword_en_" + item.getId() + ".mp3";
}
public byte[] getHeisig6CustomAsArchive(int from, int to) throws IOException, JRException, SQLException {
List<VHeisig6Custom> data = findVHeisig6Custom(from, to);
Assert.notNull(data.get(0).getExampleWordsHtml());
Map.Entry<String, byte[]> report = getReport(ECfReportType.HEISIG6_CUSTOM, JSGeneratorType.CSV, data);
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(ostream);
String name = "RTK1_" + from + "-" + to + ".csv";
Map.Entry<String, byte[]> report2 = new AbstractMap.SimpleEntry<>(name, report.getValue());
JCIOUtils.addToZipFile(report2, zos);
for (VHeisig6Custom p : data) {
if (p.getJpWordAudioFileName() != null && p.getJpWordAudio() != null && p.getJpWordAudio().length > 0) {
JCIOUtils.addToZipFile("keyword_jp/" + jpFilename(p), p.getJpWordAudio(), zos);
}
//if (p.getStrokeImage() != null && p.getStrokeImage().length > 0) {
// JCIOUtils.addToZipFile("stroke_image/" + p.getKanji() + ".svg", p.getStrokeImage(), zos);
//}
}
zos.close();
ostream.close();
return ostream.toByteArray();
}
}