openaire-usage-stats-api-r5/src/main/java/eu/dnetlib/usagestats/services/SushiLiteServiceImpl.java

358 lines
20 KiB
Java
Raw Normal View History

2020-12-30 14:56:37 +01:00
package eu.dnetlib.usagestats.services;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import eu.dnetlib.usagestats.repositories.UsageStatsRepository;
import eu.dnetlib.usagestats.sushilite.domain.ReportItem;
import eu.dnetlib.usagestats.sushilite.domain.ReportException;
import eu.dnetlib.usagestats.sushilite.domain.ReportResponse;
import eu.dnetlib.usagestats.sushilite.domain.ReportResponseWrapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
@Service
public class SushiLiteServiceImpl implements SushiLiteService {
private final UsageStatsRepository usageStatsRepository;
private final Logger log = Logger.getLogger(this.getClass());
@Value("${usagestats.redis.hostname}")
private String hostname;
@Value("${usagestats.redis.port}")
private int port;
@Value("${compression.max_number_of_records}")
private int compression_max_number_of_records;
@Value("${download.folder}")
private String download_folder;
@Value("${sushi-lite.server}")
private String sushi_lite_server;
String finalcompressedString = "";
boolean reportForCompression = false;
private int noOfItems = 0;
String userAgent;
public SushiLiteServiceImpl(UsageStatsRepository usageStatsRepository) {
this.usageStatsRepository = usageStatsRepository;
}
@Override
public ReportResponseWrapper buildReport(String reportName, String release, String requestorId, String beginDate,
String endDate, String repositoryIdentifier, String itemIdentifier,
String itemDataType, String hasDoi, String granularity, String callback) {
List<ReportItem> reportItems = new ArrayList<>();
List<ReportException> reportExceptions = new ArrayList<>();
if (!granularity.equalsIgnoreCase("totals") && !granularity.equalsIgnoreCase("monthly")) {
reportExceptions.add(new ReportException("3062", "Warning", "Invalid ReportAttribute Value", "Granularity: \'" + granularity + "\' unknown. Defaulting to Monthly"));
granularity = "Monthly";
}
Date beginDateParsed;
if (!beginDate.equals("")) {
beginDateParsed = tryParse(beginDate);
if (beginDateParsed != null && (granularity.toLowerCase().equals("monthly") || beginDate.length() == 7)) {
Calendar temp = Calendar.getInstance();
temp.setTime(beginDateParsed);
temp.set(Calendar.DAY_OF_MONTH, temp.getActualMinimum(Calendar.DAY_OF_MONTH));
beginDateParsed = temp.getTime();
}
} else {
Calendar temp = Calendar.getInstance();
temp.add(Calendar.MONTH, -1);
temp.set(Calendar.DAY_OF_MONTH, temp.getActualMinimum(Calendar.DAY_OF_MONTH));
beginDateParsed = temp.getTime();
reportExceptions.add(new ReportException("3021", "Warning", "Unspecified Date Arguments", "Begin Date set to default: " + new SimpleDateFormat("yyyy-MM-dd").format(beginDateParsed)));
}
Date endDateParsed;
if (!endDate.equals("")) {
endDateParsed = tryParse(endDate);
if (endDateParsed != null && (granularity.toLowerCase().equals("monthly") || endDate.length() == 7)) {
Calendar temp = Calendar.getInstance();
temp.setTime(endDateParsed);
temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
endDateParsed = temp.getTime();
}
} else {
Calendar temp = Calendar.getInstance();
temp.add(Calendar.MONTH, -1);
temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
endDateParsed = temp.getTime();
reportExceptions.add(new ReportException("3021", "Warning", "Unspecified Date Arguments", "End Date set to default: " + new SimpleDateFormat("yyyy-MM-dd").format(endDateParsed)));
}
//log.error("dates: " + beginDateParsed.toString() + " - " + endDateParsed.toString());
if (beginDateParsed == null) {
reportExceptions.add(new ReportException("3020", "Error", "Invalid Date Arguments", "Begin Date: " + beginDate + " is not a valid date"));
}
if (endDateParsed == null) {
reportExceptions.add(new ReportException("3020", "Error", "Invalid Date Arguments", "End Date: " + endDate + " is not a valid date"));
}
if (beginDateParsed != null && endDateParsed != null && !beginDateParsed.before(endDateParsed)) {
reportExceptions.add(new ReportException("3020", "Error", "Invalid Date Arguments", "BeginDate \'" + new SimpleDateFormat("yyyy-MM-dd").format(beginDateParsed) + "\' is greater than EndDate \'" + new SimpleDateFormat("yyyy-MM-dd").format(endDateParsed) + "\'"));
}
String repoid = "";
if (!repositoryIdentifier.equals("")) {
repoid = usageStatsRepository.executeRepoId(repositoryIdentifier, reportName.toLowerCase());
if (repoid.equals("-1")) {
reportExceptions.add(new ReportException("3060", "Error", "Invalid Filter Value", "RepositoryIdentifier: " + repositoryIdentifier + " is not valid"));
}
}
String itemid = "";
if (!itemIdentifier.equals("")) {
String[] split = itemIdentifier.split(":");
switch (split[0].toLowerCase()) {
case "oid":
itemid = itemIdentifier;
break;
case "doi":
itemid = itemIdentifier;
break;
case "openaire":
itemid = itemIdentifier;
break;
default:
reportExceptions.add(new ReportException("3060", "Error", "Invalid Filter Value", "ItemIdentifier: " + itemIdentifier + " is not valid"));
itemid = "-1";
}
}
if (itemid.equals("") && repoid.equals("") && !reportName.equalsIgnoreCase("rr1") && !reportName.equalsIgnoreCase("jr1")) {
reportExceptions.add(new ReportException("3070", "Error", "Required Filter Missing", "ItemIdentifier or RepositoryIdentifier must be supplied"));
}
if (reportName.equalsIgnoreCase("ar1")) {
if (!itemid.equals("-1") && !repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
if (!itemid.equals("")) {
if (itemDataType.equalsIgnoreCase("") || itemDataType.equalsIgnoreCase("article")) {
usageStatsRepository.executeItem(reportItems, itemIdentifier, repoid, "Article", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else if (!repoid.equals("")) {
usageStatsRepository.executeBatchItems(reportItems, repoid, "Article", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
}
}
} else if (reportName.equalsIgnoreCase("br1")) {
if (!itemid.equals("-1") && !repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
if (!itemid.equals("")) {
if (itemDataType.equalsIgnoreCase("") || itemDataType.equalsIgnoreCase("book")) {
usageStatsRepository.executeItem(reportItems, itemIdentifier, repoid, "Book", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else if (!repoid.equals("")) {
usageStatsRepository.executeBatchItems(reportItems, repoid, "Book", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
}
}
} else if (reportName.equalsIgnoreCase("br2")) {
if (!itemid.equals("-1") && !repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
if (!itemid.equals("")) {
if (itemDataType.equalsIgnoreCase("") || itemDataType.equalsIgnoreCase("part of book or chapter of book")) {
usageStatsRepository.executeItem(reportItems, itemIdentifier, repoid, "Part of book or chapter of book", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else if (!repoid.equals("")) {
usageStatsRepository.executeBatchItems(reportItems, repoid, "Part of book or chapter of book", beginDateParsed, endDateParsed, granularity);
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
}
}
} else if (reportName.equalsIgnoreCase("ir1")) {
if (!itemid.equals("-1") && !repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
if (!itemid.equals("")) {
usageStatsRepository.executeItem(reportItems, itemIdentifier, repoid, itemDataType, beginDateParsed, endDateParsed, granularity);
} else if (!repoid.equals("")) {
usageStatsRepository.executeBatchItems(reportItems, repoid, itemDataType, beginDateParsed, endDateParsed, granularity);
}
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
}
} else if (reportName.equalsIgnoreCase("rr1")) {
if (!repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
usageStatsRepository.executeRepo(reportItems, repoid, itemDataType, beginDateParsed, endDateParsed, granularity);
}
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else if (reportName.equalsIgnoreCase("jr1")) {
if (!repoid.equals("-1") && beginDateParsed != null && endDateParsed != null && beginDateParsed.before(endDateParsed)) {
usageStatsRepository.executeJournal(reportItems, repoid, itemDataType, beginDateParsed, endDateParsed, granularity);
}
if (reportItems.isEmpty()) {
reportExceptions.add(new ReportException("3030", "Error", "No Usage Available for Requested Dates", "Service did not find any data"));
}
} else if (reportName.equals("")) {
reportExceptions.add(new ReportException("3050", "Error", "Report argument is missing", "You must supply a Report argument"));
} else {
reportExceptions.add(new ReportException("3000", "Error", "Report " + reportName + " not supported", "Supported reports: AR1, IR1, RR1, BR1, BR2"));
}
ReportResponse reportResponse = new ReportResponse(reportName, release, requestorId, beginDate, endDate,
repositoryIdentifier, itemIdentifier, itemDataType, hasDoi, granularity, callback, reportItems, reportExceptions);
if (reportItems.size() > compression_max_number_of_records) {
log.info("Compression due to "+reportItems.size());
reportForCompression = true;
}
noOfItems = reportItems.size();
return new ReportResponseWrapper(reportResponse);
}
@Override
public String displayReport(String reportName, String release, String requestorId, String beginDate, String endDate, String repositoryIdentifier, String itemIdentifier, String itemDataType, String hasDoi, String granularity, String callback, String pretty, String userAgent) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
java.sql.Timestamp timestamp = new java.sql.Timestamp(System.currentTimeMillis());
//System.out.println("Display report start " + timestamp);
log.info("Starting process...." + timestamp);
this.userAgent = userAgent;
try {
ReportResponseWrapper reportResponseWrapper = buildReport(reportName, release, requestorId, beginDate, endDate, repositoryIdentifier, itemIdentifier, itemDataType, hasDoi, granularity, callback);
if (pretty.equalsIgnoreCase("pretty")) {
if (reportForCompression == false) {
if (userAgent.contains("Mozilla")) {
return "<pre>" + objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(reportResponseWrapper) + "</pre>";
} else {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(reportResponseWrapper);
}
} else {
if (userAgent.contains("Mozilla")) {
byte[] sourceReport = objectMapper.writeValueAsBytes(reportResponseWrapper);
ObjectWriter writer = objectMapper.writer();
java.sql.Timestamp timestamp1 = new java.sql.Timestamp(System.currentTimeMillis());
//System.out.println("String start " + timestamp1);
log.info("Start building report..." + timestamp1);
String outputname = reportName + "_" + repositoryIdentifier.replace("_", "").replace(":", "") + beginDate.replace("-", "") + "_" + endDate.replace("-", "");
String directory = new File(download_folder).getAbsolutePath();
writer.writeValue(new File(directory + "/" + outputname + ".json"), new String(sourceReport));
FileOutputStream fos = new FileOutputStream(directory + "/" + outputname + ".zip");
ZipOutputStream zipOut = new ZipOutputStream(fos);
File fileToZip = new File(directory + "/" + outputname + ".json");
FileInputStream fis = new FileInputStream(fileToZip);
ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
zipOut.close();
fis.close();
fos.close();
fileToZip.delete();
java.sql.Timestamp timestamp2 = new java.sql.Timestamp(System.currentTimeMillis());
//System.out.println("String end " + timestamp2);
log.info("Report created..." + timestamp2);
return new String(sushi_lite_server + "/download/" + outputname + ".zip");
//return "report is available. Download it from localhost:8080/download/"+outputname+".zip";
} else {
byte[] sourceReport = objectMapper.writeValueAsBytes(reportResponseWrapper);
return new String(sourceReport);
}
}
}
if (reportForCompression == false) {
byte[] sourceReport = objectMapper.writeValueAsBytes(reportResponseWrapper);
return new String(sourceReport);
} else if (userAgent.contains("Mozilla")) {
java.sql.Timestamp timestamp3 = new java.sql.Timestamp(System.currentTimeMillis());
//System.out.println("String start " + timestamp3);
log.info("Start building report..." + timestamp3);
byte[] sourceReport = objectMapper.writeValueAsBytes(reportResponseWrapper);
ObjectWriter writer = objectMapper.writer();
String outputname = reportName + "_" + repositoryIdentifier.replace("_", "").replace(":", "") + beginDate.replace("-", "") + "_" + endDate.replace("-", "");
String directory = new File(download_folder).getAbsolutePath();
writer.writeValue(new File(directory + "/" + outputname + ".json"), new String(sourceReport).replaceAll("\\\"", ""));
FileOutputStream fos = new FileOutputStream(directory + "/" + outputname + ".zip");
ZipOutputStream zipOut = new ZipOutputStream(fos);
File fileToZip = new File(directory + "/" + outputname + ".json");
FileInputStream fis = new FileInputStream(fileToZip);
ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
zipOut.close();
fis.close();
fos.close();
fileToZip.delete();
java.sql.Timestamp timestamp4 = new java.sql.Timestamp(System.currentTimeMillis());
//System.out.println("String end " + timestamp4);
log.info("Report created..." + timestamp4);
return new String(sushi_lite_server + "/download/" + outputname + ".zip");
} else {
byte[] sourceReport = objectMapper.writeValueAsBytes(reportResponseWrapper);
return new String(sourceReport);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private Date tryParse(String dateString) {
try {
if (dateString.length() == 7) {
return new SimpleDateFormat("yyyy-MM").parse(dateString);
} else if (dateString.length() == 10) {
return new SimpleDateFormat("yyyy-MM-dd").parse(dateString);
}
} catch (Exception e) {
log.error("ParseError: ", e);
}
return null;
}
}