/// <summary>Creates a new <see cref="BplService"/> instance.</summary> internal BplService(BplServiceAttribute attr, Assembly assembly, BplService parent) { Assembly = assembly; Parent = parent; IsAbstract = attr.IsAbstract; Namespace = attr.Namespace; Version = attr.Version; if (Version.IsEmpty()) { Version = assembly.GetName().Version; } if (Namespace.NotEmpty()) { Urn = (XNamespace)("{0}?version={1}".Substitute(Namespace, Version.ToString(3))); ; if (attr.UseLocalSchema && BplLanguage.Schemas.Contains(Urn)) { LocalSchema = Urn; } } else if (!IsAbstract || attr.UseLocalSchema) { BplRuntimeException.Throw("Service namespace is missing"); } Label = attr.Label; if (Label.IsEmpty() && !IsAbstract) { Label = Namespace.After(Namespace.LastIndexOf(".")); if (Label.NotEmpty() && !Label.EndsWith("Services", true)) { Label += "Services"; } } if (attr.OperationsKind != BplOperationKind.Unspecified) { OperationsKind = attr.OperationsKind; } else if (parent != null) { OperationsKind = parent.OperationsKind; } else { OperationsKind = BplOperationKind.RemoteCall; } var baseProvider = (Parent != null ? Parent.Provider : BplPermissions.Unspecified); Provider = BplPermissions.Parse(baseProvider, attr.Provider); var baseConsumer = (Parent != null ? Parent.Consumer: BplPermissions.Unspecified); Consumer = BplPermissions.Parse(baseConsumer, attr.Consumer); Func<Type, Func<BplService, BplClass>, BplClass> inheritType = (type, selector) => { if (type != null) return BplLanguage.LoadClass(type); if (Parent != null) return selector(Parent); return null; }; RequestHeaderType = inheritType(attr.RequestHeaderType, p => p.RequestHeaderType); ResponseHeaderType = inheritType(attr.ResponseHeaderType, p => p.ResponseHeaderType); FailureHeaderType = inheritType(attr.FailureHeaderType, p => p.FailureHeaderType); GeneralFailureType = inheritType(attr.GeneralFailureType, p => p.GeneralFailureType); }
private string TnsName(BplService service) { return TnsName(service.Label); }
private XElement _generateWSDLService_11(BplService service) { var wsdl = XNamespaces.wsdl_11; var soap = XNamespaces.soap_11; var svc = new XElement(wsdl + "service", new XAttribute("name", service.Label) ); if (HasSOAP) { svc.Add(new XElement(wsdl + "port", new XAttribute("name", service.Label + "Port"), new XAttribute("binding", TnsName(service) + "SoapBinding"), new XElement(soap + "address", new XAttribute("location", FormatSoapAddress(service.Label, null)) ) )); } return svc; }
private XElement _generateWSDLService_20(BplService service) { var wsdl = XNamespaces.wsdl_20; var svc = new XElement(wsdl + "service", new XAttribute("name", service.Label), new XAttribute("interface", TnsName("I" + service.Label)) ); if (HasSOAP) { svc.Add(new XElement(wsdl + "endpoint", new XAttribute("name", service.Label + "SoapEndpoint"), new XAttribute("binding", TnsName(service) + "SoapBinding"), new XAttribute("address", FormatSoapAddress(service.Label, null)) )); } if (HasREST) { svc.Add(new XElement(wsdl + "endpoint", new XAttribute("name", service.Label + "RestEndpoint"), new XAttribute("binding", TnsName(service) + "RestBinding"), new XAttribute("address", FormatRestAddress(service.Label, null)) )); } return svc; }
private XElement _generateWSDLSoapBinding_20(BplService service, IEnumerable<BplOperation> operations) { var wsdl = XNamespaces.wsdl_20; var binding = new XElement(wsdl + "binding", new XAttribute("name", service.Label + "SoapBinding"), new XAttribute("interface", TnsName("I" + service.Label)), new XAttribute("type", XNamespaces.wsoap_20.NamespaceName), new XAttribute(XNamespaces.wsoap_20 + "protocol", XNamespaces.soapHttp_20.NamespaceName) ); foreach (var failure in GetDistinctFailures(operations)) { binding.Add(new XElement(wsdl + "fault", new XAttribute("ref", TnsName(failure)) )); } foreach (var op in operations) { var bindingOp = new XElement(wsdl + "operation", new XAttribute("ref", TnsName(op)), new XAttribute(XNamespaces.wsoap_20 + "mep", "http://www.w3.org/2003/05/soap/mep/soap-response") ); binding.Add(bindingOp); } return binding; }
private XElement _generateWSDLRestBinding_20(BplService service, IEnumerable<BplOperation> operations) { var wsdl = XNamespaces.wsdl_20; var binding = new XElement(wsdl + "binding", new XAttribute("name", service.Label + "RestBinding"), new XAttribute("interface", TnsName("I" + service.Label)), new XAttribute("type", XNamespaces.whttp_20.NamespaceName) ); foreach (var op in operations) { var bindingOp = new XElement(wsdl + "operation", new XAttribute("ref", TnsName(op)), new XAttribute(XNamespaces.whttp_20 + "method", "GET") ); binding.Add(bindingOp); } return binding; }
private XElement _generateWSDLSoapBinding_11(BplService service, IEnumerable<BplOperation> operations) { var wsdl = XNamespaces.wsdl_11; var soap = XNamespaces.soap_11; var binding = new XElement(wsdl + "binding", new XAttribute("name", service.Label + "SoapBinding"), new XAttribute("type", TnsName("I" + service.Label)) ); binding.Add(new XElement(soap + "binding", new XAttribute("style", "document"), new XAttribute("transport", XNamespaces.soapHttp_11.NamespaceName) )); foreach (var op in operations) { var bindingOp = new XElement(wsdl + "operation", new XAttribute("name", op.Name)); bindingOp.Add(new XElement(soap + "operation", new XAttribute("soapAction", FormatSoapAddress(service.Label, op.Name)) )); Action<string, string, BplClass> addBinding = (partType, partName, headerClass) => { var bindingPart = new XElement(wsdl + partType); if (partName.NotEmpty()) bindingPart.Add(new XAttribute("name", partName)); bindingPart.Add(new XElement(soap + "body", new XAttribute("use", "literal"))); if (headerClass != null) { bindingPart.Add(new XElement(soap + "header", new XAttribute("message", TnsName(headerClass)), new XAttribute("part", "body"), new XAttribute("use", "literal")) ); } bindingOp.Add(bindingPart); }; if (op.Input != null) { addBinding("input", null, service.RequestHeaderType); } if (op.Output != null) { addBinding("output", null, service.ResponseHeaderType); } if (op.Failures != null) { foreach (var failure in op.Failures) { addBinding("fault", failure.Name, service.FailureHeaderType); } } binding.Add(bindingOp); } return binding; }
private XElement _generateWSDLInterface_20(BplService service, IEnumerable<BplOperation> operations) { var wsdl = XNamespaces.wsdl_20; var intf = new XElement(wsdl + "interface", new XAttribute("name", "I" + service.Label)); foreach (var failure in GetDistinctFailures(operations)) { intf.Add(new XElement(wsdl + "fault", new XAttribute("name", failure.Name), new XAttribute("element", failure.Name) )); } foreach (var op in operations) { var pattern = op.Input != null ? (op.Output != null ? "in-out" : "in") : (op.Output != null ? "out" : ""); var intfOper = new XElement(wsdl + "operation", new XAttribute("name", op.Name), new XAttribute("pattern", "http://www.w3.org/ns/wsdl/" + pattern), new XAttribute("style", "http://www.w3.org/ns/wsdl/style/iri"), new XAttribute(XNamespaces.wsdlx_20 + "safe", "true") ); if (op.Input != null) { intfOper.Add(new XElement(wsdl + "input", new XAttribute("messageLabel", "In"), new XAttribute("element", QName(op.Input)) )); } if (op.Output != null) { intfOper.Add(new XElement(wsdl + "output", new XAttribute("messageLabel", "Out"), new XAttribute("element", QName(op.Output)) )); } if (op.Failures != null) { foreach (var failure in op.Failures) { intfOper.Add(new XElement(wsdl + "outfault", new XAttribute("messageLabel", failure.Name), new XAttribute("ref", TnsName(failure)) )); } } intf.Add(intfOper); } return intf; }
private XElement _generateWSDLInterface_11(BplService service, IEnumerable<BplOperation> operations) { var wsdl = XNamespaces.wsdl_11; var intf = new XElement(wsdl + "portType", new XAttribute("name", "I" + service.Label)); foreach (var op in operations) { var intfOper = new XElement(wsdl + "operation", new XAttribute("name", op.Name)); if (op.Input != null) { intfOper.Add(new XElement(wsdl + "input", new XAttribute("message", TnsName(op.Input)) )); } if (op.Output != null) { intfOper.Add(new XElement(wsdl + "output", new XAttribute("message", TnsName(op.Output)) )); } if (op.Failures != null) { foreach (var failure in op.Failures) { intfOper.Add(new XElement(wsdl + "fault", new XAttribute("name", failure.Name), new XAttribute("message", TnsName(failure)) )); } } intf.Add(intfOper); } return intf; }
private XElement _generateWSDLMessageHeader(BplService service, BplClass headerClass) { var xsd = XNamespaces.xsd; var headerFields = new XElement(xsd + "sequence"); var headerSelector = headerClass.OwnProperties.Where(p => p.IsPrimitive || p.IsTaxonomy); if (SortMembers) { headerSelector = headerSelector.OrderBy(p => p.Name); } foreach (var prop in headerSelector) { var propType = (prop.IsPrimitive ? QName(prop.PrimitiveType) : QName(BplPrimitive.Get<BplIdentity>())); headerFields.Add(new XElement(xsd + "element", new XAttribute("name", prop.Name), new XAttribute("type", propType) )); }; return new XElement(xsd + "element", new XAttribute("name", headerClass.Name), new XElement(xsd + "complexType", headerFields) ); }
private XDocument _generateWSDL(BplService service) { // get service operations var operations = _services[service].OrderBy(op => op.Name).ToArray(); var imports = new HashSet<XNamespace>(); foreach (var op in operations) { if (op.Input != null) { imports.Add(op.Input.Schema); } if (op.Output != null) { imports.Add(op.Output.Schema); } if (op.Failures != null) { foreach (var failure in op.Failures) { imports.Add(failure.Schema); } } } // get local schema var xsd = XNamespaces.xsd; var localSchema = new XElement(xsd + "schema", new XAttribute("targetNamespace", service.Urn)); var localImports = new HashSet<XNamespace>(); var useLocalPrefix = false; _tnsPrefix = "tns"; if (UseLocalSchemas && service.LocalSchema != null) { var localFile = FormatFileName(service.LocalSchema, ".xsd"); if (_output.ContainsKey(localFile)) { foreach (var node in _output[localFile].Root.Elements()) { if (node.Name == xsd + "import") { localImports.Add((XNamespace)node.Get("namespace")); } else { localSchema.Add(node); } } if (localSchema.HasElements) { localSchema.AddFirst(new XComment(" Local Types ")); } _output.Remove(localFile); _tnsPrefix = BplLanguage.Schemas[service.LocalSchema]; useLocalPrefix = true; } } // generate header var wsdl = IsWSDL_20 ? XNamespaces.wsdl_20 : XNamespaces.wsdl_11; var soap = IsWSDL_20 ? XNamespaces.soap_20 : XNamespaces.soap_11; var root = new XElement(wsdl + "definitions"); root.Add(new XAttribute("targetNamespace", service.Urn)); if (!useLocalPrefix) { root.Add(new XAttribute(XNamespaces.xmlns + _tnsPrefix, service.Urn)); } foreach (var ns in imports.Union(localImports)) { root.Add(new XAttribute(XNamespaces.xmlns + NSPrefix(ns), NSName(ns))); } root.Add(XNamespaces.GetDeclaration(xsd)); root.Add(XNamespaces.GetDeclaration(soap)); root.Add(XNamespaces.GetDeclaration(wsdl)); if (IsWSDL_20) { root.Add(XNamespaces.GetDeclaration(XNamespaces.wsoap_20)); root.Add(XNamespaces.GetDeclaration(XNamespaces.wsdlx_20)); root.Add(XNamespaces.GetDeclaration(XNamespaces.whttp_20)); } Action<string> addComment = text => root.Add(new XComment(" " + text + " ")); // generate types addComment("TYPES"); var types = new XElement(wsdl + "types"); foreach (var ns in imports.Union(localImports)) { if (UseLocalSchemas && service.LocalSchema == ns) continue; types.Add(_generateWSDLImport(ns)); } Action<string, BplClass> addMessageHeader = (label, headerClass) => { if (headerClass != null) { localSchema.Add(new XComment(" " + label + " ")); localSchema.Add(_generateWSDLMessageHeader(service, headerClass)); } }; addMessageHeader("Input Header", service.RequestHeaderType); addMessageHeader("Output Header", service.ResponseHeaderType); addMessageHeader("Fault Header", service.FailureHeaderType); if (localSchema.HasElements) { types.Add(localSchema); } root.Add(types); // generate messages if (IsWSDL_11) { addComment("MESSAGES"); var messages = new HashSet<BplClass>(); Action<BplClass, bool> addMessage = (bplClass, isMessageHeader) => { if (bplClass == null || messages.Contains(bplClass)) return; root.Add(_generateWSDLMessage_11(bplClass, isMessageHeader)); messages.Add(bplClass); }; foreach (var failure in GetDistinctFailures(operations)) { addMessage(failure, false); } foreach (var op in operations) { addMessage(op.Input, false); addMessage(op.Output, false); } addMessage(service.RequestHeaderType, true); addMessage(service.ResponseHeaderType, true); addMessage(service.FailureHeaderType, true); } // generate interface addComment("INTERFACE"); if (IsWSDL_11) { root.Add(_generateWSDLInterface_11(service, operations)); } else if (IsWSDL_20) { root.Add(_generateWSDLInterface_20(service, operations)); } // generate bindings if (IsWSDL_11) { if (HasSOAP) { addComment("SOAP BINDING"); root.Add(_generateWSDLSoapBinding_11(service, operations)); } } else if (IsWSDL_20) { if (HasSOAP) { addComment("SOAP BINDING"); root.Add(_generateWSDLSoapBinding_20(service, operations)); } if (HasREST) { addComment("REST BINDING"); root.Add(_generateWSDLRestBinding_20(service, operations)); } } // generate service addComment("SERVICE"); if (IsWSDL_11) { root.Add(_generateWSDLService_11(service)); } else if (IsWSDL_20) { root.Add(_generateWSDLService_20(service)); } return new XDocument(root); }