[bcl] Don't build not installed mobile assemblies
[mono.git] / mcs / class / referencesource / System.Runtime.Serialization / System / Runtime / Serialization / Json / XmlObjectSerializerReadContextComplexJson.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.Runtime.Serialization.Json
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Runtime;
10     using System.Security;
11 #if !MONO
12     using System.ServiceModel;
13 #endif
14     using System.Text;
15     using System.Xml;
16
17 #if USE_REFEMIT
18     public class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
19 #else
20     class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
21 #endif
22     {
23         string extensionDataValueType;
24         DateTimeFormat dateTimeFormat;
25         bool useSimpleDictionaryFormat;
26
27         public XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
28             : base(serializer, serializer.MaxItemsInObjectGraph,
29                 new StreamingContext(StreamingContextStates.All),
30                 serializer.IgnoreExtensionDataObject)
31         {
32             this.rootTypeDataContract = rootTypeDataContract;
33             this.serializerKnownTypeList = serializer.knownTypeList;
34             this.dataContractSurrogate = serializer.DataContractSurrogate;
35             this.dateTimeFormat = serializer.DateTimeFormat;
36             this.useSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat;
37         }
38
39         internal IList<Type> SerializerKnownTypeList
40         {
41             get
42             {
43                 return this.serializerKnownTypeList;
44             }
45         }
46
47         public bool UseSimpleDictionaryFormat
48         {
49             get
50             {
51                 return this.useSimpleDictionaryFormat;
52             }
53         }
54
55         protected override void StartReadExtensionDataValue(XmlReaderDelegator xmlReader)
56         {
57             extensionDataValueType = xmlReader.GetAttribute(JsonGlobals.typeString);
58         }
59
60         protected override IDataNode ReadPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
61         {
62             IDataNode dataNode;
63
64             switch (extensionDataValueType)
65             {
66                 case null:
67                 case JsonGlobals.stringString:
68                     dataNode = new DataNode<string>(xmlReader.ReadContentAsString());
69                     break;
70                 case JsonGlobals.booleanString:
71                     dataNode = new DataNode<bool>(xmlReader.ReadContentAsBoolean());
72                     break;
73                 case JsonGlobals.numberString:
74                     dataNode = ReadNumericalPrimitiveExtensionDataValue(xmlReader);
75                     break;
76                 default:
77                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
78                         XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonUnexpectedAttributeValue, extensionDataValueType)));
79             }
80
81             xmlReader.ReadEndElement();
82             return dataNode;
83         }
84
85         IDataNode ReadNumericalPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader)
86         {
87             TypeCode type;
88             object numericalValue = JsonObjectDataContract.ParseJsonNumber(xmlReader.ReadContentAsString(), out type);
89             switch (type)
90             {
91                 case TypeCode.Byte:
92                     return new DataNode<byte>((byte)numericalValue);
93                 case TypeCode.SByte:
94                     return new DataNode<sbyte>((sbyte)numericalValue);
95                 case TypeCode.Int16:
96                     return new DataNode<short>((short)numericalValue);
97                 case TypeCode.Int32:
98                     return new DataNode<int>((int)numericalValue);
99                 case TypeCode.Int64:
100                     return new DataNode<long>((long)numericalValue);
101                 case TypeCode.UInt16:
102                     return new DataNode<ushort>((ushort)numericalValue);
103                 case TypeCode.UInt32:
104                     return new DataNode<uint>((uint)numericalValue);
105                 case TypeCode.UInt64:
106                     return new DataNode<ulong>((ulong)numericalValue);
107                 case TypeCode.Single:
108                     return new DataNode<float>((float)numericalValue);
109                 case TypeCode.Double:
110                     return new DataNode<double>((double)numericalValue);
111                 case TypeCode.Decimal:
112                     return new DataNode<decimal>((decimal)numericalValue);
113                 default:
114                     throw Fx.AssertAndThrow("JsonObjectDataContract.ParseJsonNumber shouldn't return a TypeCode that we're not expecting");
115             }
116         }
117
118         internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
119         {
120             return new XmlObjectSerializerReadContextComplexJson(serializer, rootTypeDataContract);
121         }
122
123 #if USE_REFEMIT
124         public override int GetArraySize()
125 #else
126         internal override int GetArraySize()
127 #endif
128         {
129             return -1;
130         }
131
132         protected override object ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
133         {
134             return DataContractJsonSerializer.ReadJsonValue(dataContract, reader, this);
135         }
136
137 #if USE_REFEMIT
138         public override void ReadAttributes(XmlReaderDelegator xmlReader)
139 #else
140         internal override void ReadAttributes(XmlReaderDelegator xmlReader)
141 #endif
142         {
143             if (attributes == null)
144                 attributes = new Attributes();
145             attributes.Reset();
146
147             if (xmlReader.MoveToAttribute(JsonGlobals.typeString) && xmlReader.Value == JsonGlobals.nullString)
148             {
149                 attributes.XsiNil = true;
150             }
151             else if (xmlReader.MoveToAttribute(JsonGlobals.serverTypeString))
152             {
153                 XmlQualifiedName qualifiedTypeName = JsonReaderDelegator.ParseQualifiedName(xmlReader.Value);
154                 attributes.XsiTypeName = qualifiedTypeName.Name;
155
156                 string serverTypeNamespace = qualifiedTypeName.Namespace;
157
158                 if (!string.IsNullOrEmpty(serverTypeNamespace))
159                 {
160                     switch (serverTypeNamespace[0])
161                     {
162                         case '#':
163                             serverTypeNamespace = string.Concat(Globals.DataContractXsdBaseNamespace, serverTypeNamespace.Substring(1));
164                             break;
165                         case '\\':
166                             if (serverTypeNamespace.Length >= 2)
167                             {
168                                 switch (serverTypeNamespace[1])
169                                 {
170                                     case '#':
171                                     case '\\':
172                                         serverTypeNamespace = serverTypeNamespace.Substring(1);
173                                         break;
174                                     default:
175                                         break;
176                                 }
177                             }
178                             break;
179                         default:
180                             break;
181                     }
182                 }
183
184                 attributes.XsiTypeNamespace = serverTypeNamespace;
185             }
186             xmlReader.MoveToElement();
187         }
188
189         public int GetJsonMemberIndex(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, int memberIndex, ExtensionDataObject extensionData)
190         {
191             int length = memberNames.Length;
192             if (length != 0)
193             {
194                 for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
195                 {
196                     if (xmlReader.IsStartElement(memberNames[index], XmlDictionaryString.Empty))
197                     {
198                         return index;
199                     }
200                 }
201                 string name;
202                 if (TryGetJsonLocalName(xmlReader, out name))
203                 {
204                     for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
205                     {
206                         if (memberNames[index].Value == name)
207                         {
208                             return index;
209                         }
210                     }
211                 }
212             }
213             HandleMemberNotFound(xmlReader, extensionData, memberIndex);
214             return length;
215         }
216
217         internal static bool TryGetJsonLocalName(XmlReaderDelegator xmlReader, out string name)
218         {
219             if (xmlReader.IsStartElement(JsonGlobals.itemDictionaryString, JsonGlobals.itemDictionaryString))
220             {
221                 if (xmlReader.MoveToAttribute(JsonGlobals.itemString))
222                 {
223                     name = xmlReader.Value;
224                     return true;
225                 }
226             }
227             name = null;
228             return false;
229         }
230
231         public static string GetJsonMemberName(XmlReaderDelegator xmlReader)
232         {
233             string name;
234             if (!TryGetJsonLocalName(xmlReader, out name))
235             {
236                 name = xmlReader.LocalName;
237             }
238             return name;
239         }
240
241         public static void ThrowMissingRequiredMembers(object obj, XmlDictionaryString[] memberNames, byte[] expectedElements, byte[] requiredElements)
242         {
243             StringBuilder stringBuilder = new StringBuilder();
244             int missingMembersCount = 0;
245             for (int i = 0; i < memberNames.Length; i++)
246             {
247                 if (IsBitSet(expectedElements, i) && IsBitSet(requiredElements, i))
248                 {
249                     if (stringBuilder.Length != 0)
250                         stringBuilder.Append(", ");
251                     stringBuilder.Append(memberNames[i]);
252                     missingMembersCount++;
253                 }
254             }
255
256             if (missingMembersCount == 1)
257             {
258                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
259                  SR.JsonOneRequiredMemberNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
260             }
261             else
262             {
263                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
264                     SR.JsonRequiredMembersNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
265             }
266         }
267
268
269
270         public static void ThrowDuplicateMemberException(object obj, XmlDictionaryString[] memberNames, int memberIndex)
271         {
272             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(
273                 SR.GetString(SR.JsonDuplicateMemberInInput, DataContract.GetClrTypeFullName(obj.GetType()), memberNames[memberIndex])));
274         }
275
276         [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'BitFlagsGenerator'.",
277             Safe = "This method is safe to call.")]
278         [SecuritySafeCritical]
279         static bool IsBitSet(byte[] bytes, int bitIndex)
280         {
281             return BitFlagsGenerator.IsBitSet(bytes, bitIndex);
282         }
283
284         protected override bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
285         {
286             return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.arrayString;
287         }
288
289         protected override bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)
290         {
291             return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.objectString;
292         }
293
294         protected override XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
295         {
296             return new JsonReaderDelegator(xmlReader, this.dateTimeFormat);
297         }
298
299         internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
300         {
301             DataContract dataContract = base.GetDataContract(typeHandle, type);
302             DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
303             return dataContract;
304         }
305
306         internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
307         {
308             DataContract dataContract = base.GetDataContractSkipValidation(typeId, typeHandle, type);
309             DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
310             return dataContract;
311         }
312
313         internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
314         {
315             DataContract dataContract = base.GetDataContract(id, typeHandle);
316             DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
317             return dataContract;
318         }
319
320         protected override DataContract ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
321         {
322             return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract);
323         }
324     }
325 }