Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Common / Tizen.Applications / ApplicationManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21 using System.Threading.Tasks;
22
23 namespace Tizen.Applications
24 {
25     /// <summary>
26     /// This class has the methods and events of the ApplicationManager.
27     /// </summary>
28     public static class ApplicationManager
29     {
30         private const string LogTag = "Tizen.Applications";
31         private static EventHandler<ApplicationLaunchedEventArgs> s_launchedHandler;
32         private static EventHandler<ApplicationTerminatedEventArgs> s_terminatedHandler;
33         private static Interop.ApplicationManager.AppManagerAppContextEventCallback s_applicationChangedEventCallback;
34         private static EventHandler<ApplicationEnabledEventArgs> _enabledHandler;
35         private static EventHandler<ApplicationDisabledEventArgs> _disabledHandler;
36         private static Interop.ApplicationManager.AppManagerEventCallback _eventCallback;
37         private static IntPtr _eventHandle = IntPtr.Zero;
38
39         /// <summary>
40         /// Occurs whenever the installed application is enabled.
41         /// </summary>
42         public static event EventHandler<ApplicationEnabledEventArgs> ApplicationEnabled
43         {
44             add
45             {
46                 if (_enabledHandler == null && _disabledHandler == null)
47                 {
48                     RegisterApplicationEvent();
49                 }
50                 _enabledHandler += value;
51             }
52             remove
53             {
54                 _enabledHandler -= value;
55                 if (_enabledHandler == null && _disabledHandler == null)
56                 {
57                     UnRegisterApplicationEvent();
58                 }
59             }
60         }
61
62         /// <summary>
63         /// Occurs whenever the installed application is disabled.
64         /// </summary>
65         public static event EventHandler<ApplicationDisabledEventArgs> ApplicationDisabled
66         {
67             add
68             {
69                 if (_disabledHandler == null && _enabledHandler == null)
70                 {
71                     RegisterApplicationEvent();
72                 }
73                 _disabledHandler += value;
74             }
75             remove
76             {
77                 _disabledHandler -= value;
78                 if (_disabledHandler == null && _enabledHandler == null)
79                 {
80                     UnRegisterApplicationEvent();
81                 }
82             }
83         }
84
85         /// <summary>
86         /// Occurs whenever the installed applications get launched.
87         /// </summary>
88         public static event EventHandler<ApplicationLaunchedEventArgs> ApplicationLaunched
89         {
90             add
91             {
92                 if (s_launchedHandler == null && s_terminatedHandler == null)
93                 {
94                     RegisterApplicationChangedEvent();
95                 }
96                 s_launchedHandler += value;
97             }
98             remove
99             {
100                 s_launchedHandler -= value;
101                 if (s_launchedHandler == null && s_terminatedHandler == null)
102                 {
103                     UnRegisterApplicationChangedEvent();
104                 }
105             }
106         }
107
108         /// <summary>
109         /// Occurs whenever the installed applications get terminated.
110         /// </summary>
111         public static event EventHandler<ApplicationTerminatedEventArgs> ApplicationTerminated
112         {
113             add
114             {
115                 if (s_launchedHandler == null && s_terminatedHandler == null)
116                 {
117                     RegisterApplicationChangedEvent();
118                 }
119                 s_terminatedHandler += value;
120             }
121             remove
122             {
123                 s_terminatedHandler -= value;
124                 if (s_launchedHandler == null && s_terminatedHandler == null)
125                 {
126                     UnRegisterApplicationChangedEvent();
127                 }
128             }
129         }
130
131         /// <summary>
132         /// Gets the information of the installed applications asynchronously.
133         /// </summary>
134         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync()
135         {
136             return await Task.Run(() =>
137             {
138                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
139                 List<ApplicationInfo> result = new List<ApplicationInfo>();
140
141                 Interop.ApplicationManager.AppManagerAppInfoCallback cb = (IntPtr infoHandle, IntPtr userData) =>
142                 {
143                     if (infoHandle != IntPtr.Zero)
144                     {
145                         IntPtr clonedHandle = IntPtr.Zero;
146                         err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
147                         if (err != Interop.ApplicationManager.ErrorCode.None)
148                         {
149                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
150                             return false;
151                         }
152                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
153                         result.Add(app);
154                         return true;
155                     }
156                     return false;
157                 };
158                 err = Interop.ApplicationManager.AppManagerForeachAppInfo(cb, IntPtr.Zero);
159                 if (err != Interop.ApplicationManager.ErrorCode.None)
160                 {
161                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach the appinfo.");
162                 }
163                 return result;
164             });
165         }
166
167         /// <summary>
168         /// Gets the information of the installed applications with the ApplicationInfoFilter asynchronously.
169         /// </summary>
170         /// <param name="filter">Key-value pairs for filtering.</param>
171         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoFilter filter)
172         {
173             return await Task.Run(() =>
174             {
175                 List<ApplicationInfo> result = new List<ApplicationInfo>();
176
177                 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
178                 {
179                     if (infoHandle != IntPtr.Zero)
180                     {
181                         IntPtr clonedHandle = IntPtr.Zero;
182                         Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
183                         if (err != Interop.ApplicationManager.ErrorCode.None)
184                         {
185                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
186                             return false;
187                         }
188                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
189                         result.Add(app);
190                         return true;
191                     }
192                     return false;
193                 };
194                 filter.Fetch(cb);
195                 return result;
196             });
197         }
198
199         /// <summary>
200         /// Gets the information of the installed applications with the ApplicationInfoMetadataFilter asynchronously.
201         /// </summary>
202         /// <param name="filter">Key-value pairs for filtering.</param>
203         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoMetadataFilter filter)
204         {
205             return await Task.Run(() =>
206             {
207                 List<ApplicationInfo> result = new List<ApplicationInfo>();
208
209                 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
210                 {
211                     if (infoHandle != IntPtr.Zero)
212                     {
213                         IntPtr clonedHandle = IntPtr.Zero;
214                         Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
215                         if (err != Interop.ApplicationManager.ErrorCode.None)
216                         {
217                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
218                             return false;
219                         }
220                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
221                         result.Add(app);
222                         return true;
223                     }
224                     return false;
225                 };
226                 filter.Fetch(cb);
227                 return result;
228             });
229         }
230
231         /// <summary>
232         /// Gets the information of the running applications asynchronously.
233         /// </summary>
234         public static async Task<IEnumerable<ApplicationRunningContext>> GetRunningApplicationsAsync()
235         {
236             return await Task.Run(() =>
237             {
238                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
239                 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
240
241                 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
242                 {
243                     if (contextHandle != IntPtr.Zero)
244                     {
245                         IntPtr clonedHandle = IntPtr.Zero;
246                         err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
247                         if (err != Interop.ApplicationManager.ErrorCode.None)
248                         {
249                             Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
250                             return false;
251                         }
252                         ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
253                         result.Add(context);
254                         return true;
255                     }
256                     return false;
257                 };
258
259                 err = Interop.ApplicationManager.AppManagerForeachAppContext(cb, IntPtr.Zero);
260                 if (err != Interop.ApplicationManager.ErrorCode.None)
261                 {
262                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach appcontext.");
263                 }
264                 return result;
265             });
266         }
267
268         /// <summary>
269         /// Gets the information of the running applications including subapp asynchronously.
270         /// </summary>
271         public static async Task<IEnumerable<ApplicationRunningContext>> GetAllRunningApplicationsAsync()
272         {
273             return await Task.Run(() =>
274             {
275                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
276                 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
277
278                 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
279                 {
280                     if (contextHandle != IntPtr.Zero)
281                     {
282                         IntPtr clonedHandle = IntPtr.Zero;
283                         err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
284                         if (err != Interop.ApplicationManager.ErrorCode.None)
285                         {
286                             Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
287                             return false;
288                         }
289                         ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
290                         result.Add(context);
291                         return true;
292                     }
293                     return false;
294                 };
295
296                 err = Interop.ApplicationManager.AppManagerForeachRunningAppContext(cb, IntPtr.Zero);
297                 if (err != Interop.ApplicationManager.ErrorCode.None)
298                 {
299                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to foreach appcontext.");
300                 }
301                 return result;
302             });
303         }
304
305         /// <summary>
306         /// Gets the information of the specified application with the application id.
307         /// </summary>
308         /// <param name="applicationId">Application id.</param>
309         public static ApplicationInfo GetInstalledApplication(string applicationId)
310         {
311             IntPtr infoHandle = IntPtr.Zero;
312             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerGetAppInfo(applicationId, out infoHandle);
313             if (err != Interop.ApplicationManager.ErrorCode.None)
314             {
315                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get the installed application information of " + applicationId + ".");
316             }
317             ApplicationInfo app = new ApplicationInfo(infoHandle);
318             return app;
319         }
320
321         /// <summary>
322         /// Returns if the specified application is running or not.
323         /// </summary>
324         /// <param name="applicationId">The application Id.</param>
325         /// <returns>Returns true if the given application is running, otherwise false.</returns>
326         /// <exception cref="ArgumentException">Thrown when the given parameter is invalid.</exception>
327         public static bool IsRunning(string applicationId)
328         {
329             bool isRunning = false;
330             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerIsRunning(applicationId, out isRunning);
331             if (err != Interop.ApplicationManager.ErrorCode.None)
332             {
333                 throw ApplicationManagerErrorFactory.GetException(Interop.ApplicationManager.ErrorCode.InvalidParameter, "Invalid parameter");
334             }
335             return isRunning;
336         }
337
338         private static void RegisterApplicationChangedEvent()
339         {
340             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
341             s_applicationChangedEventCallback = (IntPtr contextHandle, Interop.ApplicationManager.AppContextEvent state, IntPtr userData) =>
342             {
343                 if (contextHandle == IntPtr.Zero) return;
344
345                 IntPtr clonedHandle = IntPtr.Zero;
346                 err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
347                 if (err != Interop.ApplicationManager.ErrorCode.None)
348                 {
349                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
350                 }
351                 using (ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle))
352                 {
353                     if (state == Interop.ApplicationManager.AppContextEvent.Launched)
354                     {
355                         s_launchedHandler?.Invoke(null, new ApplicationLaunchedEventArgs { ApplicationRunningContext = context });
356                     }
357                     else if (state == Interop.ApplicationManager.AppContextEvent.Terminated)
358                     {
359                         s_terminatedHandler?.Invoke(null, new ApplicationTerminatedEventArgs { ApplicationRunningContext = context });
360                     }
361                 }
362             };
363             err = Interop.ApplicationManager.AppManagerSetAppContextEvent(s_applicationChangedEventCallback, IntPtr.Zero);
364             if (err != Interop.ApplicationManager.ErrorCode.None)
365             {
366                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
367             }
368         }
369
370         private static void UnRegisterApplicationChangedEvent()
371         {
372             Interop.ApplicationManager.AppManagerUnSetAppContextEvent();
373         }
374
375         private static void RegisterApplicationEvent()
376         {
377             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
378             err = Interop.ApplicationManager.AppManagerEventCreate(out _eventHandle);
379             if (err != Interop.ApplicationManager.ErrorCode.None)
380             {
381                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the application event handle");
382             }
383
384             err = Interop.ApplicationManager.AppManagerEventSetStatus(_eventHandle, Interop.ApplicationManager.AppManagerEventStatusType.All);
385             if (err != Interop.ApplicationManager.ErrorCode.None)
386             {
387                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
388                 _eventHandle = IntPtr.Zero;
389                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event");
390             }
391
392             _eventCallback = (string appType, string appId, Interop.ApplicationManager.AppManagerEventType eventType, Interop.ApplicationManager.AppManagerEventState eventState, IntPtr eventHandle, IntPtr UserData) =>
393             {
394                 if (eventType == Interop.ApplicationManager.AppManagerEventType.Enable)
395                 {
396                     _enabledHandler?.Invoke(null, new ApplicationEnabledEventArgs(appId, (ApplicationEventState)eventState));
397                 }
398                 else if (eventType == Interop.ApplicationManager.AppManagerEventType.Disable)
399                 {
400                     _disabledHandler?.Invoke(null, new ApplicationDisabledEventArgs(appId, (ApplicationEventState)eventState));
401                 }
402             };
403             err = Interop.ApplicationManager.AppManagerSetEventCallback(_eventHandle, _eventCallback, IntPtr.Zero);
404             if (err != Interop.ApplicationManager.ErrorCode.None)
405             {
406                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
407                 _eventHandle = IntPtr.Zero;
408                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event callback");
409             }
410         }
411
412         private static void UnRegisterApplicationEvent()
413         {
414             if (_eventHandle != IntPtr.Zero)
415             {
416                 Interop.ApplicationManager.AppManagerUnSetEventCallback(_eventHandle);
417                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
418                 _eventHandle = IntPtr.Zero;
419             }
420         }
421
422         /// <summary>
423         /// Gets the information of the recent applications.
424         /// </summary>
425         /// <returns>Returns a dictionary containing all recent application info.</returns>
426         /// <exception cref="InvalidOperationException">Thrown when failed because of invalid operation</exception>
427         [EditorBrowsable(EditorBrowsableState.Never)]
428         public static IEnumerable<RecentApplicationInfo> GetRecentApplications()
429         {
430             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
431
432             List<RecentApplicationInfo> result = new List<RecentApplicationInfo>();
433             IntPtr table;
434             int nrows, ncols;
435
436             err = Interop.ApplicationManager.RuaHistoryLoadDb(out table, out nrows, out ncols);
437             if (err != Interop.ApplicationManager.ErrorCode.None)
438             {
439                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to load a table for the recent application list.");
440             }
441
442             for (int row = 0; row < nrows; ++row)
443             {
444                 Interop.ApplicationManager.RuaRec record;
445
446                 err = Interop.ApplicationManager.RuaHistoryGetRecord(out record, table, nrows, ncols, row);
447                 if (err != Interop.ApplicationManager.ErrorCode.None)
448                 {
449                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get record.");
450                 }
451
452                 RecentApplicationInfo info = new RecentApplicationInfo(record);
453                 result.Add(info);
454             }
455
456             err = Interop.ApplicationManager.RuaHistoryUnLoadDb(ref table);
457             if (err != Interop.ApplicationManager.ErrorCode.None)
458             {
459                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to unload a table for the recent application list.");
460             }
461
462             return result;
463         }
464     }
465
466     internal static class FilterExtension
467     {
468         private const string LogTag = "Tizen.Applications";
469         internal static void Fetch(this ApplicationInfoFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
470         {
471             if (filter is ApplicationInfoMetadataFilter)
472             {
473                 ApplicationInfoMetadataFilter metaFilter = (ApplicationInfoMetadataFilter)filter;
474                 metaFilter.Fetch(callback);
475                 return;
476             }
477
478             IntPtr nativeHandle = MakeNativeAppInfoFilter(filter.Filter);
479             if (nativeHandle == IntPtr.Zero)
480             {
481                 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
482             }
483             try
484             {
485                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterForeachAppinfo(nativeHandle, callback, IntPtr.Zero);
486                 if (err != Interop.ApplicationManager.ErrorCode.None)
487                 {
488                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get application information list with filter.");
489                 }
490             }
491             finally
492             {
493                 Interop.ApplicationManager.AppInfoFilterDestroy(nativeHandle);
494             }
495         }
496
497         internal static void Fetch(this ApplicationInfoMetadataFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
498         {
499             IntPtr nativeHandle = MakeNativeAppMetadataFilter(filter.Filter);
500             if (nativeHandle == IntPtr.Zero)
501             {
502                 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
503             }
504             try
505             {
506                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterForeach(nativeHandle, callback, IntPtr.Zero);
507                 if (err != Interop.ApplicationManager.ErrorCode.None)
508                 {
509                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get metadata list with filter.");
510                 }
511             }
512             finally
513             {
514                 Interop.ApplicationManager.AppInfoMetadataFilterDestroy(nativeHandle);
515             }
516         }
517
518         private static IntPtr MakeNativeAppInfoFilter(IDictionary<string, string> filter)
519         {
520             if (filter == null || filter.Count == 0)
521             {
522                 throw ApplicationManagerErrorFactory.FilterIsInvalid();
523             }
524
525             IntPtr infoHandle = IntPtr.Zero;
526             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterCreate(out infoHandle);
527             if (err != Interop.ApplicationManager.ErrorCode.None)
528             {
529                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter handle.");
530             }
531
532             foreach (var item in filter)
533             {
534                 if ((item.Key == ApplicationInfoFilter.Keys.Id) ||
535                     (item.Key == ApplicationInfoFilter.Keys.Type) ||
536                     (item.Key == ApplicationInfoFilter.Keys.Category))
537                 {
538                     err = Interop.ApplicationManager.AppInfoFilterAddString(infoHandle, item.Key, item.Value);
539                 }
540                 else if ((item.Key == ApplicationInfoFilter.Keys.NoDisplay) ||
541                          (item.Key == ApplicationInfoFilter.Keys.TaskManage))
542                 {
543                     err = Interop.ApplicationManager.AppInfoFilterAddBool(infoHandle, item.Key, Convert.ToBoolean(item.Value));
544                 }
545                 else
546                 {
547                     Log.Warn(LogTag, string.Format("'{0}' is not supported key for the filter.", item.Key));
548                 }
549                 if (err != Interop.ApplicationManager.ErrorCode.None)
550                 {
551                     Interop.ApplicationManager.AppInfoFilterDestroy(infoHandle);
552                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to add item to the filter.");
553                 }
554             }
555             return infoHandle;
556         }
557
558         private static IntPtr MakeNativeAppMetadataFilter(IDictionary<string, string> filter)
559         {
560             if (filter == null || filter.Count == 0)
561             {
562                 throw ApplicationManagerErrorFactory.FilterIsInvalid();
563             }
564
565             IntPtr infoHandle = IntPtr.Zero;
566             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterCreate(out infoHandle);
567             if (err != Interop.ApplicationManager.ErrorCode.None)
568             {
569                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter for searching with metadata.");
570             }
571             foreach (var item in filter)
572             {
573                 err = Interop.ApplicationManager.AppInfoMetadataFilterAdd(infoHandle, item.Key, item.Value);
574                 if (err != Interop.ApplicationManager.ErrorCode.None)
575                 {
576                     Interop.ApplicationManager.AppInfoMetadataFilterDestroy(infoHandle);
577                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to add the item to the filter.");
578                 }
579             }
580             return infoHandle;
581         }
582     }
583
584     internal static class ApplicationManagerErrorFactory
585     {
586         internal static Exception NativeFilterHandleIsInvalid()
587         {
588             return new InvalidOperationException("The native handle for filtering is invalid.");
589         }
590
591         internal static Exception FilterIsInvalid()
592         {
593             return new ArgumentException("The filter is invalid.");
594         }
595
596         internal static Exception GetException(Interop.ApplicationManager.ErrorCode err, string message)
597         {
598             string errMessage = String.Format("{0} err = {1}", message, err);
599             switch (err)
600             {
601                 case Interop.ApplicationManager.ErrorCode.InvalidParameter:
602                     return new ArgumentException(errMessage);
603                 default:
604                     return new InvalidOperationException(errMessage);
605             }
606         }
607     }
608 }