[bcl] Add missing APIs for netstandard parity and expose a few APIs on mobile
[mono.git] / mcs / class / System.Runtime.Serialization / ReferenceSources / SchemaExporter_mobile.cs
1
2 namespace System.Runtime.Serialization
3 {
4         using System;
5         using System.Collections;
6         using System.Collections.Generic;
7         using System.Collections.ObjectModel;
8         using System.Diagnostics;
9         using System.Globalization;
10         using System.IO;
11         using System.Reflection;
12         using System.Runtime.Diagnostics;
13         using System.Security;
14         using System.Xml;
15         using System.Xml.Schema;
16         using System.Xml.Serialization;
17         using System.Runtime.Serialization.Diagnostics;
18
19         class SchemaExporter
20         {
21         internal static void GetXmlTypeInfo(Type type, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot)
22         {
23             if (IsSpecialXmlType(type, out stableName, out xsdType, out hasRoot))
24                 return;
25             XmlSchemaSet schemas = new XmlSchemaSet();
26             schemas.XmlResolver = null;
27             InvokeSchemaProviderMethod(type, schemas, out stableName, out xsdType, out hasRoot);
28             if (stableName.Name == null || stableName.Name.Length == 0)
29                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidXmlDataContractName, DataContract.GetClrTypeFullName(type))));
30         }
31
32         internal static bool IsSpecialXmlType(Type type, out XmlQualifiedName typeName, out XmlSchemaType xsdType, out bool hasRoot)
33         {
34             xsdType = null;
35             hasRoot = true;
36             if (type == Globals.TypeOfXmlElement || type == Globals.TypeOfXmlNodeArray)
37             {
38                 string name = null;
39                 if (type == Globals.TypeOfXmlElement)
40                 {
41                     xsdType = CreateAnyElementType();
42                     name = "XmlElement";
43                     hasRoot = false;
44                 }
45                 else
46                 {
47                     xsdType = CreateAnyType();
48                     name = "ArrayOfXmlNode";
49                     hasRoot = true;
50                 }
51                 typeName = new XmlQualifiedName(name, DataContract.GetDefaultStableNamespace(type));
52                 return true;
53             }
54             typeName = null;
55             return false;
56         }
57
58         internal static void AddDefaultXmlType(XmlSchemaSet schemas, string localName, string ns)
59         {
60             throw new NotImplementedException();
61         }
62
63         static bool InvokeSchemaProviderMethod(Type clrType, XmlSchemaSet schemas, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot)
64         {
65             xsdType = null;
66             hasRoot = true;
67             object[] attrs = clrType.GetCustomAttributes(Globals.TypeOfXmlSchemaProviderAttribute, false);
68             if (attrs == null || attrs.Length == 0)
69             {
70                 stableName = DataContract.GetDefaultStableName(clrType);
71                 return false;
72             }
73
74             XmlSchemaProviderAttribute provider = (XmlSchemaProviderAttribute)attrs[0];
75             if (provider.IsAny)
76             {
77                 xsdType = CreateAnyElementType();
78                 hasRoot = false;
79             }
80             string methodName = provider.MethodName;
81             if (methodName == null || methodName.Length == 0)
82             {
83                 if (!provider.IsAny)
84                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidGetSchemaMethod, DataContract.GetClrTypeFullName(clrType))));
85                 stableName = DataContract.GetDefaultStableName(clrType);
86             }
87             else
88             {
89                 MethodInfo getMethod = clrType.GetMethod(methodName,  /*BindingFlags.DeclaredOnly |*/ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(XmlSchemaSet) }, null);
90                 if (getMethod == null)
91                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.MissingGetSchemaMethod, DataContract.GetClrTypeFullName(clrType), methodName)));
92
93                 if (!(Globals.TypeOfXmlQualifiedName.IsAssignableFrom(getMethod.ReturnType)) && !(Globals.TypeOfXmlSchemaType.IsAssignableFrom(getMethod.ReturnType)))
94                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidReturnTypeOnGetSchemaMethod, DataContract.GetClrTypeFullName(clrType), methodName, DataContract.GetClrTypeFullName(getMethod.ReturnType), DataContract.GetClrTypeFullName(Globals.TypeOfXmlQualifiedName), typeof(XmlSchemaType))));
95
96                 object typeInfo = getMethod.Invoke(null, new object[] { schemas });
97
98                 if (provider.IsAny)
99                 {
100                     if (typeInfo != null)
101                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidNonNullReturnValueByIsAny, DataContract.GetClrTypeFullName(clrType), methodName)));
102                     stableName = DataContract.GetDefaultStableName(clrType);
103                 }
104                 else if (typeInfo == null)
105                 {
106                     xsdType = CreateAnyElementType();
107                     hasRoot = false;
108                     stableName = DataContract.GetDefaultStableName(clrType);
109                 }
110                 else
111                 {
112                     XmlSchemaType providerXsdType = typeInfo as XmlSchemaType;
113                     if (providerXsdType != null)
114                     {
115                         string typeName = providerXsdType.Name;
116                         string typeNs = null;
117                         if (typeName == null || typeName.Length == 0)
118                         {
119                             DataContract.GetDefaultStableName(DataContract.GetClrTypeFullName(clrType), out typeName, out typeNs);
120                             stableName = new XmlQualifiedName(typeName, typeNs);
121                             providerXsdType.Annotation = GetSchemaAnnotation(ExportActualType(stableName, new XmlDocument()));
122                             xsdType = providerXsdType;
123                         }
124                         else
125                         {
126                             foreach (XmlSchema schema in schemas.Schemas())
127                             {
128                                 foreach (XmlSchemaObject schemaItem in schema.Items)
129                                 {
130                                     if ((object)schemaItem == (object)providerXsdType)
131                                     {
132                                         typeNs = schema.TargetNamespace;
133                                         if (typeNs == null)
134                                             typeNs = String.Empty;
135                                         break;
136                                     }
137                                 }
138                                 if (typeNs != null)
139                                     break;
140                             }
141                             if (typeNs == null)
142                                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.MissingSchemaType, typeName, DataContract.GetClrTypeFullName(clrType))));
143                             stableName = new XmlQualifiedName(typeName, typeNs);
144                         }
145                     }
146                     else
147                         stableName = (XmlQualifiedName)typeInfo;
148                 }
149             }
150             return true;
151         }
152
153         static XmlSchemaComplexType CreateAnyElementType()
154         {
155             XmlSchemaComplexType anyElementType = new XmlSchemaComplexType();
156             anyElementType.IsMixed = false;
157             anyElementType.Particle = new XmlSchemaSequence();
158             XmlSchemaAny any = new XmlSchemaAny();
159             any.MinOccurs = 0;
160             any.ProcessContents = XmlSchemaContentProcessing.Lax;
161             ((XmlSchemaSequence)anyElementType.Particle).Items.Add(any);
162             return anyElementType;
163         }
164
165         static XmlSchemaAnnotation GetSchemaAnnotation(params XmlNode[] nodes)
166         {
167             if (nodes == null || nodes.Length == 0)
168                 return null;
169             bool hasAnnotation = false;
170             for (int i = 0; i < nodes.Length; i++)
171                 if (nodes[i] != null)
172                 {
173                     hasAnnotation = true;
174                     break;
175                 }
176             if (!hasAnnotation)
177                 return null;
178
179             XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();
180             XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();
181             annotation.Items.Add(appInfo);
182             appInfo.Markup = nodes;
183             return annotation;
184         }
185
186         static XmlSchemaComplexType CreateAnyType()
187         {
188             XmlSchemaComplexType anyType = new XmlSchemaComplexType();
189             anyType.IsMixed = true;
190             anyType.Particle = new XmlSchemaSequence();
191             XmlSchemaAny any = new XmlSchemaAny();
192             any.MinOccurs = 0;
193             any.MaxOccurs = Decimal.MaxValue;
194             any.ProcessContents = XmlSchemaContentProcessing.Lax;
195             ((XmlSchemaSequence)anyType.Particle).Items.Add(any);
196             anyType.AnyAttribute = new XmlSchemaAnyAttribute();
197             return anyType;
198         }
199
200         static XmlElement ExportActualType(XmlQualifiedName typeName, XmlDocument xmlDoc)
201         {
202             XmlElement actualTypeElement = xmlDoc.CreateElement(ActualTypeAnnotationName.Name, ActualTypeAnnotationName.Namespace);
203
204             XmlAttribute nameAttribute = xmlDoc.CreateAttribute(Globals.ActualTypeNameAttribute);
205             nameAttribute.Value = typeName.Name;
206             actualTypeElement.Attributes.Append(nameAttribute);
207
208             XmlAttribute nsAttribute = xmlDoc.CreateAttribute(Globals.ActualTypeNamespaceAttribute);
209             nsAttribute.Value = typeName.Namespace;
210             actualTypeElement.Attributes.Append(nsAttribute);
211
212             return actualTypeElement;
213         }
214
215         static XmlQualifiedName actualTypeAnnotationName;
216         internal static XmlQualifiedName ActualTypeAnnotationName
217         {
218             get
219             {
220                 if (actualTypeAnnotationName == null)
221                     actualTypeAnnotationName = new XmlQualifiedName(Globals.ActualTypeLocalName, Globals.SerializationNamespace);
222                 return actualTypeAnnotationName;
223             }
224         }
225         }
226 }
227