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