1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 
5 namespace System.ServiceModel.Description
6 {
7 
8     using System.Xml;
9 
10     using System.ServiceModel.Channels;
11 
12     using System.Xml.Schema;
13     using System.Collections.Generic;
14     using System.Collections.ObjectModel;
15     using WsdlNS = System.Web.Services.Description;
16 
17     // This class is created as part of the export process and passed to
18     // Wsdlmporter and WsdlExporter implementations as a utility for
19     // Correlating between the WSDL OM and the Indigo OM
20     // in the conversion process.
21     public class WsdlContractConversionContext
22     {
23 
24         readonly ContractDescription contract;
25         readonly WsdlNS.PortType wsdlPortType;
26 
27         readonly Dictionary<OperationDescription, WsdlNS.Operation> wsdlOperations;
28         readonly Dictionary<WsdlNS.Operation, OperationDescription> operationDescriptions;
29         readonly Dictionary<MessageDescription, WsdlNS.OperationMessage> wsdlOperationMessages;
30         readonly Dictionary<FaultDescription, WsdlNS.OperationFault> wsdlOperationFaults;
31         readonly Dictionary<WsdlNS.OperationMessage, MessageDescription> messageDescriptions;
32         readonly Dictionary<WsdlNS.OperationFault, FaultDescription> faultDescriptions;
33         readonly Dictionary<WsdlNS.Operation, Collection<WsdlNS.OperationBinding>> operationBindings;
34 
WsdlContractConversionContext(ContractDescription contract, WsdlNS.PortType wsdlPortType)35         internal WsdlContractConversionContext(ContractDescription contract, WsdlNS.PortType wsdlPortType)
36         {
37 
38             this.contract = contract;
39             this.wsdlPortType = wsdlPortType;
40 
41             this.wsdlOperations = new Dictionary<OperationDescription, WsdlNS.Operation>();
42             this.operationDescriptions = new Dictionary<WsdlNS.Operation, OperationDescription>();
43             this.wsdlOperationMessages = new Dictionary<MessageDescription, WsdlNS.OperationMessage>();
44             this.messageDescriptions = new Dictionary<WsdlNS.OperationMessage, MessageDescription>();
45             this.wsdlOperationFaults = new Dictionary<FaultDescription, WsdlNS.OperationFault>();
46             this.faultDescriptions = new Dictionary<WsdlNS.OperationFault, FaultDescription>();
47             this.operationBindings = new Dictionary<WsdlNS.Operation, Collection<WsdlNS.OperationBinding>>();
48         }
49 
50         internal IEnumerable<IWsdlExportExtension> ExportExtensions
51         {
52             get
53             {
54                 foreach (IWsdlExportExtension extension in contract.Behaviors.FindAll<IWsdlExportExtension>())
55                 {
56                     yield return extension;
57                 }
58 
59                 foreach (OperationDescription operation in contract.Operations)
60                 {
61                     if (!WsdlExporter.OperationIsExportable(operation))
62                     {
63                         continue;
64                     }
65 
66                     // In 3.0SP1, the DCSOB and XSOB were moved from before to after the custom behaviors.  For
67                     // IWsdlExportExtension compat, run them in the pre-SP1 order.
68                     // TEF QFE 367607
69                     Collection<IWsdlExportExtension> extensions = operation.Behaviors.FindAll<IWsdlExportExtension>();
70                     for (int i = 0; i < extensions.Count; )
71                     {
72                         if (WsdlExporter.IsBuiltInOperationBehavior(extensions[i]))
73                         {
74                             yield return extensions[i];
75                             extensions.RemoveAt(i);
76                         }
77                         else
78                         {
79                             i++;
80                         }
81                     }
82                     foreach (IWsdlExportExtension extension in extensions)
83                     {
84                         yield return extension;
85                     }
86                 }
87             }
88         }
89 
90 
91         public ContractDescription Contract { get { return contract; } }
92         public WsdlNS.PortType WsdlPortType { get { return wsdlPortType; } }
93 
GetOperation(OperationDescription operation)94         public WsdlNS.Operation GetOperation(OperationDescription operation)
95         {
96             return this.wsdlOperations[operation];
97         }
98 
GetOperationMessage(MessageDescription message)99         public WsdlNS.OperationMessage GetOperationMessage(MessageDescription message)
100         {
101             return this.wsdlOperationMessages[message];
102         }
103 
GetOperationFault(FaultDescription fault)104         public WsdlNS.OperationFault GetOperationFault(FaultDescription fault)
105         {
106             return this.wsdlOperationFaults[fault];
107         }
108 
GetOperationDescription(WsdlNS.Operation operation)109         public OperationDescription GetOperationDescription(WsdlNS.Operation operation)
110         {
111             return this.operationDescriptions[operation];
112         }
113 
GetMessageDescription(WsdlNS.OperationMessage operationMessage)114         public MessageDescription GetMessageDescription(WsdlNS.OperationMessage operationMessage)
115         {
116             return this.messageDescriptions[operationMessage];
117         }
118 
GetFaultDescription(WsdlNS.OperationFault operationFault)119         public FaultDescription GetFaultDescription(WsdlNS.OperationFault operationFault)
120         {
121             return this.faultDescriptions[operationFault];
122         }
123 
124         // --------------------------------------------------------------------------------------------------
125 
AddOperation(OperationDescription operationDescription, WsdlNS.Operation wsdlOperation)126         internal void AddOperation(OperationDescription operationDescription, WsdlNS.Operation wsdlOperation)
127         {
128             this.wsdlOperations.Add(operationDescription, wsdlOperation);
129             this.operationDescriptions.Add(wsdlOperation, operationDescription);
130         }
131 
AddMessage(MessageDescription messageDescription, WsdlNS.OperationMessage wsdlOperationMessage)132         internal void AddMessage(MessageDescription messageDescription, WsdlNS.OperationMessage wsdlOperationMessage)
133         {
134             this.wsdlOperationMessages.Add(messageDescription, wsdlOperationMessage);
135             this.messageDescriptions.Add(wsdlOperationMessage, messageDescription);
136         }
137 
AddFault(FaultDescription faultDescription, WsdlNS.OperationFault wsdlOperationFault)138         internal void AddFault(FaultDescription faultDescription, WsdlNS.OperationFault wsdlOperationFault)
139         {
140             this.wsdlOperationFaults.Add(faultDescription, wsdlOperationFault);
141             this.faultDescriptions.Add(wsdlOperationFault, faultDescription);
142         }
143 
GetOperationBindings(WsdlNS.Operation operation)144         internal Collection<WsdlNS.OperationBinding> GetOperationBindings(WsdlNS.Operation operation)
145         {
146             Collection<WsdlNS.OperationBinding> bindings;
147             if (!this.operationBindings.TryGetValue(operation, out bindings))
148             {
149                 bindings = new Collection<WsdlNS.OperationBinding>();
150                 WsdlNS.ServiceDescriptionCollection wsdlDocuments = WsdlPortType.ServiceDescription.ServiceDescriptions;
151                 foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
152                 {
153                     foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
154                     {
155                         if (wsdlBinding.Type.Name == WsdlPortType.Name && wsdlBinding.Type.Namespace == WsdlPortType.ServiceDescription.TargetNamespace)
156                         {
157                             foreach (WsdlNS.OperationBinding operationBinding in wsdlBinding.Operations)
158                             {
159                                 if (WsdlImporter.Binding2DescriptionHelper.Match(operationBinding, operation) != WsdlImporter.Binding2DescriptionHelper.MatchResult.None)
160                                 {
161                                     bindings.Add(operationBinding);
162                                     break;
163                                 }
164                             }
165                         }
166                     }
167                 }
168                 this.operationBindings.Add(operation, bindings);
169             }
170             return bindings;
171         }
172 
173     }
174 
175 }
176