Refactored tools services endpoints system and fixed json formatter. (#91)
Co-authored-by: Artur Kołecki <koleckiartur@icloud.com> Co-authored-by: Adam Bem <adam.bem@zoho.eu> Reviewed-on: R11/release11-tools-web#91
This commit is contained in:
		| @@ -96,23 +96,23 @@ def process_xml(request: request, type: str) -> str: | |||||||
|         return json.dumps(response_json), code |         return json.dumps(response_json), code | ||||||
|  |  | ||||||
|  |  | ||||||
| @app.route("/xpathpost", methods=["POST"]) | @app.route("/xpath", methods=["POST"]) | ||||||
| def xpath(): | def xpath(): | ||||||
|     return process_xml(request, "xpath") |     return process_xml(request, "xpath") | ||||||
|  |  | ||||||
| @app.route("/xsdpost", methods=["POST"]) | @app.route("/xsd", methods=["POST"]) | ||||||
| def xsd(): | def xsd(): | ||||||
|     return process_xml(request, "xsd") |     return process_xml(request, "xsd") | ||||||
|  |  | ||||||
| @app.route("/xsltpost", methods=["POST"]) | @app.route("/xslt", methods=["POST"]) | ||||||
| def xslt(): | def xslt(): | ||||||
|     return process_xml(request, "xslt") |     return process_xml(request, "xslt") | ||||||
|  |  | ||||||
| @app.route("/prettifypost", methods=["POST"]) | @app.route("/prettify", methods=["POST"]) | ||||||
| def prettify(): | def prettify(): | ||||||
|     return process_xml(request, "prettify") |     return process_xml(request, "prettify") | ||||||
|  |  | ||||||
| @app.route("/minimizepost", methods=["POST"]) | @app.route("/minimize", methods=["POST"]) | ||||||
| def minimize(): | def minimize(): | ||||||
|     return process_xml(request, "minimize") |     return process_xml(request, "minimize") | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|   <packaging>pom</packaging> |   <packaging>pom</packaging> | ||||||
|  |  | ||||||
|   <modules> |   <modules> | ||||||
|     <module>xslt-rest</module> |     <module>tools-services</module> | ||||||
|     <module>mocked-services</module> |     <module>mocked-services</module> | ||||||
|   </modules> |   </modules> | ||||||
| </project> | </project> | ||||||
| @@ -5,7 +5,7 @@ | |||||||
|   <modelVersion>4.0.0</modelVersion> |   <modelVersion>4.0.0</modelVersion> | ||||||
| 
 | 
 | ||||||
|   <groupId>com.r11.tools</groupId> |   <groupId>com.r11.tools</groupId> | ||||||
|   <artifactId>xslt-rest</artifactId> |   <artifactId>tools-services</artifactId> | ||||||
|   <version>1.0-SNAPSHOT</version> |   <version>1.0-SNAPSHOT</version> | ||||||
| 
 | 
 | ||||||
|   <properties> |   <properties> | ||||||
| @@ -15,24 +15,11 @@ | |||||||
|     <jackson.version>2.14.1</jackson.version> |     <jackson.version>2.14.1</jackson.version> | ||||||
|     <slf4j.version>2.0.6</slf4j.version> |     <slf4j.version>2.0.6</slf4j.version> | ||||||
|     <log4j.version>2.19.0</log4j.version> |     <log4j.version>2.19.0</log4j.version> | ||||||
|  |     <gson.version>2.10.1</gson.version> | ||||||
|   </properties> |   </properties> | ||||||
| 
 | 
 | ||||||
|   <build> |   <build> | ||||||
|     <plugins> |     <plugins> | ||||||
|       <!--            <plugin>--> |  | ||||||
|       <!--                <artifactId>maven-jar-plugin</artifactId>--> |  | ||||||
|       <!--                <version>3.1.0</version>--> |  | ||||||
|       <!--                <configuration>--> |  | ||||||
|       <!--                    <archive>--> |  | ||||||
|       <!--                        <manifest>--> |  | ||||||
|       <!--                            <addClasspath>true</addClasspath>--> |  | ||||||
|       <!--                            <classpathPrefix>lib/</classpathPrefix>--> |  | ||||||
|       <!--                            <mainClass>com.r11.tools.xslt.Main</mainClass>--> |  | ||||||
|       <!--                        </manifest>--> |  | ||||||
|       <!--                    </archive>--> |  | ||||||
|       <!--                </configuration>--> |  | ||||||
|       <!--            </plugin>--> |  | ||||||
| 
 |  | ||||||
|       <plugin> |       <plugin> | ||||||
|         <artifactId>maven-compiler-plugin</artifactId> |         <artifactId>maven-compiler-plugin</artifactId> | ||||||
|         <version>3.8.1</version> |         <version>3.8.1</version> | ||||||
| @@ -51,7 +38,7 @@ | |||||||
|             <manifest> |             <manifest> | ||||||
|               <addClasspath>true</addClasspath> |               <addClasspath>true</addClasspath> | ||||||
|               <classpathPrefix>lib/</classpathPrefix> |               <classpathPrefix>lib/</classpathPrefix> | ||||||
|               <mainClass>com.r11.tools.xslt.Main</mainClass> |               <mainClass>com.r11.tools.SparkInitializer</mainClass> | ||||||
|             </manifest> |             </manifest> | ||||||
|           </archive> |           </archive> | ||||||
|           <descriptorRefs> |           <descriptorRefs> | ||||||
| @@ -82,6 +69,11 @@ | |||||||
|     </dependency> |     </dependency> | ||||||
| 
 | 
 | ||||||
|     <!--    JSON    --> |     <!--    JSON    --> | ||||||
|  |     <dependency> | ||||||
|  |       <groupId>com.google.code.gson</groupId> | ||||||
|  |       <artifactId>gson</artifactId> | ||||||
|  |       <version>${gson.version}</version> | ||||||
|  |     </dependency> | ||||||
|     <dependency> |     <dependency> | ||||||
|       <groupId>com.fasterxml.jackson.core</groupId> |       <groupId>com.fasterxml.jackson.core</groupId> | ||||||
|       <artifactId>jackson-core</artifactId> |       <artifactId>jackson-core</artifactId> | ||||||
| @@ -142,7 +134,5 @@ | |||||||
|       <artifactId>log4j-api</artifactId> |       <artifactId>log4j-api</artifactId> | ||||||
|       <version>${log4j.version}</version> |       <version>${log4j.version}</version> | ||||||
|     </dependency> |     </dependency> | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   </dependencies> |   </dependencies> | ||||||
| </project> | </project> | ||||||
| @@ -0,0 +1,39 @@ | |||||||
|  | package com.r11.tools; | ||||||
|  |  | ||||||
|  | import com.r11.tools.controller.JsonController; | ||||||
|  | import com.r11.tools.controller.ProcessorInfoController; | ||||||
|  | import com.r11.tools.controller.XPathController; | ||||||
|  | import com.r11.tools.controller.XsdController; | ||||||
|  | import com.r11.tools.controller.XsltController; | ||||||
|  | import com.r11.tools.controller.internal.RestControllerRegistry; | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import spark.Spark; | ||||||
|  |  | ||||||
|  | public class SparkApplication { | ||||||
|  |  | ||||||
|  |     public static void run() { | ||||||
|  |         // TODO: read port from config | ||||||
|  |         Spark.port(8081); | ||||||
|  |  | ||||||
|  |         Spark.after((request, response) -> { | ||||||
|  |             response.header("Access-Control-Allow-Origin", "*"); | ||||||
|  |             response.header("access-control-allow-headers", "*"); | ||||||
|  |             response.header("access-control-expose-headers", "*"); | ||||||
|  |             response.header("Access-Control-Allow-Methods", "POST"); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         Logger logger = LogManager.getLogger(SparkApplication.class); | ||||||
|  |  | ||||||
|  |         RestControllerRegistry registry = new RestControllerRegistry(); | ||||||
|  |         registry.registerController(new ProcessorInfoController(logger)); | ||||||
|  |         registry.registerController(new XsdController(logger)); | ||||||
|  |         registry.registerController(new XPathController(logger)); | ||||||
|  |         registry.registerController(new XsltController(logger)); | ||||||
|  |         registry.registerController(new JsonController()); | ||||||
|  |  | ||||||
|  |         registry.register(); | ||||||
|  |  | ||||||
|  |         logger.info("Server is online at port: " + Spark.port()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | package com.r11.tools; | ||||||
|  |  | ||||||
|  | public class SparkInitializer { | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         SparkApplication.run(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,58 @@ | |||||||
|  | package com.r11.tools.controller; | ||||||
|  |  | ||||||
|  | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.GsonBuilder; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import com.r11.tools.controller.internal.GlobalControllerManifest; | ||||||
|  | import com.r11.tools.controller.internal.HandlerType; | ||||||
|  | import com.r11.tools.controller.internal.RestController; | ||||||
|  | import com.r11.tools.controller.internal.ScopedControllerManifest; | ||||||
|  | import spark.Request; | ||||||
|  | import spark.Response; | ||||||
|  |  | ||||||
|  | @GlobalControllerManifest(path = "/json") | ||||||
|  | public class JsonController implements RestController { | ||||||
|  |  | ||||||
|  |     private final Gson prettyGson = new GsonBuilder() | ||||||
|  |             .disableHtmlEscaping() | ||||||
|  |             .setPrettyPrinting() | ||||||
|  |             .create(); | ||||||
|  |  | ||||||
|  |     private final Gson gson = new GsonBuilder() | ||||||
|  |             .disableHtmlEscaping() | ||||||
|  |             .create(); | ||||||
|  |  | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.POST, path = "/formatting") | ||||||
|  |     public void formatting(Request request, Response response) { | ||||||
|  |         try { | ||||||
|  |             JsonObject jsonObject = this.gson.fromJson(request.body(), JsonObject.class); | ||||||
|  |             response.status(200); | ||||||
|  |             response.body(this.prettyGson.toJson(jsonObject)); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             response.status(500); | ||||||
|  |             Throwable cause = e.getCause(); | ||||||
|  |             if (cause == null) { | ||||||
|  |                 response.body(e.getMessage()); | ||||||
|  |             } else { | ||||||
|  |                 response.body(cause.getMessage()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.POST, path = "/minimize") | ||||||
|  |     public void minimize(Request request, Response response) { | ||||||
|  |         try { | ||||||
|  |             JsonObject jsonObject = this.prettyGson.fromJson(request.body(), JsonObject.class); | ||||||
|  |             response.status(200); | ||||||
|  |             response.body(this.gson.toJson(jsonObject)); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             response.status(500); | ||||||
|  |             Throwable cause = e.getCause(); | ||||||
|  |             if (cause == null) { | ||||||
|  |                 response.body(e.getMessage()); | ||||||
|  |             } else { | ||||||
|  |                 response.body(cause.getMessage()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,34 @@ | |||||||
|  | package com.r11.tools.controller; | ||||||
|  |  | ||||||
|  | import com.r11.tools.controller.internal.GlobalControllerManifest; | ||||||
|  | import com.r11.tools.controller.internal.HandlerType; | ||||||
|  | import com.r11.tools.controller.internal.RestController; | ||||||
|  | import com.r11.tools.controller.internal.ScopedControllerManifest; | ||||||
|  | import com.r11.tools.xml.Saxon; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import spark.Request; | ||||||
|  | import spark.Response; | ||||||
|  |  | ||||||
|  | @GlobalControllerManifest | ||||||
|  | public class ProcessorInfoController implements RestController { | ||||||
|  |  | ||||||
|  |     private final Logger logger; | ||||||
|  |  | ||||||
|  |     public ProcessorInfoController(Logger logger) { | ||||||
|  |         this.logger = logger; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Handler that returns processor version | ||||||
|  |      */ | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.GET, path = "/procinfo") | ||||||
|  |     public void processorInfo(Request request, Response response) { | ||||||
|  |         try { | ||||||
|  |             response.header("processor", "Saxon " + Saxon.getVersion() + " over s9api"); | ||||||
|  |             response.body(Saxon.getVersion()); | ||||||
|  |         } catch (Exception ex) { | ||||||
|  |             this.logger.error("Error on retrieving engine version. " + ex); | ||||||
|  |             response.body(ex.getMessage()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,104 @@ | |||||||
|  | package com.r11.tools.controller; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
|  | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
|  | import com.r11.tools.controller.internal.GlobalControllerManifest; | ||||||
|  | import com.r11.tools.controller.internal.HandlerType; | ||||||
|  | import com.r11.tools.controller.internal.RestController; | ||||||
|  | import com.r11.tools.controller.internal.ScopedControllerManifest; | ||||||
|  | import com.r11.tools.xml.Saxon; | ||||||
|  | import com.r11.tools.xml.Xalan; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import spark.Request; | ||||||
|  | import spark.Response; | ||||||
|  |  | ||||||
|  | @GlobalControllerManifest | ||||||
|  | public class XPathController implements RestController { | ||||||
|  |  | ||||||
|  |     private final Logger logger; | ||||||
|  |  | ||||||
|  |     public XPathController(Logger logger) { | ||||||
|  |         this.logger = logger; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.POST, path = "/xpath") | ||||||
|  |     public void transform(Request request, Response response) throws JsonProcessingException { | ||||||
|  |         String body = request.body(); | ||||||
|  |         ObjectMapper mapper = new ObjectMapper(); | ||||||
|  |         Map<String, String> requestMap = new HashMap<>(); | ||||||
|  |         Map<String, String> responseMap = new HashMap<>(); | ||||||
|  |         try { | ||||||
|  |             requestMap = mapper.readValue(body, Map.class); | ||||||
|  |         } catch (JsonProcessingException ex) { | ||||||
|  |             this.logger.error("Request JSON error. " + ex); | ||||||
|  |             responseMap.put("result", ex.getMessage()); | ||||||
|  |             responseMap.put("processor", "N/A"); | ||||||
|  |             responseMap.put("status", "ERR"); | ||||||
|  |             responseMap.put("time", "N/A"); | ||||||
|  |             response.status(400); | ||||||
|  |             response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         String data = requestMap.get("data"); | ||||||
|  |         String query = requestMap.get("process"); | ||||||
|  |         String processor = requestMap.get("processor"); | ||||||
|  |         String version = requestMap.get("version"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         String tmp = ""; | ||||||
|  |         long timeStart; | ||||||
|  |         long duration; | ||||||
|  |  | ||||||
|  |         if (processor == null) { | ||||||
|  |             response.body("saxon, xalan"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         switch (processor) { | ||||||
|  |             case "saxon": | ||||||
|  |                 response.header("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api"); | ||||||
|  |                 timeStart = System.currentTimeMillis(); | ||||||
|  |                 try { | ||||||
|  |                     tmp = Saxon.processXPath(data, query, version).trim(); | ||||||
|  |                     responseMap.put("result", tmp); | ||||||
|  |                     responseMap.put("status", "OK"); | ||||||
|  |                 } catch (Exception ex) { | ||||||
|  |                     this.logger.error("Error on processing XPath using Saxon. " + ex); | ||||||
|  |                     responseMap.put("result", ex.getMessage()); | ||||||
|  |                     responseMap.put("status", "ERR"); | ||||||
|  |                     response.status(400); | ||||||
|  |                 } | ||||||
|  |                 duration = System.currentTimeMillis() - timeStart; | ||||||
|  |                 this.logger.info("Request" + body + " processed in " + duration + " ms."); | ||||||
|  |                 responseMap.put("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api"); | ||||||
|  |                 responseMap.put("time", "" + duration); | ||||||
|  |                 response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             case "xalan": | ||||||
|  |                 response.header("processor", Xalan.getVersion()); | ||||||
|  |                 timeStart = System.currentTimeMillis(); | ||||||
|  |                 try { | ||||||
|  |                     tmp = Xalan.processXPath(data, query).trim(); | ||||||
|  |                     responseMap.put("result", tmp); | ||||||
|  |                     responseMap.put("status", "OK"); | ||||||
|  |                 } catch (Exception ex) { | ||||||
|  |                     this.logger.error("Error on processing XPath using Xalan. " + ex); | ||||||
|  |                     responseMap.put("result", ex.getMessage()); | ||||||
|  |                     responseMap.put("status", "ERR"); | ||||||
|  |                     response.status(400); | ||||||
|  |                 } | ||||||
|  |                 duration = System.currentTimeMillis() - timeStart; | ||||||
|  |                 this.logger.info("Request: " + body + " processed in " + duration + " ms."); | ||||||
|  |                 responseMap.put("processor", Xalan.getVersion()); | ||||||
|  |                 responseMap.put("time", Long.toString(duration)); | ||||||
|  |                 response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |                 return; | ||||||
|  |             default: | ||||||
|  |                 response.body("saxon, xalan"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,70 @@ | |||||||
|  | package com.r11.tools.controller; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
|  | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
|  | import com.r11.tools.controller.internal.GlobalControllerManifest; | ||||||
|  | import com.r11.tools.controller.internal.HandlerType; | ||||||
|  | import com.r11.tools.controller.internal.RestController; | ||||||
|  | import com.r11.tools.controller.internal.ScopedControllerManifest; | ||||||
|  | import com.r11.tools.xml.Xalan; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import spark.Request; | ||||||
|  | import spark.Response; | ||||||
|  |  | ||||||
|  | @GlobalControllerManifest | ||||||
|  | public class XsdController implements RestController { | ||||||
|  |  | ||||||
|  |     private final Logger logger; | ||||||
|  |  | ||||||
|  |     public XsdController(Logger logger) { | ||||||
|  |         this.logger = logger; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.POST, path = "/xsd") | ||||||
|  |     public Response transform(Request req, Response resp) throws JsonProcessingException { | ||||||
|  |         String body = req.body(); | ||||||
|  |  | ||||||
|  |         ObjectMapper mapper = new ObjectMapper(); | ||||||
|  |         Map<String, String> requestMap = new HashMap<>(); | ||||||
|  |         Map<String, String> responseMap = new HashMap<>(); | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             requestMap = mapper.readValue(body, Map.class); | ||||||
|  |         } catch (JsonProcessingException ex) { | ||||||
|  |             this.logger.error("Request JSON error. " + ex); | ||||||
|  |             responseMap.put("result", ex.getMessage()); | ||||||
|  |             responseMap.put("processor", "N/A"); | ||||||
|  |             responseMap.put("status", "ERR"); | ||||||
|  |             responseMap.put("time", "N/A"); | ||||||
|  |             resp.status(400); | ||||||
|  |             resp.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |             return resp; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         String data = requestMap.get("data"); | ||||||
|  |         String xsd = requestMap.get("process"); | ||||||
|  |  | ||||||
|  |         resp.header("processor", Xalan.getVersion()); | ||||||
|  |         long timeStart = System.currentTimeMillis(); | ||||||
|  |         String tmp; | ||||||
|  |         try { | ||||||
|  |             tmp = Xalan.validate(data, xsd).trim(); | ||||||
|  |             responseMap.put("result", tmp); | ||||||
|  |             responseMap.put("status", "OK"); | ||||||
|  |         } catch (Exception ex) { | ||||||
|  |             this.logger.error("Error on validation against XSD using Xalan. " + ex); | ||||||
|  |             responseMap.put("result", ex.getMessage()); | ||||||
|  |             responseMap.put("status", "ERR"); | ||||||
|  |             resp.status(400); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         long duration = System.currentTimeMillis() - timeStart; | ||||||
|  |         this.logger.info("Request: " + body + " processed in " + duration + " ms."); | ||||||
|  |         responseMap.put("processor", Xalan.getVersion()); | ||||||
|  |         responseMap.put("time", "" + duration); | ||||||
|  |         resp.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |         return resp; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,105 @@ | |||||||
|  | package com.r11.tools.controller; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.core.JsonParseException; | ||||||
|  | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
|  | import com.fasterxml.jackson.databind.JsonMappingException; | ||||||
|  | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
|  | import com.r11.tools.controller.internal.GlobalControllerManifest; | ||||||
|  | import com.r11.tools.controller.internal.HandlerType; | ||||||
|  | import com.r11.tools.controller.internal.RestController; | ||||||
|  | import com.r11.tools.controller.internal.ScopedControllerManifest; | ||||||
|  | import com.r11.tools.xml.Saxon; | ||||||
|  | import com.r11.tools.xml.Xalan; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import spark.Request; | ||||||
|  | import spark.Response; | ||||||
|  |  | ||||||
|  | @GlobalControllerManifest | ||||||
|  | public class XsltController implements RestController { | ||||||
|  |  | ||||||
|  |     private final Logger logger; | ||||||
|  |  | ||||||
|  |     public XsltController(Logger logger) { | ||||||
|  |         this.logger = logger; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ScopedControllerManifest(method = HandlerType.POST, path = "/xslt") | ||||||
|  |     public void transform(Request request, Response response) throws JsonProcessingException { | ||||||
|  |         String body = request.body(); | ||||||
|  |         ObjectMapper mapper = new ObjectMapper(); | ||||||
|  |         Map<String, String> requestMap = new HashMap<>(); | ||||||
|  |         Map<String, String> responseMap = new HashMap<>(); | ||||||
|  |         try { | ||||||
|  |             requestMap = mapper.readValue(body, Map.class); | ||||||
|  |         } catch (JsonMappingException | JsonParseException ex) { | ||||||
|  |             this.logger.error("Request JSON error. " + ex); | ||||||
|  |             responseMap.put("result", ex.getMessage()); | ||||||
|  |             responseMap.put("processor", "N/A"); | ||||||
|  |             responseMap.put("status", "ERR"); | ||||||
|  |             responseMap.put("time", "N/A"); | ||||||
|  |             response.status(400); | ||||||
|  |             response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         String data = requestMap.get("data"); | ||||||
|  |         String query = requestMap.get("process"); | ||||||
|  |         String processor = requestMap.get("processor"); | ||||||
|  |         String version = requestMap.get("version"); | ||||||
|  |  | ||||||
|  |         if (processor == null) { | ||||||
|  |             response.body("saxon, xalan"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         String tmp; | ||||||
|  |         long timeStart; | ||||||
|  |         long duration; | ||||||
|  |         switch (processor) { | ||||||
|  |             case "saxon": | ||||||
|  |                 timeStart = System.currentTimeMillis(); | ||||||
|  |                 try { | ||||||
|  |                     tmp = Saxon.processXSLT(data, query); | ||||||
|  |                     responseMap.put("result", tmp); | ||||||
|  |                     responseMap.put("status", "OK"); | ||||||
|  |                 } catch (Exception ex) { | ||||||
|  |                     this.logger.error("Error on processing XSLT using Saxon. " + ex); | ||||||
|  |                     responseMap.put("result", ex.getMessage()); | ||||||
|  |                     responseMap.put("status", "ERR"); | ||||||
|  |                     response.status(400); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 duration = System.currentTimeMillis() - timeStart; | ||||||
|  |                 this.logger.info("Request: " + body + " processed in " + duration + " ms."); | ||||||
|  |                 responseMap.put("processor", "Saxon " + Saxon.getVersion() + " " + version); | ||||||
|  |                 responseMap.put("time", Long.toString(duration)); | ||||||
|  |                 response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             case "xalan": | ||||||
|  |                 timeStart = System.currentTimeMillis(); | ||||||
|  |                 try { | ||||||
|  |                     tmp = Xalan.processXSLT(data, query); | ||||||
|  |                     responseMap.put("result", tmp); | ||||||
|  |                     responseMap.put("status", "OK"); | ||||||
|  |                 } catch (Exception ex) { | ||||||
|  |                     this.logger.error("Error on processing XSLT using Xalan. " + ex); | ||||||
|  |                     responseMap.put("result", ex.getMessage()); | ||||||
|  |                     responseMap.put("status", "ERR"); | ||||||
|  |                     response.status(400); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 duration = System.currentTimeMillis() - timeStart; | ||||||
|  |                 this.logger.info("Request: " + body + " processed in " + duration + " ms."); | ||||||
|  |                 responseMap.put("processor", Xalan.getVersion()); | ||||||
|  |                 responseMap.put("time", Long.toString(duration)); | ||||||
|  |                 response.body(mapper.writeValueAsString(responseMap)); | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             default: | ||||||
|  |                 response.body("saxon, xalan"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,14 @@ | |||||||
|  | package com.r11.tools.controller.internal; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @Target(ElementType.TYPE) | ||||||
|  | public @interface GlobalControllerManifest { | ||||||
|  |  | ||||||
|  |     String path() default ""; | ||||||
|  | } | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | package com.r11.tools.controller.internal; | ||||||
|  |  | ||||||
|  | public enum HandlerType { | ||||||
|  |  | ||||||
|  |     GET, POST, PUT, DELETE | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,5 @@ | |||||||
|  | package com.r11.tools.controller.internal; | ||||||
|  |  | ||||||
|  | public interface RestController { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,59 @@ | |||||||
|  | package com.r11.tools.controller.internal; | ||||||
|  |  | ||||||
|  | import com.r11.tools.controller.internal.path.PathBuilder; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Set; | ||||||
|  | import spark.Spark; | ||||||
|  |  | ||||||
|  | public class RestControllerRegistry { | ||||||
|  |  | ||||||
|  |     private final Set<RestController> registeredControllers; | ||||||
|  |  | ||||||
|  |     public RestControllerRegistry() { | ||||||
|  |         this.registeredControllers = new HashSet<>(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void registerController(RestController restController) { | ||||||
|  |         this.registeredControllers.add(restController); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void register() { | ||||||
|  |         this.registeredControllers.forEach(controller -> { | ||||||
|  |             if (controller.getClass().isAnnotationPresent(GlobalControllerManifest.class)) { | ||||||
|  |                 for (Method method : controller.getClass().getMethods()) { | ||||||
|  |                     this.registerAssignableHandlers(controller.getClass(), controller, method); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void registerAssignableHandlers(Class<? extends RestController> parent, RestController parentValue, Method method) { | ||||||
|  |         if ( | ||||||
|  |                 (parent.isAnnotationPresent(GlobalControllerManifest.class)) && | ||||||
|  |                         (method.isAnnotationPresent(ScopedControllerManifest.class)) | ||||||
|  |         ) { | ||||||
|  |             HandlerType handlerType = method.getAnnotation(ScopedControllerManifest.class).method(); | ||||||
|  |  | ||||||
|  |             String path = PathBuilder.resolvePathOf( | ||||||
|  |                     parent.getAnnotation(GlobalControllerManifest.class).path(), | ||||||
|  |                     method.getAnnotation(ScopedControllerManifest.class).path() | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |             switch (handlerType) { | ||||||
|  |                 case GET: | ||||||
|  |                     Spark.get(path, (request, response) -> method.invoke(parentValue, request, response)); | ||||||
|  |                     break; | ||||||
|  |                 case PUT: | ||||||
|  |                     Spark.put(path, (request, response) -> method.invoke(parentValue, request, response)); | ||||||
|  |                     break; | ||||||
|  |                 case POST: | ||||||
|  |                     Spark.post(path, (request, response) -> method.invoke(parentValue, request, response)); | ||||||
|  |                     break; | ||||||
|  |                 case DELETE: | ||||||
|  |                     Spark.delete(path, (request, response) -> method.invoke(parentValue, request, response)); | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | package com.r11.tools.controller.internal; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @Target(ElementType.METHOD) | ||||||
|  | public @interface ScopedControllerManifest { | ||||||
|  |  | ||||||
|  |     HandlerType method(); | ||||||
|  |  | ||||||
|  |     String path(); | ||||||
|  | } | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | package com.r11.tools.controller.internal.path; | ||||||
|  |  | ||||||
|  | public final class PathBuilder { | ||||||
|  |  | ||||||
|  |     private static final String PATH_SEPARATOR = "/"; | ||||||
|  |  | ||||||
|  |     private PathBuilder() { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static String resolvePathOf(String globalPath, String scopedPath) { | ||||||
|  |         String resolvedPath = | ||||||
|  |                 PathBuilder.removeTrailingPathSeparator(globalPath) + | ||||||
|  |                         PathBuilder.removeTrailingPathSeparator(scopedPath); | ||||||
|  |  | ||||||
|  |         if (resolvedPath.endsWith(PATH_SEPARATOR)) { | ||||||
|  |             resolvedPath = resolvedPath.substring(0, resolvedPath.length() - 1); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return PATH_SEPARATOR + resolvedPath; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static String removeTrailingPathSeparator(String path) { | ||||||
|  |         if (path.endsWith(PATH_SEPARATOR)) { | ||||||
|  |             return path.substring(0, path.length() - 1); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return path; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package com.r11.tools.xslt.processors; | package com.r11.tools.xml; | ||||||
| 
 | 
 | ||||||
| import net.sf.saxon.om.NamespaceMap; | import net.sf.saxon.om.NamespaceMap; | ||||||
| import net.sf.saxon.s9api.XPathCompiler; | import net.sf.saxon.s9api.XPathCompiler; | ||||||
| @@ -1,8 +1,6 @@ | |||||||
| package com.r11.tools.xslt.processors; | package com.r11.tools.xml; | ||||||
| 
 | 
 | ||||||
| import net.sf.saxon.s9api.*; | import net.sf.saxon.s9api.*; | ||||||
| import org.apache.logging.log4j.LogManager; |  | ||||||
| import org.apache.logging.log4j.Logger; |  | ||||||
| 
 | 
 | ||||||
| import javax.xml.transform.stream.StreamSource; | import javax.xml.transform.stream.StreamSource; | ||||||
| import java.io.StringReader; | import java.io.StringReader; | ||||||
| @@ -1,8 +1,5 @@ | |||||||
| package com.r11.tools.xslt.processors; | package com.r11.tools.xml; | ||||||
| 
 | 
 | ||||||
| import net.sf.saxon.lib.RawResult; |  | ||||||
| import org.apache.logging.log4j.LogManager; |  | ||||||
| import org.apache.logging.log4j.Logger; |  | ||||||
| import org.apache.xpath.XPathAPI; | import org.apache.xpath.XPathAPI; | ||||||
| import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||||
| import org.w3c.dom.Node; | import org.w3c.dom.Node; | ||||||
| @@ -19,10 +16,6 @@ import javax.xml.transform.stream.StreamSource; | |||||||
| import javax.xml.validation.Schema; | import javax.xml.validation.Schema; | ||||||
| import javax.xml.validation.SchemaFactory; | import javax.xml.validation.SchemaFactory; | ||||||
| import javax.xml.validation.Validator; | import javax.xml.validation.Validator; | ||||||
| import javax.xml.xpath.XPath; |  | ||||||
| import javax.xml.xpath.XPathConstants; |  | ||||||
| import javax.xml.xpath.XPathExpression; |  | ||||||
| import javax.xml.xpath.XPathFactory; |  | ||||||
| import java.io.*; | import java.io.*; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package com.r11.tools.xslt.processors; | package com.r11.tools.xml; | ||||||
| 
 | 
 | ||||||
| import org.w3c.dom.*; | import org.w3c.dom.*; | ||||||
| 
 | 
 | ||||||
| @@ -11,7 +11,7 @@ | |||||||
| 		</File> | 		</File> | ||||||
| 	</Appenders> | 	</Appenders> | ||||||
| 	<Loggers> | 	<Loggers> | ||||||
| 		<Logger name="com.r11.tools.xslt.SparkInitializer" level="info" additivity="true"> | 		<Logger name="com.r11.tools.SparkApplication" level="info" additivity="true"> | ||||||
| 			<AppenderRef ref="Console"/> | 			<AppenderRef ref="Console"/> | ||||||
| 		</Logger> | 		</Logger> | ||||||
| 		<Root level="info"> | 		<Root level="info"> | ||||||
| @@ -1,15 +0,0 @@ | |||||||
| package com.r11.tools.xslt; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Application initializer |  | ||||||
|  * @author Wojciech Czop |  | ||||||
|  */ |  | ||||||
| public class Main { |  | ||||||
|     /** |  | ||||||
|      * Initializes the application |  | ||||||
|      * @param args |  | ||||||
|      */ |  | ||||||
|     public static void main(String[] args) { |  | ||||||
|         SparkInitializer.run(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,260 +0,0 @@ | |||||||
| package com.r11.tools.xslt; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.core.JsonParseException; |  | ||||||
| import com.fasterxml.jackson.databind.JsonMappingException; |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper; |  | ||||||
| import com.r11.tools.xslt.processors.Saxon; |  | ||||||
| import com.r11.tools.xslt.processors.Xalan; |  | ||||||
| import org.apache.logging.log4j.LogManager; |  | ||||||
| import org.apache.logging.log4j.Logger; |  | ||||||
| import spark.*; |  | ||||||
|  |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.Map; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Class contains spark configuration and method initializing spark framework |  | ||||||
|  * @author Wojciech Czop |  | ||||||
|  */ |  | ||||||
| public class SparkInitializer { |  | ||||||
|  |  | ||||||
|     private static final Logger LOG = LogManager.getLogger(SparkInitializer.class); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Initializes spark framework |  | ||||||
|      */ |  | ||||||
|     public static void run(){ |  | ||||||
| //        TODO: Port value as property |  | ||||||
|         Spark.port(8081); |  | ||||||
|  |  | ||||||
|         Spark.after((request, response) -> { |  | ||||||
|             response.header("Access-Control-Allow-Origin", "*"); |  | ||||||
|             response.header("access-control-allow-headers", "*"); |  | ||||||
|             response.header("access-control-expose-headers", "*"); |  | ||||||
|             response.header("Access-Control-Allow-Methods", "POST"); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         Spark.post("/xsltpost", xsltHandler); |  | ||||||
|         Spark.post("/xpathpost", xpathHandler); |  | ||||||
|         Spark.post("/xsdpost", xsdHandler); |  | ||||||
|         Spark.get("/procinfo", procinfoHandler); |  | ||||||
|  |  | ||||||
|         LOG.info("Server is online at port: " + Spark.port()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Handler that returns processor version |  | ||||||
|      */ |  | ||||||
|     private static final Route procinfoHandler = (Request req, Response resp) -> { |  | ||||||
|         try { |  | ||||||
|             resp.header("processor", "Saxon " + Saxon.getVersion() + " over s9api"); |  | ||||||
|             return Saxon.getVersion(); |  | ||||||
|         } catch (Exception ex) { |  | ||||||
|             LOG.error("Error on retrieving engine version. " + ex); |  | ||||||
|             return ex.getMessage(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Handler that returns info if document is valid |  | ||||||
|      * Also provides info about request time and processor |  | ||||||
|      */ |  | ||||||
|     private static final Route xsdHandler = (Request req, Response resp) -> { |  | ||||||
|         String body = req.body(); |  | ||||||
|         ObjectMapper mapper = new ObjectMapper(); |  | ||||||
|         Map<String, String> requestMap = new HashMap<>(); |  | ||||||
|         Map<String, String> responseMap = new HashMap<>(); |  | ||||||
|         try { |  | ||||||
|             requestMap = mapper.readValue(body, Map.class); |  | ||||||
|         } catch (JsonMappingException | JsonParseException ex) { |  | ||||||
|             LOG.error("Request JSON error. " + ex); |  | ||||||
|             responseMap.put("result", ex.getMessage()); |  | ||||||
|             responseMap.put("processor", "N/A"); |  | ||||||
|             responseMap.put("status", "ERR"); |  | ||||||
|             responseMap.put("time", "N/A"); |  | ||||||
|             resp.status(400); |  | ||||||
|             resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|             return resp; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         String data = requestMap.get("data"); |  | ||||||
|         String xsd = requestMap.get("process"); |  | ||||||
|  |  | ||||||
|         resp.header("processor", Xalan.getVersion()); |  | ||||||
|         long timeStart = System.currentTimeMillis(); |  | ||||||
|         String tmp; |  | ||||||
|         try { |  | ||||||
|             tmp = Xalan.validate(data, xsd).trim(); |  | ||||||
|             responseMap.put("result", tmp); |  | ||||||
|             responseMap.put("status", "OK"); |  | ||||||
|         } catch (Exception ex) { |  | ||||||
|             LOG.error("Error on validation against XSD using Xalan. " + ex); |  | ||||||
|             responseMap.put("result", ex.getMessage()); |  | ||||||
|             responseMap.put("status", "ERR"); |  | ||||||
|             resp.status(400); |  | ||||||
|         } |  | ||||||
|         long duration = System.currentTimeMillis() - timeStart; |  | ||||||
|         LOG.info("Request: " + body + " processed in " + duration + " ms."); |  | ||||||
|         responseMap.put("processor", Xalan.getVersion()); |  | ||||||
|         responseMap.put("time", "" + duration); |  | ||||||
|         resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|         return resp; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Handler that returns output of xpath query and processor data |  | ||||||
|      */ |  | ||||||
|     private static final Route xpathHandler = (Request req, Response resp) -> { |  | ||||||
|         String body = req.body(); |  | ||||||
|         ObjectMapper mapper = new ObjectMapper(); |  | ||||||
|         Map<String, String> requestMap = new HashMap<>(); |  | ||||||
|         Map<String, String> responseMap = new HashMap<>(); |  | ||||||
|         try { |  | ||||||
|             requestMap = mapper.readValue(body, Map.class); |  | ||||||
|         } catch (JsonMappingException | JsonParseException ex) { |  | ||||||
|             LOG.error("Request JSON error. " + ex); |  | ||||||
|             responseMap.put("result", ex.getMessage()); |  | ||||||
|             responseMap.put("processor", "N/A"); |  | ||||||
|             responseMap.put("status", "ERR"); |  | ||||||
|             responseMap.put("time", "N/A"); |  | ||||||
|             resp.status(400); |  | ||||||
|             resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|             return resp; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         String data = requestMap.get("data"); |  | ||||||
|         String query = requestMap.get("process"); |  | ||||||
|         String processor = requestMap.get("processor"); |  | ||||||
|         String version = requestMap.get("version"); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         String tmp = ""; |  | ||||||
|         long timeStart; |  | ||||||
|         long duration; |  | ||||||
|  |  | ||||||
|         if (processor == null) { |  | ||||||
|             return "saxon, xalan"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         switch (processor) { |  | ||||||
|             case "saxon": |  | ||||||
|                 resp.header("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api"); |  | ||||||
|                 timeStart = System.currentTimeMillis(); |  | ||||||
|                 try { |  | ||||||
|                     tmp = Saxon.processXPath(data, query, version).trim(); |  | ||||||
|                     responseMap.put("result", tmp); |  | ||||||
|                     responseMap.put("status", "OK"); |  | ||||||
|                 } catch (Exception ex) { |  | ||||||
|                     LOG.error("Error on processing XPath using Saxon. " + ex); |  | ||||||
|                     responseMap.put("result", ex.getMessage()); |  | ||||||
|                     responseMap.put("status", "ERR"); |  | ||||||
|                     resp.status(400); |  | ||||||
|                 } |  | ||||||
|                 duration = System.currentTimeMillis() - timeStart; |  | ||||||
|                 LOG.info("Request" + body + " processed in " + duration + " ms."); |  | ||||||
|                 responseMap.put("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api"); |  | ||||||
|                 responseMap.put("time", "" + duration); |  | ||||||
|                 resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|                 return resp; |  | ||||||
|  |  | ||||||
|             case "xalan": |  | ||||||
|                 resp.header("processor", Xalan.getVersion()); |  | ||||||
|                 timeStart = System.currentTimeMillis(); |  | ||||||
|                 try { |  | ||||||
|                     tmp = Xalan.processXPath(data, query).trim(); |  | ||||||
|                     responseMap.put("result", tmp); |  | ||||||
|                     responseMap.put("status", "OK"); |  | ||||||
|                 } catch (Exception ex) { |  | ||||||
|                     LOG.error("Error on processing XPath using Xalan. " + ex); |  | ||||||
|                     responseMap.put("result", ex.getMessage()); |  | ||||||
|                     responseMap.put("status", "ERR"); |  | ||||||
|                     resp.status(400); |  | ||||||
|                 } |  | ||||||
|                 duration = System.currentTimeMillis() - timeStart; |  | ||||||
|                 LOG.info("Request: " + body + " processed in " + duration + " ms."); |  | ||||||
|                 responseMap.put("processor", Xalan.getVersion()); |  | ||||||
|                 responseMap.put("time", Long.toString(duration)); |  | ||||||
|                 resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|                 return resp; |  | ||||||
|  |  | ||||||
|             default: |  | ||||||
|                 return "saxon, xalan"; |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Handler that returns outcome of xslt transformation and processor data |  | ||||||
|      */ |  | ||||||
|     private static final Route xsltHandler = (Request req, Response resp) -> { |  | ||||||
|         String body = req.body(); |  | ||||||
|         ObjectMapper mapper = new ObjectMapper(); |  | ||||||
|         Map<String, String> requestMap = new HashMap<>(); |  | ||||||
|         Map<String, String> responseMap = new HashMap<>(); |  | ||||||
|         try { |  | ||||||
|             requestMap = mapper.readValue(body, Map.class); |  | ||||||
|         } catch (JsonMappingException | JsonParseException ex) { |  | ||||||
|             LOG.error("Request JSON error. " + ex); |  | ||||||
|             responseMap.put("result", ex.getMessage()); |  | ||||||
|             responseMap.put("processor", "N/A"); |  | ||||||
|             responseMap.put("status", "ERR"); |  | ||||||
|             responseMap.put("time", "N/A"); |  | ||||||
|             resp.status(400); |  | ||||||
|             resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|             return resp; |  | ||||||
|         } |  | ||||||
|         String data = requestMap.get("data"); |  | ||||||
|         String query = requestMap.get("process"); |  | ||||||
|         String processor = requestMap.get("processor"); |  | ||||||
|         String version = requestMap.get("version"); |  | ||||||
|  |  | ||||||
|         if (processor == null) { |  | ||||||
|             return "saxon, xalan"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         String tmp; |  | ||||||
|         long timeStart; |  | ||||||
|         long duration; |  | ||||||
|         switch (processor) { |  | ||||||
|             case "saxon": |  | ||||||
|                 timeStart = System.currentTimeMillis(); |  | ||||||
|                 try { |  | ||||||
|                     tmp = Saxon.processXSLT(data, query); |  | ||||||
|                     responseMap.put("result", tmp); |  | ||||||
|                     responseMap.put("status", "OK"); |  | ||||||
|                 } catch (Exception ex) { |  | ||||||
|                     LOG.error("Error on processing XSLT using Saxon. " + ex); |  | ||||||
|                     responseMap.put("result", ex.getMessage()); |  | ||||||
|                     responseMap.put("status", "ERR"); |  | ||||||
|                     resp.status(400); |  | ||||||
|                 } |  | ||||||
|                 duration = System.currentTimeMillis() - timeStart; |  | ||||||
|                 LOG.info("Request: " + body + " processed in " + duration + " ms."); |  | ||||||
|                 responseMap.put("processor", "Saxon " + Saxon.getVersion() + " " + version); |  | ||||||
|                 responseMap.put("time", Long.toString(duration)); |  | ||||||
|                 resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|                 return resp; |  | ||||||
|  |  | ||||||
|             case "xalan": |  | ||||||
|                 timeStart = System.currentTimeMillis(); |  | ||||||
|                 try { |  | ||||||
|                     tmp = Xalan.processXSLT(data, query); |  | ||||||
|                     responseMap.put("result", tmp); |  | ||||||
|                     responseMap.put("status", "OK"); |  | ||||||
|                 } catch (Exception ex) { |  | ||||||
|                     LOG.error("Error on processing XSLT using Xalan. " + ex); |  | ||||||
|                     responseMap.put("result", ex.getMessage()); |  | ||||||
|                     responseMap.put("status", "ERR"); |  | ||||||
|                     resp.status(400); |  | ||||||
|                 } |  | ||||||
|                 duration = System.currentTimeMillis() - timeStart; |  | ||||||
|                 LOG.info("Request: " + body + " processed in " + duration + " ms."); |  | ||||||
|                 responseMap.put("processor", Xalan.getVersion()); |  | ||||||
|                 responseMap.put("time", Long.toString(duration)); |  | ||||||
|                 resp.body(mapper.writeValueAsString(responseMap)); |  | ||||||
|                 return resp; |  | ||||||
|  |  | ||||||
|             default: |  | ||||||
|                 return "saxon, xalan"; |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| @@ -1,39 +1,63 @@ | |||||||
| function formatAndValidateJson(errorElement) { | function formatAndValidateJson(errorElement) { | ||||||
|   const input = document.querySelector('#jsonBlock'); |   const input = document.querySelector('#jsonBlock'); | ||||||
|   const processInfo = document.getElementById(errorElement); |   const processInfo = document.getElementById(errorElement); | ||||||
|  |   const start = new Date(); | ||||||
|  |  | ||||||
|   try { |   const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/formatting" | ||||||
|     const start = new Date(); |  | ||||||
|  |  | ||||||
|     const obj = JSON.parse(input.textContent); |   fetch(address, { | ||||||
|     input.innerHTML = JSON.stringify(obj, null, 2); |     method: 'POST', | ||||||
|  |     body: input.textContent | ||||||
|  |   }) | ||||||
|  |   .then(async (response) => { | ||||||
|  |     if (!response.ok) { | ||||||
|  |       throw Error(await response.text()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return response.text(); | ||||||
|  |   }) | ||||||
|  |   .then((data) => { | ||||||
|  |     input.innerText = data; | ||||||
|     processInfo.innerText = ""; |     processInfo.innerText = ""; | ||||||
|     hljs.highlightElement(input); |     hljs.highlightElement(input); | ||||||
|  |  | ||||||
|     const end = new Date(); |     const end = new Date(); | ||||||
|     processInfo.innerHTML = "<b style='color: black'>Validation and formatting time:</b> <span style='color: green'>" + (end.getMilliseconds() - start.getMilliseconds()) + "ms</span>"; |     processInfo.innerHTML = "<b style='color: black'>Validation and formatting time:</b> <span style='color: green'>" + (end.getMilliseconds() - start.getMilliseconds()) + "ms</span>"; | ||||||
|   } catch (error) { |   }) | ||||||
|  |   .catch((error) => { | ||||||
|     processInfo.innerHTML = "<b style='color: red'>" + error + "</b>"; |     processInfo.innerHTML = "<b style='color: red'>" + error + "</b>"; | ||||||
|     console.error("Error: ", error) |     console.error('Error:', error); | ||||||
|   } |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| function minimizeJson(errorElement) { | function minimizeJson(errorElement) { | ||||||
|   const input = document.querySelector('#jsonBlock'); |   const input = document.querySelector('#jsonBlock'); | ||||||
|   const processInfo = document.getElementById(errorElement); |   const processInfo = document.getElementById(errorElement); | ||||||
|  |  | ||||||
|   try { |   const start = new Date(); | ||||||
|     const start = new Date(); |   const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/minimize" | ||||||
|  |  | ||||||
|     const obj = JSON.parse(input.textContent); |   fetch(address, { | ||||||
|     input.innerHTML = JSON.stringify(obj); |     method: 'POST', | ||||||
|  |     body: input.textContent | ||||||
|  |   }) | ||||||
|  |   .then(async (response) => { | ||||||
|  |     if (!response.ok) { | ||||||
|  |       throw Error(await response.text()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return response.text(); | ||||||
|  |   }) | ||||||
|  |   .then((data) => { | ||||||
|  |     input.innerText = data; | ||||||
|     processInfo.innerText = ""; |     processInfo.innerText = ""; | ||||||
|     hljs.highlightElement(input); |     hljs.highlightElement(input); | ||||||
|  |  | ||||||
|     const end = new Date(); |     const end = new Date(); | ||||||
|     processInfo.innerHTML = "<b style='color: black'>Validation and formatting time:</b> <span style='color: green'>" + (end.getMilliseconds() - start.getMilliseconds()) + "ms</span>"; |     processInfo.innerHTML = "<b style='color: black'>Validation and formatting time:</b> <span style='color: green'>" + (end.getMilliseconds() - start.getMilliseconds()) + "ms</span>"; | ||||||
|   } catch (error) { |   }) | ||||||
|  |   .catch((error) => { | ||||||
|     processInfo.innerHTML = "<b style='color: red'>" + error + "</b>"; |     processInfo.innerHTML = "<b style='color: red'>" + error + "</b>"; | ||||||
|     console.error("Error: ", error) |     console.error('Error:', error); | ||||||
|   } |   }); | ||||||
| } | } | ||||||
| @@ -1,54 +1,251 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
|  |  | ||||||
| <head> |   <head> | ||||||
|   <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|   <meta charset="utf-8" /> |     <meta charset="utf-8" /> | ||||||
|  |  | ||||||
|   <link rel="stylesheet" href="../assets/css/tools/r11form.css"> |     <link rel="stylesheet" href="../assets/css/tools/r11form.css"> | ||||||
|   <link rel="stylesheet" href="../assets/css/json.css"> |     <link rel="stylesheet" href="../assets/css/json.css"> | ||||||
|   <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css"> |     <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css"> | ||||||
|   <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script> |     <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script> | ||||||
|   <script src="../assets/scripts/tools/scripts.js"></script> |     <script src="../assets/scripts/tools/scripts.js"></script> | ||||||
|   <script src="../assets/scripts/tools/json.js"></script> |     <script src="../assets/scripts/tools/json.js"></script> | ||||||
|   <script>hljs.highlightAll();</script> |     <script>hljs.highlightAll();</script> | ||||||
| </head> |   </head> | ||||||
|  |  | ||||||
| <body> |   <body> | ||||||
|   <div class="container"> |     <div class="container"> | ||||||
|     <div id="tool" class="tool rwd-expandable"> |       <div id="tool" class="tool rwd-expandable"> | ||||||
|       <div class="tool-context"> |         <div class="tool-context"> | ||||||
|         <div class="headline"> |           <div class="headline"> | ||||||
|           <h1>Online JSON Formatter</h1> |             <h1>Online JSON Formatter</h1> | ||||||
|  |           </div> | ||||||
|  |  | ||||||
|  |           <p style="margin-bottom: -30px" id="processInfo"></p> | ||||||
|  |  | ||||||
|  |           <pre> | ||||||
|  |             <code class="hightlight-json json-block" id="jsonBlock" contenteditable="True">{"enter": "your", "json": "here"}</code> | ||||||
|  |           </pre> | ||||||
|  |  | ||||||
|  |           <button style="margin-top: 20px" | ||||||
|  |                   class="max-width block-label action-button active" | ||||||
|  |                   onclick="formatAndValidateJson('processInfo')" | ||||||
|  |           >Prettify JSON</button> | ||||||
|  |  | ||||||
|  |           <button class="max-width block-label action-button active" | ||||||
|  |                   onclick="minimizeJson('processInfo')" | ||||||
|  |           >Minimize JSON</button> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <p style="margin-bottom: -30px" id="processInfo"></p> |  | ||||||
|  |  | ||||||
|         <pre> |  | ||||||
|           <code class="hightlight-json json-block" id="jsonBlock" contenteditable="True">{"enter": "your", "json": "here"}</code> |  | ||||||
|         </pre> |  | ||||||
|  |  | ||||||
|         <button style="margin-top: 20px" |  | ||||||
|                 class="max-width block-label action-button active" |  | ||||||
|                 onclick="formatAndValidateJson('processInfo')" |  | ||||||
|         >Prettify JSON</button> |  | ||||||
|  |  | ||||||
|         <button class="max-width block-label action-button active" |  | ||||||
|                 onclick="minimizeJson('processInfo')" |  | ||||||
|         >Minimize JSON</button> |  | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|  |       <div class="tooltip-window rwd-hideable"> | ||||||
|  |         <h2>What is this?</h2> | ||||||
|  |         <p>This tool has 2 main functions: | ||||||
|  |         <ul> | ||||||
|  |           <li><strong>Prettify JSON</strong> to make it human-readable (add indentation etc.)</li> | ||||||
|  |           <li><strong>Minimize JSON</strong> to make it more compact (exactly opposite to above)</li> | ||||||
|  |         </ul> | ||||||
|  |         </p> | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div class="tooltip-window rwd-hideable"> |     <script> | ||||||
|       <h2>What is this?</h2> |       const mergeHTMLPlugin = (function () { | ||||||
|       <p>This tool has 2 main functions: |         'use strict'; | ||||||
|       <ul> |  | ||||||
|         <li><strong>Prettify JSON</strong> to make it human-readable (add indentation etc.)</li> |  | ||||||
|         <li><strong>Minimize JSON</strong> to make it more compact (exactly opposite to above)</li> |  | ||||||
|       </ul> |  | ||||||
|       </p> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
|   </div> |         var originalStream; | ||||||
| </body> |  | ||||||
|  |         /** | ||||||
|  |          * @param {string} value | ||||||
|  |          * @returns {string} | ||||||
|  |          */ | ||||||
|  |         function escapeHTML(value) { | ||||||
|  |           return value | ||||||
|  |           .replace(/&/g, '&') | ||||||
|  |           .replace(/</g, '<') | ||||||
|  |           .replace(/>/g, '>') | ||||||
|  |           .replace(/"/g, '"') | ||||||
|  |           .replace(/'/g, '''); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* plugin itself */ | ||||||
|  |  | ||||||
|  |         /** @type {HLJSPlugin} */ | ||||||
|  |         const mergeHTMLPlugin = { | ||||||
|  |           // preserve the original HTML token stream | ||||||
|  |           "before:highlightElement": ({el}) => { | ||||||
|  |             originalStream = nodeStream(el); | ||||||
|  |           }, | ||||||
|  |           // merge it afterwards with the highlighted token stream | ||||||
|  |           "after:highlightElement": ({el, result, text}) => { | ||||||
|  |             if (!originalStream.length) { | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             const resultNode = document.createElement('div'); | ||||||
|  |             resultNode.innerHTML = result.value; | ||||||
|  |             result.value = mergeStreams(originalStream, nodeStream(resultNode), text); | ||||||
|  |             el.innerHTML = result.value; | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param {Node} node | ||||||
|  |          */ | ||||||
|  |         function tag(node) { | ||||||
|  |           return node.nodeName.toLowerCase(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param {Node} node | ||||||
|  |          */ | ||||||
|  |         function nodeStream(node) { | ||||||
|  |           /** @type Event[] */ | ||||||
|  |           const result = []; | ||||||
|  |           (function _nodeStream(node, offset) { | ||||||
|  |             for (let child = node.firstChild; child; child = child.nextSibling) { | ||||||
|  |               if (child.nodeType === 3) { | ||||||
|  |                 offset += child.nodeValue.length; | ||||||
|  |               } else if (child.nodeType === 1) { | ||||||
|  |                 result.push({ | ||||||
|  |                   event: 'start', | ||||||
|  |                   offset: offset, | ||||||
|  |                   node: child | ||||||
|  |                 }); | ||||||
|  |                 offset = _nodeStream(child, offset); | ||||||
|  |  | ||||||
|  |                 if (!tag(child).match(/br|hr|img|input/)) { | ||||||
|  |                   result.push({ | ||||||
|  |                     event: 'stop', | ||||||
|  |                     offset: offset, | ||||||
|  |                     node: child | ||||||
|  |                   }); | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |             return offset; | ||||||
|  |           })(node, 0); | ||||||
|  |           return result; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param {any} original - the original stream | ||||||
|  |          * @param {any} highlighted - stream of the highlighted source | ||||||
|  |          * @param {string} value - the original source itself | ||||||
|  |          */ | ||||||
|  |         function mergeStreams(original, highlighted, value) { | ||||||
|  |           let processed = 0; | ||||||
|  |           let result = ''; | ||||||
|  |           const nodeStack = []; | ||||||
|  |  | ||||||
|  |           function selectStream() { | ||||||
|  |             if (!original.length || !highlighted.length) { | ||||||
|  |               return original.length ? original : highlighted; | ||||||
|  |             } | ||||||
|  |             if (original[0].offset !== highlighted[0].offset) { | ||||||
|  |               return (original[0].offset < highlighted[0].offset) ? original : highlighted; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return highlighted[0].event === 'start' ? original : highlighted; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           /** | ||||||
|  |            * @param {Node} node | ||||||
|  |            */ | ||||||
|  |           function open(node) { | ||||||
|  |             /** @param {Attr} attr */ | ||||||
|  |             function attributeString(attr) { | ||||||
|  |               return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"'; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // @ts-ignore | ||||||
|  |             result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('') | ||||||
|  |                 + '>'; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           /** | ||||||
|  |            * @param {Node} node | ||||||
|  |            */ | ||||||
|  |           function close(node) { | ||||||
|  |             result += '</' + tag(node) + '>'; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           /** | ||||||
|  |            * @param {Event} event | ||||||
|  |            */ | ||||||
|  |           function render(event) { | ||||||
|  |             (event.event === 'start' ? open : close)(event.node); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           while (original.length || highlighted.length) { | ||||||
|  |             let stream = selectStream(); | ||||||
|  |             result += escapeHTML(value.substring(processed, stream[0].offset)); | ||||||
|  |             processed = stream[0].offset; | ||||||
|  |             if (stream === original) { | ||||||
|  |               /* | ||||||
|  |               On any opening or closing tag of the original markup we first close | ||||||
|  |               the entire highlighted node stack, then render the original tag along | ||||||
|  |               with all the following original tags at the same offset and then | ||||||
|  |               reopen all the tags on the highlighted stack. | ||||||
|  |               */ | ||||||
|  |               nodeStack.reverse().forEach(close); | ||||||
|  |               do { | ||||||
|  |                 render(stream.splice(0, 1)[0]); | ||||||
|  |                 stream = selectStream(); | ||||||
|  |               } while (stream === original && stream.length && stream[0].offset === processed); | ||||||
|  |               nodeStack.reverse().forEach(open); | ||||||
|  |             } else { | ||||||
|  |               if (stream[0].event === 'start') { | ||||||
|  |                 nodeStack.push(stream[0].node); | ||||||
|  |               } else { | ||||||
|  |                 nodeStack.pop(); | ||||||
|  |               } | ||||||
|  |               render(stream.splice(0, 1)[0]); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           return result + escapeHTML(value.substr(processed)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return mergeHTMLPlugin; | ||||||
|  |  | ||||||
|  |       }()); | ||||||
|  |  | ||||||
|  |       hljs.addPlugin(mergeHTMLPlugin); | ||||||
|  |  | ||||||
|  |       const editorEle = document.getElementById('jsonBlock'); | ||||||
|  |  | ||||||
|  |       // Handle the `paste` event | ||||||
|  |       editorEle.addEventListener('paste', function (e) { | ||||||
|  |         // Prevent the default action | ||||||
|  |         e.preventDefault(); | ||||||
|  |  | ||||||
|  |         // Get the copied text from the clipboard | ||||||
|  |         const text = e.clipboardData | ||||||
|  |             ? (e.originalEvent || e).clipboardData.getData('text/plain') | ||||||
|  |             : // For IE | ||||||
|  |             window.clipboardData | ||||||
|  |                 ? window.clipboardData.getData('Text') | ||||||
|  |                 : ''; | ||||||
|  |  | ||||||
|  |         if (document.queryCommandSupported('insertText')) { | ||||||
|  |           document.execCommand('insertText', false, text); | ||||||
|  |         } else { | ||||||
|  |           // Insert text at the current position of caret | ||||||
|  |           const range = document.getSelection().getRangeAt(0); | ||||||
|  |           range.deleteContents(); | ||||||
|  |  | ||||||
|  |           const textNode = document.createTextNode(text); | ||||||
|  |           range.insertNode(textNode); | ||||||
|  |           range.selectNodeContents(textNode); | ||||||
|  |           range.collapse(false); | ||||||
|  |  | ||||||
|  |           const selection = window.getSelection(); | ||||||
|  |           selection.removeAllRanges(); | ||||||
|  |           selection.addRange(range); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     </script> | ||||||
|  |   </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -1,79 +1,79 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
|  |  | ||||||
| <head> |     <head> | ||||||
|     <!-- <link rel="stylesheet" href="styles.css"> --> |         <!-- <link rel="stylesheet" href="styles.css"> --> | ||||||
|     <link rel="stylesheet" href="../assets/css/tools/r11form.css"> |         <link rel="stylesheet" href="../assets/css/tools/r11form.css"> | ||||||
|     <script src="../assets/scripts/tools/scripts.js"></script> |         <script src="../assets/scripts/tools/scripts.js"></script> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |         <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <meta charset="utf-8" /> |         <meta charset="utf-8" /> | ||||||
| </head> |     </head> | ||||||
|  |  | ||||||
| <body onload="init();"> |     <body onload="init();"> | ||||||
|     <div class="container"> |         <div class="container"> | ||||||
|         <div id="tool" class="tool rwd-expandable"> |             <div id="tool" class="tool rwd-expandable"> | ||||||
|             <div class="tool-context"> |                 <div class="tool-context"> | ||||||
|                 <div class="headline"> |                     <div class="headline"> | ||||||
|                     <h1>Online XML Formatter</h1> |                         <h1>Online XML Formatter</h1> | ||||||
|                 </div> |  | ||||||
|                 <select name="processors" id="processors" class="hidden"> |  | ||||||
|                     <option value="libxml">libXML</option> |  | ||||||
|                 </select> |  | ||||||
|  |  | ||||||
|                 <div class="display-space-between"> |  | ||||||
|                     <div> |  | ||||||
|                         <b><span id="formatinfo"></span></b><br> |  | ||||||
|                         <label for="xmlArea"><b>Insert your XML:</b></label> |  | ||||||
|                     </div> |                     </div> | ||||||
|                     <div> |                     <select name="processors" id="processors" class="hidden"> | ||||||
|                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" |                         <option value="libxml">libXML</option> | ||||||
|                             onclick="clearDataField()">Clear</button> |                     </select> | ||||||
|                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" |  | ||||||
|                             onclick="fillDefaultXML(this)">Insert default XML</button> |                     <div class="display-space-between"> | ||||||
|  |                         <div> | ||||||
|  |                             <b><span id="formatinfo"></span></b><br> | ||||||
|  |                             <label for="xmlArea"><b>Insert your XML:</b></label> | ||||||
|  |                         </div> | ||||||
|  |                         <div> | ||||||
|  |                             <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" | ||||||
|  |                                 onclick="clearDataField()">Clear</button> | ||||||
|  |                             <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" | ||||||
|  |                                 onclick="fillDefaultXML(this)">Insert default XML</button> | ||||||
|  |                         </div> | ||||||
|  |  | ||||||
|                     </div> |                     </div> | ||||||
|  |  | ||||||
|  |                     <textarea id="xmlArea" name="xmlArea" rows="15" | ||||||
|  |                         class="textarea-700 bordered-field vertically-resizeable max-width" | ||||||
|  |                         onblur="setDefaultContent(this, 'Insert XML here');" | ||||||
|  |                         onfocus="clearDefaultContent(this, 'Insert XML here');"></textarea> | ||||||
|  |                     <br><br> | ||||||
|  |                     <button id="prettifyButton" class="max-width block-label action-button active" | ||||||
|  |                         onclick="performFormatRequest('prettify', true, 'xmlArea', 'xmlArea')">Prettify XML</button> | ||||||
|  |                     <button id="minimizeButton" class="max-width block-label action-button active" | ||||||
|  |                         onclick="performFormatRequest('minimize', true, 'xmlArea', 'xmlArea')">Minimize XML</button> | ||||||
|  |  | ||||||
|                 </div> |                 </div> | ||||||
|                  |  | ||||||
|                 <textarea id="xmlArea" name="xmlArea" rows="15" |  | ||||||
|                     class="textarea-700 bordered-field vertically-resizeable max-width" |  | ||||||
|                     onblur="setDefaultContent(this, 'Insert XML here');" |  | ||||||
|                     onfocus="clearDefaultContent(this, 'Insert XML here');"></textarea> |  | ||||||
|                 <br><br> |  | ||||||
|                 <button id="prettifyButton" class="max-width block-label action-button active" |  | ||||||
|                     onclick="performFormatRequest('prettifypost', true, 'xmlArea', 'xmlArea')">Prettify XML</button> |  | ||||||
|                 <button id="minimizeButton" class="max-width block-label action-button active" |  | ||||||
|                     onclick="performFormatRequest('minimizepost', true, 'xmlArea', 'xmlArea')">Minimize XML</button> |  | ||||||
|                  |  | ||||||
|             </div> |             </div> | ||||||
|         </div> |             <div class="tooltip-window rwd-hideable"> | ||||||
|         <div class="tooltip-window rwd-hideable"> |                 <h2>What is this?</h2> | ||||||
|             <h2>What is this?</h2> |                 <p>This tool has 2 main functions: | ||||||
|             <p>This tool has 2 main functions:  |                     <ul> | ||||||
|                 <ul> |                         <li><strong>Prettify XML</strong> to make it human-readable (add indentation etc.)</li> | ||||||
|                     <li><strong>Prettify XML</strong> to make it human-readable (add indentation etc.)</li> |                         <li><strong>Minimize XML</strong> to make it more compact (exactly opposite to above)</li> | ||||||
|                     <li><strong>Minimize XML</strong> to make it more compact (exactly opposite to above)</li> |                     </ul> | ||||||
|                 </ul> |                 </p> | ||||||
|             </p> |             </div> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  |         <script> | ||||||
|  |             function getProcessor() { | ||||||
|  |                 return "libxml"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             function getVersion() { | ||||||
|  |                 return "1.0" | ||||||
|  |             } | ||||||
|  |  | ||||||
|     </div> |             function init() { | ||||||
|  |                 setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here'); | ||||||
|  |             } | ||||||
|  |         </script> | ||||||
|  |  | ||||||
|     <script> |     </body> | ||||||
|         function getProcessor() { |  | ||||||
|             return "libxml"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         function getVersion() { |  | ||||||
|             return "1.0" |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         function init() { |  | ||||||
|             setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here'); |  | ||||||
|         } |  | ||||||
|     </script> |  | ||||||
|  |  | ||||||
| </body> |  | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ | |||||||
|                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="clearDataField()">Clear</button> |                             onclick="clearDataField()">Clear</button> | ||||||
|                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="performFormatRequest('prettifypost', true, 'xmlArea', 'xmlArea')">Format XML</button> |                             onclick="performFormatRequest('prettify', true, 'xmlArea', 'xmlArea')">Format XML</button> | ||||||
|                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="fillDefaultXML(this)">Insert default XML</button> |                             onclick="fillDefaultXML(this)">Insert default XML</button> | ||||||
|                     </div> |                     </div> | ||||||
| @@ -59,7 +59,7 @@ | |||||||
|                     onfocus="clearDefaultContent(this,  'Insert XPath expression here');"></textarea> |                     onfocus="clearDefaultContent(this,  'Insert XPath expression here');"></textarea> | ||||||
|                 <br> |                 <br> | ||||||
|                 <button id="requestButton" class="max-width block-label action-button active" |                 <button id="requestButton" class="max-width block-label action-button active" | ||||||
|                     onclick="performRequest('xpathpost', false, true)">Execute XPath |                     onclick="performRequest('xpath', false, true)">Execute XPath | ||||||
|                     expression</button> |                     expression</button> | ||||||
|                 <br><br> |                 <br><br> | ||||||
|                 <label for="resultArea"><b>Transform result:<span id="procinfo"></span></b></label> |                 <label for="resultArea"><b>Transform result:<span id="procinfo"></span></b></label> | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
|                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="clearDataField()">Clear</button> |                             onclick="clearDataField()">Clear</button> | ||||||
|                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="performFormatRequest('prettifypost', true, 'xmlArea', 'xmlArea')">Format XML</button> |                             onclick="performFormatRequest('prettify', true, 'xmlArea', 'xmlArea')">Format XML</button> | ||||||
|                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="fillDefaultXML(this)">Insert default XML</button> |                             onclick="fillDefaultXML(this)">Insert default XML</button> | ||||||
|                     </div> |                     </div> | ||||||
| @@ -50,7 +50,7 @@ | |||||||
|                     onfocus="clearDefaultContent(this, 'Insert XSD here');"></textarea> |                     onfocus="clearDefaultContent(this, 'Insert XSD here');"></textarea> | ||||||
|                 <br> |                 <br> | ||||||
|                 <button id="requestButton" class="max-width block-label action-button active" |                 <button id="requestButton" class="max-width block-label action-button active" | ||||||
|                     onclick="performRequest('xsdpost', true, true)">Verify XSD</button> |                     onclick="performRequest('xsd', true, true)">Verify XSD</button> | ||||||
|                 <br><br> |                 <br><br> | ||||||
|  |  | ||||||
|                 <label for="resultArea"><b>Result:<span id="procinfo"></span></b></label> |                 <label for="resultArea"><b>Result:<span id="procinfo"></span></b></label> | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ | |||||||
|                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="clearDataField()">Clear</button> |                             onclick="clearDataField()">Clear</button> | ||||||
|                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="prettyXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="performFormatRequest('prettifypost', true, 'xmlArea', 'xmlArea')">Format XML</button> |                             onclick="performFormatRequest('prettify', true, 'xmlArea', 'xmlArea')">Format XML</button> | ||||||
|                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" |                         <button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;" | ||||||
|                             onclick="fillDefaultXML(this)">Insert default XML</button> |                             onclick="fillDefaultXML(this)">Insert default XML</button> | ||||||
|                     </div> |                     </div> | ||||||
| @@ -52,7 +52,7 @@ | |||||||
|                     onfocus="clearDefaultContent(this, 'Insert XSLT here');"></textarea> |                     onfocus="clearDefaultContent(this, 'Insert XSLT here');"></textarea> | ||||||
|                 <br> |                 <br> | ||||||
|                 <button id="requestButton" class="max-width block-label action-button active" |                 <button id="requestButton" class="max-width block-label action-button active" | ||||||
|                     onclick="performRequest('xsltpost', true, true)">Execute XSLT transform</button> |                     onclick="performRequest('xslt', true, true)">Execute XSLT transform</button> | ||||||
|                 <br><br> |                 <br><br> | ||||||
|  |  | ||||||
|                 <label for="resultArea"><b>Transform result:<span id="procinfo"></span></b></label> |                 <label for="resultArea"><b>Transform result:<span id="procinfo"></span></b></label> | ||||||
|   | |||||||
| @@ -423,7 +423,89 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "/xpathpost": { |     "/json/formatting": { | ||||||
|  |       "post": { | ||||||
|  |         "tags": [ | ||||||
|  |           "JSON" | ||||||
|  |         ], | ||||||
|  |         "summary": "Json validation and formatting.", | ||||||
|  |         "description": "", | ||||||
|  |         "operationId": "json", | ||||||
|  |         "consumes": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "in": "body", | ||||||
|  |             "name": "request", | ||||||
|  |             "description": "A transform that is to be performed", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "example": "{'a': 'b', 'c': 'd'}" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "Formatted JSON", | ||||||
|  |             "schema": { | ||||||
|  |               "type": "string" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "Error message from json formatting.", | ||||||
|  |             "schema": { | ||||||
|  |               "type": "string" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/json/minimize": { | ||||||
|  |       "post": { | ||||||
|  |         "tags": [ | ||||||
|  |           "JSON" | ||||||
|  |         ], | ||||||
|  |         "summary": "Json validation and minimize formatting.", | ||||||
|  |         "description": "", | ||||||
|  |         "operationId": "json", | ||||||
|  |         "consumes": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "in": "body", | ||||||
|  |             "name": "request", | ||||||
|  |             "description": "A transform that is to be performed", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "example": "{'a': 'b', 'c': 'd'}" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "Formatted JSON", | ||||||
|  |             "schema": { | ||||||
|  |               "type": "string" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "Error message from json formatting.", | ||||||
|  |             "schema": { | ||||||
|  |               "type": "string" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/xpath": { | ||||||
|       "post": { |       "post": { | ||||||
|         "tags": [ |         "tags": [ | ||||||
|           "XPath" |           "XPath" | ||||||
| @@ -470,7 +552,7 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "/xsltpost": { |     "/xslt": { | ||||||
|       "post": { |       "post": { | ||||||
|         "tags": [ |         "tags": [ | ||||||
|           "XSLT" |           "XSLT" | ||||||
| @@ -517,7 +599,7 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "/xsdpost": { |     "/xsd": { | ||||||
|       "post": { |       "post": { | ||||||
|         "tags": [ |         "tags": [ | ||||||
|           "XSD" |           "XSD" | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ services: | |||||||
|         - 8086:80 |         - 8086:80 | ||||||
|  |  | ||||||
|     xmltools-backend: |     xmltools-backend: | ||||||
|         build: ./Backend/xslt-rest |         build: ./Backend/tools-services | ||||||
|         container_name: xmltools-backend |         container_name: xmltools-backend | ||||||
|         image: xmltools-backend |         image: xmltools-backend | ||||||
|         ports: |         ports: | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ Service is split into three microservices. | |||||||
| Main page is hosted on port 8086. | Main page is hosted on port 8086. | ||||||
|  |  | ||||||
| ## API Documentation | ## API Documentation | ||||||
| API documentation is available on port 8080/swagger/ | API documentation is available on port 8000/swagger/ | ||||||
|  |  | ||||||
| ## JavaSpark backend | ## JavaSpark backend | ||||||
| Backend is hosted by default on port 8081. Rest api documentation is contained in OpenApi document | Backend is hosted by default on port 8081. Rest api documentation is contained in OpenApi document | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user