From b1f4a741521b4c0018fb4fbc9351df0e939ea660 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Fri, 2 Jul 2021 10:54:37 +0300 Subject: [PATCH] Add REST API for Caruna/Helen parser --- .../parsers/composites/CarunaHelenParser.java | 8 +- .../devsoap/parsers/composites/upload.html | 12 +++ rest-api/build.gradle | 11 +++ .../java/com/devsoap/parsers/api/Api.java | 84 +++++++++++++++++++ settings.gradle | 1 + 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 composite-parsers/src/main/resources/com/devsoap/parsers/composites/upload.html create mode 100644 rest-api/build.gradle create mode 100644 rest-api/src/main/java/com/devsoap/parsers/api/Api.java diff --git a/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java b/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java index 718550a..fb35c7a 100644 --- a/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java +++ b/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java @@ -1,5 +1,6 @@ package com.devsoap.parsers.composites; +import java.io.PrintStream; import java.nio.file.Path; import java.util.HashSet; import java.util.Map; @@ -10,7 +11,10 @@ public class CarunaHelenParser { public static void main(String[] args) { var carunaFile = Path.of(args[0]); var helenFile = Path.of(args[1]); + run(carunaFile, helenFile, System.out); + } + public static void run(Path carunaFile, Path helenFile, PrintStream result) { var carunaPeriods = com.devsoap.parsers.caruna.Parser.parse(carunaFile); var nightSiirto = carunaPeriods.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().transferNightKwh)); @@ -18,7 +22,7 @@ public class CarunaHelenParser { .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().transferDayKwh)); var helenPeriods = com.devsoap.parsers.helen.Parser.parse(helenFile, daySiirto, nightSiirto); - System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + + result.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + ",Yösiirto (EUR),Vero"); @@ -33,7 +37,7 @@ public class CarunaHelenParser { hp.nightEnergyEur, cp.transferDayKwh, cp.transferDayTotal, cp.transferNightKwh, cp.transferNightTotal, cp.tax); csv = csv.replace(",0,",",,").replace(",0.00",","); - System.out.println(csv); + result.println(csv); }); } } \ No newline at end of file diff --git a/composite-parsers/src/main/resources/com/devsoap/parsers/composites/upload.html b/composite-parsers/src/main/resources/com/devsoap/parsers/composites/upload.html new file mode 100644 index 0000000..4b3225f --- /dev/null +++ b/composite-parsers/src/main/resources/com/devsoap/parsers/composites/upload.html @@ -0,0 +1,12 @@ + + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/rest-api/build.gradle b/rest-api/build.gradle new file mode 100644 index 0000000..ff408f4 --- /dev/null +++ b/rest-api/build.gradle @@ -0,0 +1,11 @@ +dependencies { + implementation 'io.javalin:javalin:3.13.8' + implementation "org.thymeleaf:thymeleaf:3.0.11.RELEASE" + + implementation project(':composite-parsers') + + implementation 'org.apache.logging.log4j:log4j-core:2.11.0' + implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.11.0' +} + +application.mainClass='com.devsoap.parsers.api.Api' diff --git a/rest-api/src/main/java/com/devsoap/parsers/api/Api.java b/rest-api/src/main/java/com/devsoap/parsers/api/Api.java new file mode 100644 index 0000000..437ec7c --- /dev/null +++ b/rest-api/src/main/java/com/devsoap/parsers/api/Api.java @@ -0,0 +1,84 @@ +package com.devsoap.parsers.api; + +import com.devsoap.parsers.composites.CarunaHelenParser; +import io.javalin.Javalin; +import io.javalin.http.Context; +import io.javalin.http.UploadedFile; +import org.apache.log4j.Logger; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.function.Consumer; + +import static io.javalin.apibuilder.ApiBuilder.*; + +public class Api { + + static { + var logBuilder = ConfigurationBuilderFactory.newConfigurationBuilder(); + logBuilder.add(logBuilder.newAppender("stdout", "Console")); + + var rootLogger = logBuilder.newRootLogger(Level.INFO); + rootLogger.add(logBuilder.newAppenderRef("stdout")); + logBuilder.add(rootLogger); + + Configurator.initialize(logBuilder.build()); + } + + private static final Logger LOGGER = Logger.getLogger(Api.class); + + public static void main(String[] args) { + var app = Javalin.create().start(7000); + app.routes(() -> { + get(ctx -> { ctx.result("PDF Parsers REST API"); }); + path("parsers", () -> { + path(CarunaHelenParser.class.getSimpleName(), () -> { + get(ctx -> ctx.render(renderParserStaticPage(CarunaHelenParser.class, "upload.html"))); + post(ctx -> { + withUploadedFile(ctx.uploadedFiles().get(1), carunaFile -> { + withUploadedFile(ctx.uploadedFiles().get(0), helenFile -> { + var resultStream = new ByteArrayOutputStream(); + try (var result = new PrintStream(resultStream)) { + CarunaHelenParser.run(carunaFile, helenFile, result); + } + renderReport(ctx, new ByteArrayInputStream(resultStream.toByteArray()), + "caruna-helen-report.csv"); + }); + }); + }); + }); + }); + }); + } + + private static void withUploadedFile(UploadedFile fileUpload, Consumer processor) { + try { + var file = Files.createTempFile(fileUpload.getFilename(), fileUpload.getExtension()); + Files.copy(fileUpload.getContent(), file, StandardCopyOption.REPLACE_EXISTING); + try { + processor.accept(file); + } finally { + file.toFile().delete(); + } + } catch (IOException e) { + LOGGER.error("Failed to process file " + fileUpload.getFilename(), e); + return; + } + } + + private static void renderReport(Context context, InputStream result, String filename) { + context.result(result) + .header("Content-Type", "text/csv; charset=utf-8") + .header("Content-Disposition","inline; filename=\""+filename+"\""); + } + + private static String renderParserStaticPage(Class clazz, String page) { + var folder = clazz.getPackageName().replace(".", "/"); + return folder + "/" + page; + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 50c7f17..47f46e4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,4 +18,5 @@ include 'caruna-invoice' include 'helen-invoice' include 'composite-parsers' include 'plugsurfing-invoice' +include 'rest-api'