Release 4.0.0-preview1-00271
[platform/core/csapi/tizenfx.git] / src / Tizen.Pims.Calendar / Tizen.Pims.Calendar / CalendarRecord.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.Runtime.InteropServices;
19 using System.Diagnostics.CodeAnalysis;
20
21 namespace Tizen.Pims.Calendar
22 {
23     /// <summary>
24     /// A record represents an actual record in the database
25     /// </summary>
26     /// <since_tizen> 4 </since_tizen>
27     /// <remarks>
28     /// A record represents an actual record in the database,
29     /// but you can also consider it a piece of information, such as an alarm, attendee and extended.
30     /// A record can be a complex set of data, containing other data.
31     /// For example, a calendar record contains the alarm property, which is a reference to an alarm record.
32     /// An alarm record could belong to a event record,
33     /// and its alarm id property is set to the identifier of the corresponding event.
34     /// In this case, the alarm is the child record of the event and the event is the parent record.
35     /// </remarks>
36     public class CalendarRecord : IDisposable
37     {
38         internal string _uri;
39         internal uint _id;
40         private Int64 _memoryPressure = CalendarViews.Record.AverageSize;
41         internal IntPtr _recordHandle;
42
43         internal CalendarRecord(IntPtr handle)
44         {
45             _recordHandle = handle;
46
47             IntPtr viewUri;
48             int error = Interop.Record.GetUriPointer(handle, out viewUri);
49             if (CalendarError.None != (CalendarError)error)
50             {
51                 Log.Error(Globals.LogTag, "GetUriPointer Failed with error " + error);
52                 throw CalendarErrorFactory.GetException(error);
53             }
54             _uri = Marshal.PtrToStringAnsi(viewUri);
55             GC.AddMemoryPressure(_memoryPressure);
56         }
57
58         internal CalendarRecord(IntPtr handle, bool disposedValue)
59         {
60             _recordHandle = handle;
61             _disposedValue = disposedValue;
62
63             IntPtr viewUri;
64             int error = Interop.Record.GetUriPointer(handle, out viewUri);
65             if (CalendarError.None != (CalendarError)error)
66             {
67                 Log.Error(Globals.LogTag, "GetUriPointer Failed with error " + error);
68                 throw CalendarErrorFactory.GetException(error);
69             }
70             _uri = Marshal.PtrToStringAnsi(viewUri);
71             if (!_disposedValue)
72                 GC.AddMemoryPressure(_memoryPressure);
73         }
74
75         internal CalendarRecord(IntPtr handle, int id)
76         {
77             _recordHandle = handle;
78             _id = (uint)id;
79
80             IntPtr viewUri;
81             int error = Interop.Record.GetUriPointer(handle, out viewUri);
82             if (CalendarError.None != (CalendarError)error)
83             {
84                 Log.Error(Globals.LogTag, "GetUriPointer Failed with error " + error);
85                 throw CalendarErrorFactory.GetException(error);
86             }
87             _uri = Marshal.PtrToStringAnsi(viewUri);
88             GC.AddMemoryPressure(_memoryPressure);
89         }
90
91         /// <summary>
92         /// Creates a record.
93         /// </summary>
94         /// <since_tizen> 4 </since_tizen>
95         /// <feature>http://tizen.org/feature/calendar</feature>
96         /// <param name="viewUri">The view URI</param>
97         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
98         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
99         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
100         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
101         public CalendarRecord(string viewUri)
102         {
103             int error = 0;
104             error = Interop.Record.Create(viewUri, out _recordHandle);
105             if (CalendarError.None != (CalendarError)error)
106             {
107                 Log.Error(Globals.LogTag, "CalendarRecord Failed with error " + error);
108                 throw CalendarErrorFactory.GetException(error);
109             }
110             _uri = viewUri;
111             GC.AddMemoryPressure(_memoryPressure);
112         }
113
114         /// <summary>
115         /// Destructor
116         /// </summary>
117         ~CalendarRecord()
118         {
119             Dispose(false);
120         }
121
122 #region IDisposable Support
123         /// To detect redundant calls
124         internal bool _disposedValue = false;
125
126         /// <summary>
127         /// Disposes of the resources (other than memory) used by the CalendarRecord.
128         /// </summary>
129         /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
130         protected virtual void Dispose(bool disposing)
131         {
132             if (!_disposedValue)
133             {
134                 Log.Debug(Globals.LogTag, "Dispose :" + disposing);
135
136                 int error = Interop.Record.Destroy(_recordHandle, false);
137                 if (CalendarError.None != (CalendarError)error)
138                 {
139                     Log.Error(Globals.LogTag, "Destroy Failed with error " + error);
140                 }
141                 _disposedValue = true;
142                 GC.RemoveMemoryPressure(_memoryPressure);
143             }
144         }
145
146         /// <summary>
147         /// Releases all resources used by the CalendarRecord.
148         /// It should be called after having finished using of the object.
149         /// </summary>
150         public void Dispose()
151         {
152             Dispose(true);
153             GC.SuppressFinalize(this);
154         }
155 #endregion
156
157         internal static Interop.Record.DateTime ConvertCalendarTimeToStruct(CalendarTime value)
158         {
159             Interop.Record.DateTime time = new Interop.Record.DateTime();
160             time.type = value._type;
161
162             if ((int)CalendarTime.Type.Utc == value._type)
163             {
164                 DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
165                 time.utime = (value.UtcTime.Ticks - epoch.Ticks) / 10000000;
166             }
167             else
168             {
169                 time.year = value.LocalTime.Year;
170                 time.month = value.LocalTime.Month;
171                 time.mday = value.LocalTime.Day;
172                 time.hour = value.LocalTime.Hour;
173                 time.minute = value.LocalTime.Minute;
174                 time.second = value.LocalTime.Second;
175             }
176             return time;
177         }
178
179         internal static CalendarTime ConvertIntPtrToCalendarTime(Interop.Record.DateTime time)
180         {
181             CalendarTime value;
182             if ((int)CalendarTime.Type.Utc == time.type)
183             {
184                 DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
185                 value = new CalendarTime(time.utime * 10000000 + epoch.Ticks);
186             }
187             else
188             {
189                 value = new CalendarTime(time.year, time.month, time.mday, time.hour, time.minute, time.second);
190             }
191             value._type = time.type;
192             return value;
193         }
194
195         /// <summary>
196         /// Makes a clone of a record.
197         /// </summary>
198         /// <since_tizen> 4 </since_tizen>
199         /// <returns>
200         /// A cloned record
201         /// </returns>
202         /// <feature>http://tizen.org/feature/calendar</feature>
203         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
204         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
205         public CalendarRecord Clone()
206         {
207             IntPtr _clonedRecordHandle;
208             int error = Interop.Record.Clone(_recordHandle, out _clonedRecordHandle);
209             if (CalendarError.None != (CalendarError)error)
210             {
211                 Log.Error(Globals.LogTag, "Clone Failed with error " + error);
212                 throw CalendarErrorFactory.GetException(error);
213             }
214             return new CalendarRecord(_clonedRecordHandle, (int)_id);
215         }
216
217         /// <summary>
218         /// Get record URI.
219         /// </summary>
220         /// <since_tizen> 4 </since_tizen>
221         /// <value>The URI of the record</value>
222         [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
223         public string Uri
224         {
225             get
226             {
227                 return _uri;
228             }
229         }
230
231         /// <summary>
232         /// Gets a object from a record.
233         /// </summary>
234         /// <since_tizen> 4 </since_tizen>
235         /// <param name="propertyId">The property ID</param>
236         /// <returns>
237         /// The value of the property corresponding to property id.
238         /// </returns>
239         /// <feature>http://tizen.org/feature/calendar</feature>
240         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
241         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
242         public T Get<T>(uint propertyId)
243         {
244             object parsedValue = null;
245             if (typeof(T) == typeof(string))
246             {
247                 string val;
248                 int error = Interop.Record.GetString(_recordHandle, propertyId, out val);
249                 if (CalendarError.None != (CalendarError)error)
250                 {
251                     Log.Error(Globals.LogTag, "Get String Failed [" + error + "]" + String.Format("{0:X}", propertyId));
252                     throw CalendarErrorFactory.GetException(error);
253                 }
254                 parsedValue = Convert.ChangeType(val, typeof(T));
255             }
256             else if (typeof(T) == typeof(int))
257             {
258                 int val;
259                 int error = Interop.Record.GetInteger(_recordHandle, propertyId, out val);
260                 if (CalendarError.None != (CalendarError)error)
261                 {
262                     Log.Error(Globals.LogTag, "Get Intger Failed [" + error + "]" + String.Format("{0:X}", propertyId));
263                     throw CalendarErrorFactory.GetException(error);
264                 }
265                 parsedValue = Convert.ChangeType(val, typeof(T));
266             }
267             else if (typeof(T) == typeof(long))
268             {
269                 long val;
270                 int error = Interop.Record.GetLli(_recordHandle, propertyId, out val);
271                 if (CalendarError.None != (CalendarError)error)
272                 {
273                     Log.Error(Globals.LogTag, "Get Long Failed [" + error + "]" + String.Format("{0:X}", propertyId));
274                     throw CalendarErrorFactory.GetException(error);
275                 }
276                 parsedValue = Convert.ChangeType(val, typeof(T));
277             }
278             else if (typeof(T) == typeof(double))
279             {
280                 double val;
281                 int error = Interop.Record.GetDouble(_recordHandle, propertyId, out val);
282                 if (CalendarError.None != (CalendarError)error)
283                 {
284                     Log.Error(Globals.LogTag, "Get Double Failed [" + error + "]" + String.Format("{0:X}", propertyId));
285                     throw CalendarErrorFactory.GetException(error);
286                 }
287                 parsedValue = Convert.ChangeType(val, typeof(T));
288             }
289             else if (typeof(T) == typeof(CalendarTime))
290             {
291                 Interop.Record.DateTime time;
292                 int error = Interop.Record.GetCalendarTime(_recordHandle, propertyId, out time);
293                 if (CalendarError.None != (CalendarError)error)
294                 {
295                     Log.Error(Globals.LogTag, "Get CalendarTime Failed [" + error + "]" + String.Format("{0:X}", propertyId));
296                     throw CalendarErrorFactory.GetException(error);
297                 }
298                 CalendarTime val = ConvertIntPtrToCalendarTime(time);
299                 parsedValue = Convert.ChangeType(val, typeof(T));
300             }
301             else
302             {
303                 Log.Error(Globals.LogTag, "Not supported Data T/ype");
304                 throw CalendarErrorFactory.GetException((int)CalendarError.NotSupported);
305             }
306             return (T)parsedValue;
307         }
308
309         /// <summary>
310         /// Sets a value of the property to a record.
311         /// </summary>
312         /// <since_tizen> 4 </since_tizen>
313         /// <param name="propertyId">The property ID</param>
314         /// <param name="value">value</param>
315         /// <feature>http://tizen.org/feature/calendar</feature>
316         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
317         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
318         public void Set<T>(uint propertyId, T value)
319         {
320             if (typeof(T) == typeof(string))
321             {
322                 string val = Convert.ToString(value);
323                 int error = Interop.Record.SetString(_recordHandle, propertyId, val);
324                 if (CalendarError.None != (CalendarError)error)
325                 {
326                     Log.Error(Globals.LogTag, "Set String Failed [" + error + "]" + String.Format("{0:X}", propertyId));
327                     throw CalendarErrorFactory.GetException(error);
328                 }
329             }
330             else if (typeof(T) == typeof(int))
331             {
332                 int val = Convert.ToInt32(value);
333                 int error = Interop.Record.SetInteger(_recordHandle, propertyId, val);
334                 if (CalendarError.None != (CalendarError)error)
335                 {
336                     Log.Error(Globals.LogTag, "Set Integer Failed [" + error + "]" + String.Format("{0:X}", propertyId));
337                     throw CalendarErrorFactory.GetException(error);
338                 }
339             }
340             else if (typeof(T) == typeof(long))
341             {
342                 long val = Convert.ToInt64(value);
343                 int error = Interop.Record.SetLli(_recordHandle, propertyId, val);
344                 if (CalendarError.None != (CalendarError)error)
345                 {
346                     Log.Error(Globals.LogTag, "Set Long Failed [" + error + "]" + String.Format("{0:X}", propertyId));
347                     throw CalendarErrorFactory.GetException(error);
348                 }
349             }
350             else if (typeof(T) == typeof(double))
351             {
352                 double val = Convert.ToDouble(value);
353                 int error = Interop.Record.SetDouble(_recordHandle, propertyId, val);
354                 if (CalendarError.None != (CalendarError)error)
355                 {
356                     Log.Error(Globals.LogTag, "Set Double Failed [" + error + "]" + String.Format("{0:X}", propertyId));
357                     throw CalendarErrorFactory.GetException(error);
358                 }
359             }
360             else if (typeof(T) == typeof(CalendarTime))
361             {
362                 CalendarTime time = (CalendarTime)Convert.ChangeType(value, typeof(CalendarTime));
363                 Interop.Record.DateTime val = ConvertCalendarTimeToStruct(time);
364                 int error = Interop.Record.SetCalendarTime(_recordHandle, propertyId, val);
365                 if (CalendarError.None != (CalendarError)error)
366                 {
367                     Log.Error(Globals.LogTag, "Set CalendarTime Failed [" + error + "]" + String.Format("{0:X}", propertyId));
368                     throw CalendarErrorFactory.GetException(error);
369                 }
370             }
371             else
372             {
373                 Log.Error(Globals.LogTag, "Not supported Data T/ype");
374                 throw CalendarErrorFactory.GetException((int)CalendarError.NotSupported);
375             }
376         }
377
378         /// <summary>
379         /// Adds a child record to the parent record.
380         /// </summary>
381         /// <since_tizen> 4 </since_tizen>
382         /// <param name="propertyId">The property ID</param>
383         /// <param name="childRecord">The child record</param>
384         /// <feature>http://tizen.org/feature/calendar</feature>
385         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
386         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
387         public void AddChildRecord(uint propertyId, CalendarRecord childRecord)
388         {
389             int error = Interop.Record.AddChildRecord(_recordHandle, propertyId, childRecord._recordHandle);
390             if (CalendarError.None != (CalendarError)error)
391             {
392                 Log.Error(Globals.LogTag, "AddChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
393                 throw CalendarErrorFactory.GetException(error);
394             }
395             childRecord._disposedValue = true;
396         }
397
398         /// <summary>
399         /// Removes a child record from the parent record.
400         /// </summary>
401         /// <since_tizen> 4 </since_tizen>
402         /// <param name="propertyId">The property ID</param>
403         /// <param name="childRecord">The child record</param>
404         /// <feature>http://tizen.org/feature/calendar</feature>
405         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
406         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
407         public void RemoveChildRecord(uint propertyId, CalendarRecord childRecord)
408         {
409             int error = Interop.Record.RemoveChildRecord(_recordHandle, propertyId, childRecord._recordHandle);
410             if (CalendarError.None != (CalendarError)error)
411             {
412                 Log.Error(Globals.LogTag, "RemoveChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
413                 throw CalendarErrorFactory.GetException(error);
414             }
415             childRecord._disposedValue = false;
416         }
417
418         /// <summary>
419         /// Gets a child record from the parent record
420         /// </summary>
421         /// <since_tizen> 4 </since_tizen>
422         /// <param name="propertyId">The property ID</param>
423         /// <returns>
424         /// The number of child records corresponding to property ID
425         /// </returns>
426         /// <feature>http://tizen.org/feature/calendar</feature>
427         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
428         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
429         public int GetChildRecordCount(uint propertyId)
430         {
431             int count = 0;
432             int error = Interop.Record.GetChildRecordCount(_recordHandle, propertyId, out count);
433             if (CalendarError.None != (CalendarError)error)
434             {
435                 Log.Error(Globals.LogTag, "GetChildRecordCount Failed [" + error + "]" + String.Format("{0:X}", propertyId));
436                 throw CalendarErrorFactory.GetException(error);
437             }
438             return count;
439         }
440
441         /// <summary>
442         /// Gets a child record from the parent record
443         /// </summary>
444         /// <since_tizen> 4 </since_tizen>
445         /// <param name="propertyId">The property ID</param>
446         /// <param name="index">The child record index</param>
447         /// <returns>
448         /// The record
449         /// </returns>
450         /// <feature>http://tizen.org/feature/calendar</feature>
451         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
452         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
453         public CalendarRecord GetChildRecord(uint propertyId, int index)
454         {
455             IntPtr handle;
456
457             int error = Interop.Record.GetChildRecordPointer(_recordHandle, propertyId, index, out handle);
458             if (CalendarError.None != (CalendarError)error)
459             {
460                 Log.Error(Globals.LogTag, "GetChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
461                 throw CalendarErrorFactory.GetException(error);
462             }
463             return new CalendarRecord(handle, true);
464         }
465
466         /// <summary>
467         /// Clones a child record list corresponding to property ID
468         /// </summary>
469         /// <since_tizen> 4 </since_tizen>
470         /// <param name="propertyId">The property ID</param>
471         /// <returns>
472         /// the record list
473         /// </returns>
474         /// <feature>http://tizen.org/feature/calendar</feature>
475         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
476         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
477         public CalendarList CloneChildRecordList(uint propertyId)
478         {
479             IntPtr listHandle;
480             int error = Interop.Record.CloneChildRecordList(_recordHandle, propertyId, out listHandle);
481             if (CalendarError.None != (CalendarError)error)
482             {
483                 Log.Error(Globals.LogTag, "CloneChildRecordList Failed with [" + error + "]" + String.Format("{0:X}", propertyId));
484                 throw CalendarErrorFactory.GetException(error);
485             }
486             CalendarList list = new CalendarList(listHandle);
487             return list;
488         }
489     }
490 }