Release 4.0.0-preview1-00337
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Common / Tizen.Applications / Bundle.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.Reflection;
19 using System.Collections.Generic;
20 using System.Linq;
21 using System.Runtime.InteropServices;
22 using Tizen.Internals.Errors;
23
24 namespace Tizen.Applications
25 {
26     /// <summary>
27     /// A bundle object represents a bundle.
28     /// A bundle holds items (key-value pairs) and can be used with other Tizen APIs.
29     /// Keys can be used to access values.
30     /// This class is accessed by using a constructor to create a new instance of this object.
31     /// A bundle instance is not guaranteed to be thread safe if the instance is modified by multiple threads.
32     /// </summary>
33     public class Bundle : IDisposable
34     {
35         private SafeBundleHandle _handle;
36         private bool _disposed = false;
37         private readonly HashSet<string> _keys;
38
39         /// <summary>
40         /// The bundle constructor.
41         /// </summary>
42         /// <exception cref="System.InvalidOperationException">Thrown when out of memory.</exception>
43         /// <example>
44         /// <code>
45         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
46         /// </code>
47         /// </example>
48         public Bundle()
49         {
50             _handle = Interop.Bundle.Create();
51             BundleErrorFactory.CheckAndThrowException(ErrorFacts.GetLastResult(), _handle);
52             _keys = new HashSet<string>();
53         }
54
55         /// <summary>
56         /// The bundle constructor.
57         /// </summary>
58         /// <param name="handle">The SafeBundleHandle instance.</param>
59         /// <exception cref="System.ArgumentNullException">Thrown when the handle is null or invalid.</exception>
60         public Bundle(SafeBundleHandle handle)
61         {
62             if (handle == null || handle.IsInvalid)
63             {
64                 throw new ArgumentNullException("handle");
65             }
66
67             _handle = Interop.Bundle.DangerousClone(handle.DangerousGetHandle());
68             _keys = new HashSet<string>();
69             Interop.Bundle.Iterator iterator = (string key, int type, IntPtr keyval, IntPtr userData) =>
70             {
71                 _keys.Add(key);
72             };
73
74             Interop.Bundle.Foreach(_handle, iterator, IntPtr.Zero);
75             if ((BundleErrorFactory.BundleError)ErrorFacts.GetLastResult() == BundleErrorFactory.BundleError.InvalidParameter)
76             {
77                 throw new ArgumentException("Invalid parameter - cannot create bundle instance");
78             }
79         }
80
81         private enum BundleTypeProperty
82         {
83             Array = 0x0100,
84             Primitive = 0x0200,
85             Measurable = 0x0400
86         }
87
88         private enum BundleType
89         {
90             None = -1,
91             Any = 0,
92             String = 1 | BundleTypeProperty.Measurable,
93             StringArray = String | BundleTypeProperty.Array | BundleTypeProperty.Measurable,
94             Byte = 2,
95             ByteArray = Byte | BundleTypeProperty.Array
96         }
97
98         /// <summary>
99         /// The number of items in a bundle object.
100         /// </summary>
101         /// <example>
102         /// <code>
103         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
104         /// bundle.AddItem("string", "a_string");
105         /// Console.WriteLine("There are {0} items in the bundle", bundle.Count);
106         /// </code>
107         /// </example>
108         public int Count
109         {
110             get
111             {
112                 return _keys.Count;
113             }
114         }
115
116         /// <summary>
117         /// The keys in a bundle object.
118         /// </summary>
119         /// <example>
120         /// <code>
121         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
122         /// bundle.AddItem("string1", "a_string1");
123         /// bundle.AddItem("string2", "a_string2");
124         /// bundle.AddItem("string3", "a_string3");
125         /// Console.WriteLine("The bundle contains the following keys:");
126         /// foreach(string key in bundle.Keys)
127         /// {
128         ///     Console.WriteLine(key);
129         /// }
130         /// </code>
131         /// </example>
132         public IEnumerable<string> Keys
133         {
134             get
135             {
136                 return _keys;
137             }
138         }
139
140         /// <summary>
141         /// Gets the SafeBundleHandle instance.
142         /// </summary>
143         public SafeBundleHandle SafeBundleHandle
144         {
145             get { return _handle; }
146         }
147
148         /// <summary>
149         /// Releases any unmanaged resources used by this object.
150         /// </summary>
151         public void Dispose()
152         {
153             Dispose(true);
154             GC.SuppressFinalize(this);
155         }
156
157         /// <summary>
158         /// Checks whether the bundle contains an item with a specified key.
159         /// </summary>
160         /// <param name="key">The key to check for.</param>
161         /// <returns>true if the bundle contains the key, false otherwise.</returns>
162         /// <example>
163         /// <code>
164         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
165         /// bundle.AddItem("string", "a_string");
166         /// if (bundle.Contains("string"))
167         /// {
168         ///     string aValue = bundle.GetItem&lt;string&gt;("string");
169         ///     Console.WriteLine(aValue);
170         /// }
171         /// </code>
172         /// </example>
173         public bool Contains(string key)
174         {
175             return _keys.Contains(key);
176         }
177
178         /// <summary>
179         /// Adds an item into the bundle.
180         /// </summary>
181         /// <param name="key">The key to identify the item with. If an item with the key already exists in the bundle, this method will not succeed.</param>
182         /// <param name="value">The value of the item.</param>
183         /// <exception cref="System.ArgumentException">Thrown when the key already exists or when there is an invalid parameter.</exception>
184         /// <exception cref="System.ArgumentNullException">Thrown when a value is null.</exception>
185         /// <exception cref="System.InvalidOperationException">Thrown when out of memory or when the bundle instance has been disposed.</exception>
186         /// <example>
187         /// <code>
188         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
189         /// byte[] byteArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
190         /// bundle.AddItem("byte_array", byteArray);
191         /// </code>
192         /// </example>
193         public void AddItem(string key, byte[] value)
194         {
195             if (value == null)
196             {
197                 throw new ArgumentNullException("value");
198             }
199             AddItem(key, value, 0, value.Length);
200         }
201
202         /// <summary>
203         /// Adds an item into the bundle.
204         /// </summary>
205         /// <param name="key">The key to identify the item with. If an item with the key already exists in the bundle, this method will not succeed.</param>
206         /// <param name="value">The value of the item.</param>
207         /// <param name="offset">The zero-based byte offset in value from which to add to the bundle.</param>
208         /// <param name="count">The maximum number of bytes to add to the bundle starting with offset.</param>
209         /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the offset or count is out of range.</exception>
210         /// <exception cref="System.ArgumentException">Thrown when the key already exists or when there is an invalid parameter.</exception>
211         /// <exception cref="System.ArgumentNullException">Thrown when a value is null.</exception>
212         /// <exception cref="System.InvalidOperationException">Thrown when out of memory or when the bundle instance has been disposed.</exception>
213         /// <example>
214         /// <code>
215         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
216         /// byte[] byteArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
217         /// bundle.AddItem("byte_array", byteArray, 2, 3);
218         /// </code>
219         /// </example>
220         public void AddItem(string key, byte[] value, int offset, int count)
221         {
222             if (!_keys.Contains(key))
223             {
224                 if (value == null)
225                 {
226                     throw new ArgumentNullException("value");
227                 }
228                 if (offset < 0)
229                 {
230                     throw new ArgumentOutOfRangeException("offset", offset, "Cannot be less than 0");
231                 }
232                 if (offset > value.Length - 1)
233                 {
234                     throw new ArgumentOutOfRangeException("offset", offset, "Greater than last index of array");
235                 }
236                 if (count < 1)
237                 {
238                     throw new ArgumentOutOfRangeException("count", count, "Must be at least 1");
239                 }
240                 if (offset + count > value.Length)
241                 {
242                     throw new ArgumentException("The count is too large for the specified offset");
243                 }
244                 // Code is in Interop file because it is unsafe
245                 int ret = Interop.Bundle.UnsafeCode.AddItem(_handle, key, value, offset, count);
246                 BundleErrorFactory.CheckAndThrowException(ret, _handle);
247                 _keys.Add(key);
248             }
249             else
250             {
251                 throw new ArgumentException("Key already exists", "key");
252             }
253         }
254
255         /// <summary>
256         /// Adds an item into the bundle.
257         /// </summary>
258         /// <param name="key">The key to identify the item with. If an item with the key already exists in the bundle, this method will not succeed.</param>
259         /// <param name="value">The value of the item.</param>
260         /// <exception cref="System.ArgumentException">Thrown when the key already exists or when there is an invalid parameter.</exception>
261         /// <exception cref="System.InvalidOperationException">Thrown when out of memory or when the bundle instance has been disposed.</exception>
262         /// <example>
263         /// <code>
264         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
265         /// bundle.AddItem("string", "a_string");
266         /// </code>
267         /// </example>
268         public void AddItem(string key, string value)
269         {
270             if (!_keys.Contains(key))
271             {
272                 int ret = Interop.Bundle.AddString(_handle, key, value);
273                 BundleErrorFactory.CheckAndThrowException(ret, _handle);
274                 _keys.Add(key);
275             }
276             else
277             {
278                 throw new ArgumentException("Key already exists", "key");
279             }
280         }
281
282         /// <summary>
283         /// Adds an item into the bundle.
284         /// </summary>
285         /// <param name="key">The key to identify the item with. If an item with the key already exists in the bundle, this method will not succeed.</param>
286         /// <param name="value">The value of the item.</param>
287         /// <exception cref="System.ArgumentException">Thrown when the key already exists or when there is an invalid parameter.</exception>
288         /// <exception cref="System.InvalidOperationException">Thrown when out of memory or when the bundle instance has been disposed.</exception>
289         /// <example>
290         /// <code>
291         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
292         /// string[] stringArray = { "a", "b", "c" };
293         /// bundle.AddItem("string_array", stringArray);
294         /// </code>
295         /// </example>
296         public void AddItem(string key, IEnumerable<string> value)
297         {
298             if (!_keys.Contains(key))
299             {
300                 string[] valueArray = value.Select(v => v == null ? string.Empty : v).ToArray();
301                 int ret = Interop.Bundle.AddStringArray(_handle, key, valueArray, valueArray.Count());
302                 BundleErrorFactory.CheckAndThrowException(ret, _handle);
303                 _keys.Add(key);
304             }
305             else
306             {
307                 throw new ArgumentException("Key already exists", "key");
308             }
309         }
310
311         /// <summary>
312         /// Gets the value of a bundle item with a specified key.
313         /// </summary>
314         /// <param name="key">The key of the bundle item whose value is desired.</param>
315         /// <returns>The value of the bundle item.</returns>
316         /// <exception cref="System.ArgumentException">Thrown when the key does not exist or when there is an invalid parameter.</exception>
317         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
318         /// <example>
319         /// <code>
320         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
321         /// bundle.AddItem("string", "a_string");
322         /// if (bundle.Contains("string"))
323         /// {
324         ///     object aValue = bundle.GetItem("string");
325         ///     if (bundle.Is&lt;string&gt;("string");)
326         ///     {
327         ///         string aString = (string)aValue;
328         ///         Console.WriteLine(aString);
329         ///     }
330         /// }
331         /// </code>
332         /// </example>
333         public object GetItem(string key)
334         {
335             if (_keys.Contains(key))
336             {
337                 int type = Interop.Bundle.GetType(_handle, key);
338                 BundleErrorFactory.CheckAndThrowException(ErrorFacts.GetLastResult(), _handle);
339                 switch (type)
340                 {
341                     case (int)BundleType.String:
342                         // get string
343                         IntPtr stringPtr;
344                         int retString = Interop.Bundle.GetString(_handle, key, out stringPtr);
345                         BundleErrorFactory.CheckAndThrowException(retString, _handle);
346                         string stringValue = Marshal.PtrToStringAnsi(stringPtr);
347                         if (stringValue == null)
348                             return string.Empty;
349                         return stringValue;
350
351                     case (int)BundleType.StringArray:
352                         // get string array
353                         int stringArraySize;
354                         IntPtr stringArrayPtr = Interop.Bundle.GetStringArray(_handle, key, out stringArraySize);
355                         BundleErrorFactory.CheckAndThrowException(ErrorFacts.GetLastResult(), _handle);
356                         string[] stringArray;
357                         IntPtrToStringArray(stringArrayPtr, stringArraySize, out stringArray);
358                         return stringArray;
359
360                     case (int)BundleType.Byte:
361                         // get byte array
362                         IntPtr byteArrayPtr;
363                         int byteArraySize;
364                         int retByte = Interop.Bundle.GetByte(_handle, key, out byteArrayPtr, out byteArraySize);
365                         BundleErrorFactory.CheckAndThrowException(retByte, _handle);
366                         byte[] byteArray = new byte[byteArraySize];
367                         Marshal.Copy(byteArrayPtr, byteArray, 0, byteArraySize);
368                         return byteArray;
369
370                     default:
371                         throw new ArgumentException("Key does not exist in the bundle", "key");
372                 }
373             }
374             else
375             {
376                 throw new ArgumentException("Key does not exist in the bundle (may be null or empty string)", "key");
377             }
378         }
379
380         /// <summary>
381         /// Gets the value of a bundle item with a specified key.
382         /// Note that this is a generic method.
383         /// </summary>
384         /// <typeparam name="T">The generic type to return.</typeparam>
385         /// <param name="key">The key of the bundle item whose value is desired.</param>
386         /// <returns>The value of the bundle item if it is of the specified generic type.</returns>
387         /// <exception cref="System.ArgumentException">Thrown when the key does not exist or when there is an invalid parameter.</exception>
388         /// <exception cref="System.InvalidCastException">Thrown when the value of the bundle item cannot be converted to the specified generic type.</exception>
389         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
390         /// <example>
391         /// <code>
392         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
393         /// string[] stringArray = { "a", "b", "c" };
394         /// bundle.AddItem("string_array", stringArray);
395         /// if (bundle.Is&lt;string&gt;("string_array"))
396         /// {
397         ///     Console.WriteLine("It is a string");
398         ///     Console.WriteLine(bundle.GetItem&lt;string&gt;("string_array"));
399         /// }
400         /// else if (bundle.Is&lt;string[]&gt;("string_array"))
401         /// {
402         ///     Console.WriteLine("It is a string[]");
403         ///     string[] anArray = bundle.GetItem&lt;string[]&gt;("string_array");
404         ///     foreach (string value in anArray)
405         ///     {
406         ///         Console.WriteLine(value);
407         ///     }
408         /// }
409         /// </code>
410         /// </example>
411         public T GetItem<T>(string key)
412         {
413             return (T)GetItem(key);
414         }
415
416         /// <summary>
417         /// Gets the value of a bundle item with a specified key.
418         /// </summary>
419         /// <param name="key">The key of the bundle item whose value is desired.</param>
420         /// <param name="value">The value of the bundle item. If the key does not exist or the type of this parameter is incorrect, it is the default value for the value parameter type.</param>
421         /// <returns>true if an item with the key exists and if the value is the same type as the output value parameter, false otherwise.</returns>
422         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
423         /// <example>
424         /// <code>
425         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
426         /// byte[] byteArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
427         /// bundle.AddItem("byte_array", byteArray);
428         /// byte[] aByteArray;
429         /// if (bundle.TryGetItem("byte_array", out aByteArray))
430         /// {
431         ///     Console.WriteLine("First item in the byte array: {0}", aByteArray[0]);
432         /// }
433         /// </code>
434         /// </example>
435         public bool TryGetItem(string key, out byte[] value)
436         {
437             if (_keys.Contains(key) && Interop.Bundle.GetType(_handle, key) == (int)BundleType.Byte)
438             {
439                 value = GetItem<byte[]>(key);
440                 return true;
441             }
442             else
443             {
444                 if (_keys.Contains(key) && ErrorFacts.GetLastResult() == (int)BundleErrorFactory.BundleError.InvalidParameter)
445                 {
446                     throw new InvalidOperationException("Invalid bundle instance (object may have been disposed or released)");
447                 }
448                 value = default(byte[]);
449                 return false;
450             }
451         }
452
453         /// <summary>
454         /// Gets the value of a bundle item with a specified key.
455         /// </summary>
456         /// <param name="key">The key of the bundle item whose value is desired.</param>
457         /// <param name="value">The value of the bundle item. If the key does not exist or the type of this parameter is incorrect, it is the default value for the value parameter type.</param>
458         /// <returns>true if an item with the key exists and if the value is the same type as the output value parameter, false otherwise.</returns>
459         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
460         /// <example>
461         /// <code>
462         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
463         /// bundle.AddItem("string", "a_string");
464         /// string aString;
465         /// if (bundle.TryGetItem("string", out aString))
466         /// {
467         ///     Console.WriteLine(aString);
468         /// }
469         /// </code>
470         /// </example>
471         public bool TryGetItem(string key, out string value)
472         {
473             if (_keys.Contains(key) && Interop.Bundle.GetType(_handle, key) == (int)BundleType.String)
474             {
475                 value = GetItem<string>(key);
476                 return true;
477             }
478             else
479             {
480                 if (_keys.Contains(key) && ErrorFacts.GetLastResult() == (int)BundleErrorFactory.BundleError.InvalidParameter)
481                 {
482                     throw new InvalidOperationException("Invalid bundle instance (object may have been disposed or released)");
483                 }
484                 value = default(string);
485                 return false;
486             }
487         }
488
489         /// <summary>
490         /// Gets the value of a bundle item with a specified key.
491         /// </summary>
492         /// <param name="key">The key of the bundle item whose value is desired.</param>
493         /// <param name="value">The value of the bundle item. If the key does not exist or the type of this parameter is incorrect, it is the default value for the value parameter type.</param>
494         /// <returns>true if an item with the key exists and if the value is the same type as the output value parameter, false otherwise.</returns>
495         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
496         /// <example>
497         /// <code>
498         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
499         /// string[] stringArray = { "a", "b", "c" };
500         /// bundle.AddItem("string_array", stringArray);
501         /// System.Collections.Generic.IEnumerable&lt;string&gt; aStringEnumerable;
502         /// if (bundle.TryGetItem("string", out aStringEnumerable))
503         /// {
504         ///     foreach (string value in aStringEnumerable)
505         ///     {
506         ///         Console.WriteLine(value);
507         ///     }
508         /// }
509         /// </code>
510         /// </example>
511         public bool TryGetItem(string key, out IEnumerable<string> value)
512         {
513             if (_keys.Contains(key) && Interop.Bundle.GetType(_handle, key) == (int)BundleType.StringArray)
514             {
515                 value = GetItem<IEnumerable<string>>(key);
516                 return true;
517             }
518             else
519             {
520                 if (_keys.Contains(key) && ErrorFacts.GetLastResult() == (int)BundleErrorFactory.BundleError.InvalidParameter)
521                 {
522                     throw new InvalidOperationException("Invalid bundle instance (object may have been disposed or released)");
523                 }
524                 value = default(IEnumerable<string>);
525                 return false;
526             }
527         }
528
529         /// <summary>
530         /// Checks whether an item is of a specific type.
531         /// </summary>
532         /// <typeparam name="T">The generic type to check for.</typeparam>
533         /// <param name="key">The key whose type wants to be checked.</param>
534         /// <returns>true if the item is of the specified type, false otherwise.</returns>
535         /// <exception cref="System.ArgumentException">Thrown when the key does not exist or when there is an invalid parameter.</exception>
536         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
537         /// <example>
538         /// <code>
539         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
540         /// string[] stringArray = { "a", "b", "c" };
541         /// bundle.AddItem("string_array", stringArray);
542         /// if (bundle.Is&lt;string[]&gt;("string_array"))
543         /// {
544         ///     Console.WriteLine("It is a string[]");
545         ///     string[] anArray = bundle.GetItem&lt;string[]&gt;("string_array");
546         ///     foreach (string value in anArray)
547         ///     {
548         ///         Console.WriteLine(value);
549         ///     }
550         /// }
551         /// </code>
552         /// </example>
553         public bool Is<T>(string key)
554         {
555             if (_keys.Contains(key))
556             {
557                 int type = Interop.Bundle.GetType(_handle, key);
558                 switch (type)
559                 {
560                     case (int)BundleType.String:
561                         return typeof(string) == typeof(T);
562
563                     case (int)BundleType.StringArray:
564                         return typeof(T).GetTypeInfo().IsAssignableFrom(typeof(string[]).GetTypeInfo());
565
566                     case (int)BundleType.Byte:
567                         return typeof(byte[]) == typeof(T);
568
569                     default:
570                         throw new ArgumentException("Key does not exist in the bundle", "key");
571                 }
572             }
573             else
574             {
575                 throw new ArgumentException("Key does not exist in the bundle (may be null or empty string)", "key");
576             }
577         }
578
579         /// <summary>
580         /// Removes a bundle item with a specific key from a Bundle.
581         /// </summary>
582         /// <param name="key">The key of the item to delete.</param>
583         /// <returns>true if the item is successfully found and removed, false otherwise (even if the item is not found).</returns>
584         /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
585         /// <exception cref="System.InvalidOperationException">Thrown when the bundle instance has been disposed.</exception>
586         /// <example>
587         /// <code>
588         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
589         /// bundle.AddItem("string", "a_string");
590         /// if (bundle.Contains("string"))
591         /// {
592         ///     if (bundle.RemoveItem("string"))
593         ///     {
594         ///         Console.WriteLine("Removed");
595         ///     }
596         /// }
597         /// </code>
598         /// </example>
599         public bool RemoveItem(string key)
600         {
601             if (_keys.Contains(key))
602             {
603                 int ret = Interop.Bundle.RemoveItem(_handle, key);
604                 if (ret == (int)BundleErrorFactory.BundleError.KeyNotAvailable)
605                 {
606                     return false;
607                 }
608                 BundleErrorFactory.CheckAndThrowException(ret, _handle);
609                 _keys.Remove(key);
610                 return true;
611             }
612             else
613             {
614                 return false;
615             }
616         }
617
618         /// <summary>
619         /// Decodes an encoded bundle data.
620         /// </summary>
621         /// <param name="bundleRaw">The encoded bundle data. bundleRaw should be the returned value of Tizen.Applications.Bundle.Encode, otherwise this method will not succeed.</param>
622         /// <returns>Decoded Bundle object.</returns>
623         /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
624         /// <example>
625         /// <code>
626         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
627         /// string bundleRaw = bundle.Encode();
628         /// Bundle data = bundle.Decode(bundleRaw);
629         /// </code>
630         /// </example>
631         public static Bundle Decode(string bundleRaw)
632         {
633             SafeBundleHandle handle;
634
635             handle = Interop.Bundle.BundleDecode(bundleRaw, bundleRaw.Length);
636             if (ErrorFacts.GetLastResult() == (int)BundleErrorFactory.BundleError.InvalidParameter)
637             {
638                 throw new ArgumentException("Invalid bundle raw");
639             }
640
641             return new Bundle(handle);
642         }
643
644         /// <summary>
645         /// Encodes bundle to string.
646         /// </summary>
647         /// <returns>Encoded bundle data in string.</returns>
648         /// <exception cref="System.InvalidOperationException">Thrown when out of memory or when the bundle instance has been disposed.</exception>
649         /// <example>
650         /// <code>
651         /// Tizen.Applications.Bundle bundle = new Tizen.Applications.Bundle();
652         /// string bundleRaw = bundle.Encode();
653         /// </code>
654         /// </example>
655         public string Encode()
656         {
657             string bundleRaw;
658             int len;
659
660             Interop.Bundle.BundleEncode(_handle, out bundleRaw, out len);
661             if (ErrorFacts.GetLastResult() == (int)BundleErrorFactory.BundleError.InvalidParameter)
662             {
663                 throw new InvalidOperationException("Invalid bundle");
664             }
665
666             return bundleRaw;
667         }
668
669         /// <summary>
670         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
671         /// </summary>
672         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
673         protected virtual void Dispose(bool disposing)
674         {
675             if (!_disposed)
676             {
677                 if (disposing)
678                 {
679                     if (_handle != null && !_handle.IsInvalid)
680                         _handle.Dispose();
681                 }
682
683                 _disposed = true;
684             }
685         }
686
687         /// <summary>
688         /// Destructor of the bundle class.
689         /// </summary>
690         ~Bundle()
691         {
692             Dispose(false);
693         }
694
695         static private void IntPtrToStringArray(IntPtr unmanagedArray, int size, out string[] managedArray)
696         {
697             managedArray = new string[size];
698             IntPtr[] IntPtrArray = new IntPtr[size];
699
700             Marshal.Copy(unmanagedArray, IntPtrArray, 0, size);
701
702             for (int iterator = 0; iterator < size; iterator++)
703             {
704                 managedArray[iterator] = Marshal.PtrToStringAnsi(IntPtrArray[iterator]);
705             }
706         }
707     }
708
709     internal static class BundleErrorFactory
710     {
711         internal enum BundleError
712         {
713             None = ErrorCode.None,
714             OutOfMemory = ErrorCode.OutOfMemory,
715             InvalidParameter = ErrorCode.InvalidParameter,
716             KeyNotAvailable = ErrorCode.KeyNotAvailable,
717             KeyExists = -0x01180000 | 0x01
718         }
719
720         static internal void CheckAndThrowException(int error, SafeBundleHandle handle)
721         {
722             if ((BundleError)error == BundleError.None)
723             {
724                 return;
725             }
726             else if ((BundleError)error == BundleError.OutOfMemory)
727             {
728                 throw new InvalidOperationException("Out of memory");
729             }
730             else if ((BundleError)error == BundleError.InvalidParameter)
731             {
732                 if (handle.IsInvalid)
733                 {
734                     throw new InvalidOperationException("Invalid bundle instance (object may have been disposed or released)");
735                 }
736                 throw new ArgumentException("Invalid parameter");
737             }
738             else if ((BundleError)error == BundleError.KeyNotAvailable)
739             {
740                 throw new ArgumentException("Key does not exist in the bundle");
741             }
742             else if ((BundleError)error == BundleError.KeyExists)
743             {
744                 throw new ArgumentException("Key already exists");
745             }
746         }
747     }
748 }