diff --git a/Backend/tools-services/pom.xml b/Backend/tools-services/pom.xml index af5a89e..029aca1 100644 --- a/Backend/tools-services/pom.xml +++ b/Backend/tools-services/pom.xml @@ -84,8 +84,14 @@ xalan xalan - 2.7.2 + 2.7.3 + + xerces + xercesImpl + 2.12.2 + + diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java index b6c24bb..ad87cf2 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java @@ -68,7 +68,7 @@ public class MultipleXMLController implements RestController { private XMLResponseBody processData(MultipleXmlJob xmlJob) throws Exception { XmlEngine engine = xmlJob.getEngine(); XMLMultipleFilesBody requestBody = xmlJob.getRequestBody(); - String result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData()); + String result = engine.processXSLT(requestBody.getParams(), requestBody.getData(), requestBody.getProcessorData()); return new XMLResponseBody(result, "OK", requestBody.getVersion()); } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java index 7759a62..d4c59d4 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java @@ -1,17 +1,26 @@ package com.r11.tools.controller; import com.google.gson.Gson; -import com.r11.tools.controller.internal.*; +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.controller.internal.XmlJob; +import com.r11.tools.controller.internal.XmlJobType; import com.r11.tools.model.XMLRequestBody; import com.r11.tools.model.XMLResponseBody; import com.r11.tools.model.XPathQueryResult; +import com.r11.tools.model.XmlTools; import com.r11.tools.xml.XmlEngine; import org.apache.logging.log4j.Logger; import spark.Request; import spark.Response; +import java.util.Objects; + /** * Controller used to handle XML tools: XPath, XSD validation, XQuery and XSLT + * * @author Adam Bem */ @GlobalControllerManifest @@ -22,12 +31,15 @@ public class XmlController implements RestController { private final XmlEngine saxon; private final XmlEngine xalan; + private final XmlTools tools; public XmlController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) { this.gson = gson; this.logger = logger; this.saxon = saxon; this.xalan = xalan; + this.tools = new XmlTools(); + } @ScopedControllerManifest(method = HandlerType.POST, path = "/xpath") @@ -48,6 +60,7 @@ public class XmlController implements RestController { @ScopedControllerManifest(method = HandlerType.POST, path = "/xslt") public void acceptRequestXslt(Request request, Response response) { + System.out.println("received xslt"); acceptRequest(request, response, XmlJobType.XSLT); } @@ -91,7 +104,6 @@ public class XmlController implements RestController { responseBody.setDuration(duration); xmlJob.getResponse().status(200); - this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " + xmlJob.getEngine().getVersion() + ") processed in " + duration + " ms."); @@ -130,7 +142,7 @@ public class XmlController implements RestController { String result = null; switch (xmlJob.getXmlJobType()) { case XSLT: - result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData()); + result = engine.processXSLT(requestBody.getParams(),requestBody.getData(), requestBody.getProcessorData()); break; case XSD: result = engine.validate(requestBody.getData(), requestBody.getProcessorData()).trim(); @@ -141,9 +153,10 @@ public class XmlController implements RestController { requestBody.getVersion()); break; } - return new XMLResponseBody(result, "OK", requestBody.getVersion()); + return new XMLResponseBody(result, "OK", requestBody.getProcessorData()); } + private XMLResponseBody processingErrorResponse(Exception ex, XmlJob xmlJob) { XmlEngine engine = xmlJob.getEngine(); XmlJobType xmlJobType = xmlJob.getXmlJobType(); diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java index 3537d2c..2fef936 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java @@ -7,7 +7,7 @@ import spark.Response; public class XmlJob { private final Response response; private final XMLRequestBody requestBody; - private final XmlEngine engine; + private XmlEngine engine; private final XmlJobType xmlJobType; public XmlJob(Response response, XMLRequestBody requestBody, XmlEngine engine, XmlJobType xmlJobType) { @@ -16,7 +16,11 @@ public class XmlJob { this.engine = engine; this.xmlJobType = xmlJobType; } - + public XmlJob(Response response, XMLRequestBody requestBody, XmlJobType xmlJobType) { + this.response = response; + this.requestBody = requestBody; + this.xmlJobType = xmlJobType; + } public Response getResponse() { return response; } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java index 0967e42..8bd1a06 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java @@ -1,7 +1,7 @@ package com.r11.tools.controller.internal; public enum XmlJobType { - XPath("XPath"), XSD("XSD"), XQuery("XQuery"), XSLT("XSLT"); + XPath("XPath"), XSD("XSD"), XQuery("XQuery"), XSLT("XSLT"), XSLT_PARAM("XSLT_PARAM"); XmlJobType(String type) { } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/Param.java b/Backend/tools-services/src/main/java/com/r11/tools/model/Param.java new file mode 100644 index 0000000..f60308d --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/Param.java @@ -0,0 +1,20 @@ +package com.r11.tools.model; + +import com.google.gson.annotations.SerializedName; + + +public class Param { + @SerializedName("key") + private String key; + @SerializedName("value") + private String value; + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } +} + diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java index 67291a4..9223c83 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java @@ -2,6 +2,8 @@ package com.r11.tools.model; import com.google.gson.annotations.SerializedName; +import java.util.List; + public class XMLMultipleFilesBody { @SerializedName("data") @@ -12,6 +14,8 @@ public class XMLMultipleFilesBody { private String processor; @SerializedName("version") private String version; + @SerializedName("params") + private List params; public String getProcessorData() { @@ -29,4 +33,9 @@ public class XMLMultipleFilesBody { public XMLMultipleFilesData[] getData() { return data; } + + public List getParams() { + return params; + } + } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java index e7b06aa..13914a3 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java @@ -2,6 +2,8 @@ package com.r11.tools.model; import com.google.gson.annotations.SerializedName; +import java.util.List; + /** * POJO class used to contain body of XML related requests * @author Adam Bem @@ -15,20 +17,22 @@ public class XMLRequestBody { private String processor; @SerializedName("version") private String version; + @SerializedName("params") + private List params; public String getData() { return data; } - - public String getProcessorData() { - return processorData; - } - + public String getProcessorData() {return processorData;} public String getProcessor() { return processor; } - public String getVersion() { return version; } + public List getParams() { + return params; + } + + } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java index 81f8d73..cb0ea36 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java @@ -10,6 +10,10 @@ public class XMLResponseBody { // Optional private String type; + public XMLResponseBody(String status){ + this.status = status; + } + public XMLResponseBody(String result, String status, String processor) { this.result = result; this.status = status; diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XmlTools.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XmlTools.java new file mode 100644 index 0000000..c307730 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XmlTools.java @@ -0,0 +1,64 @@ +package com.r11.tools.model; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class XmlTools { + private final Map createdParameters = new HashMap<>(); + private void createNewNode(String paramName, String paramValue, Document doc) { + String parameter = "xsl:param"; + Element param = doc.createElement(parameter); + String nameAttribute = "name"; + param.setAttribute(nameAttribute, paramName); + String valueAttribute = "select"; + param.setAttribute(valueAttribute, "'" + paramValue + "'"); + doc.getDocumentElement().appendChild(param); + } + public String addParams(List params,String processorData) { + params.forEach(param -> + createdParameters.put(param.getKey(), param.getValue()) + ); + try { + return docToString(addNode(processorData)); + + } catch (ParserConfigurationException | SAXException | IOException | TransformerException e) { + throw new RuntimeException(e); + }finally { + createdParameters.clear(); + } + } + private Document addNode(String processorData) throws ParserConfigurationException, SAXException, IOException { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputStream stream = new ByteArrayInputStream(processorData.getBytes(StandardCharsets.UTF_8)); + Document doc = builder.parse(stream); + createdParameters.forEach((paramName, paramValue) -> createNewNode(paramName, paramValue, doc)); + return doc; + } + private String docToString(Document doc) throws TransformerException { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + return outputStream.toString(); + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java index f610a9e..677a44b 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java @@ -1,7 +1,10 @@ package com.r11.tools.xml; +import com.r11.tools.model.Param; import com.r11.tools.model.XMLMultipleFilesData; +import com.r11.tools.model.XMLRequestBody; import com.r11.tools.model.XPathQueryResult; +import com.r11.tools.model.XmlTools; import net.sf.saxon.s9api.*; import javax.xml.transform.stream.StreamSource; @@ -10,6 +13,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Comparator; +import java.util.List; import java.util.UUID; /** @@ -26,10 +30,13 @@ public class Saxon implements XmlEngine{ * @throws SaxonApiException thrown on stylesheet or transformation error * @throws IOException thrown when file does not exist, or cannot be read. */ - public String processXSLT(XMLMultipleFilesData[] data, String transform) throws SaxonApiException, IOException{ + XmlTools tools = new XmlTools(); + public String processXSLT(List params, XMLMultipleFilesData[] data, String transform) throws SaxonApiException, IOException{ Processor processor = new Processor(false); XsltCompiler compiler = processor.newXsltCompiler(); + transform = tools.addParams(params,transform); + String filesPath = "/tmp/"+UUID.randomUUID()+"/"; try{ createXMLFilesFromData(data, filesPath); @@ -78,14 +85,18 @@ public class Saxon implements XmlEngine{ /** * Transforms string containing xml document via xslt - * @param data xml to be transformed + * + * @param params + * @param data xml to be transformed * @param transform xslt * @return transformed xml * @throws SaxonApiException thrown on stylesheet or transformation errors */ - public String processXSLT(String data, String transform) throws SaxonApiException { + public String processXSLT(List params, String data, String transform) throws SaxonApiException { Processor processor = new Processor(false); XsltCompiler compiler = processor.newXsltCompiler(); + transform = tools.addParams(params,transform); + System.out.println(transform); XsltExecutable stylesheet = compiler.compile(new StreamSource(new StringReader(transform))); StringWriter sw = new StringWriter(); Serializer out = processor.newSerializer(sw); diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java index 5c64093..2b4d64c 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java @@ -1,7 +1,10 @@ package com.r11.tools.xml; +import com.r11.tools.model.Param; import com.r11.tools.model.XMLMultipleFilesData; +import com.r11.tools.model.XMLRequestBody; import com.r11.tools.model.XPathQueryResult; +import com.r11.tools.model.XmlTools; import org.apache.xpath.XPathAPI; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -22,6 +25,7 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.StringReader; import java.io.StringWriter; +import java.util.List; /** * Handler for Xalan engine @@ -31,16 +35,20 @@ public class Xalan implements XmlEngine{ /** * Transforms string containing xml document via xslt - * @param data xml to be transformed + * + * @param params + * @param data xml to be transformed * @param transform xslt * @return transformed xml * @throws Exception thrown on stylesheet or transformation errors */ - public String processXSLT(String data, String transform) throws Exception { + public String processXSLT(List params, String data, String transform) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new InputSource(new StringReader(data))); + XmlTools tools = new XmlTools(); + transform = tools.addParams(params,transform); StreamSource stylesource = new StreamSource(new StringReader(transform)); Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); @@ -62,7 +70,7 @@ public class Xalan implements XmlEngine{ } @Override - public String processXSLT(XMLMultipleFilesData[] data, String transform) throws Exception { + public String processXSLT(List params, XMLMultipleFilesData[] data, String transform) throws Exception { throw new UnsupportedOperationException("Xalan does not support multiple files XSLT processing"); } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java index 7e7b8db..e422509 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java @@ -1,17 +1,17 @@ package com.r11.tools.xml; +import com.r11.tools.model.Param; import com.r11.tools.model.XMLMultipleFilesData; import com.r11.tools.model.XPathQueryResult; +import java.util.List; + public interface XmlEngine { - String processXSLT(XMLMultipleFilesData[] data, String transform) throws Exception; + String processXSLT(List params, XMLMultipleFilesData[] data, String transform) throws Exception; XPathQueryResult processXPath(String data, String query, String version) throws Exception; - String processXSLT(String data, String transform) throws Exception; + String processXSLT(List params, String data, String transform) throws Exception; String validate(String data, String xsd) throws Exception; - String executeXQuery(String data, String xquery, String version) throws Exception; - public String getVersion(); - } diff --git a/Frontend/src/components/XsltParamComponent.vue b/Frontend/src/components/XsltParamComponent.vue new file mode 100644 index 0000000..42761b9 --- /dev/null +++ b/Frontend/src/components/XsltParamComponent.vue @@ -0,0 +1,72 @@ + + + + diff --git a/Frontend/src/components/xml/XmlInputFieldComponent.vue b/Frontend/src/components/xml/XmlInputFieldComponent.vue index 51e9264..d1f01a0 100644 --- a/Frontend/src/components/xml/XmlInputFieldComponent.vue +++ b/Frontend/src/components/xml/XmlInputFieldComponent.vue @@ -2,69 +2,95 @@ import InsertTemplateComponent from '@components/common/InsertTemplateComponent.vue' import XMLButtonFormatterComponent from '@components/formatter/XMLButtonFormatterComponent.vue' import CodeEditor from '@/components/common/CodeEditorComponent.vue' +import XsltParamComponent from '@/components/XsltParamComponent.vue' -import { ref } from 'vue' +import {ref} from 'vue' -const props = defineProps( - { - stylizedName: {type: String, required: true}, - data: {type: String}, - } -) -const emit = defineEmits(['update:modelValue']) +const props = defineProps<{ + stylizedName: string; + data?: string; + params?: { name: string }[]; +}>(); + +const emit = defineEmits(['update:modelValue','update:params']) const data = ref('') const inputFile = ref() +const params = ref<{ name: string }[]>([]); function sendValue() { - emit('update:modelValue', data.value) + emit('update:modelValue', data.value) } +function updateParams(newParams: { name: string }[]) { + emit('update:params', newParams); +} + + function updateData(newData: string, clearFileSelector: boolean = true) { - data.value = newData - if (clearFileSelector) - inputFile.value.value = ''; - sendValue() + data.value = newData + if (clearFileSelector) + inputFile.value.value = ''; + sendValue() } function clear() { - updateData('') + updateData('') } function canBeFormatted() { - return props.stylizedName.toLowerCase() == 'xml' || - props.stylizedName.toLowerCase() == 'xsd' || - props.stylizedName.toLowerCase() == 'xslt' + return props.stylizedName.toLowerCase() == 'xml' || + props.stylizedName.toLowerCase() == 'xsd' || + props.stylizedName.toLowerCase() == 'xslt' } -function readFile(file : any) { - - const reader = new FileReader() - reader.onloadend = () => { - let result = reader.result?.toString() - if (typeof result == "string") - updateData(result, false); - - } - reader.readAsText(file.target.files[0]) +function addParameters() { + return props.stylizedName?.toLowerCase() == "xslt" } +function readFile(file: any) { + + const reader = new FileReader() + reader.onloadend = () => { + let result = reader.result?.toString() + if (typeof result == "string") + updateData(result, false) + + } + reader.readAsText(file.target.files[0]) +} + +const handleUpdateValue = (options: { name: string }[]) => { + console.log("from parent" +options.length) + params.value = options + updateParams(params.value) +}; + \ No newline at end of file diff --git a/Frontend/src/components/xml/XmlOutputFieldComponent.vue b/Frontend/src/components/xml/XmlOutputFieldComponent.vue index 2e0adc8..403bfb6 100644 --- a/Frontend/src/components/xml/XmlOutputFieldComponent.vue +++ b/Frontend/src/components/xml/XmlOutputFieldComponent.vue @@ -1,21 +1,22 @@