Release 4.0.0-preview1-00253
[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                     throw CalendarErrorFactory.GetException(error);
141                 }
142                 _disposedValue = true;
143                 GC.RemoveMemoryPressure(_memoryPressure);
144             }
145         }
146
147         /// <summary>
148         /// Releases all resources used by the CalendarRecord.
149         /// It should be called after having finished using of the object.
150         /// </summary>
151         public void Dispose()
152         {
153             Dispose(true);
154             GC.SuppressFinalize(this);
155         }
156 #endregion
157
158         internal static Interop.Record.DateTime ConvertCalendarTimeToStruct(CalendarTime value)
159         {
160             Interop.Record.DateTime time = new Interop.Record.DateTime();
161             time.type = value._type;
162
163             if ((int)CalendarTime.Type.Utc == value._type)
164             {
165                 DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
166                 time.utime = (value.UtcTime.Ticks - epoch.Ticks) / 10000000;
167             }
168             else
169             {
170                 time.year = value.LocalTime.Year;
171                 time.month = value.LocalTime.Month;
172                 time.mday = value.LocalTime.Day;
173                 time.hour = value.LocalTime.Hour;
174                 time.minute = value.LocalTime.Minute;
175                 time.second = value.LocalTime.Second;
176             }
177             return time;
178         }
179
180         internal static CalendarTime ConvertIntPtrToCalendarTime(Interop.Record.DateTime time)
181         {
182             CalendarTime value;
183             if ((int)CalendarTime.Type.Utc == time.type)
184             {
185                 DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
186                 value = new CalendarTime(time.utime * 10000000 + epoch.Ticks);
187             }
188             else
189             {
190                 value = new CalendarTime(time.year, time.month, time.mday, time.hour, time.minute, time.second);
191             }
192             value._type = time.type;
193             return value;
194         }
195
196         /// <summary>
197         /// Makes a clone of a record.
198         /// </summary>
199         /// <since_tizen> 4 </since_tizen>
200         /// <returns>
201         /// A cloned record
202         /// </returns>
203         /// <feature>http://tizen.org/feature/calendar</feature>
204         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
205         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
206         public CalendarRecord Clone()
207         {
208             IntPtr _clonedRecordHandle;
209             int error = Interop.Record.Clone(_recordHandle, out _clonedRecordHandle);
210             if (CalendarError.None != (CalendarError)error)
211             {
212                 Log.Error(Globals.LogTag, "Clone Failed with error " + error);
213                 throw CalendarErrorFactory.GetException(error);
214             }
215             return new CalendarRecord(_clonedRecordHandle, (int)_id);
216         }
217
218         /// <summary>
219         /// Get record URI.
220         /// </summary>
221         /// <since_tizen> 4 </since_tizen>
222         /// <value>The URI of the record</value>
223         [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
224         public string Uri
225         {
226             get
227             {
228                 return _uri;
229             }
230         }
231
232         /// <summary>
233         /// Gets a object from a record.
234         /// </summary>
235         /// <since_tizen> 4 </since_tizen>
236         /// <param name="propertyId">The property ID</param>
237         /// <returns>
238         /// The value of the property corresponding to property id.
239         /// </returns>
240         /// <feature>http://tizen.org/feature/calendar</feature>
241         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
242         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
243         public T Get<T>(uint propertyId)
244         {
245             object parsedValue = null;
246             if (typeof(T) == typeof(string))
247             {
248                 string val;
249                 int error = Interop.Record.GetString(_recordHandle, propertyId, out val);
250                 if (CalendarError.None != (CalendarError)error)
251                 {
252                     Log.Error(Globals.LogTag, "Get String Failed [" + error + "]" + String.Format("{0:X}", propertyId));
253                     throw CalendarErrorFactory.GetException(error);
254                 }
255                 parsedValue = Convert.ChangeType(val, typeof(T));
256             }
257             else if (typeof(T) == typeof(int))
258             {
259                 int val;
260                 int error = Interop.Record.GetInteger(_recordHandle, propertyId, out val);
261                 if (CalendarError.None != (CalendarError)error)
262                 {
263                     Log.Error(Globals.LogTag, "Get Intger Failed [" + error + "]" + String.Format("{0:X}", propertyId));
264                     throw CalendarErrorFactory.GetException(error);
265                 }
266                 parsedValue = Convert.ChangeType(val, typeof(T));
267             }
268             else if (typeof(T) == typeof(long))
269             {
270                 long val;
271                 int error = Interop.Record.GetLli(_recordHandle, propertyId, out val);
272                 if (CalendarError.None != (CalendarError)error)
273                 {
274                     Log.Error(Globals.LogTag, "Get Long Failed [" + error + "]" + String.Format("{0:X}", propertyId));
275                     throw CalendarErrorFactory.GetException(error);
276                 }
277                 parsedValue = Convert.ChangeType(val, typeof(T));
278             }
279             else if (typeof(T) == typeof(double))
280             {
281                 double val;
282                 int error = Interop.Record.GetDouble(_recordHandle, propertyId, out val);
283                 if (CalendarError.None != (CalendarError)error)
284                 {
285                     Log.Error(Globals.LogTag, "Get Double Failed [" + error + "]" + String.Format("{0:X}", propertyId));
286                     throw CalendarErrorFactory.GetException(error);
287                 }
288                 parsedValue = Convert.ChangeType(val, typeof(T));
289             }
290             else if (typeof(T) == typeof(CalendarTime))
291             {
292                 Interop.Record.DateTime time;
293                 int error = Interop.Record.GetCalendarTime(_recordHandle, propertyId, out time);
294                 if (CalendarError.None != (CalendarError)error)
295                 {
296                     Log.Error(Globals.LogTag, "Get CalendarTime Failed [" + error + "]" + String.Format("{0:X}", propertyId));
297                     throw CalendarErrorFactory.GetException(error);
298                 }
299                 CalendarTime val = ConvertIntPtrToCalendarTime(time);
300                 parsedValue = Convert.ChangeType(val, typeof(T));
301             }
302             else
303             {
304                 Log.Error(Globals.LogTag, "Not supported Data T/ype");
305                 throw CalendarErrorFactory.GetException((int)CalendarError.NotSupported);
306             }
307             return (T)parsedValue;
308         }
309
310         /// <summary>
311         /// Sets a value of the property to a record.
312         /// </summary>
313         /// <since_tizen> 4 </since_tizen>
314         /// <param name="propertyId">The property ID</param>
315         /// <param name="value">value</param>
316         /// <feature>http://tizen.org/feature/calendar</feature>
317         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
318         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
319         public void Set<T>(uint propertyId, T value)
320         {
321             if (typeof(T) == typeof(string))
322             {
323                 string val = Convert.ToString(value);
324                 int error = Interop.Record.SetString(_recordHandle, propertyId, val);
325                 if (CalendarError.None != (CalendarError)error)
326                 {
327                     Log.Error(Globals.LogTag, "Set String Failed [" + error + "]" + String.Format("{0:X}", propertyId));
328                     throw CalendarErrorFactory.GetException(error);
329                 }
330             }
331             else if (typeof(T) == typeof(int))
332             {
333                 int val = Convert.ToInt32(value);
334                 int error = Interop.Record.SetInteger(_recordHandle, propertyId, val);
335                 if (CalendarError.None != (CalendarError)error)
336                 {
337                     Log.Error(Globals.LogTag, "Set Integer Failed [" + error + "]" + String.Format("{0:X}", propertyId));
338                     throw CalendarErrorFactory.GetException(error);
339                 }
340             }
341             else if (typeof(T) == typeof(long))
342             {
343                 long val = Convert.ToInt64(value);
344                 int error = Interop.Record.SetLli(_recordHandle, propertyId, val);
345                 if (CalendarError.None != (CalendarError)error)
346                 {
347                     Log.Error(Globals.LogTag, "Set Long Failed [" + error + "]" + String.Format("{0:X}", propertyId));
348                     throw CalendarErrorFactory.GetException(error);
349                 }
350             }
351             else if (typeof(T) == typeof(double))
352             {
353                 double val = Convert.ToDouble(value);
354                 int error = Interop.Record.SetDouble(_recordHandle, propertyId, val);
355                 if (CalendarError.None != (CalendarError)error)
356                 {
357                     Log.Error(Globals.LogTag, "Set Double Failed [" + error + "]" + String.Format("{0:X}", propertyId));
358                     throw CalendarErrorFactory.GetException(error);
359                 }
360             }
361             else if (typeof(T) == typeof(CalendarTime))
362             {
363                 CalendarTime time = (CalendarTime)Convert.ChangeType(value, typeof(CalendarTime));
364                 Interop.Record.DateTime val = ConvertCalendarTimeToStruct(time);
365                 int error = Interop.Record.SetCalendarTime(_recordHandle, propertyId, val);
366                 if (CalendarError.None != (CalendarError)error)
367                 {
368                     Log.Error(Globals.LogTag, "Set CalendarTime Failed [" + error + "]" + String.Format("{0:X}", propertyId));
369                     throw CalendarErrorFactory.GetException(error);
370                 }
371             }
372             else
373             {
374                 Log.Error(Globals.LogTag, "Not supported Data T/ype");
375                 throw CalendarErrorFactory.GetException((int)CalendarError.NotSupported);
376             }
377         }
378
379         /// <summary>
380         /// Adds a child record to the parent record.
381         /// </summary>
382         /// <since_tizen> 4 </since_tizen>
383         /// <param name="propertyId">The property ID</param>
384         /// <param name="childRecord">The child record</param>
385         /// <feature>http://tizen.org/feature/calendar</feature>
386         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
387         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
388         public void AddChildRecord(uint propertyId, CalendarRecord childRecord)
389         {
390             int error = Interop.Record.AddChildRecord(_recordHandle, propertyId, childRecord._recordHandle);
391             if (CalendarError.None != (CalendarError)error)
392             {
393                 Log.Error(Globals.LogTag, "AddChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
394                 throw CalendarErrorFactory.GetException(error);
395             }
396             childRecord._disposedValue = true;
397         }
398
399         /// <summary>
400         /// Removes a child record from the parent record.
401         /// </summary>
402         /// <since_tizen> 4 </since_tizen>
403         /// <param name="propertyId">The property ID</param>
404         /// <param name="childRecord">The child record</param>
405         /// <feature>http://tizen.org/feature/calendar</feature>
406         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
407         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
408         public void RemoveChildRecord(uint propertyId, CalendarRecord childRecord)
409         {
410             int error = Interop.Record.RemoveChildRecord(_recordHandle, propertyId, childRecord._recordHandle);
411             if (CalendarError.None != (CalendarError)error)
412             {
413                 Log.Error(Globals.LogTag, "RemoveChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
414                 throw CalendarErrorFactory.GetException(error);
415             }
416             childRecord._disposedValue = false;
417         }
418
419         /// <summary>
420         /// Gets a child record from the parent record
421         /// </summary>
422         /// <since_tizen> 4 </since_tizen>
423         /// <param name="propertyId">The property ID</param>
424         /// <returns>
425         /// The number of child records corresponding to property ID
426         /// </returns>
427         /// <feature>http://tizen.org/feature/calendar</feature>
428         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
429         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
430         public int GetChildRecordCount(uint propertyId)
431         {
432             int count = 0;
433             int error = Interop.Record.GetChildRecordCount(_recordHandle, propertyId, out count);
434             if (CalendarError.None != (CalendarError)error)
435             {
436                 Log.Error(Globals.LogTag, "GetChildRecordCount Failed [" + error + "]" + String.Format("{0:X}", propertyId));
437                 throw CalendarErrorFactory.GetException(error);
438             }
439             return count;
440         }
441
442         /// <summary>
443         /// Gets a child record from the parent record
444         /// </summary>
445         /// <since_tizen> 4 </since_tizen>
446         /// <param name="propertyId">The property ID</param>
447         /// <param name="index">The child record index</param>
448         /// <returns>
449         /// The record
450         /// </returns>
451         /// <feature>http://tizen.org/feature/calendar</feature>
452         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
453         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
454         public CalendarRecord GetChildRecord(uint propertyId, int index)
455         {
456             IntPtr handle;
457
458             int error = Interop.Record.GetChildRecordPointer(_recordHandle, propertyId, index, out handle);
459             if (CalendarError.None != (CalendarError)error)
460             {
461                 Log.Error(Globals.LogTag, "GetChildRecord Failed [" + error + "]" + String.Format("{0:X}", propertyId));
462                 throw CalendarErrorFactory.GetException(error);
463             }
464             return new CalendarRecord(handle, true);
465         }
466
467         /// <summary>
468         /// Clones a child record list corresponding to property ID
469         /// </summary>
470         /// <since_tizen> 4 </since_tizen>
471         /// <param name="propertyId">The property ID</param>
472         /// <returns>
473         /// the record list
474         /// </returns>
475         /// <feature>http://tizen.org/feature/calendar</feature>
476         /// <exception cref="NotSupportedException">Thrown when feature is not supported</exception>
477         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
478         public CalendarList CloneChildRecordList(uint propertyId)
479         {
480             IntPtr listHandle;
481             int error = Interop.Record.CloneChildRecordList(_recordHandle, propertyId, out listHandle);
482             if (CalendarError.None != (CalendarError)error)
483             {
484                 Log.Error(Globals.LogTag, "CloneChildRecordList Failed with [" + error + "]" + String.Format("{0:X}", propertyId));
485                 throw CalendarErrorFactory.GetException(error);
486             }
487             CalendarList list = new CalendarList(listHandle);
488             return list;
489         }
490     }
491 }