private IServiceMap AddServiceMap(XName qualifiedName) { var operationDefinition = GetOperationDefinition(contractAssembly, qualifiedName); if (operationDefinition == null || qualifiedName.NamespaceName != operationDefinition.Name.NamespaceName) { throw XRoadException.UnknownOperation(qualifiedName); } var requestValueDefinition = schemaDefinitionProvider.GetRequestValueDefinition(operationDefinition); var inputTypeMap = GetContentDefinitionTypeMap(requestValueDefinition, null); var outputTuple = GetReturnValueTypeMap(operationDefinition); var responseValueDefinition = outputTuple.Item1; var outputTypeMap = outputTuple.Item2; var serviceMap = (IServiceMap)Activator.CreateInstance( operationDefinition.ServiceMapType, this, operationDefinition, requestValueDefinition, responseValueDefinition, inputTypeMap, outputTypeMap ); return(serviceMaps.GetOrAdd(qualifiedName, serviceMap)); }
private IEnumerable <XmlSchema> BuildSchemas(string targetNamespace, MessageCollection messages) { var schemaTypes = new List <Tuple <string, XmlSchemaType> >(); var schemaElements = new List <XmlSchemaElement>(); var referencedTypes = new Dictionary <XmlQualifiedName, XmlSchemaType>(); var faultDefinition = schemaDefinitionProvider.GetFaultDefinition(); var addFaultType = false; foreach (var operationDefinition in GetOperationDefinitions(targetNamespace)) { var requestValueDefinition = schemaDefinitionProvider.GetRequestValueDefinition(operationDefinition); Func <XmlSchemaElement> createRequestElement = () => requestValueDefinition.ParameterInfo != null ? CreateContentElement(requestValueDefinition, targetNamespace, referencedTypes) : new XmlSchemaElement { Name = requestValueDefinition.RequestElementName, SchemaType = new XmlSchemaComplexType { Particle = new XmlSchemaSequence() } }; var requestElement = createRequestElement(); AddCustomAttributes(requestValueDefinition, requestElement, ns => addRequiredImport(targetNamespace, ns, operationDefinition.ExtensionSchemaExporter)); if (protocol.Style.UseElementInMessagePart) { schemaElements.Add(new XmlSchemaElement { Name = operationDefinition.Name.LocalName, SchemaType = new XmlSchemaComplexType { Particle = new XmlSchemaSequence { Items = { requestElement } } } }); } var responseValueDefinition = schemaDefinitionProvider.GetResponseValueDefinition(operationDefinition); if (!responseValueDefinition.ContainsNonTechnicalFault) { addFaultType = true; } XmlSchemaElement responseElement; XmlSchemaElement resultElement = null; if (responseValueDefinition.XRoadFaultPresentation != XRoadFaultPresentation.Implicit && responseValueDefinition.ContainsNonTechnicalFault) { var outputParticle = new XmlSchemaSequence(); responseElement = new XmlSchemaElement { Name = responseValueDefinition.ResponseElementName, SchemaType = new XmlSchemaComplexType { Particle = outputParticle } }; var faultSequence = CreateFaultSequence(); if (operationDefinition.MethodInfo.ReturnType == typeof(void)) { faultSequence.MinOccurs = 0; outputParticle.Items.Add(faultSequence); } else if (responseValueDefinition.XRoadFaultPresentation == XRoadFaultPresentation.Choice) { resultElement = CreateContentElement(responseValueDefinition, targetNamespace, referencedTypes); outputParticle.Items.Add(new XmlSchemaChoice { Items = { resultElement, faultSequence } }); } else { resultElement = CreateContentElement(responseValueDefinition, targetNamespace, referencedTypes); resultElement.MinOccurs = 0; outputParticle.Items.Add(resultElement); faultSequence.MinOccurs = 0; outputParticle.Items.Add(faultSequence); } } else { responseElement = resultElement = CreateContentElement(responseValueDefinition, targetNamespace, referencedTypes); } AddCustomAttributes(responseValueDefinition, responseElement, ns => addRequiredImport(targetNamespace, ns, operationDefinition.ExtensionSchemaExporter)); if (protocol.Style.UseElementInMessagePart) { var responseRequestElement = requestElement; if (requestValueDefinition.RequestElementName != responseValueDefinition.RequestElementName) { responseRequestElement = createRequestElement(); responseRequestElement.Name = responseValueDefinition.RequestElementName; } schemaElements.Add(new XmlSchemaElement { Name = $"{operationDefinition.Name.LocalName}Response", SchemaType = CreateOperationResponseSchemaType(responseValueDefinition, responseRequestElement, responseElement, faultDefinition) }); } if (operationDefinition.IsAbstract) { continue; } var inputMessage = new Message { Name = operationDefinition.InputMessageName }; if (protocol.Style.UseElementInMessagePart) { inputMessage.Parts.Add(new MessagePart { Name = "body", Element = new XmlQualifiedName(operationDefinition.Name.LocalName, operationDefinition.Name.NamespaceName) }); } else { var requestTypeName = requestElement?.SchemaTypeName; inputMessage.Parts.Add(new MessagePart { Name = requestValueDefinition.RequestElementName, Type = requestTypeName }); } if (operationDefinition.InputBinaryMode == BinaryMode.Attachment) { inputMessage.Parts.Add(new MessagePart { Name = "file", Type = new XmlQualifiedName("base64Binary", NamespaceConstants.XSD) }); } messages.Add(inputMessage); var outputMessage = new Message { Name = operationDefinition.OutputMessageName }; if (protocol.Style.UseElementInMessagePart) { outputMessage.Parts.Add(new MessagePart { Name = "body", Element = new XmlQualifiedName($"{operationDefinition.Name.LocalName}Response", operationDefinition.Name.NamespaceName) }); } else { var requestTypeName = requestElement?.SchemaTypeName; var responseTypeName = GetOutputMessageTypeName(resultElement, operationDefinition.MethodInfo.ReturnType, schemaTypes); outputMessage.Parts.Add(new MessagePart { Name = responseValueDefinition.RequestElementName, Type = requestTypeName }); outputMessage.Parts.Add(new MessagePart { Name = responseValueDefinition.ResponseElementName, Type = responseTypeName }); } if (operationDefinition.OutputBinaryMode == BinaryMode.Attachment) { outputMessage.Parts.Add(new MessagePart { Name = "file", Type = new XmlQualifiedName("base64Binary", NamespaceConstants.XSD) }); } messages.Add(outputMessage); AddPortTypeOperation(operationDefinition, inputMessage, outputMessage, targetNamespace); AddBindingOperation(operationDefinition); } int initialCount; do { initialCount = referencedTypes.Count; foreach (var kvp in referencedTypes.ToList().Where(x => x.Value == null)) { TypeDefinition typeDefinition; if (!schemaTypeDefinitions.TryGetValue(XName.Get(kvp.Key.Name, kvp.Key.Namespace), out typeDefinition)) { continue; } if (typeDefinition.IsSimpleType) { continue; } XmlSchemaType schemaType; if (typeDefinition.Type.GetTypeInfo().IsEnum) { schemaType = new XmlSchemaSimpleType(); AddEnumTypeContent(typeDefinition.Type, (XmlSchemaSimpleType)schemaType); } else { schemaType = new XmlSchemaComplexType { IsAbstract = typeDefinition.Type.GetTypeInfo().IsAbstract }; if (AddComplexTypeContent((XmlSchemaComplexType)schemaType, typeDefinition.Name.NamespaceName, typeDefinition, referencedTypes) != null) { throw new NotImplementedException(); } } schemaType.Name = typeDefinition.Name.LocalName; schemaType.Annotation = CreateSchemaAnnotation(typeDefinition.Name.NamespaceName, typeDefinition); AddSchemaType(schemaTypes, typeDefinition.Name.NamespaceName, schemaType); referencedTypes[kvp.Key] = schemaType; List <Type> typeList; if (!derivedTypes.TryGetValue(typeDefinition.Type, out typeList)) { continue; } foreach (var qualifiedName in typeList.Select(x => runtimeTypeDefinitions[x]).Select(x => new XmlQualifiedName(x.Name.LocalName, x.Name.NamespaceName)).Where(x => !referencedTypes.ContainsKey(x))) { referencedTypes.Add(qualifiedName, null); } } } while (initialCount != referencedTypes.Count); if (addFaultType && faultDefinition.State == DefinitionState.Default) { AddSchemaType(schemaTypes, faultDefinition.Name.NamespaceName, new XmlSchemaComplexType { Name = faultDefinition.Name.LocalName, Particle = CreateFaultSequence(), Annotation = CreateSchemaAnnotation(faultDefinition.Name.NamespaceName, faultDefinition) }); } return(schemaTypes .Select(x => x.Item1) .Where(x => x != NamespaceConstants.XSD && x != targetNamespace) .Distinct() .Where(ns => schemaLocations[ns] == null) .Select(x => BuildSchemaForNamespace(x, schemaTypes, null)) .Concat(new [] { BuildSchemaForNamespace(targetNamespace, schemaTypes, schemaElements) }) .ToList()); }