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