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 }