| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using System.Collections; |
| | | 6 | | using System.Collections.Generic; |
| | | 7 | | using System.Collections.ObjectModel; |
| | | 8 | | using System.Xml; |
| | | 9 | | using System.Xml.Schema; |
| | | 10 | | using CoreWCF.Runtime; |
| | | 11 | | |
| | | 12 | | namespace CoreWCF.Description |
| | | 13 | | { |
| | | 14 | | internal static class SchemaHelper |
| | | 15 | | { |
| | | 16 | | internal static void AddElementForm(XmlSchemaElement element, XmlSchema schema) |
| | | 17 | | { |
| | 217 | 18 | | if (schema.ElementFormDefault != XmlSchemaForm.Qualified) |
| | | 19 | | { |
| | 0 | 20 | | element.Form = XmlSchemaForm.Qualified; |
| | | 21 | | } |
| | 217 | 22 | | } |
| | | 23 | | |
| | | 24 | | internal static void AddElementToSchema(XmlSchemaElement element, XmlSchema schema, XmlSchemaSet schemaSet) |
| | | 25 | | { |
| | 220 | 26 | | XmlSchemaElement existingElement = (XmlSchemaElement)schema.Elements[new XmlQualifiedName(element.Name, sche |
| | 220 | 27 | | if (existingElement != null) |
| | | 28 | | { |
| | 0 | 29 | | if (element.SchemaType == existingElement.SchemaType && element.SchemaTypeName == existingElement.Schema |
| | | 30 | | { |
| | 0 | 31 | | return; |
| | | 32 | | } |
| | | 33 | | |
| | 0 | 34 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.SFx |
| | | 35 | | } |
| | | 36 | | |
| | 220 | 37 | | schema.Items.Add(element); |
| | 220 | 38 | | if (!element.SchemaTypeName.IsEmpty) |
| | | 39 | | { |
| | 0 | 40 | | AddImportToSchema(element.SchemaTypeName.Namespace, schema); |
| | | 41 | | } |
| | | 42 | | |
| | 220 | 43 | | schemaSet.Reprocess(schema); |
| | 220 | 44 | | } |
| | | 45 | | |
| | | 46 | | internal static void AddImportToSchema(string ns, XmlSchema schema) |
| | | 47 | | { |
| | 216 | 48 | | if (NamespacesEqual(ns, schema.TargetNamespace) |
| | 216 | 49 | | || NamespacesEqual(ns, XmlSchema.Namespace) |
| | 216 | 50 | | || NamespacesEqual(ns, XmlSchema.InstanceNamespace)) |
| | | 51 | | { |
| | 118 | 52 | | return; |
| | | 53 | | } |
| | | 54 | | |
| | 284 | 55 | | foreach (object item in schema.Includes) |
| | | 56 | | { |
| | 82 | 57 | | if (item is XmlSchemaImport && NamespacesEqual(ns, ((XmlSchemaImport)item).Namespace)) |
| | | 58 | | { |
| | 76 | 59 | | return; |
| | | 60 | | } |
| | | 61 | | } |
| | | 62 | | |
| | 22 | 63 | | XmlSchemaImport import = new XmlSchemaImport(); |
| | 22 | 64 | | if (ns != null && ns.Length > 0) |
| | | 65 | | { |
| | 22 | 66 | | import.Namespace = ns; |
| | | 67 | | } |
| | | 68 | | |
| | 22 | 69 | | schema.Includes.Add(import); |
| | 98 | 70 | | } |
| | | 71 | | |
| | | 72 | | internal static void AddTypeToSchema(XmlSchemaType type, XmlSchema schema, XmlSchemaSet schemaSet) |
| | | 73 | | { |
| | 15 | 74 | | XmlSchemaType existingType = (XmlSchemaType)schema.SchemaTypes[new XmlQualifiedName(type.Name, schema.Target |
| | 15 | 75 | | if (existingType != null) |
| | | 76 | | { |
| | 0 | 77 | | if (existingType == type) |
| | | 78 | | { |
| | 0 | 79 | | return; |
| | | 80 | | } |
| | | 81 | | |
| | 0 | 82 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.SFx |
| | | 83 | | } |
| | | 84 | | |
| | 15 | 85 | | schema.Items.Add(type); |
| | | 86 | | |
| | 15 | 87 | | schemaSet.Reprocess(schema); |
| | 15 | 88 | | } |
| | | 89 | | |
| | | 90 | | internal static XmlSchema GetSchema(string ns, XmlSchemaSet schemaSet) |
| | | 91 | | { |
| | 497 | 92 | | if (ns == null) { ns = string.Empty; } |
| | | 93 | | |
| | 497 | 94 | | ICollection schemas = schemaSet.Schemas(); |
| | 1694 | 95 | | foreach (XmlSchema existingSchema in schemas) |
| | | 96 | | { |
| | 580 | 97 | | if ((existingSchema.TargetNamespace == null && ns.Length == 0) || ns.Equals(existingSchema.TargetNamespa |
| | | 98 | | { |
| | 460 | 99 | | return existingSchema; |
| | | 100 | | } |
| | | 101 | | } |
| | | 102 | | |
| | 37 | 103 | | XmlSchema schema = new XmlSchema(); |
| | 37 | 104 | | schema.ElementFormDefault = XmlSchemaForm.Qualified; |
| | 37 | 105 | | if (ns.Length > 0) |
| | | 106 | | { |
| | 37 | 107 | | schema.TargetNamespace = ns; |
| | | 108 | | } |
| | | 109 | | |
| | 37 | 110 | | schemaSet.Add(schema); |
| | 37 | 111 | | return schema; |
| | 460 | 112 | | } |
| | | 113 | | |
| | | 114 | | private static string GetTypeName(XmlSchemaElement element) |
| | | 115 | | { |
| | 0 | 116 | | if (element.SchemaType != null) |
| | | 117 | | { |
| | 0 | 118 | | return "anonymous"; |
| | | 119 | | } |
| | | 120 | | |
| | 0 | 121 | | if (!element.SchemaTypeName.IsEmpty) |
| | | 122 | | { |
| | 0 | 123 | | return element.SchemaTypeName.ToString(); |
| | | 124 | | } |
| | | 125 | | |
| | 0 | 126 | | return string.Empty; |
| | | 127 | | } |
| | | 128 | | |
| | | 129 | | // Compare XmlSchemaElement properties set by WsdlExporter: do not check element QName, |
| | | 130 | | // this code only called for elements with matching name and namespace |
| | | 131 | | internal static bool IsMatch(XmlSchemaElement e1, XmlSchemaElement e2) |
| | | 132 | | { |
| | | 133 | | // this code only called for elements with matching name and namespace |
| | | 134 | | Fx.Assert(e1.Name == e2.Name, ""); |
| | | 135 | | // Anonymous types never match |
| | 0 | 136 | | if (e1.SchemaType != null || e2.SchemaType != null) |
| | | 137 | | { |
| | 0 | 138 | | return false; |
| | | 139 | | } |
| | | 140 | | |
| | 0 | 141 | | if (e1.SchemaTypeName != e2.SchemaTypeName) |
| | | 142 | | { |
| | 0 | 143 | | return false; |
| | | 144 | | } |
| | | 145 | | |
| | | 146 | | // do not need to check parent Schema.ElementFormDefault: see AddElementForm in this class. |
| | 0 | 147 | | if (e1.Form != e2.Form) |
| | | 148 | | { |
| | 0 | 149 | | return false; |
| | | 150 | | } |
| | | 151 | | |
| | 0 | 152 | | if (e1.IsNillable != e2.IsNillable) |
| | | 153 | | { |
| | 0 | 154 | | return false; |
| | | 155 | | } |
| | | 156 | | |
| | 0 | 157 | | return true; |
| | | 158 | | } |
| | | 159 | | |
| | | 160 | | internal static bool NamespacesEqual(string ns1, string ns2) |
| | | 161 | | { |
| | 1972 | 162 | | if (ns1 == null || ns1.Length == 0) |
| | | 163 | | { |
| | 0 | 164 | | return ns2 == null || ns2.Length == 0; |
| | | 165 | | } |
| | | 166 | | else |
| | | 167 | | { |
| | 1972 | 168 | | return ns1 == ns2; |
| | | 169 | | } |
| | | 170 | | } |
| | | 171 | | |
| | | 172 | | internal static void Compile(XmlSchemaSet schemaSet, Collection<MetadataConversionError> errors) |
| | | 173 | | { |
| | 243 | 174 | | ValidationEventHandler validationEventHandler = new ValidationEventHandler(delegate (object sender, Validati |
| | 243 | 175 | | { |
| | 0 | 176 | | HandleSchemaValidationError(sender, args, errors); |
| | 243 | 177 | | }); |
| | 243 | 178 | | schemaSet.ValidationEventHandler += validationEventHandler; |
| | 243 | 179 | | schemaSet.Compile(); |
| | 243 | 180 | | schemaSet.ValidationEventHandler -= validationEventHandler; |
| | 243 | 181 | | } |
| | | 182 | | |
| | | 183 | | internal static void HandleSchemaValidationError(object sender, ValidationEventArgs args, Collection<MetadataCon |
| | | 184 | | { |
| | | 185 | | MetadataConversionError warning; |
| | 0 | 186 | | if (args.Exception != null && args.Exception.SourceUri != null) |
| | | 187 | | { |
| | 0 | 188 | | XmlSchemaException ex = args.Exception; |
| | 0 | 189 | | warning = new MetadataConversionError(SR.Format(SR.SchemaValidationError, ex.SourceUri, ex.LineNumber, e |
| | | 190 | | } |
| | | 191 | | else |
| | | 192 | | { |
| | 0 | 193 | | warning = new MetadataConversionError(SR.Format(SR.GeneralSchemaValidationError, args.Message)); |
| | | 194 | | } |
| | | 195 | | |
| | 0 | 196 | | if (!errors.Contains(warning)) |
| | | 197 | | { |
| | 0 | 198 | | errors.Add(warning); |
| | | 199 | | } |
| | 0 | 200 | | } |
| | | 201 | | |
| | 0 | 202 | | private static IList<string> xsdValueTypePrimitives = new string[] |
| | 0 | 203 | | { |
| | 0 | 204 | | "boolean", "float", "double", "decimal", "long", "unsignedLong", "int", "unsignedInt", "short", "unsignedSho |
| | 0 | 205 | | "duration", "dateTime", "integer", "positiveInteger", "negativeInteger", "nonPositiveInteger" |
| | 0 | 206 | | }; |
| | 0 | 207 | | private static IList<string> dataContractPrimitives = new string[] { "char", "guid" }; |
| | 0 | 208 | | private static string dataContractSerializerNamespace = "http://schemas.microsoft.com/2003/10/Serialization/"; |
| | 0 | 209 | | private static string xmlSerializerNamespace = "http://microsoft.com/wsdl/types/"; |
| | | 210 | | |
| | | 211 | | internal static bool IsElementValueType(XmlSchemaElement element) |
| | | 212 | | { |
| | 0 | 213 | | XmlQualifiedName typeName = element.SchemaTypeName; |
| | 0 | 214 | | if (typeName == null || typeName.IsEmpty) |
| | | 215 | | { |
| | 0 | 216 | | return false; |
| | | 217 | | } |
| | | 218 | | |
| | 0 | 219 | | if (typeName.Namespace == XmlSchema.Namespace) |
| | | 220 | | { |
| | 0 | 221 | | return xsdValueTypePrimitives.Contains(typeName.Name); |
| | | 222 | | } |
| | | 223 | | |
| | 0 | 224 | | if (typeName.Namespace == dataContractSerializerNamespace) |
| | | 225 | | { |
| | 0 | 226 | | return dataContractPrimitives.Contains(typeName.Name); |
| | | 227 | | } |
| | | 228 | | |
| | 0 | 229 | | if (typeName.Namespace == xmlSerializerNamespace) |
| | | 230 | | { |
| | 0 | 231 | | return dataContractPrimitives.Contains(typeName.Name); |
| | | 232 | | } |
| | | 233 | | |
| | 0 | 234 | | return false; |
| | | 235 | | } |
| | | 236 | | } |
| | | 237 | | } |