implement backend endpoints and file creating logic for processing multiple XMLs with XSLT
This commit is contained in:
		| @@ -42,6 +42,7 @@ public class SparkApplication { | ||||
|         registry.registerController(new ProcessorInfoController(logger, saxon, xalan)); | ||||
|  | ||||
|         registry.registerController(new XmlController(gson, logger, saxon, xalan)); | ||||
|         registry.registerController(new MultipleXMLController(gson,logger, (Saxon) saxon)); | ||||
|         registry.registerController(new JsonController(gson, jsongson, logger)); | ||||
|  | ||||
|         registry.register(); | ||||
|   | ||||
| @@ -0,0 +1,101 @@ | ||||
| package com.r11.tools.controller; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import com.r11.tools.controller.internal.*; | ||||
| import com.r11.tools.model.XMLMultipleFilesBody; | ||||
| import com.r11.tools.model.XMLResponseBody; | ||||
| import com.r11.tools.xml.Saxon; | ||||
| import com.r11.tools.xml.XmlEngine; | ||||
| import net.sf.saxon.s9api.SaxonApiException; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import spark.Request; | ||||
| import spark.Response; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| @GlobalControllerManifest | ||||
| public class MultipleXMLController implements RestController { | ||||
|  | ||||
|     private final Gson gson; | ||||
|     private final Logger logger; | ||||
|  | ||||
|     private final Saxon saxon; | ||||
|  | ||||
|     public MultipleXMLController(Gson gson, Logger logger, Saxon saxon) { | ||||
|         this.gson = gson; | ||||
|         this.logger = logger; | ||||
|         this.saxon = saxon; | ||||
|     } | ||||
|  | ||||
|     @ScopedControllerManifest(method = HandlerType.POST, path = "/multiple/xslt") | ||||
|     public void acceptRequestXslt(Request request, Response response) { | ||||
|         acceptRequest(request, response, XmlJobType.XSLT); | ||||
|     } | ||||
|  | ||||
|     private void acceptRequest(Request request, Response response, XmlJobType xmlJobType) { | ||||
|         XMLMultipleFilesBody requestBody; | ||||
|         try { | ||||
|             requestBody = this.gson.fromJson(request.body(), XMLMultipleFilesBody.class); | ||||
|         } catch (Exception e) { | ||||
|             requestErrorResponse(response, e); | ||||
|             return; | ||||
|         } | ||||
|         processRequest(new MultipleXmlJob(response, requestBody, saxon, xmlJobType)); | ||||
|     } | ||||
|  | ||||
|     private void processRequest(MultipleXmlJob xmlJob) { | ||||
|         logger.info(xmlJob); | ||||
|         XMLResponseBody responseBody = null; | ||||
|         long timeStart = System.currentTimeMillis(); | ||||
|         long duration; | ||||
|  | ||||
|         try { | ||||
|             responseBody = processData(xmlJob); | ||||
|  | ||||
|             duration = System.currentTimeMillis() - timeStart; | ||||
|             responseBody.setDuration(duration); | ||||
|  | ||||
|             xmlJob.getResponse().status(200); | ||||
|  | ||||
|             this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " + | ||||
|                     xmlJob.getEngine().getVersion() + | ||||
|                     ") processed in " + duration + " ms."); | ||||
|  | ||||
|         } catch (Exception ex) { | ||||
|             responseBody = processingErrorResponse(ex, xmlJob); | ||||
|  | ||||
|         } finally { | ||||
|             xmlJob.getResponse().body(this.gson.toJson(responseBody)); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private XMLResponseBody processData(MultipleXmlJob xmlJob) throws IOException, SaxonApiException, InterruptedException { | ||||
|         Saxon engine = xmlJob.getEngine(); | ||||
|         XMLMultipleFilesBody requestBody = xmlJob.getRequestBody(); | ||||
|         String result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData()); | ||||
|         return new XMLResponseBody(result, "OK", requestBody.getVersion()); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private XMLResponseBody processingErrorResponse(Exception ex, MultipleXmlJob xmlJob) { | ||||
|         XmlEngine engine = xmlJob.getEngine(); | ||||
|         XmlJobType xmlJobType = xmlJob.getXmlJobType(); | ||||
|         Response response = xmlJob.getResponse(); | ||||
|  | ||||
|         XMLResponseBody responseBody = | ||||
|                 new XMLResponseBody(ex.getMessage(), "ERR", engine.getVersion(), -1); | ||||
|  | ||||
|         response.status(400); | ||||
|         this.logger.error("Error on processing " + xmlJobType + " using " + engine.getVersion() + ". " + ex); | ||||
|  | ||||
|         return responseBody; | ||||
|     } | ||||
|  | ||||
|     private void requestErrorResponse(Response response, Exception ex) { | ||||
|         XMLResponseBody responseBody = new XMLResponseBody(ex.getMessage(), "ERR", "N/A", -1); | ||||
|         response.status(400); | ||||
|         response.body(this.gson.toJson(responseBody)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -2,6 +2,7 @@ package com.r11.tools.controller; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import com.r11.tools.controller.internal.*; | ||||
| import com.r11.tools.model.XMLMultipleFilesBody; | ||||
| import com.r11.tools.model.XMLRequestBody; | ||||
| import com.r11.tools.model.XMLResponseBody; | ||||
| import com.r11.tools.model.XPathQueryResult; | ||||
|   | ||||
| @@ -0,0 +1,38 @@ | ||||
| package com.r11.tools.controller.internal; | ||||
|  | ||||
| import com.r11.tools.model.XMLMultipleFilesBody; | ||||
| import com.r11.tools.model.XMLRequestBody; | ||||
| import com.r11.tools.xml.Saxon; | ||||
| import com.r11.tools.xml.XmlEngine; | ||||
| import spark.Response; | ||||
|  | ||||
| public class MultipleXmlJob { | ||||
|  | ||||
|     private final Response response; | ||||
|     private final XMLMultipleFilesBody requestBody; | ||||
|     private final Saxon engine; | ||||
|     private final XmlJobType xmlJobType; | ||||
|  | ||||
|     public MultipleXmlJob(Response response, XMLMultipleFilesBody requestBody, Saxon engine, XmlJobType xmlJobType) { | ||||
|         this.response = response; | ||||
|         this.requestBody = requestBody; | ||||
|         this.engine = engine; | ||||
|         this.xmlJobType = xmlJobType; | ||||
|     } | ||||
|  | ||||
|     public Response getResponse() { | ||||
|         return response; | ||||
|     } | ||||
|  | ||||
|     public XMLMultipleFilesBody getRequestBody() { | ||||
|         return requestBody; | ||||
|     } | ||||
|  | ||||
|     public Saxon getEngine() { | ||||
|         return engine; | ||||
|     } | ||||
|  | ||||
|     public XmlJobType getXmlJobType() { | ||||
|         return xmlJobType; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| package com.r11.tools.model; | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName; | ||||
|  | ||||
| public class XMLMultipleFilesBody { | ||||
|  | ||||
|     @SerializedName("data") | ||||
|     private XMLMultipleFilesData[] data; | ||||
|     @SerializedName("processorData") | ||||
|     private String processorData; | ||||
|     @SerializedName("processor") | ||||
|     private String processor; | ||||
|     @SerializedName("version") | ||||
|     private String version; | ||||
|  | ||||
|  | ||||
|     public String getProcessorData() { | ||||
|         return processorData; | ||||
|     } | ||||
|  | ||||
|     public String getProcessor() { | ||||
|         return processor; | ||||
|     } | ||||
|  | ||||
|     public String getVersion() { | ||||
|         return version; | ||||
|     } | ||||
|  | ||||
|     public XMLMultipleFilesData[] getData() { | ||||
|         return data; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.r11.tools.model; | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName; | ||||
|  | ||||
| public class XMLMultipleFilesData { | ||||
|     @SerializedName("fileName") | ||||
|     private String filename; | ||||
|     @SerializedName("fileData") | ||||
|     private String data; | ||||
|  | ||||
|     public String getFilename() { | ||||
|         return filename; | ||||
|     } | ||||
|  | ||||
|     public String getData() { | ||||
|         return data; | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +1,18 @@ | ||||
| package com.r11.tools.xml; | ||||
|  | ||||
| import com.r11.tools.model.XMLMultipleFilesData; | ||||
| import com.r11.tools.model.XPathQueryResult; | ||||
| import net.sf.saxon.Configuration; | ||||
| import net.sf.saxon.lib.CatalogResourceResolver; | ||||
| import net.sf.saxon.s9api.*; | ||||
|  | ||||
| import javax.xml.transform.stream.StreamSource; | ||||
| import java.io.StringReader; | ||||
| import java.io.StringWriter; | ||||
| import java.io.*; | ||||
| import java.nio.file.*; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Comparator; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
|  | ||||
| /** | ||||
|  * Handler for Saxon engine | ||||
| @@ -13,6 +20,54 @@ import java.io.StringWriter; | ||||
|  */ | ||||
| public class Saxon implements XmlEngine{ | ||||
|  | ||||
|     /** | ||||
|      *  Transforms many XML documents via XSLT. | ||||
|      * @param data XML Files to be transformed. | ||||
|      * @param transform XSLT | ||||
|      * @return transformed xml | ||||
|      * @throws SaxonApiException thrown on stylesheet or transformation error | ||||
|      */ | ||||
|     public String processXSLT(XMLMultipleFilesData[] data, String transform) throws SaxonApiException, IOException, InterruptedException { | ||||
|         Processor processor = new Processor(false); | ||||
|  | ||||
|         XsltCompiler compiler = processor.newXsltCompiler(); | ||||
|         XsltExecutable stylesheet = compiler.compile(new StreamSource( new StringReader(transform) )); | ||||
|         String filesPath = "/tmp/"+UUID.randomUUID()+"/"; | ||||
|         ArrayList<String> xmlFilesUri = new ArrayList<>(); | ||||
|         try{ | ||||
|             Path processPath = Paths.get(filesPath); | ||||
|             Files.createDirectories(processPath); | ||||
|  | ||||
|             for (XMLMultipleFilesData fileData : data) { | ||||
|                 Path filePath = Files.createFile( Paths.get(filesPath + fileData.getFilename() ) ); | ||||
|                 try (FileWriter writer = new FileWriter(filePath.toFile())) { | ||||
|                     writer.write(fileData.getData()); | ||||
|                     xmlFilesUri.add(filesPath + fileData.getFilename()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|             StringWriter sw = new StringWriter(); | ||||
|             Serializer out = processor.newSerializer(sw); | ||||
|             out.setOutputProperty(Serializer.Property.METHOD, "xml"); | ||||
|             out.setOutputProperty(Serializer.Property.INDENT, "yes"); | ||||
|             Xslt30Transformer transformer = stylesheet.load30(); | ||||
|             transformer.setResourceResolver(  ); | ||||
|             processor.setCatalogFiles(xmlFilesUri.toArray(new String[0])); | ||||
|             transformer.transform( new StreamSource( new File(filesPath+data[0].getFilename()) ) , out ); | ||||
|             return sw.toString(); | ||||
|  | ||||
|         } finally { | ||||
|             Thread.sleep(1000000); | ||||
|             Files | ||||
|                     .walk( Paths.get(filesPath) ) | ||||
|                     .sorted(Comparator.reverseOrder()) | ||||
|                     .map(Path::toFile) | ||||
|                     .forEach(File::delete); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Transforms string containing xml document via xslt | ||||
|      * @param data xml to be transformed | ||||
|   | ||||
| @@ -1,6 +1,10 @@ | ||||
| package com.r11.tools.xml; | ||||
|  | ||||
| import com.r11.tools.model.XMLMultipleFilesData; | ||||
| import com.r11.tools.model.XPathQueryResult; | ||||
| import net.sf.saxon.s9api.SaxonApiException; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| public interface XmlEngine { | ||||
|     XPathQueryResult processXPath(String data, String query, String version) throws Exception; | ||||
|   | ||||
| @@ -104,6 +104,7 @@ function prepareRequestBody():string { | ||||
|         "processor": engine.value, | ||||
|         "version": version.value | ||||
|     }); | ||||
|     console.log(requestBody) | ||||
|     return requestBody; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user