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.porttypeparser;
7 
8 import std.array : split, join;
9 import std..string : format;
10 
11 import diamond.dom;
12 import diamond.xml;
13 import diamond.web.soap.service.message;
14 import diamond.web.soap.service.messageoperation;
15 import diamond.errors.exceptions.soapexception;
16 
17 package(diamond.web.soap.service.parser):
18 /**
19 * Parses the port types of the wsdl file.
20 * Params:
21 *   root =              The root node of the wsdl file.
22 *   inputs =            The input messages.
23 *   outputs =           The output messages.
24 *   messageOperations = The message operations.
25 */
26 string parsePortTypes(XmlNode root, SoapMessage[string] inputs, SoapMessage[string] outputs, out SoapMessageOperation[][string] messageOperations)
27 {
28   static const portTypeInterfaceFormat = q{
29 interface I%s
30 {
31   public:
32 %s
33 }
34   };
35 
36   static const portTypeOperationFormat = "\t@SoapAction(\"%s\") %s %s(%s);\r\n";
37 
38   string result = "";
39 
40   auto portTypes = root.getByTagName("wsdl:portType");
41 
42   if (!portTypes || !portTypes.length)
43   {
44     portTypes = root.getByTagName("xs:portType");
45   }
46 
47   if (!portTypes || !portTypes.length)
48   {
49     portTypes = root.getByTagName("xsd:portType");
50   }
51 
52   if (!portTypes || !portTypes.length)
53   {
54     portTypes = root.getByTagName("portType");
55   }
56 
57   if (portTypes && portTypes.length)
58   {
59     foreach (portType; portTypes)
60     {
61       auto name = portType.getAttribute("name");
62 
63       if (!name)
64       {
65         throw new SoapException("Missing name for portType.");
66       }
67 
68       SoapMessageOperation[] portMessageOperations;
69 
70       auto operations = portType.getByTagName("wsdl:operation");
71 
72       if (!operations || !operations.length)
73       {
74         operations = portType.getByTagName("xs:operation");
75       }
76 
77       if (!operations || !operations.length)
78       {
79         operations = portType.getByTagName("xsd:operation");
80       }
81 
82       if (!operations || !operations.length)
83       {
84         operations = portType.getByTagName("operation");
85       }
86 
87       string[] operationsResult;
88 
89       if (operations && operations.length)
90       {
91         foreach (operation; operations)
92         {
93           auto operationName = operation.getAttribute("name");
94 
95           if (!operationName)
96           {
97             throw new SoapException("Missing operation name.");
98           }
99 
100           auto inputTags = operation.getByTagName("wsdl:input");
101 
102           if (!inputTags || !inputTags.length)
103           {
104             inputTags = operation.getByTagName("xs:input");
105           }
106 
107           if (!inputTags || !inputTags.length)
108           {
109             inputTags = operation.getByTagName("xsd:input");
110           }
111 
112           if (!inputTags || !inputTags.length)
113           {
114             inputTags = operation.getByTagName("input");
115           }
116 
117           if (!inputTags || !inputTags.length)
118           {
119             throw new SoapException("Missing input from operation.");
120           }
121 
122           auto outputTags = operation.getByTagName("wsdl:output");
123 
124           if (!outputTags || !outputTags.length)
125           {
126             outputTags = operation.getByTagName("xs:output");
127           }
128 
129           if (!outputTags || !outputTags.length)
130           {
131             outputTags = operation.getByTagName("xsd:output");
132           }
133 
134           if (!outputTags || !outputTags.length)
135           {
136             outputTags = operation.getByTagName("output");
137           }
138 
139           if (!outputTags || !outputTags.length)
140           {
141             throw new SoapException("Missing output for operation.");
142           }
143 
144           auto input = inputTags[0];
145           auto output = outputTags[0];
146 
147           auto inputName = input.getAttribute("message").value;
148 
149           if (inputName.split(":").length == 2)
150           {
151             inputName = inputName.split(":")[1];
152           }
153 
154           auto inputParameters = inputs.get(inputName, null);
155 
156           auto outputName = output.getAttribute("message").value;
157 
158           if (outputName.split(":").length == 2)
159           {
160             outputName = outputName.split(":")[1];
161           }
162 
163           auto outputParameters = outputs.get(outputName, null);
164 
165           if (!outputParameters || !outputParameters.output)
166           {
167             throw new SoapException("Missing output parameters.");
168           }
169 
170           auto action = input.getAttribute("wsaw:action");
171 
172           if (!action)
173           {
174             action = input.getAttribute("wsdl:action");
175           }
176 
177           if (!action)
178           {
179             action = input.getAttribute("xs:action");
180           }
181 
182           if (!action)
183           {
184             action = input.getAttribute("xsd:action");
185           }
186 
187           if (!action)
188           {
189             action = input.getAttribute("action");
190           }
191 
192           if (!action)
193           {
194             action = output.getAttribute("wsaw:action");
195           }
196 
197           if (!action)
198           {
199             action = output.getAttribute("wsdl:action");
200           }
201 
202           if (!action)
203           {
204             action = output.getAttribute("xs:action");
205           }
206 
207           if (!action)
208           {
209             action = output.getAttribute("xsd:action");
210           }
211 
212           if (!action)
213           {
214             action = output.getAttribute("action");
215           }
216 
217           auto returnType = outputParameters.output.type;
218 
219           string[] parameters;
220 
221           if (inputParameters && inputParameters.input && inputParameters.input.length)
222           {
223             foreach (inputParameter; inputParameters.input)
224             {
225               parameters ~= "%s %s".format(inputParameter.type, inputParameter.name);
226             }
227           }
228 
229           auto portMessageOperation = new SoapMessageOperation(action ? action.value : "", operationName.value, returnType,  parameters ? parameters.join(",") : "");
230 
231           portMessageOperations ~= portMessageOperation;
232 
233           operationsResult ~= portTypeOperationFormat.format(portMessageOperation.action, portMessageOperation.returnType, portMessageOperation.name, portMessageOperation.parameters);
234         }
235       }
236 
237       if (portMessageOperations)
238       {
239         messageOperations[name.value] = portMessageOperations;
240       }
241 
242       result ~= portTypeInterfaceFormat.format(name.value, operationsResult ? operationsResult.join("\r\n") : "");
243     }
244   }
245 
246   return result;
247 }