Compare commits
368 Commits
0.0.1
...
f66a5fcf84
| Author | SHA1 | Date | |
|---|---|---|---|
| f66a5fcf84 | |||
| 3cc014310e | |||
| edab2fa900 | |||
| 5bc89fc514 | |||
| fa620baa9c | |||
| f3f88ad659 | |||
| 79959c5ff9 | |||
| 469b5a584f | |||
| ea83e95a00 | |||
| 307e732608 | |||
| aad0d068d3 | |||
| ebb6730a1b | |||
| 26a183133c | |||
| 2f6c2c216a | |||
| 50c44fc9a8 | |||
| 1a8df78222 | |||
| 44bc6b8b97 | |||
| db7a8e9c2a | |||
| 6f93b03449 | |||
| b5fdf0fc9f | |||
| 19e73f0c5d | |||
| 01a21a58b2 | |||
| 2360c19f4a | |||
| 46f662b5c3 | |||
| e5704e7e3e | |||
| f97b9ac62e | |||
| 776dc69d87 | |||
| dc44d5120b | |||
| 099cdeae5e | |||
| 687a90431c | |||
| 9de234da91 | |||
| 47b10a4238 | |||
| 6b68f4a513 | |||
| ad6aaa8d77 | |||
| fb4aba3d29 | |||
| 83916db267 | |||
| de0b447344 | |||
| 6f2d16c2b9 | |||
| e91ee99f99 | |||
| 5ac6fb65fb | |||
| a6fa615bc4 | |||
| d72f91d810 | |||
| 064cd9cc87 | |||
| 859809810d | |||
| 82c3420414 | |||
| e0fe2482c6 | |||
| 00e64ee83d | |||
| fd5996c572 | |||
| ca9b07fabc | |||
| d90fd9d38e | |||
| 02fbb78e51 | |||
| 2e2f571c93 | |||
| 6831a510fb | |||
| a5b59adacb | |||
| e79cb7d873 | |||
| fc7ce1883e | |||
| c2d9deb322 | |||
| 1a8672734d | |||
| af140c30a4 | |||
| c45d1ee83d | |||
| 00786bf157 | |||
| 252cadea16 | |||
| 5febb10d22 | |||
| 1913c292d2 | |||
| 430b6de5f0 | |||
| 6adc1af638 | |||
| 33508b7383 | |||
| a78f3bd52b | |||
| 6319d7c427 | |||
| 242f0fc025 | |||
| 99ea6367e8 | |||
| e5844a913f | |||
| dcf3d3c43c | |||
| b81c96f2a3 | |||
| 9731625ecc | |||
| 242b9026f1 | |||
| cbfb8971ed | |||
| 653caa8675 | |||
| 2cc4370516 | |||
| c57ab9a06a | |||
| d6287469b6 | |||
| 4da8cb705f | |||
| b4190f35df | |||
| 1af0feb325 | |||
| 7fdcbf7a28 | |||
| b4d9b73f78 | |||
| ba55773c47 | |||
| 69fc33fdf9 | |||
| 377f0041c5 | |||
| 88cafa9f56 | |||
| dc8ed79230 | |||
| 7066f13193 | |||
| c589c3713e | |||
| 233f41237e | |||
| 1229abc0b9 | |||
| 1088d27fea | |||
| 26cb947d9f | |||
| 201db42fc5 | |||
| e0955f2729 | |||
| adfd104416 | |||
| e8d6183c0d | |||
| 6a3c9f9410 | |||
| 56ed20f1f7 | |||
| 59e50e4797 | |||
| 02e39cb4d0 | |||
| 5dcbf12afe | |||
| bd8e96047d | |||
| ddc7b72871 | |||
| 395ca6817d | |||
| cab5602f78 | |||
| f16639b45e | |||
| 3c79bddde3 | |||
| 3ec139c8bd | |||
| 6132a2873a | |||
| e4549c7baf | |||
| 0c9b1f70e6 | |||
| 7d0cb03bf5 | |||
| 3c5798cfa2 | |||
| 86b3572003 | |||
| a8e902e910 | |||
| 89517a6821 | |||
| 57a08c3246 | |||
| 5a331d9815 | |||
| e9221e2393 | |||
| 7318708bd2 | |||
| 66b20f8256 | |||
| b6e6277074 | |||
| fb128070dc | |||
| d0c19e19df | |||
| c41c3f5abc | |||
| 9b18a9f42d | |||
| a8d93fc2a5 | |||
| 6058169818 | |||
| d336f5d18e | |||
| 45fab20cc4 | |||
| b733e1e344 | |||
| 97042faaa3 | |||
| 8815f657e0 | |||
| ecafb17f05 | |||
| f9b426bb30 | |||
| 02c10b8354 | |||
| 5b69fd1de0 | |||
| 2aaf993f7a | |||
| d5e33381a2 | |||
| d231a7476b | |||
| 369256baf2 | |||
| e697a783ae | |||
| 1930cde695 | |||
| bcbfd34feb | |||
| 2d97e39dbe | |||
| c89623c3a8 | |||
| dc3df79fc1 | |||
| 34038a2ce9 | |||
| d8504ee8f8 | |||
| 6a1c6aac46 | |||
| 72d69f2967 | |||
| 7fd6fd3788 | |||
| 41d3b90fd8 | |||
| c55942c24a | |||
| 21f5911b1c | |||
| 71bbe668f6 | |||
| 4a04ac3b70 | |||
| b26840ffba | |||
| 1199e06bef | |||
| 1b7f6e6f70 | |||
| fe6585d509 | |||
| 093c8756b1 | |||
| 2b8a9c3008 | |||
| 1f10a1d5b5 | |||
| 8a852b7a83 | |||
| 38c1215889 | |||
| 1fc1ab76ec | |||
| 2f0541fe3d | |||
| 5c39b7cfe0 | |||
| db055ef58b | |||
| 420bfaccd9 | |||
| 3d41447581 | |||
| a773022f0d | |||
| afcd52815f | |||
| 59ffeb9363 | |||
| b72157377d | |||
| 0946982ab6 | |||
| 8098aeacd9 | |||
| de94eca0ac | |||
| a7edf934f7 | |||
| 7c0d79612a | |||
| 02f1977ff0 | |||
| 1816302ba1 | |||
| 64ae2d044d | |||
| 00f3606da6 | |||
| f77a6f15c2 | |||
| 0e9a87bfe7 | |||
| 994804b640 | |||
| 9265c0a051 | |||
| 71f9ae9553 | |||
| 19de505ca4 | |||
| 13d51c05d8 | |||
| 0bd80b1878 | |||
| bd565ffd7d | |||
| 60922ea3c7 | |||
| 02ac7e09d3 | |||
| 353d95e377 | |||
| 09409dc698 | |||
| 8f6047bb9f | |||
| 715facf35b | |||
| 5ef85cb484 | |||
| 6874e463fa | |||
| 0844525f8e | |||
| 04fc103016 | |||
| 599bcf96b2 | |||
| 6d104948cc | |||
| 9135a9221f | |||
| c440b08bdf | |||
| a3d781f477 | |||
| dcad69d43c | |||
| 02f46169d9 | |||
| fd95d7e845 | |||
| c5190f7b62 | |||
| b0b930926c | |||
| a90cbb938f | |||
| eb8518afab | |||
| dee92f0e3d | |||
| 773e2ac17e | |||
| ff7e7461e9 | |||
| 50a8082f32 | |||
| 28e76b2374 | |||
| d6c2c863eb | |||
| 4d7c0d6acd | |||
| 24c9c2fe5a | |||
| f96f8270ce | |||
| 3c927f91cf | |||
| d4c4d38aef | |||
| 7042959ee3 | |||
| 15830d7adf | |||
| c7d34ed05f | |||
| 1e56b2885a | |||
| 9bc3370f3b | |||
| 5db10ab1c1 | |||
| d9a413f88d | |||
| c2095f4bcf | |||
| fde28a5880 | |||
| 75c31a7c58 | |||
| a95c745ae2 | |||
| 8083d7fa63 | |||
| ac908e49e6 | |||
| 05857a7d7e | |||
| 28a9a1f670 | |||
| 169ba0d2d1 | |||
| d3c02e164f | |||
| 9b212ccb17 | |||
| f295fcc693 | |||
| 8524ecd6ca | |||
| d1d54c82f9 | |||
| eed5454755 | |||
| 89d70b32d2 | |||
| 5032985787 | |||
| ec5cc7cc0c | |||
| bd5c615017 | |||
| 84203c825c | |||
| d7926a64e2 | |||
| 65a730105d | |||
| 56a9906c58 | |||
| 8f3d1a13de | |||
| 91dc131fba | |||
| d4791a1959 | |||
| 8381a3e4de | |||
| e37ce3c678 | |||
| cc7664519e | |||
| 935b1d01ea | |||
| 947e5d621e | |||
| f5c8910277 | |||
| b9e2e527fd | |||
| 153a7313ef | |||
| 4955a7cc4f | |||
| 78cc13a661 | |||
| e2cf490f9d | |||
| 8c132d12d3 | |||
| df8b7cd007 | |||
| 19c47d3cd2 | |||
| cb48f3017a | |||
| db02993bde | |||
| 3f5aa29a3b | |||
| d6bacc6b4f | |||
| 8254f9387f | |||
| 9aa6593608 | |||
| c76b677f0e | |||
| 829bdeca81 | |||
| 8e18fd9964 | |||
| 134696f73c | |||
| bb18cb53c6 | |||
| 4b3fac59c0 | |||
| 86e46ad205 | |||
| 1f4d4056c7 | |||
| 1760b89e05 | |||
| 3c3f2ef8ad | |||
| 9ef61086df | |||
| a2b4f28c26 | |||
| 2907d40a2e | |||
| 1d648890cc | |||
| 65ad318a5c | |||
| ce02db8f6d | |||
| b487c5f0bc | |||
| e994881ff0 | |||
| e6e3a704bc | |||
| 84aef5d830 | |||
| d35103422b | |||
| 9a6e8c543e | |||
| 81cc70b5e7 | |||
| 6a0e49546c | |||
| c14cfe8a52 | |||
| 6e53f2f1bf | |||
| fa1a03f6e3 | |||
| c537bed4a1 | |||
| 45e46de8f5 | |||
| 58ef4dcdc4 | |||
| f8d5934998 | |||
| 4b241978e0 | |||
| 45a7e60ae4 | |||
| 5a2164b839 | |||
| d2e5586792 | |||
| 96f80e4589 | |||
| 07f2adcc1f | |||
| 0c5a83d3b6 | |||
| 9384011377 | |||
| c0a54291ae | |||
| e408840f6d | |||
| 7dbf3add28 | |||
| 06458cfd10 | |||
| f68217f83a | |||
| 07ab4f83a1 | |||
| b5018dfece | |||
| 7b05343e69 | |||
| 9bd74d036c | |||
| 9ce0e6fcd3 | |||
| 9409638b5c | |||
| dd695a1c2d | |||
| 74f1f6f1c2 | |||
| c0f117a4af | |||
| e0f7c48801 | |||
| e50a9dd95a | |||
| 9dad3e6d37 | |||
| 10d23e456c | |||
| 656aeb17dc | |||
| ce417f8b94 | |||
| 598f074654 | |||
| 3817b1ac5a | |||
| a914282a5d | |||
| 0b0f0b55d0 | |||
| 228f94569b | |||
| 6683ef688e | |||
| e8352dfe3d | |||
| e714c34726 | |||
| 17299a9a94 | |||
| 8bac9db2a9 | |||
| fadd8f468b | |||
| c48d139e6b | |||
| 9a1c690e46 | |||
| 7657691019 | |||
| fb673b100b | |||
| d328d4718f | |||
| 64acb901ff | |||
| 8f4e42c533 | |||
| 5655e46112 | |||
| 37cfacd1e5 | |||
| d05a8a5ce2 | |||
| cf47fb09fe | |||
| 916f4321ea | |||
| 9d7a62c37c |
2
.gitignore
vendored
@@ -7,3 +7,5 @@
|
||||
.vscode
|
||||
nbactions.xml
|
||||
target/
|
||||
__pycache__
|
||||
venv
|
||||
|
||||
3
Backend-libXML/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
__pycache**
|
||||
venv
|
||||
8
Backend-libXML/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM tiangolo/meinheld-gunicorn-flask:python3.9
|
||||
|
||||
COPY ./requirements.txt /app/requirements.txt
|
||||
|
||||
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
|
||||
|
||||
COPY ./main.py /app/
|
||||
COPY ./Parser.py /app/
|
||||
126
Backend-libXML/Parser.py
Normal file
@@ -0,0 +1,126 @@
|
||||
from lxml import etree, html
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
def convertHTML(source: str, sourceFrom: str):
|
||||
htmlParser = html.HTMLParser(remove_comments=True, remove_blank_text=True)
|
||||
xmlParser = etree.XMLParser(remove_comments=True, remove_blank_text=True)
|
||||
|
||||
if sourceFrom == "xml":
|
||||
xmldoc = etree.parse(BytesIO(source.encode("utf-8")), xmlParser)
|
||||
return html.tostring(xmldoc, method="html", pretty_print=True, doctype="<!DOCTYPE html>").decode()
|
||||
elif sourceFrom == "html":
|
||||
htmldoc = html.parse(BytesIO(source.encode("utf-8")), htmlParser)
|
||||
return etree.tostring(htmldoc, method="xml", pretty_print=True, doctype="", xml_declaration=True, encoding="utf-8").decode()
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
def formatHTML(source: str, prettify: bool) -> str:
|
||||
parser = html.HTMLParser(remove_blank_text=True, remove_comments=True, remove_pis=True)
|
||||
htmlDoc = html.parse(BytesIO(source.encode("utf-8")),parser=parser)
|
||||
if not prettify:
|
||||
return html.tostring(htmlDoc).decode().replace("\n", "").replace("> ", ">")
|
||||
return etree.tostring(htmlDoc, encoding='unicode', pretty_print=True)
|
||||
|
||||
def formatXML(source: str, prettify: bool) -> str:
|
||||
"""Method used to format XML
|
||||
|
||||
:param source: XML to format
|
||||
:param prettify: sets if XML must be prettified
|
||||
(added indentations etc.) or not
|
||||
:return: formatted XML
|
||||
"""
|
||||
|
||||
# Prolog is removed when XML is parsed
|
||||
# so program has to copy it
|
||||
prolog = ""
|
||||
prolog_start = source.find("<?")
|
||||
|
||||
if prolog_start != -1:
|
||||
prolog_end = source.find("?>") + 2
|
||||
prolog = source[prolog_start:prolog_end]
|
||||
source = source[prolog_end: ]
|
||||
|
||||
byte_input = BytesIO(source.encode("utf-8"))
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
xml = etree.parse(byte_input, parser=parser)
|
||||
|
||||
if prettify:
|
||||
prolog += "\n"
|
||||
|
||||
return prolog + etree.tostring(xml, pretty_print=prettify).decode()
|
||||
|
||||
|
||||
def xpath(source: str, xpath: str) -> str:
|
||||
"""
|
||||
Method used to get nodes from XML string using XPath
|
||||
|
||||
:param source: XML string used for selection
|
||||
:param xpath: XPath query used for selection
|
||||
:return: Nodes selected using XPath
|
||||
"""
|
||||
|
||||
byte_input = BytesIO(source.encode("utf-8"))
|
||||
root = etree.parse(byte_input).getroot()
|
||||
nsmap = root.nsmap
|
||||
|
||||
# LXML doesn't accept empty (None) namespace prefix,
|
||||
# so it need to be deleted if exists
|
||||
if None in nsmap:
|
||||
nsmap.pop(None)
|
||||
|
||||
result = root.xpath(xpath, namespaces=nsmap)
|
||||
|
||||
# root.xpath can return 4 types: float, string, bool and list.
|
||||
# List is the only one that can't be simply converted to str
|
||||
if type(result) is not list:
|
||||
return str(result), type(result).__name__
|
||||
else:
|
||||
result_string = ""
|
||||
for e in result:
|
||||
if isinstance(e, etree._Element):
|
||||
result_string += etree.tostring(e, pretty_print=True).decode() + "\n"
|
||||
else:
|
||||
result_string += str(e) + "\n"
|
||||
return result_string, "node"
|
||||
|
||||
|
||||
def xsd(source: str, xsd: str) -> bool:
|
||||
"""
|
||||
Method used to validate XML string against XSD schema
|
||||
:param source: XML string used for validation
|
||||
:param xsd: XSD schema to validate XML against
|
||||
:return: Message saying, if the validation was successful or not
|
||||
"""
|
||||
|
||||
schema_input = BytesIO(xsd.encode("utf-8"))
|
||||
xml_schema = etree.XMLSchema(etree.parse(schema_input).getroot())
|
||||
|
||||
document_input = BytesIO(source.encode("utf-8"))
|
||||
xml = etree.parse(document_input).getroot()
|
||||
|
||||
try:
|
||||
xml_schema.assertValid(xml)
|
||||
return "XML is valid"
|
||||
except etree.DocumentInvalid as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
|
||||
def xslt(source: str, xslt: str) -> str:
|
||||
"""
|
||||
Method used to transform XML string using XSLT
|
||||
|
||||
:param source: XML string to transform
|
||||
:param xslt: XSLT string used to transform XML
|
||||
:return: Result of transformation
|
||||
"""
|
||||
xslt_input = BytesIO(xslt.encode("utf-8"))
|
||||
xslt_transform = etree.XSLT(etree.parse(xslt_input))
|
||||
|
||||
document_input = BytesIO(source.encode("utf-8"))
|
||||
xml = etree.parse(document_input).getroot()
|
||||
|
||||
transformed = str(xslt_transform(xml))
|
||||
return formatXML(transformed, True)
|
||||
101
Backend-libXML/main.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from flask import Flask
|
||||
from flask_cors import CORS
|
||||
from flask import request
|
||||
from lxml import etree
|
||||
import json
|
||||
import time
|
||||
import Parser
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
# cors = CORS(app, resource={
|
||||
# r"/*":{
|
||||
# "origins":"*"
|
||||
# }
|
||||
# })
|
||||
|
||||
def process_xml(request: request, type: str) -> str:
|
||||
"""Function to process
|
||||
|
||||
:param request: Received request
|
||||
:param type: Type of needed processing: xsd, xslt or xpath
|
||||
:raises ValueError: is raised when type is different than those provided above
|
||||
:return: response JSON converted to string and response code
|
||||
"""
|
||||
start = time.time_ns()
|
||||
code = 200
|
||||
response_json = dict()
|
||||
try:
|
||||
request_data = json.loads(request.get_data(as_text=True))
|
||||
data = request_data['data']
|
||||
processorData = request_data['processorData']
|
||||
if (type == "xsd"):
|
||||
response_json['result'] = Parser.xsd(data, processorData)
|
||||
elif (type == "xslt"):
|
||||
response_json['result'] = Parser.xslt(data, processorData)
|
||||
elif (type == "xpath"):
|
||||
response_json['result'], response_json['type'] = Parser.xpath(data, processorData)
|
||||
elif (type == "prettify"):
|
||||
response_json['result'] = Parser.formatXML(data, True)
|
||||
elif (type == "minimize"):
|
||||
response_json['result'] = Parser.formatXML(data, False)
|
||||
elif (type == "prettifyHtml"):
|
||||
response_json['result'] = Parser.formatHTML(data, True)
|
||||
elif (type == "minimizeHtml"):
|
||||
response_json['result'] = Parser.formatHTML(data, False)
|
||||
elif (type == "convertHTML"):
|
||||
response_json['result'] = Parser.convertHTML(data, processorData)
|
||||
else:
|
||||
raise ValueError("Valid operation types are: xsd, xslt, xpath")
|
||||
|
||||
response_json['status'] = "OK"
|
||||
except KeyError as e:
|
||||
response_json['result'] = "Missing key: " + str(e)
|
||||
response_json['status'] = "ERR"
|
||||
code = 400
|
||||
except Exception as e:
|
||||
response_json['result'] = str(e)
|
||||
response_json['status'] = "ERR"
|
||||
code = 400
|
||||
finally:
|
||||
exec_time = (time.time_ns() - start) / 10**6
|
||||
response_json['duration'] = f"{exec_time:.03f}"
|
||||
response_json['processor'] = "libxml2 over lxml"
|
||||
return json.dumps(response_json), code
|
||||
|
||||
|
||||
@app.route("/xpath", methods=["POST"])
|
||||
def xpath():
|
||||
return process_xml(request, "xpath")
|
||||
|
||||
@app.route("/xsd", methods=["POST"])
|
||||
def xsd():
|
||||
return process_xml(request, "xsd")
|
||||
|
||||
@app.route("/xslt", methods=["POST"])
|
||||
def xslt():
|
||||
return process_xml(request, "xslt")
|
||||
|
||||
@app.route("/prettify", methods=["POST"])
|
||||
def prettify():
|
||||
return process_xml(request, "prettify")
|
||||
|
||||
@app.route("/minimize", methods=["POST"])
|
||||
def minimize():
|
||||
return process_xml(request, "minimize")
|
||||
|
||||
@app.route("/html/prettify",methods=["POST"])
|
||||
def prettifyHtml():
|
||||
return process_xml(request, "prettifyHtml")
|
||||
|
||||
@app.route("/html/minimize",methods=["POST"])
|
||||
def minimizeHtml():
|
||||
return process_xml(request, "minimizeHtml")
|
||||
|
||||
@app.route("/html/convert",methods=["POST"])
|
||||
def XMLToHTMLConvertion():
|
||||
return process_xml(request, "convertHTML")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
3
Backend-libXML/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
lxml==4.9.2
|
||||
flask==2.3.2
|
||||
flask_cors==3.0.10
|
||||
19
Backend/mocked-services/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
FROM maven:3.6.3-jdk-14 as builder
|
||||
WORKDIR application
|
||||
COPY ./ ./
|
||||
RUN mvn clean install
|
||||
|
||||
FROM openjdk:14 as layerBuilder
|
||||
WORKDIR application
|
||||
ARG JAR_FILE=application/target/*.jar
|
||||
COPY --from=builder ${JAR_FILE} application.jar
|
||||
RUN java -Djarmode=layertools -jar application.jar extract
|
||||
|
||||
FROM openjdk:14
|
||||
WORKDIR application
|
||||
COPY --from=layerBuilder application/dependencies/ ./
|
||||
COPY --from=layerBuilder application/spring-boot-loader/ ./
|
||||
COPY --from=layerBuilder application/snapshot-dependencies/ ./
|
||||
COPY --from=layerBuilder application/application/ ./
|
||||
|
||||
ENTRYPOINT ["java", "-Djava.security.cgd=file:/dev/./urandom", "-Dspring.profiles.active=DEV", "org.springframework.boot.loader.JarLauncher"]
|
||||
48
Backend/mocked-services/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# R11-MockedServices
|
||||
Mockup service for middleware testing.
|
||||
|
||||
Available scripts:
|
||||
|
||||
### Running the application on a local machine
|
||||
For Intellij:
|
||||
Plugins:
|
||||
settings -> plugins -> install lombok plugin
|
||||
settings -> annotation processors -> enable annotation processing
|
||||
|
||||
A connection to a Redis database is expected to run the application successfully. You need to download and run Redis DB on
|
||||
your local machine with default values localhost 6379.
|
||||
|
||||
You can also run the application via Docker.
|
||||
#### docker-compose up --build -d
|
||||
|
||||
However, you need either to run it with Docker-compose ensuring that all containers are within a network or start application locally.
|
||||
In order to change environment two properties must be changed.
|
||||
|
||||
1) data-access.properties - property redis.host
|
||||
2) logback.xml - configuration/appender/host element value
|
||||
|
||||
If application is to be run locally, both of above should be set to "localhost"
|
||||
If application is to be run in docker environment, both should be set to name of a redis container (by default "redis")
|
||||
|
||||
Docker automaticly translates container name to IP address, considering all containers are within same network.
|
||||
Try to avoid using any symbols in names of containers, because it may cause that URL exception to be thrown. Instead use letters only.
|
||||
|
||||
### Operations on Redis DB
|
||||
|
||||
Use Redis CLI or attach to Redis docker image in order to manually operate on DB.
|
||||
|
||||
#### docker exec -it mockedservices_redis-server redis-cli
|
||||
Attach to redis server image and open a redis client.
|
||||
|
||||
Useful redis-cli commands:
|
||||
###### KEYS *
|
||||
Show all keys in the db.
|
||||
###### TYPE key
|
||||
Show key type.
|
||||
###### LRANGE key start stop
|
||||
Display elements from the list.
|
||||
###### LLEN key
|
||||
Display list length.
|
||||
###### SMEMBERS key
|
||||
Display elements from hashSet.
|
||||
Logs can be found in lists with names logstash_yyyy-mm-dd.
|
||||
20
Backend/mocked-services/docker-compose.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
version: '3'
|
||||
services:
|
||||
redis:
|
||||
image: 'redis'
|
||||
restart: "no"
|
||||
klaus:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: klaus
|
||||
restart: "no"
|
||||
ports:
|
||||
- "8097:8097"
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: DEV
|
||||
networks:
|
||||
default:
|
||||
name: shared_network_mocked_services
|
||||
105
Backend/mocked-services/pom.xml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.11</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<artifactId>mocked-services</artifactId>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
<jedis.version>3.3.0</jedis.version>
|
||||
<logback-redis-appender.version>1.1.6</logback-redis-appender.version>
|
||||
<assertj.version>3.16.1</assertj.version>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<docker.image.prefix>Release11</docker.image.prefix>
|
||||
<docker.image.name>${project.artifactId}</docker.image.name>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<layers>
|
||||
<enabled>true</enabled>
|
||||
<includeLayerTools>true</includeLayerTools>
|
||||
</layers>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
|
||||
</compilerArgs>
|
||||
<source>13</source>
|
||||
<target>13</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.r11.tools;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* It's generic Spring context starter. Move along...
|
||||
*
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class KlausApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(KlausApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.repository.MockedResponseRepository;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Based on configuration deletes all outdated messages and history records from database.
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
public class RetentionConfiguration {
|
||||
|
||||
private final MockedResponseRepository responseRepository;
|
||||
private final RequestHistoryRepository historyRepository;
|
||||
private final RetentionConfigurationProperties retentionProperties;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
|
||||
public RetentionConfiguration(MockedResponseRepository responseRepository,
|
||||
RequestHistoryRepository historyRepository,
|
||||
RetentionConfigurationProperties retentionProperties){
|
||||
this.historyRepository = historyRepository;
|
||||
this.responseRepository = responseRepository;
|
||||
this.retentionProperties = retentionProperties;
|
||||
}
|
||||
@Scheduled(fixedDelayString = "#{${retention.retention-cooldown} * 60000 }")
|
||||
@Async
|
||||
public void deleteMessagesAndHistoryRecords(){
|
||||
log.info("OUTDATED MESSAGES AND HISTORY RECORDS DELETED!");
|
||||
responseRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining( mockedMessage -> {
|
||||
if (mockedMessage.getCreatedAt().plusMinutes(retentionProperties.getMinutesToDeleteMessage()).isBefore(LocalDateTime.now())){
|
||||
responseRepository.delete(mockedMessage);
|
||||
}
|
||||
} );
|
||||
|
||||
historyRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining(
|
||||
historyRecord -> {
|
||||
if (historyRecord.getDateTimeStamp().plusMinutes(retentionProperties.getMinutesToDeleteHistoryRecord()).isBefore(LocalDateTime.now())){
|
||||
historyRepository.delete(historyRecord);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.validation.constraints.Positive;
|
||||
|
||||
/**
|
||||
* Store all properties needed to change a retention in {@link RetentionConfiguration}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "retention")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RetentionConfigurationProperties {
|
||||
@Positive
|
||||
private Integer minutesToDeleteMessage;
|
||||
@Positive
|
||||
private Integer minutesToDeleteHistoryRecord;
|
||||
@Positive
|
||||
private Integer retentionCooldown;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.interceptor.IncomingMockRequestInterceptor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Configuration for {@link IncomingMockRequestInterceptor}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class WebConfig implements WebMvcConfigurer{
|
||||
|
||||
private final IncomingMockRequestInterceptor requestInterceptor;
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor( requestInterceptor )
|
||||
.addPathPatterns("/api/mock/r/**");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import com.r11.tools.service.KlausService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Returns the homepage and provides the api for javascript async requests.
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/mock")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MockController {
|
||||
private final KlausService klausService;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public void errorHandler(Exception ex){
|
||||
log.error(Arrays.toString(ex.getStackTrace()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates queried message with given set of data
|
||||
* @param message {@link MockedMessageDto} json representation
|
||||
* @return confirmation and 200 OK
|
||||
*/
|
||||
@SneakyThrows
|
||||
@PutMapping
|
||||
public ResponseEntity<String> updateMessage(@RequestBody MockedMessageDto message){
|
||||
return klausService.setMockedResponse(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full list of messages. It's used by javascript on the client side to initialize homepage
|
||||
* with data from the database.
|
||||
* @param uuidValue the key-uuid of given set of messages
|
||||
* @return responds with 200 OK and {@link MockedMessageDto}
|
||||
*/
|
||||
@GetMapping({"/", "/{uuidValue}"})
|
||||
public MockedMessageDto getMessage(@PathVariable(required = false) String uuidValue){
|
||||
UUID clientUUID;
|
||||
MockedMessageDto message ;
|
||||
if(uuidValue == null || uuidValue.equals("")) clientUUID = UUID.randomUUID();
|
||||
else clientUUID = UUID.fromString(uuidValue);
|
||||
message = klausService.getMockedResponse(clientUUID.toString());
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's one of the most important features - the bread and butter of the Mocked Service. It's link that allows
|
||||
* to receive mocked response from the server and use it to mock!
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/r/{clientUUID}")
|
||||
public ResponseEntity getMockedResponse(
|
||||
@PathVariable String clientUUID) {
|
||||
MockedMessageDto mockedMessageDto = klausService.getMockedResponse(clientUUID);
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
if (mockedMessageDto.getHttpHeaders() != null) mockedMessageDto.getHttpHeaders().forEach(httpHeaders::set);
|
||||
httpHeaders.add("Content-Type", mockedMessageDto.getContentType());
|
||||
return new ResponseEntity<>(mockedMessageDto.getMessageBody(), httpHeaders,
|
||||
Objects.requireNonNull(HttpStatus.valueOf(mockedMessageDto.getHttpStatus())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Custom exception handler for {@link ConstraintViolationException}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@ControllerAdvice
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MvcExceptionHandler {
|
||||
|
||||
/**
|
||||
* Provides handling for {@link ConstraintViolationException}
|
||||
* @param e exception argument
|
||||
* @return response with error list and status 400 bad request
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public ResponseEntity<List> validationErrorHandler(ConstraintViolationException e){
|
||||
List<String> errors = new ArrayList<>(e.getConstraintViolations().size());
|
||||
|
||||
e.getConstraintViolations().forEach(constraintViolation -> {
|
||||
errors.add(constraintViolation.getPropertyPath() + " : " + constraintViolation.getMessage());
|
||||
});
|
||||
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides handling for {@link BindException}
|
||||
* @param ex exception argument
|
||||
* @return response with error list and status 400 bad request
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
public ResponseEntity<List> handleBindException(BindException ex){
|
||||
return new ResponseEntity(ex.getAllErrors(), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* It's the REST api for {@link RequestHistory}
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/event")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class RequestHistoryController {
|
||||
private final RequestHistoryService service;
|
||||
private final RequestHistoryMapper mapper;
|
||||
|
||||
/**
|
||||
* Returns the list of Events.
|
||||
* @param uuid unique id of message list
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
@GetMapping(path = "/{uuid}")
|
||||
public ResponseEntity<List<RequestHistoryDTO>> getLastDay(@PathVariable String uuid){
|
||||
List<RequestHistoryDTO> requestHistory = service.getHistoryRecordsByUUID(
|
||||
uuid
|
||||
).stream()
|
||||
.map(mapper::requestHistoryToRequestHistoryDTO)
|
||||
.collect(Collectors.toList());
|
||||
return ResponseEntity.ok(requestHistory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.r11.tools.interceptor;
|
||||
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* Interceptor that gets needed data from HttpRequest, and saves it to history
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class IncomingMockRequestInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final RequestHistoryService historyService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse response, Object handler){
|
||||
Map<String,String> headers = getHeadersFromHttpRequest(httpRequest);
|
||||
Map<String,String> pathVariable = getPathVariablesFromHttpRequest(httpRequest);
|
||||
String requestBody = getRequestBodyFromHttpRequest(httpRequest);
|
||||
|
||||
RequestHistoryDTO historyDTO = RequestHistoryDTO.builder()
|
||||
.httpMethod(HttpMethod.valueOf(httpRequest.getMethod()))
|
||||
.headers( headers )
|
||||
.clientUUID(UUID.fromString(pathVariable.get("clientUUID")))
|
||||
.dateTimeStamp(LocalDateTime.now())
|
||||
.requestBody(requestBody)
|
||||
.build();
|
||||
historyService.saveRequest(historyDTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String,String> getHeadersFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
Set<String> headersName = StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(
|
||||
httpRequest.getHeaderNames().asIterator(),
|
||||
Spliterator.ORDERED
|
||||
), false
|
||||
).collect(Collectors.toSet());
|
||||
|
||||
return headersName.stream()
|
||||
.collect(Collectors.toMap(
|
||||
value -> value,
|
||||
httpRequest::getHeader
|
||||
));
|
||||
}
|
||||
|
||||
private Map<String,String> getPathVariablesFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
return (Map<String, String>) httpRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private String getRequestBodyFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest);
|
||||
try {
|
||||
return StreamUtils.copyToString(wrappedRequest.getInputStream(), Charset.defaultCharset());
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.r11.tools.mappers;
|
||||
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import org.mapstruct.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Creates key value for redis entry
|
||||
* @author Rafał Źukowicz
|
||||
*/
|
||||
@Mapper
|
||||
public interface MockedMessageMapper {
|
||||
@Mapping( target = "createdAt" , expression = "java(java.time.LocalDateTime.now())")
|
||||
MockedMessage mockedMessageDtoToMockedMessage(MockedMessageDto mockedMessageDto);
|
||||
MockedMessageDto mockedMessageToMockedMessageDto(MockedMessage mockedMessage);
|
||||
|
||||
default Optional<MockedMessageDto> optionalMockedMessageToOptionalMockedMessageDTO(Optional<MockedMessage> optionalMockedMessage){
|
||||
return optionalMockedMessage.map(this::mockedMessageToMockedMessageDto);
|
||||
}
|
||||
|
||||
default Optional<MockedMessage> optionalMockedMessageDTOToOptionalMockedMessage(Optional<MockedMessageDto> optionalMockedMessageDto){
|
||||
return optionalMockedMessageDto.map(this::mockedMessageDtoToMockedMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.mappers;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* Map between DTO and Entity
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface RequestHistoryMapper {
|
||||
|
||||
@Mapping(target = "clientUUID", expression = "java(requestHistoryDTO.getClientUUID().toString())")
|
||||
RequestHistory requestHistoryDTOToRequestHistory(RequestHistoryDTO requestHistoryDTO);
|
||||
@Mapping(target = "clientUUID", expression = "java(java.util.UUID.fromString(requestHistory.getClientUUID()))")
|
||||
RequestHistoryDTO requestHistoryToRequestHistoryDTO(RequestHistory requestHistory);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.r11.tools.model.constraints.HttpCode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* MockedMessage redis entity pojo
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@RedisHash("mockedMessage")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MockedMessage implements Serializable {
|
||||
@Indexed
|
||||
@Id
|
||||
private String clientUUID;
|
||||
private String contentType;
|
||||
private String messageBody;
|
||||
private Map<String, String> httpHeaders;
|
||||
@HttpCode
|
||||
private Integer httpStatus;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.r11.tools.model.constraints.HttpCode;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Alternative version of {@link MockedMessage} used in http body
|
||||
* @author Rafał Żukowicz
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MockedMessageDto implements Serializable{
|
||||
private String clientUUID;
|
||||
private String contentType;
|
||||
private String messageBody;
|
||||
private Map<String, String> httpHeaders;
|
||||
@HttpCode
|
||||
private Integer httpStatus;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Pojo class for Event entity
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RedisHash("mockHistory")
|
||||
public class RequestHistory implements Comparable<RequestHistory>, Serializable {
|
||||
@Id
|
||||
private String id;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss")
|
||||
private LocalDateTime dateTimeStamp;
|
||||
@Indexed
|
||||
private String clientUUID;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
@Override
|
||||
public int compareTo(RequestHistory o) {
|
||||
return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Pojo for history query request. Contains information necessary to obtain {@link RequestHistory} list
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RequestHistoryDTO {
|
||||
|
||||
private UUID clientUUID;
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
|
||||
private LocalDateTime dateTimeStamp;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.model.constraints;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
|
||||
/**
|
||||
* Annotation interface that is used to annotate Integer fields that contain http status values.
|
||||
* It provides validation and throws an error when trying to send response with incorrect status.
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Target({ ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = HttpCodeValidation.class )
|
||||
public @interface HttpCode {
|
||||
String message() default "must be a valid http code";
|
||||
|
||||
Class<?>[] groups() default { };
|
||||
Class<? extends Payload>[] payload() default { };
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.r11.tools.model.constraints;
|
||||
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* It's validator class. It checks if status value of {@link MockedMessageDto} is within bonds of http status values map.
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
public class HttpCodeValidation implements ConstraintValidator<HttpCode, Integer> {
|
||||
private Set<Integer> allowedValues;
|
||||
|
||||
/**
|
||||
* Initializes {@link #allowedValues} with possible http status values.
|
||||
* @param targetEnum HttpCode context
|
||||
*/
|
||||
@Override
|
||||
public void initialize(HttpCode targetEnum) {
|
||||
allowedValues = Stream.of(HttpStatus.values())
|
||||
.map(HttpStatus::value)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer value of {@link MockedMessageDto#getHttpStatus()} or {@link MockedMessage#getHttpStatus()}
|
||||
* @param context context for validation
|
||||
* @return true if valid
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid(Integer integer, ConstraintValidatorContext context) {
|
||||
return allowedValues.contains(integer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Spring repository that allows to retrieve message list by key-uuid from redis database
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface MockedResponseRepository extends CrudRepository<MockedMessage, String> {}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* History Record entity dao interface
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface RequestHistoryRepository extends CrudRepository<RequestHistory,String> {
|
||||
List<RequestHistory> findAllByClientUUID(String clientUUID);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Service interface for {@link com.r11.tools.controller.KlausController} and {@link com.r11.tools.controller.MockController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface KlausService {
|
||||
MockedMessageDto getMockedResponse(String clientUUID);
|
||||
ResponseEntity<String> setMockedResponse(MockedMessageDto mockedMessageDto);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.mappers.MockedMessageMapper;
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import com.r11.tools.repository.MockedResponseRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Service for {@link com.r11.tools.controller.MockController} and {@link com.r11.tools.controller.MockController}
|
||||
* Allows for performing CRUD operations on {@link MockedMessageDto}
|
||||
* @author Rafał Żukowicz
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class KlausServiceImpl implements KlausService {
|
||||
private final MockedMessageMapper mockedMessageMapper;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
private final MockedResponseRepository mockedResponseRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@link MockedMessageDto} of given id and key-uuid. If message doesn't then empty message is returned
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @return {@link MockedMessageDto} object
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public MockedMessageDto getMockedResponse(String clientUUID){
|
||||
Optional<MockedMessage> optionalMockedMessage = mockedResponseRepository.findById(clientUUID);
|
||||
MockedMessageDto mockedMessageDto;
|
||||
if (optionalMockedMessage.isPresent()) {
|
||||
mockedMessageDto = mockedMessageMapper.mockedMessageToMockedMessageDto(optionalMockedMessage.get());
|
||||
return mockedMessageDto;
|
||||
} else {
|
||||
MockedMessageDto defaultMessage = buildDefaultMessage(clientUUID);
|
||||
setMockedResponse(defaultMessage);
|
||||
return defaultMessage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs message with default set of data
|
||||
* @param uuid the key-uuid of given set of messages
|
||||
* @return message with default dataset
|
||||
*/
|
||||
|
||||
|
||||
private MockedMessageDto buildDefaultMessage(String uuid){
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Keep-Alive", "timeout=60");
|
||||
headers.put("Connection", "keep-alive");
|
||||
headers.put("Date", LocalDateTime.now().toString());
|
||||
return MockedMessageDto.builder()
|
||||
.clientUUID(uuid)
|
||||
.contentType(MediaType.APPLICATION_XML_VALUE)
|
||||
.messageBody("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<note>\n" +
|
||||
" <to>Tove</to>\n" +
|
||||
" <from>Jani</from>\n" +
|
||||
" <heading>Reminder</heading>\n" +
|
||||
" <body>Don't forget me this weekend!</body>\n" +
|
||||
"</note>")
|
||||
.httpHeaders(headers)
|
||||
.httpStatus(200)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to modify mocked message. If message of given id and key-uuid doesn't exist a new entry is created
|
||||
* @param mockedMessageDto message to be saved
|
||||
* @return Confirmation and status 200 OK
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ResponseEntity<String> setMockedResponse(MockedMessageDto mockedMessageDto) {
|
||||
MockedMessage message = mockedMessageMapper.mockedMessageDtoToMockedMessage(mockedMessageDto);
|
||||
message.setCreatedAt(LocalDateTime.now());
|
||||
log.info("SAVE:"+message.toString().replace("\n"," "));
|
||||
mockedResponseRepository.save(message);
|
||||
return new ResponseEntity<>("MockedResponse has been setup successfully!", new HttpHeaders(),
|
||||
HttpStatus.ACCEPTED);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spring service interface for {@link RequestHistoryController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface RequestHistoryService {
|
||||
/**
|
||||
* Searches for {@link RequestHistory} objects between date brackets
|
||||
* @param uuid user uuid
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
List<RequestHistory> getHistoryRecordsByUUID(String uuid);
|
||||
void saveRequest(RequestHistoryDTO requestDTO);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spring Service for {@link RequestHistoryController}. Contains logic required for quering
|
||||
* the database for {@link RequestHistory} objects
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class RequestHistoryServiceImpl implements RequestHistoryService {
|
||||
|
||||
private final RequestHistoryRepository repository;
|
||||
private final RequestHistoryMapper requestMapper;
|
||||
|
||||
@Override
|
||||
public List<RequestHistory> getHistoryRecordsByUUID(String uuid) {
|
||||
List<RequestHistory> history = repository.findAllByClientUUID(uuid);
|
||||
Collections.sort(history);
|
||||
return history;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest(RequestHistoryDTO requestDTO) {
|
||||
repository.save(requestMapper.requestHistoryDTOToRequestHistory(requestDTO));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#environment:
|
||||
server.port = 8097
|
||||
spring.application.name = klaus
|
||||
spring.mvc.view.suffix=.html
|
||||
logging.level.root=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.com.release11=INFO
|
||||
|
||||
#database:
|
||||
spring.redis.host=redis
|
||||
spring.redis.port=6379
|
||||
|
||||
#retention
|
||||
retention.minutes-to-delete-message=1440
|
||||
retention.minutes-to-delete-history-record=1440
|
||||
retention.retention-cooldown=1440
|
||||
25
Backend/mocked-services/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<property name="HOME_LOG" value="/log/mockServices.log"/>
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${HOME_LOG}</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/mockServices.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<totalSizeCap>20GB</totalSizeCap>
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
||||
|
||||
|
||||
25
Backend/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.r11.tools</groupId>
|
||||
<artifactId>release11-tools</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jackson.version>2.14.1</jackson.version>
|
||||
<slf4j.version>2.0.6</slf4j.version>
|
||||
</properties>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>tools-services</module>
|
||||
<module>mocked-services</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -1,10 +1,10 @@
|
||||
# Using maven image, based on java 8
|
||||
FROM maven:3.6.3-jdk-8 as target
|
||||
WORKDIR /build
|
||||
COPY pom.xml .
|
||||
COPY src/ /build/src/
|
||||
WORKDIR build
|
||||
COPY ./ ./
|
||||
RUN mvn -ntp package
|
||||
|
||||
|
||||
# Go to working directory in docker image
|
||||
# WORKDIR /usr/app/
|
||||
|
||||
128
Backend/tools-services/pom.xml
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.r11.tools</groupId>
|
||||
<artifactId>tools-services</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jackson.version>2.14.1</jackson.version>
|
||||
<slf4j.version>2.0.6</slf4j.version>
|
||||
<log4j.version>2.19.0</log4j.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
<mainClass>com.r11.tools.SparkInitializer</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spark -->
|
||||
<dependency>
|
||||
<groupId>com.sparkjava</groupId>
|
||||
<artifactId>spark-core</artifactId>
|
||||
<version>2.9.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- XSLT -->
|
||||
<dependency>
|
||||
<groupId>net.sf.saxon</groupId>
|
||||
<artifactId>Saxon-HE</artifactId>
|
||||
<version>11.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
<version>2.7.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.r11.tools;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.r11.tools.controller.*;
|
||||
import com.r11.tools.controller.internal.RestControllerRegistry;
|
||||
import com.r11.tools.xml.Saxon;
|
||||
import com.r11.tools.xml.Xalan;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
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);
|
||||
|
||||
Gson gson = new GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
Gson jsongson = new GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
XmlEngine saxon = new Saxon();
|
||||
XmlEngine xalan = new Xalan();
|
||||
|
||||
|
||||
RestControllerRegistry registry = new RestControllerRegistry();
|
||||
registry.registerController(new ProcessorInfoController(logger, saxon, xalan));
|
||||
|
||||
registry.registerController(new XmlController(gson, logger, saxon, xalan));
|
||||
registry.registerController(new MultipleXMLController(gson,logger, saxon));
|
||||
registry.registerController(new JsonController(gson, jsongson, logger));
|
||||
|
||||
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,85 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.google.gson.*;
|
||||
//import com.google.gson.GsonBuilder;
|
||||
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;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@GlobalControllerManifest(path = "/json")
|
||||
public class JsonController implements RestController {
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
private final Gson prettyGson;
|
||||
|
||||
private final Gson gson;
|
||||
|
||||
public JsonController(Gson prettyGson, Gson jsongson,Logger logger) {
|
||||
this.logger = logger;
|
||||
this.prettyGson = prettyGson;
|
||||
this.gson = jsongson;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/formatting")
|
||||
public void formatting(Request request, Response response) {
|
||||
long startProcess = System.currentTimeMillis();
|
||||
JsonObject responseJson = new JsonObject();
|
||||
|
||||
try {
|
||||
Object requestJson = this.gson.fromJson(request.body(), Object.class);
|
||||
|
||||
responseJson.addProperty("result", this.prettyGson.toJson(requestJson));
|
||||
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
this.logger.error("Error on formatting Json " + e);
|
||||
Throwable cause = e.getCause();
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage());
|
||||
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
|
||||
|
||||
|
||||
}
|
||||
this.logger.info("Json processed in " + responseJson.get("time").toString() + " ms.");
|
||||
response.body(this.prettyGson.toJson(responseJson));
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/minimize")
|
||||
public void minimize(Request request, Response response) {
|
||||
long startProcess = System.currentTimeMillis();
|
||||
JsonObject responseJson = new JsonObject();
|
||||
|
||||
try {
|
||||
Object requestJson = this.prettyGson.fromJson(request.body(), Object.class);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", this.gson.toJson(requestJson));
|
||||
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
} catch (Exception e) {
|
||||
this.logger.error("Error on minimizing Json " + e);
|
||||
Throwable cause = e.getCause();
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage());
|
||||
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
|
||||
|
||||
response.body(this.prettyGson.toJson(responseJson));
|
||||
}
|
||||
this.logger.info("Json processed in " + responseJson.get("time").toString() + " ms.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.r11.tools.controller.internal.*;
|
||||
import com.r11.tools.model.XMLMultipleFilesBody;
|
||||
import com.r11.tools.model.XMLResponseBody;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
@GlobalControllerManifest
|
||||
public class MultipleXMLController implements RestController {
|
||||
|
||||
private final Gson gson;
|
||||
private final Logger logger;
|
||||
|
||||
private final XmlEngine engine;
|
||||
|
||||
public MultipleXMLController(Gson gson, Logger logger, XmlEngine engine) {
|
||||
this.gson = gson;
|
||||
this.logger = logger;
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/multiple/xslt")
|
||||
public void acceptRequestXslt(Request request, Response response) {
|
||||
acceptRequest(request, response, XmlJobType.XSLT);
|
||||
}
|
||||
|
||||
private void acceptRequest(Request request, Response response, XmlJobType xmlJobType) {
|
||||
XMLMultipleFilesBody requestBody;
|
||||
try {
|
||||
requestBody = this.gson.fromJson(request.body(), XMLMultipleFilesBody.class);
|
||||
} catch (Exception e) {
|
||||
requestErrorResponse(response, e);
|
||||
return;
|
||||
}
|
||||
processRequest(new MultipleXmlJob(response, requestBody, engine, xmlJobType));
|
||||
}
|
||||
|
||||
private void processRequest(MultipleXmlJob xmlJob) {
|
||||
XMLResponseBody responseBody = null;
|
||||
long timeStart = System.currentTimeMillis();
|
||||
long duration;
|
||||
|
||||
try {
|
||||
responseBody = processData(xmlJob);
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
responseBody.setDuration(duration);
|
||||
|
||||
xmlJob.getResponse().status(200);
|
||||
|
||||
this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " +
|
||||
xmlJob.getEngine().getVersion() +
|
||||
") processed in " + duration + " ms.");
|
||||
|
||||
} catch (Exception ex) {
|
||||
responseBody = processingErrorResponse(ex, xmlJob);
|
||||
|
||||
} finally {
|
||||
xmlJob.getResponse().body(this.gson.toJson(responseBody));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private XMLResponseBody processData(MultipleXmlJob xmlJob) throws Exception {
|
||||
XmlEngine engine = xmlJob.getEngine();
|
||||
XMLMultipleFilesBody requestBody = xmlJob.getRequestBody();
|
||||
String result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData());
|
||||
return new XMLResponseBody(result, "OK", requestBody.getVersion());
|
||||
}
|
||||
|
||||
|
||||
private XMLResponseBody processingErrorResponse(Exception ex, MultipleXmlJob xmlJob) {
|
||||
XmlEngine engine = xmlJob.getEngine();
|
||||
XmlJobType xmlJobType = xmlJob.getXmlJobType();
|
||||
Response response = xmlJob.getResponse();
|
||||
|
||||
XMLResponseBody responseBody =
|
||||
new XMLResponseBody(ex.getMessage(), "ERR", engine.getVersion(), -1);
|
||||
|
||||
response.status(400);
|
||||
this.logger.error("Error on processing " + xmlJobType + " using " + engine.getVersion() + ". " + ex);
|
||||
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
private void requestErrorResponse(Response response, Exception ex) {
|
||||
XMLResponseBody responseBody = new XMLResponseBody(ex.getMessage(), "ERR", "N/A", -1);
|
||||
response.status(400);
|
||||
response.body(this.gson.toJson(responseBody));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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 com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
@GlobalControllerManifest
|
||||
public class ProcessorInfoController implements RestController {
|
||||
|
||||
private final Logger logger;
|
||||
private final XmlEngine saxon;
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public ProcessorInfoController(Logger logger, XmlEngine saxon, XmlEngine xalan) {
|
||||
this.logger = logger;
|
||||
this.saxon = saxon;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,173 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.r11.tools.controller.internal.*;
|
||||
import com.r11.tools.model.XMLRequestBody;
|
||||
import com.r11.tools.model.XMLResponseBody;
|
||||
import com.r11.tools.model.XPathQueryResult;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
/**
|
||||
* Controller used to handle XML tools: XPath, XSD validation, XQuery and XSLT
|
||||
* @author Adam Bem
|
||||
*/
|
||||
@GlobalControllerManifest
|
||||
public class XmlController implements RestController {
|
||||
|
||||
private final Gson gson;
|
||||
private final Logger logger;
|
||||
|
||||
private final XmlEngine saxon;
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public XmlController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) {
|
||||
this.gson = gson;
|
||||
this.logger = logger;
|
||||
this.saxon = saxon;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xpath")
|
||||
public void acceptRequestXPath(Request request, Response response) {
|
||||
acceptRequest(request, response, XmlJobType.XPath);
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xquery")
|
||||
public void acceptRequestXQuery(Request request, Response response) {
|
||||
acceptRequest(request, response, XmlJobType.XQuery);
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xsd")
|
||||
public void acceptRequestXsd(Request request, Response response) {
|
||||
acceptRequest(request, response, XmlJobType.XSD);
|
||||
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xslt")
|
||||
public void acceptRequestXslt(Request request, Response response) {
|
||||
acceptRequest(request, response, XmlJobType.XSLT);
|
||||
}
|
||||
|
||||
private void acceptRequest(Request request, Response response, XmlJobType xmlJobType) {
|
||||
XMLRequestBody requestBody;
|
||||
try {
|
||||
requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class);
|
||||
} catch (Exception e) {
|
||||
requestErrorResponse(response, e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestBody.getProcessor() == null) {
|
||||
invalidEngineSelectedResponse(response);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (requestBody.getProcessor().toLowerCase()) {
|
||||
case "saxon":
|
||||
processRequest(new XmlJob(response, requestBody, saxon, xmlJobType));
|
||||
return;
|
||||
|
||||
case "xalan":
|
||||
processRequest(new XmlJob(response, requestBody, xalan, xmlJobType));
|
||||
return;
|
||||
|
||||
default:
|
||||
invalidEngineSelectedResponse(response);
|
||||
}
|
||||
}
|
||||
|
||||
private void processRequest(XmlJob xmlJob) {
|
||||
XMLResponseBody responseBody = null;
|
||||
long timeStart = System.currentTimeMillis();
|
||||
long duration;
|
||||
|
||||
try {
|
||||
responseBody = processData(xmlJob);
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
responseBody.setDuration(duration);
|
||||
|
||||
xmlJob.getResponse().status(200);
|
||||
|
||||
this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " +
|
||||
xmlJob.getEngine().getVersion() +
|
||||
") processed in " + duration + " ms.");
|
||||
|
||||
} catch (Exception ex) {
|
||||
responseBody = processingErrorResponse(ex, xmlJob);
|
||||
|
||||
} finally {
|
||||
xmlJob.getResponse().body(this.gson.toJson(responseBody));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private XMLResponseBody processData(XmlJob xmlJob) throws Exception {
|
||||
if (xmlJob.getXmlJobType() == XmlJobType.XPath)
|
||||
return processXPath(xmlJob);
|
||||
else
|
||||
return processOther(xmlJob);
|
||||
}
|
||||
|
||||
private XMLResponseBody processXPath(XmlJob xmlJob) throws Exception {
|
||||
XmlEngine engine = xmlJob.getEngine();
|
||||
XMLRequestBody requestBody = xmlJob.getRequestBody();
|
||||
|
||||
XPathQueryResult xPathQueryResult =
|
||||
engine.processXPath(requestBody.getData(), requestBody.getProcessorData(), requestBody.getVersion());
|
||||
|
||||
return new XMLResponseBody(xPathQueryResult.getData().trim(),
|
||||
"OK", engine.getVersion(), xPathQueryResult.getType());
|
||||
}
|
||||
|
||||
private XMLResponseBody processOther(XmlJob xmlJob) throws Exception {
|
||||
XmlEngine engine = xmlJob.getEngine();
|
||||
XMLRequestBody requestBody = xmlJob.getRequestBody();
|
||||
|
||||
String result = null;
|
||||
switch (xmlJob.getXmlJobType()) {
|
||||
case XSLT:
|
||||
result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData());
|
||||
break;
|
||||
case XSD:
|
||||
result = engine.validate(requestBody.getData(), requestBody.getProcessorData()).trim();
|
||||
break;
|
||||
case XQuery:
|
||||
result = engine.executeXQuery(requestBody.getData(),
|
||||
requestBody.getProcessorData(),
|
||||
requestBody.getVersion());
|
||||
break;
|
||||
}
|
||||
return new XMLResponseBody(result, "OK", requestBody.getVersion());
|
||||
}
|
||||
|
||||
private XMLResponseBody processingErrorResponse(Exception ex, XmlJob xmlJob) {
|
||||
XmlEngine engine = xmlJob.getEngine();
|
||||
XmlJobType xmlJobType = xmlJob.getXmlJobType();
|
||||
Response response = xmlJob.getResponse();
|
||||
|
||||
XMLResponseBody responseBody =
|
||||
new XMLResponseBody(ex.getMessage(), "ERR", engine.getVersion(), -1);
|
||||
|
||||
response.status(400);
|
||||
this.logger.error("Error on processing " + xmlJobType + " using " + engine.getVersion() + ". " + ex);
|
||||
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
private void invalidEngineSelectedResponse(Response response) {
|
||||
XMLResponseBody responseBody =
|
||||
new XMLResponseBody("Valid engines are: saxon, xalan", "ERR", "N/A", -1);
|
||||
response.body(this.gson.toJson(responseBody));
|
||||
response.status(400);
|
||||
}
|
||||
|
||||
private void requestErrorResponse(Response response, Exception ex) {
|
||||
XMLResponseBody responseBody = new XMLResponseBody(ex.getMessage(), "ERR", "N/A", -1);
|
||||
response.status(400);
|
||||
response.body(this.gson.toJson(responseBody));
|
||||
}
|
||||
}
|
||||
@@ -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,36 @@
|
||||
package com.r11.tools.controller.internal;
|
||||
|
||||
import com.r11.tools.model.XMLMultipleFilesBody;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import spark.Response;
|
||||
|
||||
public class MultipleXmlJob {
|
||||
|
||||
private final Response response;
|
||||
private final XMLMultipleFilesBody requestBody;
|
||||
private final XmlEngine engine;
|
||||
private final XmlJobType xmlJobType;
|
||||
|
||||
public MultipleXmlJob(Response response, XMLMultipleFilesBody requestBody, XmlEngine engine, XmlJobType xmlJobType) {
|
||||
this.response = response;
|
||||
this.requestBody = requestBody;
|
||||
this.engine = engine;
|
||||
this.xmlJobType = xmlJobType;
|
||||
}
|
||||
|
||||
public Response getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public XMLMultipleFilesBody getRequestBody() {
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
public XmlEngine getEngine() {
|
||||
return engine;
|
||||
}
|
||||
|
||||
public XmlJobType getXmlJobType() {
|
||||
return xmlJobType;
|
||||
}
|
||||
}
|
||||
@@ -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,35 @@
|
||||
package com.r11.tools.controller.internal;
|
||||
|
||||
import com.r11.tools.model.XMLRequestBody;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import spark.Response;
|
||||
|
||||
public class XmlJob {
|
||||
private final Response response;
|
||||
private final XMLRequestBody requestBody;
|
||||
private final XmlEngine engine;
|
||||
private final XmlJobType xmlJobType;
|
||||
|
||||
public XmlJob(Response response, XMLRequestBody requestBody, XmlEngine engine, XmlJobType xmlJobType) {
|
||||
this.response = response;
|
||||
this.requestBody = requestBody;
|
||||
this.engine = engine;
|
||||
this.xmlJobType = xmlJobType;
|
||||
}
|
||||
|
||||
public Response getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public XMLRequestBody getRequestBody() {
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
public XmlEngine getEngine() {
|
||||
return engine;
|
||||
}
|
||||
|
||||
public XmlJobType getXmlJobType() {
|
||||
return xmlJobType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.r11.tools.controller.internal;
|
||||
|
||||
public enum XmlJobType {
|
||||
XPath("XPath"), XSD("XSD"), XQuery("XQuery"), XSLT("XSLT");
|
||||
|
||||
XmlJobType(String type) {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class XMLMultipleFilesBody {
|
||||
|
||||
@SerializedName("data")
|
||||
private XMLMultipleFilesData[] data;
|
||||
@SerializedName("processorData")
|
||||
private String processorData;
|
||||
@SerializedName("processor")
|
||||
private String processor;
|
||||
@SerializedName("version")
|
||||
private String version;
|
||||
|
||||
|
||||
public String getProcessorData() {
|
||||
return processorData;
|
||||
}
|
||||
|
||||
public String getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public XMLMultipleFilesData[] getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class XMLMultipleFilesData {
|
||||
@SerializedName("fileName")
|
||||
private String filename;
|
||||
@SerializedName("fileData")
|
||||
private String data;
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* POJO class used to contain body of XML related requests
|
||||
* @author Adam Bem
|
||||
*/
|
||||
public class XMLRequestBody {
|
||||
@SerializedName("data")
|
||||
private String data;
|
||||
@SerializedName("processorData")
|
||||
private String processorData;
|
||||
@SerializedName("processor")
|
||||
private String processor;
|
||||
@SerializedName("version")
|
||||
private String version;
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getProcessorData() {
|
||||
return processorData;
|
||||
}
|
||||
|
||||
public String getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
public class XMLResponseBody {
|
||||
|
||||
private String result;
|
||||
private String status;
|
||||
private String processor;
|
||||
private long duration;
|
||||
|
||||
// Optional
|
||||
private String type;
|
||||
|
||||
public XMLResponseBody(String result, String status, String processor) {
|
||||
this.result = result;
|
||||
this.status = status;
|
||||
this.processor = processor;
|
||||
}
|
||||
public XMLResponseBody(String result, String status, String processor, long duration) {
|
||||
this.result = result;
|
||||
this.status = status;
|
||||
this.processor = processor;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public XMLResponseBody(String result, String status, String processor, String type) {
|
||||
this.result = result;
|
||||
this.status = status;
|
||||
this.processor = processor;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(String result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public void setProcessor(String processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
/**
|
||||
* Class used to store data received from parser and type of that data (node, string, etc.)
|
||||
*/
|
||||
public class XPathQueryResult {
|
||||
private String data;
|
||||
private String type;
|
||||
|
||||
public XPathQueryResult(String data, String type) {
|
||||
this.data = data;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package r11.mltx.restxslt.processors;
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import net.sf.saxon.om.NamespaceBinding;
|
||||
import net.sf.saxon.om.NamespaceMap;
|
||||
import net.sf.saxon.s9api.XPathCompiler;
|
||||
import net.sf.saxon.s9api.XdmNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Handler for saxon namespace scan engine.
|
||||
@@ -13,6 +12,7 @@ import java.util.Iterator;
|
||||
* @author Wojciech Czop
|
||||
*/
|
||||
public class NewNamespaceResolver {
|
||||
private static final Logger LOG = LogManager.getLogger("NewNamespaceResolver");
|
||||
|
||||
private NamespaceMap namespaceMap;
|
||||
|
||||
@@ -21,12 +21,13 @@ public class NewNamespaceResolver {
|
||||
* @param doc dom structure object
|
||||
* @return map of namespaces
|
||||
*/
|
||||
|
||||
// TODO: Closer inspection. Return value is never used according to IntelliJ
|
||||
//
|
||||
public NamespaceMap process(XdmNode doc) {
|
||||
namespaceMap = NamespaceMap.emptyMap();
|
||||
Iterator<XdmNode> it = doc.children().iterator();
|
||||
// TODO: remove
|
||||
while (it.hasNext()) {
|
||||
XdmNode tmp = it.next();
|
||||
// TODO: remove
|
||||
for (XdmNode tmp : doc.children()) {
|
||||
extractNamespace(tmp);
|
||||
}
|
||||
// end
|
||||
@@ -38,12 +39,6 @@ public class NewNamespaceResolver {
|
||||
* @param compiler compiler used to compile xpath statements
|
||||
*/
|
||||
public void exportNamespaces(XPathCompiler compiler){
|
||||
Iterator<NamespaceBinding> it = namespaceMap.iterator();
|
||||
// TODO: remove
|
||||
while(it.hasNext()){
|
||||
System.out.println(it.next());
|
||||
}
|
||||
// end
|
||||
namespaceMap.forEach(namespaceBinding -> compiler.declareNamespace(namespaceBinding.getPrefix(), namespaceBinding.getURI()));
|
||||
}
|
||||
|
||||
@@ -58,17 +53,11 @@ public class NewNamespaceResolver {
|
||||
}
|
||||
if (node.children().iterator().hasNext()) {
|
||||
|
||||
Iterator<XdmNode> it = node.children().iterator();
|
||||
while (it.hasNext()) {
|
||||
XdmNode rNode = it.next();
|
||||
// TODO: remove
|
||||
if(rNode.getUnderlyingNode().getPrefix().isEmpty() && !rNode.getParent().getUnderlyingNode().getPrefix().isEmpty()){
|
||||
|
||||
System.out.println("prefix missing, parent has "+rNode.getParent().getUnderlyingNode().getPrefix() + ", but child has none");
|
||||
|
||||
System.out.println();
|
||||
for (XdmNode rNode : node.children()) {
|
||||
if (rNode.getUnderlyingNode().getPrefix().isEmpty() && !rNode.getParent().getUnderlyingNode().getPrefix().isEmpty()) {
|
||||
LOG.warn("Missing prefix. Parent has " + rNode.getParent().getUnderlyingNode().getPrefix() + ", but child has none");
|
||||
}
|
||||
// end
|
||||
|
||||
extractNamespace(rNode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import com.r11.tools.model.XMLMultipleFilesData;
|
||||
import com.r11.tools.model.XPathQueryResult;
|
||||
import net.sf.saxon.s9api.*;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Comparator;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Handler for Saxon engine
|
||||
* @author Wojciech Czop
|
||||
*/
|
||||
public class Saxon implements XmlEngine{
|
||||
|
||||
/**
|
||||
* Transforms many XML documents via XSLT.
|
||||
* @param data XML Files to be transformed.
|
||||
* @param transform XSLT
|
||||
* @return transformed xml
|
||||
* @throws SaxonApiException thrown on stylesheet or transformation error
|
||||
* @throws IOException thrown when file does not exist, or cannot be read.
|
||||
*/
|
||||
public String processXSLT(XMLMultipleFilesData[] data, String transform) throws SaxonApiException, IOException{
|
||||
Processor processor = new Processor(false);
|
||||
XsltCompiler compiler = processor.newXsltCompiler();
|
||||
|
||||
String filesPath = "/tmp/"+UUID.randomUUID()+"/";
|
||||
try{
|
||||
createXMLFilesFromData(data, filesPath);
|
||||
Path transformPath = createXSLTFileAndReturnPath(transform,filesPath);
|
||||
XsltExecutable stylesheet = compiler.compile( new StreamSource( transformPath.toFile() ));
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
Serializer out = processor.newSerializer(sw);
|
||||
out.setOutputProperty(Serializer.Property.METHOD, "xml");
|
||||
out.setOutputProperty(Serializer.Property.INDENT, "yes");
|
||||
Xslt30Transformer transformer = stylesheet.load30();
|
||||
transformer.transform( new StreamSource( new File(filesPath+data[0].getFilename()) ) , out );
|
||||
return sw.toString();
|
||||
} finally {
|
||||
deleteTemporaryFiles(filesPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void createXMLFilesFromData( XMLMultipleFilesData[] data , String filesPath ) throws IOException {
|
||||
Files.createDirectories(Paths.get(filesPath));
|
||||
for (XMLMultipleFilesData fileData : data) {
|
||||
Path filePath = Files.createFile( Paths.get(filesPath + fileData.getFilename() ) );
|
||||
try (FileWriter writer = new FileWriter(filePath.toFile())) {
|
||||
writer.write(fileData.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Path createXSLTFileAndReturnPath( String xsltTransform, String filesPath ) throws IOException {
|
||||
Path transformPath = Files.createFile( Paths.get(filesPath + "transform.xsl") );
|
||||
FileWriter writer = new FileWriter(transformPath.toFile());
|
||||
writer.write(xsltTransform);
|
||||
writer.close();
|
||||
|
||||
return transformPath;
|
||||
}
|
||||
|
||||
private void deleteTemporaryFiles(String filesPath) throws IOException {
|
||||
Files
|
||||
.walk( Paths.get(filesPath) )
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms string containing xml document via xslt
|
||||
* @param data xml to be transformed
|
||||
* @param transform xslt
|
||||
* @return transformed xml
|
||||
* @throws SaxonApiException thrown on stylesheet or transformation errors
|
||||
*/
|
||||
public String processXSLT(String data, String transform) throws SaxonApiException {
|
||||
Processor processor = new Processor(false);
|
||||
XsltCompiler compiler = processor.newXsltCompiler();
|
||||
XsltExecutable stylesheet = compiler.compile(new StreamSource(new StringReader(transform)));
|
||||
StringWriter sw = new StringWriter();
|
||||
Serializer out = processor.newSerializer(sw);
|
||||
out.setOutputProperty(Serializer.Property.METHOD, "xml");
|
||||
out.setOutputProperty(Serializer.Property.INDENT, "yes");
|
||||
|
||||
Xslt30Transformer transformer = stylesheet.load30();
|
||||
transformer.transform(new StreamSource(new StringReader(data)), out);
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validate(String data, String xsd) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method evaluates XQuery expression on given xml
|
||||
* @param data xml
|
||||
* @param xquery expression
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public String executeXQuery(String data, String xquery, String version) throws Exception {
|
||||
Processor processor = new Processor(false);
|
||||
|
||||
XQueryCompiler compiler = processor.newXQueryCompiler();
|
||||
compiler.setLanguageVersion(version);
|
||||
|
||||
XQueryExecutable executable = compiler.compile(xquery);
|
||||
|
||||
XQueryEvaluator evaluator = executable.load();
|
||||
evaluator.setSource(new StreamSource(new StringReader(data)));
|
||||
|
||||
XdmValue result = evaluator.evaluate();
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process xpath and return either node or wrapped atomic value
|
||||
* @param data xml to be processed
|
||||
* @param query xpath query
|
||||
* @param version processor version
|
||||
* @return string xml representation of the node
|
||||
* @throws Exception thrown on node building errors or invalid xpath
|
||||
*/
|
||||
public XPathQueryResult processXPath(String data, String query, String version) throws Exception {
|
||||
Processor p = new Processor(false);
|
||||
XPathCompiler compiler = p.newXPathCompiler();
|
||||
DocumentBuilder builder = p.newDocumentBuilder();
|
||||
XdmNode doc = builder.build(new StreamSource(new StringReader(data)));
|
||||
|
||||
compiler.setLanguageVersion(version);
|
||||
|
||||
NewNamespaceResolver resolver = new NewNamespaceResolver();
|
||||
|
||||
resolver.process(doc);
|
||||
|
||||
resolver.exportNamespaces(compiler);
|
||||
|
||||
XdmValue result = compiler.evaluate(query, doc);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (XdmItem xdmItem : result) {
|
||||
sb.append(xdmItem);
|
||||
sb.append('\n');
|
||||
}
|
||||
return new XPathQueryResult(sb.toString(), "N/A");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version of the processor
|
||||
* @return version of the processor
|
||||
*/
|
||||
public String getVersion() {
|
||||
return "Saxon " + new Processor(false).getSaxonProductVersion();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import com.r11.tools.model.XMLMultipleFilesData;
|
||||
import com.r11.tools.model.XPathQueryResult;
|
||||
import org.apache.xpath.XPathAPI;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import javax.xml.validation.Validator;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* Handler for Xalan engine
|
||||
* @author Wojciech Czop
|
||||
*/
|
||||
public class Xalan implements XmlEngine{
|
||||
|
||||
/**
|
||||
* Transforms string containing xml document via xslt
|
||||
* @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 {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document document = builder.parse(new InputSource(new StringReader(data)));
|
||||
|
||||
StreamSource stylesource = new StreamSource(new StringReader(transform));
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
|
||||
Source source = new DOMSource(document);
|
||||
StringWriter sw = new StringWriter();
|
||||
Result outputTarget = new StreamResult(sw);
|
||||
transformer.transform(source, outputTarget);
|
||||
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
private boolean isTextNode(Node n) {
|
||||
if (n == null)
|
||||
return false;
|
||||
short nodeType = n.getNodeType();
|
||||
return nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.TEXT_NODE;
|
||||
}
|
||||
|
||||
private boolean isAttributeNode(Node n) {
|
||||
if (n == null)
|
||||
return false;
|
||||
short nodeType = n.getNodeType();
|
||||
return nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.ATTRIBUTE_NODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processXSLT(XMLMultipleFilesData[] data, String transform) throws Exception {
|
||||
throw new UnsupportedOperationException("Xalan does not support multiple files XSLT processing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Process xpath and return either node or wrapped atomic value
|
||||
* @param data xml
|
||||
* @param transform xpath
|
||||
* @return xml processed using given xpath
|
||||
* @throws Exception thrown on node building errors or invalid xpath
|
||||
*/
|
||||
public XPathQueryResult processXPath(String data, String transform, String version) throws Exception {
|
||||
|
||||
// Set up a DOM tree to query.
|
||||
InputSource in = new InputSource(new StringReader(data));
|
||||
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
|
||||
dfactory.setNamespaceAware(true);
|
||||
Document doc = dfactory.newDocumentBuilder().parse(in);
|
||||
|
||||
// Set up an identity transformer to use as serializer.
|
||||
Transformer serializer = TransformerFactory.newInstance().newTransformer();
|
||||
serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
|
||||
// Use the simple XPath API to select a nodeIterator.
|
||||
try {
|
||||
NodeIterator nl = XPathAPI.selectNodeIterator(doc, transform);
|
||||
|
||||
// Serialize the found nodes to result object.
|
||||
StringBuilder resultString = new StringBuilder();
|
||||
Node n;
|
||||
while ((n = nl.nextNode())!= null) {
|
||||
StringBuilder sb;
|
||||
if (isTextNode(n)) {
|
||||
// DOM may have more than one node corresponding to a
|
||||
// single XPath text node. Coalesce all contiguous text nodes
|
||||
// at this level
|
||||
for (Node nn = n.getNextSibling(); isTextNode(nn); nn = nn.getNextSibling()) {
|
||||
resultString.append(nn.getNodeValue());
|
||||
}
|
||||
} else if (isAttributeNode(n)) {
|
||||
resultString.append(n.getNodeValue());
|
||||
}
|
||||
else {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
serializer.transform(new DOMSource(n), new StreamResult(new OutputStreamWriter(outputStream)));
|
||||
resultString.append(outputStream);
|
||||
}
|
||||
resultString.append("\n");
|
||||
}
|
||||
return new XPathQueryResult(resultString.toString(), "node");
|
||||
} catch (TransformerException e) {
|
||||
String returnData = XPathAPI.eval(doc, transform).toString();
|
||||
return new XPathQueryResult(returnData, "string");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version of the processor
|
||||
* @return version of the processor
|
||||
*/
|
||||
public String getVersion(){
|
||||
return org.apache.xalan.Version.getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates string representation of the xml document against xsd schema
|
||||
* @param data xml document
|
||||
* @param xsd xsd schema
|
||||
* @return statement of validity
|
||||
* @throws Exception thrown on invalid xsd schema or xml
|
||||
*/
|
||||
public String validate(String data, String xsd) throws Exception {
|
||||
Source dataSource = new StreamSource(new StringReader(data));
|
||||
Source xsdSource = new StreamSource(new StringReader(xsd));
|
||||
SchemaFactory schemaFactory = SchemaFactory
|
||||
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
Schema schema = schemaFactory.newSchema(xsdSource);
|
||||
Validator validator = schema.newValidator();
|
||||
validator.validate(dataSource);
|
||||
return "XML file is valid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String executeXQuery(String data, String xquery, String version) throws Exception {
|
||||
throw new UnsupportedOperationException("Xalan doesn't support XQuery evaluation");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package r11.mltx.restxslt.processors;
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import com.r11.tools.model.XMLMultipleFilesData;
|
||||
import com.r11.tools.model.XPathQueryResult;
|
||||
|
||||
public interface XmlEngine {
|
||||
|
||||
String processXSLT(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 validate(String data, String xsd) throws Exception;
|
||||
|
||||
String executeXQuery(String data, String xquery, String version) throws Exception;
|
||||
|
||||
public String getVersion();
|
||||
|
||||
}
|
||||
21
Backend/tools-services/src/main/resources/log4j2.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%c] %-5level - %msg%n"/>
|
||||
</Console>
|
||||
<File name="File" fileName="/tmp/xml_tools_java_backend.log" append="true">
|
||||
<PatternLayout>
|
||||
<Pattern>%d{HH:mm:ss.SSS} [%c] %-5level - %msg%n</Pattern>
|
||||
</PatternLayout>
|
||||
</File>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="com.r11.tools.SparkApplication" level="info" additivity="true">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Logger>
|
||||
<Root level="info">
|
||||
<AppenderRef ref="File"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
2
Filebeat/Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
FROM docker.elastic.co/beats/filebeat:8.6.2
|
||||
COPY --chown=root:filebeat filebeat.docker.yml /usr/share/filebeat/filebeat.yml
|
||||
21
Filebeat/filebeat.docker.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
filebeat.config:
|
||||
modules:
|
||||
path: ${path.config}/modules.d/*.yml
|
||||
reload.enabled: false
|
||||
|
||||
filebeat.autodiscover:
|
||||
providers:
|
||||
- type: docker
|
||||
hints.enabled: true
|
||||
|
||||
processors:
|
||||
- add_cloud_metadata: ~
|
||||
|
||||
output.elasticsearch:
|
||||
hosts: '${ELASTICSEARCH_HOSTS:elc-0.zipper.release11.com:9200}'
|
||||
index: 'xmltools-${ENV_TYPE:dev}-%{+YYYY.MM}'
|
||||
|
||||
|
||||
setup.template:
|
||||
name: "xmltools"
|
||||
pattern: "xmltools-*"
|
||||
28
Frontend/.dockerignore
Normal file
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
15
Frontend/.eslintrc.cjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier/skip-formatting'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
28
Frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
8
Frontend/.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
30
Frontend/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
||||
FROM node:20.9.0-bullseye-slim as build-stage
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY ./ .
|
||||
RUN npm run build
|
||||
|
||||
|
||||
|
||||
FROM nginx:stable-alpine3.17-slim as production-stage
|
||||
RUN mkdir /app
|
||||
|
||||
RUN apk add --no-cache tzdata
|
||||
ENV TZ Europe/Warsaw
|
||||
|
||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
||||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
|
||||
FROM node:20.9.0-bullseye-slim as dev
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
ENV HOST=0.0.0.0
|
||||
COPY . .
|
||||
EXPOSE 8080
|
||||
CMD ["npm", "run", "dev"]
|
||||
89
Frontend/README.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Modern frontend for Release 11 Tools
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||
|
||||
1. Disable the built-in TypeScript Extension
|
||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## Structure of Vuejs 3 components and views in this project
|
||||
|
||||
For this document's needs components and views will be named "modules" even though this is not a correct term for these files officially.
|
||||
|
||||
### Main structure
|
||||
|
||||
- \<script\>
|
||||
- \<template\>
|
||||
- \<style\> - if really needed
|
||||
|
||||
### Scripts
|
||||
|
||||
#### Elements should be placed in this order:
|
||||
- Imports
|
||||
- Props - constant defined by defineProps function, named "props" in code
|
||||
This name allows to have readable code sending data to parent module:
|
||||
```TS
|
||||
props.exampleProp
|
||||
```
|
||||
- Emits - constant defined by defineEmits function, named "emit" in code. This name allows to have readable code sending data to parent module:
|
||||
```TS
|
||||
emit("update:modelValue", exampleVariable)
|
||||
```
|
||||
- Interfaces
|
||||
- Refs - constants defined by ref functions with appropriate values
|
||||
- Injects - variables assigned by "inject" function
|
||||
- Other variables/constants
|
||||
- onFunctions - functions like onBeforeUpdate
|
||||
- Other functions
|
||||
|
||||
#### Rules regarding functions:
|
||||
- Functions ought to have descriptive name
|
||||
- Ought to do one thing. ie. function sendRequest should send request, but not prepare request body or process response data
|
||||
- In practice, if function has more than 10 SLoC, it probably should be split
|
||||
- DO NOT use "any" type. Just don't. *Optional
|
||||
- Function used in other function should be placed below it (if possible, as function can be called from many places in the code)
|
||||
|
||||
#### Rules regarding variables and refs:
|
||||
- Variables ought to have descriptive name
|
||||
|
||||
In cases not covered in this convention, TypeScript, VueJS 3 conventions and good programming practices are applied
|
||||
|
||||
1
Frontend/env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
13
Frontend/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Release11 Tools</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
48
Frontend/nginx.conf
Normal file
@@ -0,0 +1,48 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
expires -1;
|
||||
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
|
||||
}
|
||||
|
||||
location /java/ {
|
||||
proxy_pass http://xmltools-backend:8081/;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /api/mock {
|
||||
proxy_pass http://xmltools-mocked-services:8097/api/mock;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /libxml/ {
|
||||
proxy_pass http://xmltools-libxml-backend/;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /mock/ {
|
||||
proxy_pass http://xmltools-mocked-services:8097/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Content-Type $http_content_type;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
}
|
||||
8083
Frontend/package-lock.json
generated
Normal file
45
Frontend/package.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "new-frontend",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.4.5",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"codemirror": "^6.0.1",
|
||||
"material-icons": "^1.13.14",
|
||||
"thememirror": "^2.0.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-router": "^4.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@tsconfig/node18": "^2.0.1",
|
||||
"@types/node": "^18.16.17",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-plugin-vue": "^9.11.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.24",
|
||||
"prettier": "^2.8.8",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "~5.0.4",
|
||||
"vite": "^4.3.9",
|
||||
"vue-tsc": "^1.6.5"
|
||||
}
|
||||
}
|
||||
7
Frontend/postcss.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/* eslint-disable no-undef */
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
57
Frontend/src/App.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterView } from 'vue-router';
|
||||
import 'material-icons/iconfont/material-icons.css';
|
||||
import SidebarComponent from '@components/sidebar/SidebarComponent.vue';
|
||||
import {onMounted, provide, ref } from 'vue';
|
||||
|
||||
const theme = ref( getTheme() );
|
||||
provide('theme', theme );
|
||||
|
||||
onMounted( ()=> {
|
||||
if (localStorage.theme)
|
||||
selectThemeFromLocalStorage();
|
||||
else if (browserPrefersDarkMode()) {
|
||||
setDarkTheme();
|
||||
}
|
||||
})
|
||||
|
||||
function setDarkTheme() {
|
||||
document.documentElement.classList.add('dark');
|
||||
theme.value = "dark";
|
||||
localStorage.setItem("theme", "dark");
|
||||
}
|
||||
|
||||
function selectThemeFromLocalStorage() {
|
||||
if (localStorage.theme == "dark")
|
||||
document.documentElement.classList.add('dark');
|
||||
else
|
||||
document.documentElement.classList.remove('dark');
|
||||
|
||||
theme.value = localStorage.theme;
|
||||
}
|
||||
|
||||
function browserPrefersDarkMode(){
|
||||
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
|
||||
function setTheme(newTheme : string){
|
||||
theme.value = newTheme;
|
||||
}
|
||||
|
||||
function getTheme(){
|
||||
return localStorage.theme;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="layout" class="font-sans flex h-screen bg-[#f5f7fa] dark:bg-gray-700 dark:from-sky-950 dark:to-indigo-950">
|
||||
<SidebarComponent @theme:changed="setTheme" />
|
||||
<div class="relative p-4 w-full m-4 ml-0 bg-[#f5f7fa] dark:bg-gray-700 rounded-2xl overflow-hidden ">
|
||||
<RouterView></RouterView>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
BIN
Frontend/src/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
101
Frontend/src/assets/logo_biale.svg
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Release11_xA0_Image_1_"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 1010.2 146"
|
||||
style="enable-background:new 0 0 1010.2 146;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs31" /><sodipodi:namedview
|
||||
id="namedview29"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.3155811"
|
||||
inkscape:cx="375.11942"
|
||||
inkscape:cy="72.971558"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1135"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Release11_xA0_Image_1_" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#2A93B0;}
|
||||
.st1{fill:#2A93B0;}
|
||||
.st2{fill:#1A161A;}
|
||||
</style>
|
||||
<path
|
||||
class="st0"
|
||||
d="M41.8,58.5L3,143.7h145.5V4.8L41.8,58.5z"
|
||||
id="path4" />
|
||||
<g
|
||||
id="g10">
|
||||
<path
|
||||
class="st1"
|
||||
d="M961.1,79.2h-16.9V25.3l-16.6,4.9V17.4l32-11.1h1.6V79.2z"
|
||||
id="path6" />
|
||||
<path
|
||||
class="st1"
|
||||
d="M1010.2,79.2h-16.9V25.3l-16.6,4.9V17.4l32-11.1h1.6V79.2z"
|
||||
id="path8" />
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
style="fill:#ffffff">
|
||||
<path
|
||||
class="st2"
|
||||
d="M290.7,71.3c5-7.3,7.5-15.5,7.5-24.4c0-15-4.8-26.4-14.5-34.1C275,5.9,263,2.4,247.9,2.4h-41.6v138.1h25.5V87 l36.2,53.5h31.9l-37.5-50.9C275,86.8,284.4,80.7,290.7,71.3z M231.8,68V27.2h13.8c8,0,14.2,1.2,18.6,3.7c5.6,3.1,8.4,8.2,8.4,15.2 c0,7.5-2.2,13-6.6,16.6c-4.4,3.6-10.3,5.3-17.8,5.3H231.8z"
|
||||
id="path12"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
class="st2"
|
||||
d="M397.5,48.4c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2c-8.6,10.6-12.9,22.1-12.9,34.7v4.7 c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2c8.5-6.2,14.6-14.1,18.3-24h-27.4 c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1c0.6-4.3,0.9-8.2,0.9-11.6 C414.5,72.2,408.9,59,397.5,48.4z M333.1,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7 c4.5,3.7,7.6,8.1,9.3,13.2H333.1z"
|
||||
id="path14"
|
||||
style="fill:#ffffff" />
|
||||
<rect
|
||||
x="431.5"
|
||||
y="2.6"
|
||||
class="st2"
|
||||
width="24.8"
|
||||
height="137.9"
|
||||
id="rect16"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
class="st2"
|
||||
d="M561.8,48.4c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2c-8.6,10.6-12.9,22.1-12.9,34.7v4.7 c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2c8.5-6.2,14.6-14.1,18.3-24h-27.4 c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1c0.6-4.3,0.9-8.2,0.9-11.6 C578.7,72.2,573.1,59,561.8,48.4z M497.3,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7 c4.5,3.7,7.6,8.1,9.3,13.2H497.3z"
|
||||
id="path18"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
class="st2"
|
||||
d="M773.6,81.7c-7-2.2-13.9-4.5-20.9-6.7c-2.5-1-4.3-2.2-5.5-3.6c-1.2-1.4-1.9-2.9-2.1-4.4c0-2.4,1-4.4,3.1-6.1 c2-1.7,4.3-2.5,6.8-2.5c2.4,0,4.4,0.6,6.2,1.8c1.8,1.2,3.2,3,4.2,5.5h23.7c0-9.2-3.4-16.8-10.3-22.7c-6.9-6-14.8-8.9-23.8-8.9 c-6.7,0-13.1,1.8-19,5.4c-11.4,7-15.5,16.8-15.7,26.7c-0.1,5,1.4,9.8,4.2,14.5c2.8,4.7,7.1,8.4,13,11.3c6.3,2.6,12.8,5.3,19.5,7.9 c6.6,2.7,10,5.8,10,9.2c0,3.2-1.2,5.9-3.4,7.9c-2.3,2.1-5.1,3.1-8.5,3.1c-2.9,0-5.5-1-7.9-3c-2.4-2-4.1-5-4.9-8.9h-25 c0,9.2,2.6,17.1,7.8,23.4c4.8,6,10.9,9.7,18.3,11.1c3.7,0.7,7.4,1.1,11,1.1c12.2,0,21.7-4.1,28.5-12.3c6-7.1,9.5-16.1,8.9-27.1 C791.2,94,784.6,86.8,773.6,81.7z"
|
||||
id="path20"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
class="st2"
|
||||
d="M912,88.1c0-15.9-5.7-29.1-17-39.7c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2 c-8.6,10.6-12.9,22.1-12.9,34.7v4.7c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2 c8.5-6.2,14.6-14.1,18.3-24h-27.4c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1 C911.7,95.3,912,91.5,912,88.1z M830.6,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7 c4.5,3.7,7.6,8.1,9.3,13.2H830.6z"
|
||||
id="path22"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
class="st2"
|
||||
d="M680.5,44.4c-9.6-8-20.5-12-32.8-12c-7,0-14,1.5-21,4.5c-7,3-13.7,7.6-19.9,13.8c-5,6.2-8.6,12.2-10.7,18.2 c-2.1,6-3.2,12.2-3.2,18.8c0,15.6,5.3,28.8,15.9,39.7c10.6,10.9,23.5,16.3,38.6,16.3c12.6,0,23.7-3.9,33.2-11.8v8.5h22.3V37h-22.3 V44.4z M667.8,110.5c-5.4,5.8-12.5,8.8-21.2,8.8c-8.2,0-15.1-3-20.8-9.1s-8.5-13.3-8.5-21.8c0-4,0.7-7.9,2.2-11.6 c1.5-3.7,3.4-7.1,5.7-10.3c5.7-6.3,12.8-9.4,21.1-9.4c8.6,0,15.7,3,21.3,9c5.6,6,8.4,13.4,8.4,22.2 C675.9,97.3,673.2,104.7,667.8,110.5z"
|
||||
id="path24"
|
||||
style="fill:#ffffff" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
47
Frontend/src/assets/logo_czarne.svg
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Release11_xA0_Image_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" viewBox="0 0 1010.2 146" style="enable-background:new 0 0 1010.2 146;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#2A93B0;}
|
||||
.st1{fill:#2A93B0;}
|
||||
.st2{fill:#1A161A;}
|
||||
</style>
|
||||
<path class="st0" d="M41.8,58.5L3,143.7h145.5V4.8L41.8,58.5z"/>
|
||||
<g>
|
||||
<path class="st1" d="M961.1,79.2h-16.9V25.3l-16.6,4.9V17.4l32-11.1h1.6V79.2z"/>
|
||||
<path class="st1" d="M1010.2,79.2h-16.9V25.3l-16.6,4.9V17.4l32-11.1h1.6V79.2z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M290.7,71.3c5-7.3,7.5-15.5,7.5-24.4c0-15-4.8-26.4-14.5-34.1C275,5.9,263,2.4,247.9,2.4h-41.6v138.1h25.5V87
|
||||
l36.2,53.5h31.9l-37.5-50.9C275,86.8,284.4,80.7,290.7,71.3z M231.8,68V27.2h13.8c8,0,14.2,1.2,18.6,3.7c5.6,3.1,8.4,8.2,8.4,15.2
|
||||
c0,7.5-2.2,13-6.6,16.6c-4.4,3.6-10.3,5.3-17.8,5.3H231.8z"/>
|
||||
<path class="st2" d="M397.5,48.4c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2c-8.6,10.6-12.9,22.1-12.9,34.7v4.7
|
||||
c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2c8.5-6.2,14.6-14.1,18.3-24h-27.4
|
||||
c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1c0.6-4.3,0.9-8.2,0.9-11.6
|
||||
C414.5,72.2,408.9,59,397.5,48.4z M333.1,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7
|
||||
c4.5,3.7,7.6,8.1,9.3,13.2H333.1z"/>
|
||||
<rect x="431.5" y="2.6" class="st2" width="24.8" height="137.9"/>
|
||||
<path class="st2" d="M561.8,48.4c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2c-8.6,10.6-12.9,22.1-12.9,34.7v4.7
|
||||
c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2c8.5-6.2,14.6-14.1,18.3-24h-27.4
|
||||
c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1c0.6-4.3,0.9-8.2,0.9-11.6
|
||||
C578.7,72.2,573.1,59,561.8,48.4z M497.3,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7
|
||||
c4.5,3.7,7.6,8.1,9.3,13.2H497.3z"/>
|
||||
<path class="st2" d="M773.6,81.7c-7-2.2-13.9-4.5-20.9-6.7c-2.5-1-4.3-2.2-5.5-3.6c-1.2-1.4-1.9-2.9-2.1-4.4c0-2.4,1-4.4,3.1-6.1
|
||||
c2-1.7,4.3-2.5,6.8-2.5c2.4,0,4.4,0.6,6.2,1.8c1.8,1.2,3.2,3,4.2,5.5h23.7c0-9.2-3.4-16.8-10.3-22.7c-6.9-6-14.8-8.9-23.8-8.9
|
||||
c-6.7,0-13.1,1.8-19,5.4c-11.4,7-15.5,16.8-15.7,26.7c-0.1,5,1.4,9.8,4.2,14.5c2.8,4.7,7.1,8.4,13,11.3c6.3,2.6,12.8,5.3,19.5,7.9
|
||||
c6.6,2.7,10,5.8,10,9.2c0,3.2-1.2,5.9-3.4,7.9c-2.3,2.1-5.1,3.1-8.5,3.1c-2.9,0-5.5-1-7.9-3c-2.4-2-4.1-5-4.9-8.9h-25
|
||||
c0,9.2,2.6,17.1,7.8,23.4c4.8,6,10.9,9.7,18.3,11.1c3.7,0.7,7.4,1.1,11,1.1c12.2,0,21.7-4.1,28.5-12.3c6-7.1,9.5-16.1,8.9-27.1
|
||||
C791.2,94,784.6,86.8,773.6,81.7z"/>
|
||||
<path class="st2" d="M912,88.1c0-15.9-5.7-29.1-17-39.7c-10.4-9.7-22.6-14.5-36.5-14.5c-16.9,0-30.6,6.4-41,19.2
|
||||
c-8.6,10.6-12.9,22.1-12.9,34.7v4.7c0,13.4,5.4,25.3,16.3,35.7c10.9,10.4,24,15.6,39.2,15.6c11.5,0,21.5-3.1,30-9.2
|
||||
c8.5-6.2,14.6-14.1,18.3-24h-27.4c-6.1,6.1-13.5,9.1-22.2,9.1c-6.6,0-12.5-1.8-17.8-5.4c-5.3-3.6-8.7-8.5-10.2-14.5h80.1
|
||||
C911.7,95.3,912,91.5,912,88.1z M830.6,77.9c1.7-5.2,4.8-9.6,9.1-13.2c5.3-4.5,11.7-6.7,19.1-6.7c7.3,0,13.7,2.2,19.1,6.7
|
||||
c4.5,3.7,7.6,8.1,9.3,13.2H830.6z"/>
|
||||
<path class="st2" d="M680.5,44.4c-9.6-8-20.5-12-32.8-12c-7,0-14,1.5-21,4.5c-7,3-13.7,7.6-19.9,13.8c-5,6.2-8.6,12.2-10.7,18.2
|
||||
c-2.1,6-3.2,12.2-3.2,18.8c0,15.6,5.3,28.8,15.9,39.7c10.6,10.9,23.5,16.3,38.6,16.3c12.6,0,23.7-3.9,33.2-11.8v8.5h22.3V37h-22.3
|
||||
V44.4z M667.8,110.5c-5.4,5.8-12.5,8.8-21.2,8.8c-8.2,0-15.1-3-20.8-9.1s-8.5-13.3-8.5-21.8c0-4,0.7-7.9,2.2-11.6
|
||||
c1.5-3.7,3.4-7.1,5.7-10.3c5.7-6.3,12.8-9.4,21.1-9.4c8.6,0,15.7,3,21.3,9c5.6,6,8.4,13.4,8.4,22.2
|
||||
C675.9,97.3,673.2,104.7,667.8,110.5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
BIN
Frontend/src/assets/man/rest-mock/Body_section.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Frontend/src/assets/man/rest-mock/Header_section.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
Frontend/src/assets/man/rest-mock/History.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
Frontend/src/assets/man/rest-mock/Status_section.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
Frontend/src/assets/man/rest-mock/URL_section.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
14
Frontend/src/assets/sampleHtml.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Example Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>That's paragraph</p>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
||||
5
Frontend/src/assets/sampleXQuery.xquery
Normal file
@@ -0,0 +1,5 @@
|
||||
declare default element namespace "http://www.release11.com/schemas/Sample.xsd";
|
||||
declare namespace u = "http://www.release11.com/schemas/Sample.xsd";
|
||||
|
||||
for $x in /u:root/u:UserList[@Id = 'a']/u:User
|
||||
return string($x/u:Name)
|
||||
62
Frontend/src/assets/sampleXml.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8"?>
|
||||
<u:root xmlns:u = "http://www.release11.com/schemas/Sample.xsd" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www.tibco.com/schemas/Shemy4tools/Folder/Schema.xsd Schema4tools.xsd">
|
||||
<u:UserList Id = "a">
|
||||
<u:User Id = "1">
|
||||
<u:Name>John</u:Name>
|
||||
<u:Surname>Wick</u:Surname>
|
||||
<u:DateOfDeath>2023-10-10</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "2">
|
||||
<u:Name>Martha</u:Name>
|
||||
<u:Surname>Whane</u:Surname>
|
||||
<u:DateOfDeath>1970-06-13</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "3">
|
||||
<u:Name>Bruce</u:Name>
|
||||
<u:Surname>Lee</u:Surname>
|
||||
<u:DateOfDeath>1985-01-24</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "4">
|
||||
<u:Name>John</u:Name>
|
||||
<u:Surname>Rambo</u:Surname>
|
||||
<u:DateOfDeath>2024-06-19</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:NameList>FirstList</u:NameList>
|
||||
</u:UserList>
|
||||
<u:UserList Id = "b">
|
||||
<u:User Id = "1">
|
||||
<u:Name>Jack</u:Name>
|
||||
<u:Surname>Wicker</u:Surname>
|
||||
<u:DateOfDeath>2023-10-10</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:NameList>SecondList</u:NameList>
|
||||
</u:UserList>
|
||||
<u:UserList Id = "c">
|
||||
<u:User Id = "1">
|
||||
<u:Name>New</u:Name>
|
||||
<u:Surname>Folder</u:Surname>
|
||||
<u:DateOfDeath>2023-11-10</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "2">
|
||||
<u:Name>Newer</u:Name>
|
||||
<u:Surname>Folder</u:Surname>
|
||||
<u:DateOfDeath>2023-11-11</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "3">
|
||||
<u:Name>Newest</u:Name>
|
||||
<u:Surname>Folder</u:Surname>
|
||||
<u:DateOfDeath>2023-11-12</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "4">
|
||||
<u:Name>New</u:Name>
|
||||
<u:Surname>Folder2</u:Surname>
|
||||
<u:DateOfDeath>2023-11-13</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:User Id = "5">
|
||||
<u:Name>New</u:Name>
|
||||
<u:Surname>Folder-Final</u:Surname>
|
||||
<u:DateOfDeath>2023-11-14</u:DateOfDeath>
|
||||
</u:User>
|
||||
<u:NameList>ThirdList</u:NameList>
|
||||
</u:UserList>
|
||||
</u:root>
|
||||
41
Frontend/src/assets/sampleXsd.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:u="http://www.release11.com/schemas/Sample.xsd"
|
||||
targetNamespace="http://www.release11.com/schemas/Sample.xsd"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
<xs:element name="root">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="u:UserList" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="UserList">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element ref="u:User" maxOccurs="unbounded"/>
|
||||
<xs:element ref="u:NameList"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:simpleType name="User">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:element name="User">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="u:Name"/>
|
||||
<xs:element ref="u:Surname"/>
|
||||
<xs:element ref="u:DateOfDeath"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="xs:int" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="Name" type="xs:string"/>
|
||||
<xs:element name="Surname" type="xs:string"/>
|
||||
<xs:element name="DateOfDeath" type="xs:date"/>
|
||||
<xs:element name="NameList" type="xs:string"/>
|
||||
</xs:schema>
|
||||
17
Frontend/src/assets/sampleXslt.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:u = "http://www.release11.com/schemas/Sample.xsd"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<UserLists>
|
||||
<UserListCount>
|
||||
<xsl:value-of select="count(/u:root/u:UserList)" />
|
||||
</UserListCount>
|
||||
<xsl:for-each select="/u:root/u:UserList">
|
||||
<UserListStats>
|
||||
<Name><xsl:value-of select="u:NameList" /></Name>
|
||||
<UserCount><xsl:value-of select="count(u:User)" /></UserCount>
|
||||
</UserListStats>
|
||||
</xsl:for-each>
|
||||
</UserLists>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
537
Frontend/src/assets/tooltips/xpath/xpath1.json
Normal file
@@ -0,0 +1,537 @@
|
||||
[
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "The object to convert to a boolean"
|
||||
}
|
||||
],
|
||||
"description": "The boolean function converts its argument to a boolean",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Boolean-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "boolean('Release11')",
|
||||
"output": "true"
|
||||
},
|
||||
{
|
||||
"command": "boolean('')",
|
||||
"output": "false"
|
||||
},
|
||||
{
|
||||
"command": "boolean(2334)",
|
||||
"output": "true"
|
||||
}
|
||||
],
|
||||
"name": "boolean()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "The true function returns false.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Boolean-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "false",
|
||||
"command": "false()"
|
||||
}
|
||||
],
|
||||
"name": "false()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "The not function returns true if its argument is false, and false otherwise.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Boolean-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "false",
|
||||
"command": "not('text')"
|
||||
},
|
||||
{
|
||||
"command": "not('')",
|
||||
"output": "true"
|
||||
}
|
||||
],
|
||||
"name": "not()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "The true function returns true.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Boolean-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "true",
|
||||
"command": "true()"
|
||||
}
|
||||
],
|
||||
"name": "true()",
|
||||
"output": "boolean"
|
||||
}
|
||||
],
|
||||
"name": "Boolean"
|
||||
},
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "node-set",
|
||||
"description": "Node-set to count nodes in"
|
||||
}
|
||||
],
|
||||
"description": "Returns the number of nodes in the node-set",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "10",
|
||||
"command": "count(/u:root/u:UserList/u:User)"
|
||||
},
|
||||
{
|
||||
"output": "1",
|
||||
"command": "count(/u:root/u:UserList[@Id = 'b']/u:User)"
|
||||
}
|
||||
],
|
||||
"name": "count()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "Returns the element specified by it's unique id, requires DTD",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [],
|
||||
"name": "id()",
|
||||
"output": "node-set"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "Language that will be looked for in context node",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The lang function returns true or false depending on whether the language of the context node as specified by xml:lang attributes is the same as or is a sublanguage of the language specified by the argument string.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Boolean-Functions",
|
||||
"examples": [],
|
||||
"name": "lang()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "The position function returns a number equal to the context position from the expression evaluation context.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [],
|
||||
"name": "last()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "Extract first node and return its local name",
|
||||
"type": "node-set"
|
||||
}
|
||||
],
|
||||
"description": "Returns the number of nodes in the node-set",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "local-name(/u:root)",
|
||||
"output": "root"
|
||||
},
|
||||
{
|
||||
"command": "local-name(/u:root/u:UserList)",
|
||||
"output": "UserList"
|
||||
}
|
||||
],
|
||||
"name": "local-name()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "Extract first node and return QName",
|
||||
"type": "node-set? (Optional)"
|
||||
}
|
||||
],
|
||||
"description": "Returns the number of nodes in the node-set",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "name(/u:root)",
|
||||
"output": "u:root"
|
||||
},
|
||||
{
|
||||
"command": "name(/u:root/u:UserList)",
|
||||
"output": "u:UserList"
|
||||
}
|
||||
],
|
||||
"name": "name()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "Extract first node and return the namespace URI",
|
||||
"type": "node-set"
|
||||
}
|
||||
],
|
||||
"description": "Returns the namespace-uri for the first node in the node-set",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "http://www.release11.com/schemas/Sample.xsd",
|
||||
"command": "namespace-uri(/u:root)"
|
||||
}
|
||||
],
|
||||
"name": "namespace-uri()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [],
|
||||
"description": "Returns the position of the current context node.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Node-Set-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "3",
|
||||
"command": "position()"
|
||||
}
|
||||
],
|
||||
"name": "position()",
|
||||
"output": "number"
|
||||
}
|
||||
],
|
||||
"name": "Node-Set"
|
||||
},
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "number",
|
||||
"description": "Number to round"
|
||||
}
|
||||
],
|
||||
"description": "The floor function returns the largest (closest to positive infinity) number that is not greater than the argument and that is an integer.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Number-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "3",
|
||||
"command": "floor(3.1)"
|
||||
},
|
||||
{
|
||||
"output": "3",
|
||||
"command": "floor(3.9)"
|
||||
},
|
||||
{
|
||||
"output": "3",
|
||||
"command": "floor(3.5)"
|
||||
}
|
||||
],
|
||||
"name": "floor()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "The object to convert to a number"
|
||||
}
|
||||
],
|
||||
"description": "The number function converts its argument to a number",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Number-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "10",
|
||||
"command": "number(10)"
|
||||
},
|
||||
{
|
||||
"output": "NaN",
|
||||
"command": "number('')"
|
||||
}
|
||||
],
|
||||
"name": "number()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "number",
|
||||
"description": "Number to round"
|
||||
}
|
||||
],
|
||||
"description": "The round function returns the number that is closest to the argument and that is an integer. If there are two such numbers, then the one that is closest to positive infinity is returned. If the argument is NaN, then NaN is returned. If the argument is positive infinity, then positive infinity is returned. If the argument is negative infinity, then negative infinity is returned. If the argument is positive zero, then positive zero is returned. If the argument is negative zero, then negative zero is returned. If the argument is less than zero, but greater than or equal to -0.5, then negative zero is returned.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Number-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "3",
|
||||
"command": "round(3.1)"
|
||||
},
|
||||
{
|
||||
"output": "4",
|
||||
"command": "round(3.9)"
|
||||
},
|
||||
{
|
||||
"output": "4",
|
||||
"command": "round(3.5)"
|
||||
}
|
||||
],
|
||||
"name": "round()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "Node set to sum",
|
||||
"type": "node-set"
|
||||
}
|
||||
],
|
||||
"description": "The sum function returns the sum, for each node in the argument node-set, of the result of converting the string-values of the node to a number.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Number-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "78",
|
||||
"command": "sum(/someNode/value)"
|
||||
}
|
||||
],
|
||||
"name": "sum()",
|
||||
"output": "number"
|
||||
}
|
||||
],
|
||||
"name": "Number"
|
||||
},
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string* (One or More)",
|
||||
"description": "Strings to concatenate"
|
||||
}
|
||||
],
|
||||
"description": "The concat function returns the concatenation of its arguments.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "concat('Release', 11)",
|
||||
"output": "Release11"
|
||||
}
|
||||
],
|
||||
"name": "concat()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to test"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String that first string has to contain"
|
||||
}
|
||||
],
|
||||
"description": "The contains function returns true if the first argument string contains the second argument string, and otherwise returns false.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "contains('Release11', 'eas')",
|
||||
"output": "true"
|
||||
}
|
||||
],
|
||||
"name": "contains()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "String to normalize",
|
||||
"type": "string? (Optional)"
|
||||
}
|
||||
],
|
||||
"description": "The normalize-space function returns the argument string with whitespace normalized by stripping leading and trailing whitespace and replacing sequences of whitespace characters by a single space.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "abc def",
|
||||
"command": "normalize-space(' abc def ')"
|
||||
}
|
||||
],
|
||||
"name": "normalize-space(()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to test"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String that first string has to start from"
|
||||
}
|
||||
],
|
||||
"description": "Returns true if the first argument string starts with the second argument string, and otherwise returns false.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"command": "starts-with('Release11', 'Rel'))",
|
||||
"output": "true"
|
||||
},
|
||||
{
|
||||
"output": "false",
|
||||
"command": "starts-with('Release11', 'ease'))"
|
||||
}
|
||||
],
|
||||
"name": "starts-with()",
|
||||
"output": "boolean"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "The object to convert to a string"
|
||||
}
|
||||
],
|
||||
"description": "The string function converts an object to a string",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "10",
|
||||
"command": "string(10)"
|
||||
},
|
||||
{
|
||||
"output": "Release11",
|
||||
"command": "string('Release11')"
|
||||
}
|
||||
],
|
||||
"name": "string()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"description": "String to test",
|
||||
"type": "string? (Optional)"
|
||||
}
|
||||
],
|
||||
"description": "The string-length returns the number of characters in the string.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "6",
|
||||
"command": "string-length('abcdef')"
|
||||
}
|
||||
],
|
||||
"name": "string-length()",
|
||||
"output": "number"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to split"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"description": "Starting index"
|
||||
},
|
||||
{
|
||||
"description": "Length of target substring",
|
||||
"type": "number? (Optional)"
|
||||
}
|
||||
],
|
||||
"description": "The substring function returns the substring of the first argument starting at the position specified in the second argument with length specified in the third argument.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "2345",
|
||||
"command": "substring('12345',2)"
|
||||
},
|
||||
{
|
||||
"output": "234",
|
||||
"command": "substring('12345',2,3)"
|
||||
}
|
||||
],
|
||||
"name": "substring()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to split"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String that splits first string"
|
||||
}
|
||||
],
|
||||
"description": "The substring-after function returns the substring of the first argument string that follows the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "ase11",
|
||||
"command": "substring-after('Release11', 'le')"
|
||||
}
|
||||
],
|
||||
"name": "substring-after()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to split"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String that splits first string"
|
||||
}
|
||||
],
|
||||
"description": "The substring-before function returns the substring of the first argument string that precedes the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "Release",
|
||||
"command": "substring-before('Release11', '11')"
|
||||
}
|
||||
],
|
||||
"name": "substring-before()",
|
||||
"output": "string"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to process"
|
||||
},
|
||||
{
|
||||
"description": "Characters to remove",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "String to insert characters from second argument"
|
||||
}
|
||||
],
|
||||
"description": "The translate function returns the first argument string with occurrences of characters in the second argument string replaced by the character at the corresponding position in the third argument string. If there is a character in the second argument string with no character at a corresponding position in the third argument string (because the second argument string is longer than the third argument string), then occurrences of that character in the first argument string are removed.",
|
||||
"documentationReferenceURL": "https://www.w3.org/TR/1999/REC-xpath-19991116/#section-String-Functions",
|
||||
"examples": [
|
||||
{
|
||||
"output": "BAr",
|
||||
"command": "translate('bar','abc','ABC')"
|
||||
},
|
||||
{
|
||||
"output": "AAA",
|
||||
"command": "translate('--aaa--','abc-','ABC')"
|
||||
}
|
||||
],
|
||||
"name": "translate()",
|
||||
"output": "string"
|
||||
}
|
||||
],
|
||||
"name": "String"
|
||||
}
|
||||
]
|
||||
2522
Frontend/src/assets/tooltips/xpath/xpath2.json
Normal file
3109
Frontend/src/assets/tooltips/xpath/xpath3.json
Normal file
3328
Frontend/src/assets/tooltips/xpath/xpath31.json
Normal file
48
Frontend/src/assets/tooltips/xpath/xpathdiffs.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"universalInfo":
|
||||
[
|
||||
{
|
||||
"category":"What is XPath?",
|
||||
"description":"XPath is a query language used for selecting nodes from XML and processing them. It may perform operations on strings, numbers and boolean values."
|
||||
},
|
||||
{
|
||||
"category":"What's new in XPath"
|
||||
}
|
||||
],
|
||||
"VersionDiffs":
|
||||
[
|
||||
{
|
||||
"version":"2.0",
|
||||
"diffs":
|
||||
[
|
||||
"Added support for all XML simple types",
|
||||
"Many new functions (tripled instruction count)",
|
||||
"All expressions evaluate to sequence",
|
||||
"Introduces conditional expressions and for-loops"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version":"3.0",
|
||||
"diffs":
|
||||
[
|
||||
"Dynamic function calls (function may be called without being referenced by name (find function in collection and call)",
|
||||
"Inline functions",
|
||||
"Namespace literals - Namespace may be embedded into function name",
|
||||
"Support for union types - collections containing elements of different types",
|
||||
"Mapping operator - '!' performs evaluation for each element in sequence and concatenates results",
|
||||
"Introduced maps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version":"3.1",
|
||||
"diffs":
|
||||
[
|
||||
"New operator for function chaining '=>'",
|
||||
"Introduced maps that store data in pair 'key:value' - 'map{ key : value, key : value }'",
|
||||
"Introduced arrays - they differ from sequences in that they can be nested 'array{1, 5, 7, (10 to 20)}'"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
845
Frontend/src/assets/tooltips/xslt/xslt1.json
Normal file
@@ -0,0 +1,845 @@
|
||||
[
|
||||
{
|
||||
"name": "Templates",
|
||||
"entries": [
|
||||
{
|
||||
"name": "<xsl:template>",
|
||||
"description": "Defines an output producing template. This element must have either the match attribute or the name attribute set.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"match",
|
||||
"description":"Specifies a pattern that determines the elements for which this template should be used. It is a required attribute if there is no name attribute."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"name",
|
||||
"description":"Specifies a name for this template"
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"mode",
|
||||
"description":"Specifies a particular mode for this template, which can be matched by an attribute of the <xsl:apply-templates> element"
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"priority",
|
||||
"description":"Specifies a numeric priority for this template."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/template",
|
||||
"output": "XML Tree"
|
||||
},{
|
||||
"name": "<xsl:apply-templates>",
|
||||
"description": "Selects a set of nodes in the input tree and instructs the processor to apply the proper templates to them.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"mode",
|
||||
"description":"Specifies a particular mode for this template, which can be matched by an attribute of the <xsl:apply-templates> element"
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"select",
|
||||
"description":"XPath expression that specifies the nodes to be processed. If this attribute is not set, all child nodes of the current node are selected."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/apply-templates",
|
||||
"output": "XML Nodes"
|
||||
},{
|
||||
"name": "<xsl:apply-imports/>",
|
||||
"description": "Import precedence requires that template rules in main stylesheets have higher precedence than template rules in imported stylesheets",
|
||||
"attributes":
|
||||
[
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/apply-imports",
|
||||
"output": "Imported output from another XSLT"
|
||||
},{
|
||||
"name": "<xsl:call-template>",
|
||||
"description": "Invokes a named template",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies the name of the template you wish to invoke."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/call-template",
|
||||
"output": "Called template XML"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Loops and conditional processing",
|
||||
"entries":
|
||||
[
|
||||
{
|
||||
"name": "<xsl:for-each>",
|
||||
"description": "Selects a set of nodes and processes each of them in the same way",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"select",
|
||||
"description":"XPath expression that specifies the nodes to be processed."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each",
|
||||
"output": "Processed set of nodes"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:if>",
|
||||
"description": "Element contains a test attribute and a template. If the test evaluates to true, the template is processed.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"test",
|
||||
"description":"Contains an XPath expression that can be evaluated to a Boolean value."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/if",
|
||||
"output": "Depending on test processed template or not."
|
||||
},
|
||||
{
|
||||
"name": "<xsl:choose>",
|
||||
"description": "Element defines a choice among a number of alternatives. It behaves like a switch statement in procedural languages.",
|
||||
"attributes":
|
||||
[
|
||||
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/choose",
|
||||
"output": "Choosed XML template"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:when>",
|
||||
"description": "Element always appears within an <xsl:choose> element, acting like a case statement.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"test",
|
||||
"description":"Boolean expression to be evaluated. If true, the contents of the element are processed; if false, they are ignored."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/when",
|
||||
"output": "Processed or not XML Template"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:otherwise>",
|
||||
"description": "Element is used to define the action that should be taken when none of the <xsl:when> conditions apply.",
|
||||
"attributes":
|
||||
[
|
||||
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/otherwise",
|
||||
"output": "processed XML Template"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Creating Result Tree",
|
||||
"entries":
|
||||
[
|
||||
{
|
||||
"name": "<xsl:attribute>",
|
||||
"description": "Creates an attribute in the output document, using any values that can be accessed from the stylesheet. The element must be defined before any other output document element inside the output document element for which it establishes attribute values",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies the name of the attribute to be created in the output document."
|
||||
} ,
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"namespace",
|
||||
"description":"Defines the namespace URI for this attribute in the output document."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/attribute",
|
||||
"output": "XML Element with provided attribute"
|
||||
},{
|
||||
"name": "<xsl:attribute-set>",
|
||||
"description": "Creates a named set of attributes, which can then be applied as whole to the output document, in a manner similar to named styles in CSS",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies the name of the attribute set."
|
||||
} ,
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"use-attribute-sets",
|
||||
"description":"Builds an attribute set from other attribute sets. The names of the contributing sets must be separated with whitespace characters"
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/attribute-set",
|
||||
"output": "Named set of attributes"
|
||||
},{
|
||||
"name": "<xsl:copy>",
|
||||
"description": "Transfers a shallow copy (the node and any associated namespace node) of the current node to the output document.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"use-attribute-sets",
|
||||
"description":"Lists attribute sets that should be applied to the output node, if it is an element"
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/copy",
|
||||
"output": "Copy of XML node"
|
||||
},{
|
||||
"name": "<xsl:number>",
|
||||
"description": "Counts things sequentially. It can also be used to quickly format a number.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"count",
|
||||
"description":"Specifies what in the source tree should be numbered sequentially. It uses an XPath expression."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"level",
|
||||
"description":"Defines how levels of the source tree should be considered in generating sequential numbers. It has three valid values: single, multiple, and any."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"from",
|
||||
"description":"Specifies where the numbering should start or start over."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"value",
|
||||
"description":"Applies a given format to a number."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"format",
|
||||
"description":"Defines the format of the generated number."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"lang",
|
||||
"description":"Specifies which language's alphabet should be used in letter-based numbering formats."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"letter-value",
|
||||
"description":"Disambiguates between numbering sequences that use letters. Some languages have more than one numbering system that use letters."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"grouping-separator",
|
||||
"description":"Specifies what character should be used as the group (e.g. thousands) separator."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"grouping-size",
|
||||
"description":"Indicates the number of digits that make up a numeric group."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/number",
|
||||
"output": "Formatted number"
|
||||
},{
|
||||
"name": "<xsl:value-of>",
|
||||
"description": "Evaluates an XPath expression, converts it to a string, and writes that string to the result tree.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"select",
|
||||
"description":"Specifies the XPath expression to be evaluated and written to the output tree."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"disable-output-escaping",
|
||||
"description":"Specifies whether special characters are escaped when written to the output."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/value-of",
|
||||
"output": "Value from XML nodes"
|
||||
},{
|
||||
"name": "<xsl:text>",
|
||||
"description": "Writes literal text to the output tree.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"disable-output-escaping",
|
||||
"description":"Specifies whether special characters are escaped when written to the output."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/text",
|
||||
"output": "XML Node with writed text"
|
||||
},{
|
||||
"name": "<xsl:comment>",
|
||||
"description": "Writes a comment to the output document. It must include only text.",
|
||||
"attributes":
|
||||
[
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/comment",
|
||||
"output": "XML Node with writed comment"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:processing-instruction>",
|
||||
"description": "Writes a processing instruction to the output document.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies the name of this processing instruction."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/processing-instruction",
|
||||
"output": "XML Node with output of processed instruction"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:key>",
|
||||
"description": "Declares a named key which can be used elsewhere in the stylesheet with the key( ) function.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies a name for this key. Must be a QName."
|
||||
},
|
||||
{
|
||||
"type":"required",
|
||||
"name":"match",
|
||||
"description":"Defines the nodes for which this key is applicable."
|
||||
},
|
||||
{
|
||||
"type":"required",
|
||||
"name":"use",
|
||||
"description":"Specifies an XPath expression that will be used to determine the value of the key for each of the applicable nodes."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/key",
|
||||
"output": "key to use in stylesheet"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:decimal-format>",
|
||||
"description": "Declares a named key which can be used elsewhere in the stylesheet with the key( ) function.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"name",
|
||||
"description":"Specifies a name for this format."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"decimal-separator",
|
||||
"description":"Specifies the decimal point character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"grouping-separator",
|
||||
"description":"Specifies the thousands separator character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"infinity",
|
||||
"description":"Specifies the string used to represent infinity."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"minus-sign",
|
||||
"description":"Specifies the minus sign character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"NaN",
|
||||
"description":"Specifies the string used when the value is not a number."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"percent",
|
||||
"description":"Specifies the percentage sign character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"per-mille",
|
||||
"description":"Specifies the per thousand character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"zero-digit",
|
||||
"description":"Specifies the digit zero character."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"digit",
|
||||
"description":"Specifies the character used in the format pattern to stand for a digit."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"pattern-separator",
|
||||
"description":"Specifies the character separating positive and negative subpatterns in a format pattern."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/decimal-format",
|
||||
"output": "decimal format"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:preserve-space>",
|
||||
"description": "Defines the elements in the source document for which whitespace should be preserved.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"elements",
|
||||
"description":"Specifies the elements for which whitespace should be preserved."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/preserve-space",
|
||||
"output": "preserved space"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:strip-space>",
|
||||
"description": "Defines the elements in the source document for which whitespace should be removed.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"elements",
|
||||
"description":"Specifies the elements for which whitespace should be preserved."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/strip-space",
|
||||
"output": "elements with removed whitespace"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:sort>",
|
||||
"description": "Defines a sort key for nodes selected by <xsl:apply-templates> or <xsl:for-each> and determines the order in which they are processed.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"select",
|
||||
"description":"Uses an XPath expression to specify the nodes to be sorted."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"order",
|
||||
"description":"Specifies whether the nodes should be processed in \"ascending\" or \"descending\" order."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"case-order",
|
||||
"description":"Indicates whether upper- or lowercase letters are to be ordered first."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"lang",
|
||||
"description":"Specifies which language is to be used by the sort."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"data-type",
|
||||
"description":"Defines whether items are to be ordered alphabetically or numerically."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/sort",
|
||||
"output": "sorted elements"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:output>",
|
||||
"description": "Controls the characteristics of the output document.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"method",
|
||||
"description":"Specifies output format."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"version",
|
||||
"description":"Specifies the value of the version attribute of the XML or HTML declaration in the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"encoding",
|
||||
"description":"Specifies the value of the encoding attribute in the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"omit-xml-declaration",
|
||||
"description":"Indicates whether or not to include an XML declaration in the output."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"doctype-public",
|
||||
"description":"Specifies the value of the PUBLIC attribute of the DOCTYPE declaration in the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"doctype-system",
|
||||
"description":"Specifies the value of the SYSTEM attribute of the DOCTYPE declaration in the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"cdata-section-elements",
|
||||
"description":"Lists elements whose text contents should be written as CDATA sections."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/output",
|
||||
"output": "changed document prefix"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Stylesheet structure",
|
||||
"entries":
|
||||
[
|
||||
{
|
||||
"name": "<xsl:stylesheet>",
|
||||
"description": "Is the outermost element of a stylesheet.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"version",
|
||||
"description":"Specifies the version of XSLT required by this stylesheet."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"exclude-result-prefixes",
|
||||
"description":"Specifies any namespace used in this document that should not be sent to the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"extension-element-prefixes",
|
||||
"description":"Specifies a space-separated list of any namespace prefixes for extension elements in this document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-collation",
|
||||
"description":"Specifies the default collation used by all XPath expressions appearing in attributes or text value templates that have the element as an ancestor"
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-mode",
|
||||
"description":"Defines the default value for the mode attribute of all <xsl:template> and <xsl:apply-templates> elements within its scope."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-validation",
|
||||
"description":"Defines the default value of the validation attribute of all relevant instructions appearing within its scope."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"expand-text",
|
||||
"description":"Determines whether descendant text nodes of the element are treated as text value templates."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"id",
|
||||
"description":"Specifies an id for this stylesheet. This is most often used when the stylesheet is embedded in another XML document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"input-type-annotations",
|
||||
"description":"Specifies whether type annotations are stripped from the element so the same results are produced whether the source documents have been validated against a schema or not."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"use-when",
|
||||
"description":"Determines whether the element and all the nodes that have it as ancestor are excluded from the stylesheet."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"xpath-default-namespace",
|
||||
"description":"Specifies the namespace that will be used if the element name is unprefixed or an unprefixed type name within an XPath expression."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/stylesheet",
|
||||
"output": "XSLT Stylesheet"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:tranform>",
|
||||
"description": "Exactly equivalent to the <xsl:stylesheet> element.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"version",
|
||||
"description":"Specifies the version of XSLT required by this stylesheet."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"exclude-result-prefixes",
|
||||
"description":"Specifies any namespace used in this document that should not be sent to the output document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"extension-element-prefixes",
|
||||
"description":"Specifies a space-separated list of any namespace prefixes for extension elements in this document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-collation",
|
||||
"description":"Specifies the default collation used by all XPath expressions appearing in attributes or text value templates that have the element as an ancestor"
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-mode",
|
||||
"description":"Defines the default value for the mode attribute of all <xsl:template> and <xsl:apply-templates> elements within its scope."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"default-validation",
|
||||
"description":"Defines the default value of the validation attribute of all relevant instructions appearing within its scope."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"expand-text",
|
||||
"description":"Determines whether descendant text nodes of the element are treated as text value templates."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"id",
|
||||
"description":"Specifies an id for this stylesheet. This is most often used when the stylesheet is embedded in another XML document."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"input-type-annotations",
|
||||
"description":"Specifies whether type annotations are stripped from the element so the same results are produced whether the source documents have been validated against a schema or not."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"use-when",
|
||||
"description":"Determines whether the element and all the nodes that have it as ancestor are excluded from the stylesheet."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"xpath-default-namespace",
|
||||
"description":"Specifies the namespace that will be used if the element name is unprefixed or an unprefixed type name within an XPath expression."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/transform",
|
||||
"output": "XSLT Stylesheet"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:import>",
|
||||
"description": "Top-level element that serves to import the contents of one stylesheet into another stylesheet.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"href",
|
||||
"description":"Specifies the URI of the stylesheet to import."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/import",
|
||||
"output": "XSLT Stylesheet from another file"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:include>",
|
||||
"description": "Merges the contents of one stylesheet with another. Unlike the case of <xsl:import>, the contents of an included stylesheet have exactly the same precedence as the contents of the including stylesheet.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"href",
|
||||
"description":"Specifies the URI of the stylesheet to import."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/include",
|
||||
"output": "XSLT Stylesheet with XSLT from another file."
|
||||
},
|
||||
{
|
||||
"name": "<xsl:namespace-alias>",
|
||||
"description": "Maps a namespace in the stylesheet to a different namespace in the output tree. The most common use for this element is in generating a stylesheet from another stylesheet.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"stylesheet-prefix",
|
||||
"description":"Specifies the temporary namespace."
|
||||
},
|
||||
{
|
||||
"type":"required",
|
||||
"name":"result-prefix",
|
||||
"description":"Specifies the desired namespace for the output tree."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/namespace-alias",
|
||||
"output": "XML Tree with changed namespaces"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:element>",
|
||||
"description": "Creates an element in the output document.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Specifies the desired name of the output element. The name must be a valid QName."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"namespace",
|
||||
"description":"Specifies the namespace of the output element."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"use-attribute-sets",
|
||||
"description":"A whitespace-separated list of attribute-set element names to be applied to the element element's output element."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/namespace-alias",
|
||||
"output": "XML with provided element"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Variables and parameters",
|
||||
"entries":
|
||||
[
|
||||
{
|
||||
"name": "<xsl:param>",
|
||||
"description": "Establishes a parameter by name and, optionally, a default value for that parameter. When used as a top-level element, the parameter is global. When used inside an <xsl:template> element, the parameter is local to that template.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Names the parameter. This must be a QName."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"select",
|
||||
"description":"Uses an XPath expression to provide a default value if none is specified."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/param",
|
||||
"output": "XML parameter"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:variable>",
|
||||
"description": "Declares a global or local variable in a stylesheet and gives it a value.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Gives the variable a name."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"select",
|
||||
"description":"Defines the value of the variable through an XPath expression. If the element contains a template, this attribute is ignored."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/variable",
|
||||
"output": "XML Variable"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:with-param>",
|
||||
"description": "Sets the value of a parameter to be passed into a template.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"name",
|
||||
"description":"Gives this parameter a name."
|
||||
},
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"select",
|
||||
"description":"Defines the value of the parameter through an XPath expression. If the element contains a template, this attribute is ignored."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/with-param",
|
||||
"output": "XML Parameter"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:copy-of>",
|
||||
"description": "Makes a deep copy (including descendant nodes) of whatever the select attribute specifies to the output document.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"required",
|
||||
"name":"select",
|
||||
"description":"Uses an XPath expression that specifies what is to be copied."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/copy-of",
|
||||
"output": "Copy of Selected node"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"Misc",
|
||||
"entries":
|
||||
[
|
||||
{
|
||||
"name": "<xsl:message>",
|
||||
"description": "Outputs a message (to the JavaScript Console in NS) and optionally terminates execution of the stylesheet.",
|
||||
"attributes":
|
||||
[
|
||||
{
|
||||
"type":"optional",
|
||||
"name":"terminate",
|
||||
"description":"Set to \"yes\", indicates that execution should be terminated. The default value is \"no\", in which case the message is output and execution continues."
|
||||
}
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/message",
|
||||
"output": "Message in console"
|
||||
},
|
||||
{
|
||||
"name": "<xsl:fallback>",
|
||||
"description": "specifies what template to use if a given extension (or, eventually, newer version) element is not supported.",
|
||||
"attributes":
|
||||
[
|
||||
],
|
||||
"examples": [],
|
||||
"documentationReferenceURL": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/fallback",
|
||||
"output": "Fallbacks"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
2064
Frontend/src/assets/tooltips/xslt/xslt3.json
Normal file
52
Frontend/src/assets/tooltips/xslt/xsltdiffs.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"universalInfo":
|
||||
[
|
||||
{
|
||||
"category":"What is XSLT",
|
||||
"description":"XSLT (Extensible Stylesheet Language Transformations) is a language for converting and manipulating XML data into various formats. It uses rules defined in stylesheets to transform XML documents into HTML, XML, or other text-based outputs."
|
||||
},
|
||||
{
|
||||
"category":"Differences between XSLT versions"
|
||||
}
|
||||
],
|
||||
"VersionDiffs":
|
||||
[
|
||||
{
|
||||
"version":"2.0",
|
||||
"diffs":
|
||||
[
|
||||
"Introduced a richer data model with support for various data types and sequences, allowing more flexible handling of data.",
|
||||
"Added native support for regular expressions, making text processing and pattern matching more powerful.",
|
||||
"Introduced the concept of higher-order functions, enabling functions to be used as arguments and returned as results, enhancing the language's functional capabilities.",
|
||||
"Expanded the set of built-in string functions, making string manipulation and formatting more versatile.",
|
||||
"Introduced the concept of sequences, where nodes could be processed without relying solely on their order in the source document.",
|
||||
"Provided improved error handling and reporting mechanisms, making it easier to diagnose and fix issues in transformations.",
|
||||
"Allowed variable and function parameters to have type annotations, enhancing clarity and enabling better optimization.",
|
||||
"Refined the handling of namespaces and introduced features for dealing with namespaces more effectively.",
|
||||
"Introduced more advanced grouping capabilities, allowing grouping based on multiple criteria.",
|
||||
"Expanded sorting options, making it possible to sort data based on multiple keys and in different directions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"version":"3.0",
|
||||
"diffs":
|
||||
[
|
||||
"Extended the support for higher-order functions by introducing new functions like map and filter, enabling more functional programming patterns.",
|
||||
"Introduced streaming capabilities, allowing processing of large documents without loading the entire document into memory, which improves performance and memory usage.",
|
||||
"Introduced functions to parse and serialize JSON data, enabling transformations between XML and JSON formats.",
|
||||
"Enhanced type annotations, allowing for more precise typing of variables and parameters, aiding both readability and optimization.",
|
||||
"Introduced new standard functions, expanding the range of operations and calculations that can be performed within transformations.",
|
||||
"Introduced a new data structure called maps, allowing for efficient key-value pair storage and manipulation.",
|
||||
"Introduced tunnel parameters, which can pass data through templates without explicitly listing them in the template's parameter list",
|
||||
"Introduced a try-catch construct for better error handling, allowing you to catch and handle errors more gracefully.",
|
||||
"Introduced the ability to execute multiple templates concurrently, improving performance in multi-core environments.",
|
||||
"Integrated new features from XPath 3.1, including support for higher-order functions and enhanced string manipulation functions.",
|
||||
"Enhanced grouping capabilities, making it more powerful and flexible for complex grouping scenarios.",
|
||||
"Allowed dynamic function calls using the xsl:evaluate element, enabling more dynamic transformations."
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
||||
}
|
||||