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.bindingparser; 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 bindings of the wsdl file. 20 * Params: 21 * root = The root node of the wsdl file. 22 * operations = The message operations. 23 */ 24 string parseBinding(XmlNode root, SoapMessageOperation[][string] operations) 25 { 26 // TODO: 27 /* 28 1. Create a class with the name attribute which inherits interface from type attribute 29 2. Loop through operation tags 30 3. Create the method with parameters. 31 4. Body has to create the soap envelop message and call using soap client. 32 5. Ignore everything else, because it's verbose information we already havve extracted and got. 33 */ 34 35 static const bindingClassFormat = q{ 36 final class %s : SoapBinding, I%s 37 { 38 public: 39 final: 40 this() 41 { 42 super(); 43 } 44 45 %s 46 } 47 }; 48 49 static const bindingOperationFormat = "\t@SoapOperation(\"%s\") %s %s(%s) { mixin SoapBindingMethod!(%s); mixin(executeSoapBinding()); }\r\n"; 50 51 /*private string parameters(alias T)() 52 { 53 import __stdtraits = std.traits; 54 import std.array : join; 55 56 string[] result; 57 enum paramsId = [__stdtraits.ParameterIdentifierTuple!T]; 58 59 static foreach (i; 0 .. paramsId.length) 60 { 61 result ~= __stdtraits.Parameters!T[i].stringof ~ " " ~ paramsId[i]; 62 } 63 64 return result.join(","); 65 }*/ 66 67 string result = q{ 68 private mixin template SoapBindingMethod(alias f) 69 { 70 string executeSoapBinding() 71 { 72 return "return new SoapClient.sendRequestFromFunctionDefinition!(" ~ __stdtraits.fullyQualifiedName!f ~ ")(" ~ __stdtraits.ParameterIdentifierTuple!f ~ ");"; 73 } 74 } 75 }; 76 77 auto bindingTypes = root.getByTagName("wsdl:binding"); 78 79 if (!bindingTypes || !bindingTypes.length) 80 { 81 bindingTypes = root.getByTagName("xs:binding"); 82 } 83 84 if (!bindingTypes || !bindingTypes.length) 85 { 86 bindingTypes = root.getByTagName("xsd:binding"); 87 } 88 89 if (!bindingTypes || !bindingTypes.length) 90 { 91 bindingTypes = root.getByTagName("binding"); 92 } 93 94 if (bindingTypes && bindingTypes.length) 95 { 96 foreach (bindingType; bindingTypes) 97 { 98 auto name = bindingType.getAttribute("name"); 99 100 if (!name) 101 { 102 throw new SoapException("Missing name for binding."); 103 } 104 105 auto type = bindingType.getAttribute("type"); 106 107 if (!type) 108 { 109 throw new SoapException("Missing type for binding."); 110 } 111 112 auto typeName = type.value.split(":").length == 2 ? type.value.split(":")[1] : type.value; 113 114 auto bindingOperations = operations.get(typeName, null); 115 116 string operationsResult = ""; 117 118 if (bindingOperations && bindingOperations.length) 119 { 120 foreach (bindingOperation; bindingOperations) 121 { 122 auto bindingOperationNodes = bindingType.getByAttribute("name", bindingOperation.name); 123 auto bindingOperationNode = bindingOperationNodes && bindingOperationNodes.length ? bindingOperationNodes[0] : null; 124 125 if (bindingOperationNode && (bindingOperationNode.name == "wsdl:operation" || bindingOperationNode.name == "xs:operation" || bindingOperationNode.name == "xsd:operation" || bindingOperationNode.name == "operation")) 126 { 127 auto soapOperations = bindingOperationNode.getByTagName("soap:operation"); 128 auto soapOperation = soapOperations && soapOperations.length ? soapOperations[0] : null; 129 130 auto action = soapOperation && soapOperation.hasAttribute("soapAction") ? soapOperation.getAttribute("soapAction").value : bindingOperation.action; 131 132 if (!action) 133 { 134 action = ""; 135 } 136 137 operationsResult ~= bindingOperationFormat.format(action, bindingOperation.returnType, bindingOperation.name, bindingOperation.parameters, "I" ~ typeName ~ "." ~ bindingOperation.name); 138 } 139 } 140 } 141 142 result ~= bindingClassFormat.format(name.value, typeName, operationsResult); 143 } 144 } 145 146 return result; 147 }