1 /** 2 * Copyright © DiamondMVC 2019 3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module diamond.web.soap.service.parser.messageparser; 7 8 import std.algorithm : startsWith; 9 import std.array : split; 10 11 import diamond.core.collections; 12 import diamond.dom; 13 import diamond.xml; 14 import diamond.web.soap.service.message; 15 import diamond.web.soap.service.parameter; 16 import diamond.errors.exceptions.soapexception; 17 18 package(diamond.web.soap.service.parser): 19 /** 20 * Parses the messages of the wsdl file. 21 * Params: 22 * moduleName = The name of the module. 23 * typeNames = A hashset of all type names within the wsdl file. 24 * root = The root node of the wsdl file. 25 * inputs = The input messages. 26 * outputs = The output messages. 27 */ 28 void parseMessages(string moduleName, HashSet!string typeNames, XmlNode root, out SoapMessage[string] inputs, out SoapMessage[string] outputs) 29 { 30 auto messages = root.getByTagName("wsdl:message"); 31 32 if (!messages || !messages.length) 33 { 34 messages = root.getByTagName("xs:messages"); 35 } 36 37 if (!messages || !messages.length) 38 { 39 messages = root.getByTagName("xsd:messages"); 40 } 41 42 if (!messages || !messages.length) 43 { 44 messages = root.getByTagName("messages"); 45 } 46 47 if (messages && messages.length) 48 { 49 foreach (i; 0 .. messages.length) 50 { 51 auto input = messages[i]; 52 auto output = (i + 1) < messages.length ? messages[i + 1] : null; 53 54 if (!output) 55 { 56 break; 57 } 58 59 auto message = new SoapMessage(input.getAttribute("name").value, output.getAttribute("name").value); 60 61 auto inputParameters = input.getByTagName("wsdl:part"); 62 63 if (!inputParameters || !inputParameters.length) 64 { 65 inputParameters = input.getByTagName("xs:part"); 66 } 67 68 if (!inputParameters || !inputParameters.length) 69 { 70 inputParameters = input.getByTagName("xsd:part"); 71 } 72 73 if (!inputParameters || !inputParameters.length) 74 { 75 inputParameters = input.getByTagName("part"); 76 } 77 78 if (inputParameters && inputParameters.length) 79 { 80 foreach (inputParameter; inputParameters) 81 { 82 auto name = inputParameter.getAttribute("name"); 83 auto element = inputParameter.getAttribute("element"); 84 85 if (!name || !element) 86 { 87 throw new SoapException("Missing name or element for input message part."); 88 } 89 90 auto elementName = element.value.split(":").length == 2 ? element.value.split(":")[1] : element.value; 91 92 if (!element.value.startsWith("tns:") || typeNames.has(elementName)) 93 { 94 if (element.value.startsWith("tns:")) 95 { 96 elementName = moduleName ~ "." ~ elementName; 97 } 98 99 message.addInputParameter(name.value, elementName); 100 } 101 } 102 } 103 104 auto outputParameters = output.getByTagName("wsdl:part"); 105 106 if (!outputParameters || !outputParameters.length) 107 { 108 outputParameters = output.getByTagName("xs:part"); 109 } 110 111 if (!outputParameters || !outputParameters.length) 112 { 113 outputParameters = output.getByTagName("xsd:part"); 114 } 115 116 if (!outputParameters || !outputParameters.length) 117 { 118 outputParameters = output.getByTagName("part"); 119 } 120 121 if (outputParameters && outputParameters.length) 122 { 123 if (outputParameters.length != 1) 124 { 125 throw new SoapException("No support for multiple output parameters."); 126 } 127 128 auto outputParameter = outputParameters[0]; 129 130 auto name = outputParameter.getAttribute("name"); 131 auto element = outputParameter.getAttribute("element"); 132 133 if (!name || !element) 134 { 135 throw new SoapException("Missing name or element for output message part."); 136 } 137 138 auto elementName = element.value.split(":").length == 2 ? element.value.split(":")[1] : element.value; 139 140 if (!element.value.startsWith("tns:") || typeNames.has(elementName)) 141 { 142 message.output = new SoapParameter(name.value, elementName); 143 } 144 } 145 146 inputs[message.inputName] = message; 147 outputs[message.outputName] = message; 148 } 149 } 150 }