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