Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity.Design / System / Data / Entity / Design / Common / MetadataUtil.cs
1 //---------------------------------------------------------------------
2 // <copyright file="MetadataUtil.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner        Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.Collections.Generic;
12 using System.Data.SqlClient;
13 using System.Text;
14 using System.Data.Metadata.Edm;
15 using System.Xml;
16 using System.Data.Common;
17 using System.Reflection;
18 using System.IO;
19 using System.Diagnostics;
20 using System.Collections;
21 using System.Globalization;
22 using System.Linq;
23
24 namespace System.Data.Entity.Design.Common
25 {
26     internal static class MetadataUtil
27     {
28         private const string s_defaultDelimiter = ", ";
29
30         internal static bool IsStoreType(GlobalItem item)
31         {
32             return item.DataSpace == DataSpace.SSpace;
33         }
34
35         internal static DbProviderServices GetProviderServices(DbProviderFactory factory)
36         {
37             EDesignUtil.CheckArgumentNull(factory, "factory");
38
39             // Special case SQL client so that it will work with System.Data from .NET 4.0 even without
40             // a binding redirect.
41             if (factory is SqlClientFactory)
42             {
43                 return SqlProviderServices.Instance;
44             }
45
46             IServiceProvider serviceProvider = factory as IServiceProvider;
47             if (serviceProvider == null)
48             {
49                 throw MetadataUtil.ProviderIncompatible(System.Data.Entity.Design.Strings.EntityClient_DoesNotImplementIServiceProvider(
50                     factory.GetType().ToString()));
51             }
52
53             DbProviderServices providerServices = serviceProvider.GetService(typeof(DbProviderServices)) as DbProviderServices;
54             if (providerServices == null)
55             {
56                 throw MetadataUtil.ProviderIncompatible(
57                     System.Data.Entity.Design.Strings.EntityClient_ReturnedNullOnProviderMethod(
58                         "GetService",
59                         factory.GetType().ToString()));
60             }
61             return providerServices;
62         }
63
64         static internal ProviderIncompatibleException ProviderIncompatible(string error)
65         {
66             ProviderIncompatibleException e = new ProviderIncompatibleException(error);
67             return e;
68         }
69
70         /// <summary>
71         /// Check if all the SchemaErrors have the serverity of SchemaErrorSeverity.Warning
72         /// </summary>
73         /// <param name="schemaErrors"></param>
74         /// <returns></returns>
75         internal static bool CheckIfAllErrorsAreWarnings(IList<EdmSchemaError> schemaErrors)
76         {
77             int length = schemaErrors.Count;
78             for (int i = 0; i < length; ++i)
79             {
80                 EdmSchemaError error = schemaErrors[i];
81                 if (error.Severity != EdmSchemaErrorSeverity.Warning)
82                 {
83                     return false;
84                 }
85             }
86             return true;
87         }
88
89         /// <summary>
90         ///   This private static method checks a string to make sure that it is not empty.
91         ///   Comparing with String.Empty is not sufficient since a string with nothing
92         ///   but white space isn't considered "empty" by that rationale.
93         /// </summary>
94         internal static bool IsNullOrEmptyOrWhiteSpace(string value)
95         {
96             return IsNullOrEmptyOrWhiteSpace(value, 0);
97         }
98
99         internal static bool IsNullOrEmptyOrWhiteSpace(string value, int offset)
100         {
101             // don't use Trim(), which will copy the string, which may be large, just to test for emptyness
102             //return String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim());
103             if (null != value)
104             {
105                 for (int i = offset; i < value.Length; ++i)
106                 {
107                     if (!Char.IsWhiteSpace(value[i]))
108                     {
109                         return false;
110                     }
111                 }
112             }
113             return true;
114         }
115
116         // separate implementation from IsNullOrEmptyOrWhiteSpace(string, int) because that one will
117         // pick up the jit optimization to avoid boundary checks and the this won't is unknown (most likely not)
118         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
119         internal static bool IsNullOrEmptyOrWhiteSpace(string value, int offset, int length)
120         {
121             // don't use Trim(), which will copy the string, which may be large, just to test for emptyness
122             //return String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim());
123             if (null != value)
124             {
125                 length = Math.Min(value.Length, length);
126                 for (int i = offset; i < length; ++i)
127                 {
128                     if (!Char.IsWhiteSpace(value[i]))
129                     {
130                         return false;
131                     }
132                 }
133             }
134             return true;
135         }
136
137         internal static string MembersToCommaSeparatedString(IEnumerable members)
138         {
139             StringBuilder builder = new StringBuilder();
140             builder.Append("{");
141             MetadataUtil.ToCommaSeparatedString(builder, members);
142             builder.Append("}");
143             return builder.ToString();
144         }
145
146         internal static void ToCommaSeparatedString(StringBuilder builder, IEnumerable list)
147         {
148             ToSeparatedStringPrivate(builder, list, s_defaultDelimiter, string.Empty, false);
149         }
150
151         // effects: Converts the list to a list of strings, sorts its (if
152         // toSort is true) and then converts to a string separated by
153         // "separator" with "nullValue" used for null values.
154         private static void ToSeparatedStringPrivate(StringBuilder stringBuilder, IEnumerable list, string separator,
155                                                      string nullValue, bool toSort)
156         {
157             if (null == list)
158             {
159                 return;
160             }
161             bool isFirst = true;
162             // Get the list of strings first
163             List<string> elementStrings = new List<string>();
164             foreach (object element in list)
165             {
166                 string str;
167                 // Get the element or its default null value
168                 if (element == null)
169                 {
170                     str = nullValue;
171                 }
172                 else
173                 {
174                     str = FormatInvariant("{0}", element);
175                 }
176                 elementStrings.Add(str);
177             }
178
179             if (toSort == true)
180             {
181                 // Sort the list
182                 elementStrings.Sort(StringComparer.Ordinal);
183             }
184
185             // Now add the strings to the stringBuilder
186             foreach (string str in elementStrings)
187             {
188                 if (false == isFirst)
189                 {
190                     stringBuilder.Append(separator);
191                 }
192                 stringBuilder.Append(str);
193                 isFirst = false;
194             }
195         }
196
197         internal static string FormatInvariant(string format, params object[] args)
198         {
199             Debug.Assert(args.Length > 0, "Formatting utilities must be called with at least one argument");
200             return String.Format(CultureInfo.InvariantCulture, format, args);
201         }
202
203         /// <summary>
204         /// replace troublesome xml characters with equivalent entities
205         /// </summary>
206         /// <param name="text">text that make have characters troublesome in xml</param>
207         /// <returns>text with troublesome characters replaced with equivalent entities</returns>
208         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
209         internal static string Entityize(string text)
210         {
211             if (string.IsNullOrEmpty(text))
212                 return "";
213
214             text = text.Replace("&", "&amp;");
215             text = text.Replace("<", "&lt;").Replace(">", "&gt;");
216             return text.Replace("\'", "&apos;").Replace("\"", "&quot;");
217         }
218
219         internal static bool TrySplitExtendedMetadataPropertyName(string name, out string xmlNamespaceUri, out string attributeName)
220         {
221             int pos = name.LastIndexOf(':');
222             if (pos < 0 || name.Length <= pos + 1)
223             {
224                 Debug.Fail("the name is not in the form we expect");
225                 xmlNamespaceUri = null;
226                 attributeName = null;
227                 return false;
228             }
229
230             xmlNamespaceUri = name.Substring(0, pos);
231             attributeName = name.Substring(pos + 1, (name.Length - 1) - pos);
232             return true;
233         }
234
235         static private readonly Type StackOverflowType = typeof(System.StackOverflowException);
236         static private readonly Type OutOfMemoryType = typeof(System.OutOfMemoryException);
237         static private readonly Type ThreadAbortType = typeof(System.Threading.ThreadAbortException);
238         static private readonly Type NullReferenceType = typeof(System.NullReferenceException);
239         static private readonly Type AccessViolationType = typeof(System.AccessViolationException);
240         static private readonly Type SecurityType = typeof(System.Security.SecurityException);
241
242         internal static bool IsCatchableExceptionType(Exception e)
243         {
244             // a 'catchable' exception is defined by what it is not.
245             Debug.Assert(e != null, "Unexpected null exception!");
246             Type type = e.GetType();
247
248             return ((type != StackOverflowType) &&
249                      (type != OutOfMemoryType) &&
250                      (type != ThreadAbortType) &&
251                      (type != NullReferenceType) &&
252                      (type != AccessViolationType) &&
253                      !SecurityType.IsAssignableFrom(type));
254         }
255
256         /// <summary>
257         /// Returns the single error message from the list of errors
258         /// </summary>
259         /// <param name="errors"></param>
260         /// <returns></returns>
261         static internal string CombineErrorMessage(IEnumerable<System.Data.Metadata.Edm.EdmSchemaError> errors)
262         {
263             Debug.Assert(errors != null);
264             StringBuilder sb = new StringBuilder(System.Environment.NewLine);
265             int count = 0;
266             foreach (System.Data.Metadata.Edm.EdmSchemaError error in errors)
267             {
268                 //Don't append a new line at the beginning of the messages
269                 if ((count++) != 0)
270                 {
271                     sb.Append(System.Environment.NewLine);
272                 }
273                 sb.Append(error.ToString());
274
275             }
276             Debug.Assert(count != 0, "Empty Error List");
277             return sb.ToString();
278         }
279
280         internal static void DisposeXmlReaders(IEnumerable<XmlReader> xmlReaders)
281         {
282             Debug.Assert(xmlReaders != null);
283
284             foreach (XmlReader xmlReader in xmlReaders)
285             {
286                 ((IDisposable)xmlReader).Dispose();
287             }
288         }
289
290         internal static bool IsCollectionType(GlobalItem item)
291         {
292             return (BuiltInTypeKind.CollectionType == item.BuiltInTypeKind);
293         }
294
295         internal static bool IsComplexType(EdmType type)
296         {
297             return (BuiltInTypeKind.ComplexType == type.BuiltInTypeKind);
298         }
299
300         internal static bool IsPrimitiveType(EdmType type)
301         {
302             return (BuiltInTypeKind.PrimitiveType == type.BuiltInTypeKind);
303         }
304
305         internal static bool IsEntitySet(EntitySetBase entitySetBase)
306         {
307             return BuiltInTypeKind.EntitySet == entitySetBase.BuiltInTypeKind;
308         }
309
310         internal static bool IsValidKeyType(Version entityFrameworkVersion, EdmType type)
311         {
312             var primitiveType = type as PrimitiveType;
313             if (primitiveType == null)
314             {
315                 return false;
316             }
317             if (EntityFrameworkVersions.Version1 == entityFrameworkVersion)
318             {
319                 return primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Binary;
320             }
321             else
322             {
323                 // From V2 onwards, Binary key properties are supported
324                 return true;
325             }
326         }
327
328         /// <summary>
329         /// determines if type is of EnumerationType.
330         /// </summary>
331         /// <param name="type"></param>
332         /// <returns></returns>
333         internal static bool IsEnumerationType(EdmType type)
334         {
335             return (BuiltInTypeKind.EnumType == type.BuiltInTypeKind);
336         }
337     }
338 }