Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / XmlSchemaDataType.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaDatatype.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright> 
5 // <owner current="true" primary="true">Microsoft</owner>                                                               
6 //------------------------------------------------------------------------------
7 using System.Collections;
8 using System.Diagnostics;
9 using System.ComponentModel;
10 using System.Xml;
11 using System.IO;
12 using System.Globalization;
13 using System.Text;
14
15 namespace System.Xml.Schema {
16
17     /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype"]/*' />
18     /// <devdoc>
19     ///    <para>[To be supplied.]</para>
20     /// </devdoc>
21     public abstract class XmlSchemaDatatype {
22
23         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.ValueType"]/*' />
24         /// <devdoc>
25         ///    <para>[To be supplied.]</para>
26         /// </devdoc>
27         public abstract Type ValueType { get; }
28
29         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.TokenizedType"]/*' />
30         /// <devdoc>
31         ///    <para>[To be supplied.]</para>
32         /// </devdoc>
33         public abstract  XmlTokenizedType TokenizedType { get; }
34
35         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.ParseValue"]/*' />
36         /// <devdoc>
37         ///    <para>[To be supplied.]</para>
38         /// </devdoc>
39         public abstract object ParseValue(string s, XmlNameTable nameTable, IXmlNamespaceResolver nsmgr);
40         
41         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.Variety"]/*' />
42         /// <devdoc>
43         ///    <para>[To be supplied.]</para>
44         /// </devdoc>
45         public virtual XmlSchemaDatatypeVariety Variety { get { return XmlSchemaDatatypeVariety.Atomic; } }
46         
47         
48         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.ChangeType1"]/*' />
49         /// <devdoc>
50         ///    <para>[To be supplied.]</para>
51         /// </devdoc>
52         public virtual object ChangeType(object value, Type targetType) {
53             if (value == null) {
54                 throw new ArgumentNullException("value");
55             }
56             if (targetType == null) {
57                 throw new ArgumentNullException("targetType");
58             }
59             return ValueConverter.ChangeType(value, targetType);
60         } 
61         
62         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.ChangeType2"]/*' />
63         /// <devdoc>
64         ///    <para>[To be supplied.]</para>
65         /// </devdoc>
66         public virtual object ChangeType(object value, Type targetType, IXmlNamespaceResolver namespaceResolver) {
67             if (value == null) {
68                 throw new ArgumentNullException("value");
69             }
70             if (targetType == null) {
71                 throw new ArgumentNullException("targetType");
72             }
73             if (namespaceResolver == null) {
74                 throw new ArgumentNullException("namespaceResolver");
75             }
76             return ValueConverter.ChangeType(value, targetType, namespaceResolver);
77         }
78         
79         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.TypeCode"]/*' />
80         /// <devdoc>
81         ///    <para>[To be supplied.]</para>
82         /// </devdoc>
83         public virtual XmlTypeCode TypeCode { get { return XmlTypeCode.None; } }
84         
85         /// <include file='doc\XmlSchemaDatatype.uex' path='docs/doc[@for="XmlSchemaDatatype.IsDerivedFrom"]/*' />
86         /// <devdoc>
87         ///    <para>[To be supplied.]</para>
88         /// </devdoc>
89         public virtual bool IsDerivedFrom(XmlSchemaDatatype datatype) {
90             return false;
91         }
92         
93         internal abstract bool HasLexicalFacets { get; }    
94
95         internal abstract bool HasValueFacets { get; }
96
97         internal abstract XmlValueConverter ValueConverter { get; }
98
99         internal abstract RestrictionFacets Restriction { get; set; }
100
101         internal abstract int Compare(object value1, object value2);
102
103         internal abstract object ParseValue(string s, Type typDest, XmlNameTable nameTable, IXmlNamespaceResolver nsmgr);
104
105         internal abstract object ParseValue(string s, XmlNameTable nameTable, IXmlNamespaceResolver nsmgr, bool createAtomicValue);
106
107         internal abstract Exception TryParseValue(string s, XmlNameTable nameTable, IXmlNamespaceResolver nsmgr, out object typedValue);
108         
109         internal abstract Exception TryParseValue(object value, XmlNameTable nameTable, IXmlNamespaceResolver namespaceResolver, out object typedValue);
110
111         internal abstract FacetsChecker FacetsChecker { get; }
112
113         internal abstract XmlSchemaWhiteSpace BuiltInWhitespaceFacet { get; }
114
115         internal abstract XmlSchemaDatatype DeriveByRestriction(XmlSchemaObjectCollection facets, XmlNameTable nameTable, XmlSchemaType schemaType) ;
116
117         internal abstract XmlSchemaDatatype DeriveByList(XmlSchemaType schemaType) ;
118         
119         internal abstract void VerifySchemaValid(XmlSchemaObjectTable notations, XmlSchemaObject caller) ;
120
121         internal abstract bool IsEqual(object o1, object o2) ;
122
123         internal abstract bool IsComparable(XmlSchemaDatatype dtype) ;
124
125         //Error message helper
126         internal string TypeCodeString {
127             get {
128                 string typeCodeString = string.Empty;
129                 XmlTypeCode typeCode = this.TypeCode;
130                 switch(this.Variety) {
131                     case XmlSchemaDatatypeVariety.List:
132                         if (typeCode == XmlTypeCode.AnyAtomicType) { //List of union
133                             typeCodeString = "List of Union";
134                         }
135                         else {
136                             typeCodeString = "List of " + TypeCodeToString(typeCode);
137                         }
138                         break;
139
140                     case XmlSchemaDatatypeVariety.Union:
141                         typeCodeString = "Union";
142                         break;
143
144                     case XmlSchemaDatatypeVariety.Atomic:
145                         if (typeCode == XmlTypeCode.AnyAtomicType) {
146                             typeCodeString = "anySimpleType";
147                         }
148                         else {
149                             typeCodeString = TypeCodeToString(typeCode);
150                         }
151                         break;
152                 }
153                 return typeCodeString;
154             }
155         }
156
157         internal string TypeCodeToString(XmlTypeCode typeCode) {
158             switch (typeCode) {
159                 case XmlTypeCode.None:
160                     return "None";
161                 case XmlTypeCode.Item:
162                     return "AnyType";
163                 case XmlTypeCode.AnyAtomicType:
164                     return "AnyAtomicType";
165                 case XmlTypeCode.String:
166                     return "String";
167                 case XmlTypeCode.Boolean:
168                     return "Boolean";
169                 case XmlTypeCode.Decimal:
170                     return "Decimal";
171                 case XmlTypeCode.Float:
172                     return "Float";
173                 case XmlTypeCode.Double:
174                     return "Double";
175                 case XmlTypeCode.Duration:
176                     return "Duration";
177                 case XmlTypeCode.DateTime:
178                     return "DateTime";
179                 case XmlTypeCode.Time:
180                     return "Time";
181                 case XmlTypeCode.Date:
182                     return "Date";
183                 case XmlTypeCode.GYearMonth:
184                     return "GYearMonth";
185                 case XmlTypeCode.GYear:
186                     return "GYear";
187                 case XmlTypeCode.GMonthDay:
188                     return "GMonthDay";
189                 case XmlTypeCode.GDay:
190                     return "GDay";
191                 case XmlTypeCode.GMonth:
192                     return "GMonth";
193                 case XmlTypeCode.HexBinary:
194                     return "HexBinary";
195                 case XmlTypeCode.Base64Binary:
196                     return "Base64Binary";
197                 case XmlTypeCode.AnyUri:
198                     return "AnyUri";
199                 case XmlTypeCode.QName:
200                     return "QName";
201                 case XmlTypeCode.Notation:
202                     return "Notation";
203                 case XmlTypeCode.NormalizedString:
204                     return "NormalizedString";
205                 case XmlTypeCode.Token:
206                     return "Token";
207                 case XmlTypeCode.Language:
208                     return "Language";
209                 case XmlTypeCode.NmToken:
210                     return "NmToken";
211                 case XmlTypeCode.Name:
212                     return "Name";
213                 case XmlTypeCode.NCName:
214                     return "NCName";
215                 case XmlTypeCode.Id:
216                     return "Id";
217                 case XmlTypeCode.Idref:
218                     return "Idref";
219                 case XmlTypeCode.Entity:
220                     return "Entity";
221                 case XmlTypeCode.Integer:
222                     return "Integer";
223                 case XmlTypeCode.NonPositiveInteger:
224                     return "NonPositiveInteger";
225                 case XmlTypeCode.NegativeInteger:
226                     return "NegativeInteger";
227                 case XmlTypeCode.Long:
228                     return "Long";
229                 case XmlTypeCode.Int:
230                     return "Int";
231                 case XmlTypeCode.Short:
232                    return "Short";
233                 case XmlTypeCode.Byte:
234                     return "Byte";
235                 case XmlTypeCode.NonNegativeInteger:
236                     return "NonNegativeInteger";
237                 case XmlTypeCode.UnsignedLong:
238                     return "UnsignedLong";
239                 case XmlTypeCode.UnsignedInt:
240                     return "UnsignedInt";
241                 case XmlTypeCode.UnsignedShort:
242                     return "UnsignedShort";
243                 case XmlTypeCode.UnsignedByte:
244                     return "UnsignedByte";
245                 case XmlTypeCode.PositiveInteger:
246                     return "PositiveInteger";
247                 
248                 default:
249                     return typeCode.ToString();
250             }
251         }
252
253         internal static string ConcatenatedToString(object value) {
254             Type t = value.GetType();
255             string stringValue = string.Empty;
256             if (t == typeof(IEnumerable) && t != typeof(System.String)) {
257                 StringBuilder bldr = new StringBuilder();
258                 IEnumerator enumerator = (value as IEnumerable).GetEnumerator();
259                 if (enumerator.MoveNext()) {
260                     bldr.Append("{");
261                     Object cur = enumerator.Current;
262                     if (cur is IFormattable) {
263                         bldr.Append( ((IFormattable)cur).ToString("", CultureInfo.InvariantCulture) );
264                     }
265                     else {
266                         bldr.Append(cur.ToString());
267                     }
268                     while(enumerator.MoveNext()) {
269                         bldr.Append(" , ");
270                         cur = enumerator.Current;
271                         if (cur is IFormattable) {
272                             bldr.Append( ((IFormattable)cur).ToString("", CultureInfo.InvariantCulture) );
273                         }
274                         else {
275                             bldr.Append(cur.ToString());
276                         }
277                     }
278                     bldr.Append("}");
279                     stringValue = bldr.ToString();
280                 }
281             }
282             else if (value is IFormattable) {
283                 stringValue = ((IFormattable)value).ToString("", CultureInfo.InvariantCulture);
284             }
285             else {
286                 stringValue = value.ToString();
287             }
288             return stringValue;
289         }
290
291         internal static XmlSchemaDatatype FromXmlTokenizedType(XmlTokenizedType token) {
292             return DatatypeImplementation.FromXmlTokenizedType(token);
293         }
294
295         internal static XmlSchemaDatatype FromXmlTokenizedTypeXsd(XmlTokenizedType token) {
296             return DatatypeImplementation.FromXmlTokenizedTypeXsd(token);
297         }
298
299         internal static XmlSchemaDatatype FromXdrName(string name) {
300             return DatatypeImplementation.FromXdrName(name);
301         }
302         
303         internal static XmlSchemaDatatype DeriveByUnion(XmlSchemaSimpleType[] types, XmlSchemaType schemaType) {
304             return DatatypeImplementation.DeriveByUnion(types, schemaType);
305         }
306         
307         internal static string XdrCanonizeUri(string uri, XmlNameTable nameTable, SchemaNames schemaNames) {
308             string canonicalUri;
309             int offset = 5;
310             bool convert = false;
311
312             if (uri.Length > 5 && uri.StartsWith("uuid:", StringComparison.Ordinal)) {
313                 convert = true;
314             }
315             else if (uri.Length > 9 && uri.StartsWith("urn:uuid:", StringComparison.Ordinal)) {
316                 convert = true;
317                 offset = 9;
318             }
319
320             if (convert) {
321                 canonicalUri = nameTable.Add(uri.Substring(0, offset) + uri.Substring(offset, uri.Length - offset).ToUpper(CultureInfo.InvariantCulture));
322             }
323             else {
324                 canonicalUri = uri;
325             }
326
327             if (
328                 Ref.Equal(schemaNames.NsDataTypeAlias, canonicalUri) ||
329                 Ref.Equal(schemaNames.NsDataTypeOld  , canonicalUri)
330             ) {
331                 canonicalUri = schemaNames.NsDataType;
332             }
333             else if (Ref.Equal(schemaNames.NsXdrAlias, canonicalUri)) {
334                 canonicalUri = schemaNames.NsXdr;
335             }
336
337             return canonicalUri;
338         }
339
340 #if Microsoft
341         private bool CanConvert(object value, System.Type inputType, System.Type defaultType, out string resId) {
342             resId = null;
343             decimal decimalValue;
344             //TypeCode defaultTypeCode = Type.GetTypeCode(defaultType);
345             if (IsIntegralType(this.TypeCode)){
346                 switch (Type.GetTypeCode(inputType)) {
347                     case System.TypeCode.Single:
348                     case System.TypeCode.Double:
349                         decimalValue = new Decimal((double)value);
350                         goto case System.TypeCode.Decimal;
351                     case System.TypeCode.Decimal:
352                         decimalValue = (decimal)value;
353                         if (decimal.Truncate(decimalValue) != decimalValue) { //HasFractionDigits
354                             resId = Res.Sch_XmlTypeHasFraction;
355                             return false;
356                         } 
357                     break;
358
359                     default:
360                         return true;
361                 }                
362             }
363             else if (this.TypeCode == XmlTypeCode.Boolean) {
364                 if (IsNumericType(inputType)) {
365                     decimalValue = (decimal)value;
366                     if (decimalValue == 0 || decimalValue == 1) {
367                         return true;
368                     }
369                     resId = Res.Sch_InvalidBoolean;
370                     return false;    
371                 }
372             }
373             return true;
374         }
375
376         private bool IsIntegralType(XmlTypeCode defaultTypeCode) {
377             switch (defaultTypeCode) {
378                 case XmlTypeCode.Integer:
379                 case XmlTypeCode.NegativeInteger:
380                 case XmlTypeCode.NonNegativeInteger:
381                 case XmlTypeCode.NonPositiveInteger:
382                 case XmlTypeCode.PositiveInteger:
383                 case XmlTypeCode.Long:
384                 case XmlTypeCode.Int:
385                 case XmlTypeCode.Short:
386                 case XmlTypeCode.Byte:
387                 case XmlTypeCode.UnsignedLong:
388                 case XmlTypeCode.UnsignedInt:
389                 case XmlTypeCode.UnsignedShort:
390                 case XmlTypeCode.UnsignedByte:
391                    return true;
392                 default:
393                     return false;
394             }
395         }
396
397         private bool IsNumericType(System.Type inputType) {
398             switch (Type.GetTypeCode(inputType)) {
399                 case System.TypeCode.Decimal:
400                 case System.TypeCode.Double:
401                 case System.TypeCode.Single:
402                 case System.TypeCode.SByte:
403                 case System.TypeCode.Byte:
404                 case System.TypeCode.Int16:
405                 case System.TypeCode.Int32:
406                 case System.TypeCode.Int64:
407                 case System.TypeCode.UInt16:
408                 case System.TypeCode.UInt32:
409                 case System.TypeCode.UInt64:
410                     return true;
411                 default:
412                     return false;
413             }
414         }
415 #endif
416     }
417 }
418