6cb6b7d7bddf2f8f2ff9aabceb58a3691b077db8
[platform/core/csapi/tizenfx.git] / src / Tizen.Content.MediaContent / Tizen.Content.MediaContent / TagCommand.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.Collections.Generic;
19 using System.Linq;
20
21 namespace Tizen.Content.MediaContent
22 {
23     /// <summary>
24     /// Provides the commands to manage tags in the database.
25     /// </summary>
26     /// <seealso cref="Tag"/>
27     /// <since_tizen> 4 </since_tizen>
28     public class TagCommand : MediaCommand
29     {
30         /// <summary>
31         /// Initializes a new instance of the <see cref="TagCommand"/> class with the specified <see cref="MediaDatabase"/>.
32         /// </summary>
33         /// <param name="database">The <see cref="MediaDatabase"/> that the commands run on.</param>
34         /// <exception cref="ArgumentNullException"><paramref name="database"/> is null.</exception>
35         /// <exception cref="ObjectDisposedException"><paramref name="database"/> has already been disposed of.</exception>
36         /// <since_tizen> 4 </since_tizen>
37         public TagCommand(MediaDatabase database) : base(database)
38         {
39         }
40
41         /// <summary>
42         /// Retrieves the number of tags.
43         /// </summary>
44         /// <returns>The number of tags.</returns>
45         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
46         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
47         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
48         /// <since_tizen> 4 </since_tizen>
49         public int Count()
50         {
51             return Count(arguments: null);
52         }
53
54         /// <summary>
55         /// Retrieves the number of tags with the <see cref="CountArguments"/>.
56         /// </summary>
57         /// <param name="arguments">The criteria to use to filter. This value can be null.</param>
58         /// <returns>The number of tags filtered.</returns>
59         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
60         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
61         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
62         /// <since_tizen> 4 </since_tizen>
63         public int Count(CountArguments arguments)
64         {
65             ValidateDatabase();
66
67             return CommandHelper.Count(Interop.Tag.GetTagCount, arguments);
68         }
69
70
71         /// <summary>
72         /// Deletes a tag from the database.
73         /// </summary>
74         /// <privilege>http://tizen.org/privilege/content.write</privilege>
75         /// <param name="tagId">The tag ID to delete.</param>
76         /// <returns>true if the matched record was found and deleted, otherwise false.</returns>
77         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
78         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
79         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
80         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
81         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
82         /// <since_tizen> 4 </since_tizen>
83         public bool Delete(int tagId)
84         {
85             ValidateDatabase();
86
87             if (tagId <= 0)
88             {
89                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
90                     "Tag id can't be less than or equal to zero.");
91             }
92
93             if (CommandHelper.Count(Interop.Tag.GetTagCount, $"{TagColumns.Id}={tagId}") == 0)
94             {
95                 return false;
96             }
97
98             CommandHelper.Delete(Interop.Tag.Delete, tagId);
99             return true;
100         }
101
102
103         /// <summary>
104         /// Inserts a tag into the database with the specified name.
105         /// </summary>
106         /// <privilege>http://tizen.org/privilege/content.write</privilege>
107         /// <param name="name">The name of tag.</param>
108         /// <returns>The <see cref="Tag"/> instance that contains the record information inserted.</returns>
109         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
110         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
111         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
112         /// <exception cref="ArgumentNullException"><paramref name="name"/> is null.</exception>
113         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
114         /// <since_tizen> 4 </since_tizen>
115         public Tag Insert(string name)
116         {
117             ValidateDatabase();
118
119             if (name == null)
120             {
121                 throw new ArgumentNullException(nameof(name));
122             }
123
124             if (name.Length == 0)
125             {
126                 throw new ArgumentException("Tag name can't be an empty string.");
127             }
128
129             Interop.Tag.Insert(name, out var handle).ThrowIfError("Failed to insert a new tag");
130
131             try
132             {
133                 return new Tag(handle);
134             }
135             finally
136             {
137                 Interop.Tag.Destroy(handle);
138             }
139         }
140
141         /// <summary>
142         /// Updates a tag with the specified name.
143         /// </summary>
144         /// <privilege>http://tizen.org/privilege/content.write</privilege>
145         /// <param name="tagId">The tag ID to update.</param>
146         /// <param name="name">The new name.</param>
147         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
148         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
149         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
150         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
151         /// <exception cref="ArgumentNullException"><paramref name="name"/> is null.</exception>
152         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
153         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
154         /// <since_tizen> 4 </since_tizen>
155         public bool UpdateName(int tagId, string name)
156         {
157             ValidateDatabase();
158
159             if (tagId <= 0)
160             {
161                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
162                     "Tag id can't be less than or equal to zero.");
163             }
164
165             if (name == null)
166             {
167                 throw new ArgumentNullException(nameof(name));
168             }
169
170             if (CommandHelper.Count(Interop.Tag.GetTagCount, $"{TagColumns.Id}={tagId}") == 0)
171             {
172                 return false;
173             }
174
175             Interop.Tag.Create(out var handle).ThrowIfError("Failed to update");
176
177             try
178             {
179                 Interop.Tag.SetName(handle, name).ThrowIfError("Failed to update");
180                 Interop.Tag.Update(tagId, handle).ThrowIfError("Failed to update");
181
182                 return true;
183             }
184             finally
185             {
186                 Interop.Tag.Destroy(handle);
187             }
188         }
189
190         /// <summary>
191         /// Retrieves the tag with the specified ID.
192         /// </summary>
193         /// <param name="tagId">The tag ID to select.</param>
194         /// <returns>The <see cref="Tag"/> instance if the matched record was found in the database, otherwise null.</returns>
195         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
196         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
197         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
198         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
199         /// <since_tizen> 4 </since_tizen>
200         public Tag Select(int tagId)
201         {
202             ValidateDatabase();
203
204             if (tagId <= 0)
205             {
206                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
207                     "Tag id can't be less than or equal to zero.");
208             }
209
210             IntPtr handle = IntPtr.Zero;
211
212             try
213             {
214                 Interop.Tag.GetTagFromDb(tagId, out handle).ThrowIfError("Failed to query");
215
216                 return new Tag(handle);
217             }
218             catch (ArgumentException)
219             {
220                 // Native FW returns ArgumentException when there's no matched record.
221                 return null;
222             }
223             finally
224             {
225                 if (handle != IntPtr.Zero)
226                 {
227                     Interop.Tag.Destroy(handle);
228                 }
229             }
230
231         }
232
233         /// <summary>
234         /// Retrieves all the tags.
235         /// </summary>
236         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
237         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
238         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
239         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
240         /// <since_tizen> 4 </since_tizen>
241         public MediaDataReader<Tag> Select()
242         {
243             return Select(arguments: null);
244         }
245
246         /// <summary>
247         /// Retrieves the tags with the <see cref="SelectArguments"/>.
248         /// </summary>
249         /// <param name="arguments">The criteria to use to filter. This value can be null.</param>
250         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
251         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
252         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
253         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
254         /// <since_tizen> 4 </since_tizen>
255         public MediaDataReader<Tag> Select(SelectArguments arguments)
256         {
257             ValidateDatabase();
258
259             return CommandHelper.Select(arguments, Interop.Tag.ForeachTagFromDb, Tag.FromHandle);
260         }
261
262         /// <summary>
263         /// Retrieves the number of media info of the tag.
264         /// </summary>
265         /// <param name="tagId">The tag ID.</param>
266         /// <returns>The number of the media information.</returns>
267         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
268         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
269         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
270         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
271         /// <since_tizen> 4 </since_tizen>
272         public int CountMedia(int tagId)
273         {
274             return CountMedia(tagId, null);
275         }
276
277         /// <summary>
278         /// Retrieves the number of the media information of the tag with the <see cref="CountArguments"/>.
279         /// </summary>
280         /// <param name="tagId">The tag ID to query with.</param>
281         /// <param name="arguments">The criteria to use to filter. This value can be null.</param>
282         /// <returns>The number of the media information.</returns>
283         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
284         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
285         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
286         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
287         /// <since_tizen> 4 </since_tizen>
288         public int CountMedia(int tagId, CountArguments arguments)
289         {
290             ValidateDatabase();
291
292             if (tagId <= 0)
293             {
294                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
295                     "Tag id can't be less than or equal to zero.");
296             }
297
298             return CommandHelper.Count(Interop.Tag.GetMediaCount, tagId, arguments);
299         }
300
301         /// <summary>
302         /// Retrieves the media information of the tag.
303         /// </summary>
304         /// <param name="tagId">The tag ID.</param>
305         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
306         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
307         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
308         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
309         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
310         /// <since_tizen> 4 </since_tizen>
311         public MediaDataReader<MediaInfo> SelectMedia(int tagId)
312         {
313             return SelectMedia(tagId, null);
314         }
315
316         /// <summary>
317         /// Retrieves the media information of the tag with the <see cref="SelectArguments"/>.
318         /// </summary>
319         /// <param name="tagId">The tag ID.</param>
320         /// <param name="filter">The criteria to use to filter. This value can be null.</param>
321         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
322         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
323         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
324         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
325         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
326         /// <since_tizen> 4 </since_tizen>
327         public MediaDataReader<MediaInfo> SelectMedia(int tagId, SelectArguments filter)
328         {
329             ValidateDatabase();
330
331             if (tagId <= 0)
332             {
333                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
334                     "Tag id can't be less than or equal to zero.");
335             }
336
337             return CommandHelper.SelectMedia(Interop.Tag.ForeachMediaFromDb, tagId, filter);
338         }
339
340         private bool UpdateMember(int tagId, IEnumerable<string> mediaIds,
341             Func<IntPtr, string, MediaContentError> func)
342         {
343             ValidateDatabase();
344
345             if (tagId <= 0)
346             {
347                 throw new ArgumentOutOfRangeException(nameof(tagId), tagId,
348                     "Tag id can't be less than or equal to zero.");
349             }
350
351             if (mediaIds == null)
352             {
353                 throw new ArgumentNullException(nameof(mediaIds));
354             }
355
356             if (mediaIds.Count() == 0)
357             {
358                 throw new ArgumentException("mediaIds has no element.", nameof(mediaIds));
359             }
360
361             if (CommandHelper.Count(Interop.Tag.GetTagCount, $"{TagColumns.Id}={tagId}") == 0)
362             {
363                 return false;
364             }
365
366             IntPtr handle = IntPtr.Zero;
367             Interop.Tag.Create(out handle).ThrowIfError("Failed to initialize update member operation");
368
369             try
370             {
371                 foreach (var mediaId in mediaIds)
372                 {
373                     if (mediaId == null)
374                     {
375                         throw new ArgumentException("Media id should not be null.", nameof(mediaIds));
376                     }
377
378                     if (string.IsNullOrWhiteSpace(mediaId))
379                     {
380                         throw new ArgumentException("Media id should not be a zero-length string.", nameof(mediaId));
381                     }
382
383                     func(handle, mediaId).ThrowIfError("Failed to update member");
384                 }
385
386                 Interop.Tag.Update(tagId, handle).ThrowIfError("Failed to run member update");
387                 return true;
388             }
389             finally
390             {
391                 if (handle != IntPtr.Zero)
392                 {
393                     Interop.Tag.Destroy(handle);
394                 }
395             }
396         }
397
398         /// <summary>
399         /// Adds the media to a tag.
400         /// </summary>
401         /// <param name="tagId">The tag ID that the media will be added to.</param>
402         /// <param name="mediaId">The media ID to add to the tag.</param>
403         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
404         /// <remarks>The invalid media ID will be ignored.</remarks>
405         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
406         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
407         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
408         /// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
409         /// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
410         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
411         /// <since_tizen> 4 </since_tizen>
412         public bool AddMedia(int tagId, string mediaId)
413         {
414             ValidationUtil.ValidateNotNullOrEmpty(mediaId, nameof(mediaId));
415
416             return AddMedia(tagId, new string[] { mediaId });
417         }
418
419         /// <summary>
420         /// Adds the media set to a tag.
421         /// </summary>
422         /// <param name="tagId">The tag ID that the media will be added to.</param>
423         /// <param name="mediaIds">The media ID to add to the tag.</param>
424         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
425         /// <remarks>The invalid media IDs will be ignored.</remarks>
426         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
427         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
428         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
429         /// <exception cref="ArgumentNullException"><paramref name="mediaIds"/> is null.</exception>
430         /// <exception cref="ArgumentException">
431         ///     <paramref name="mediaIds"/> has no element.<br/>
432         ///     -or-<br/>
433         ///     <paramref name="mediaIds"/> contains null value.<br/>
434         ///     -or-<br/>
435         ///     <paramref name="mediaIds"/> contains a zero-length string, contains only white space.
436         /// </exception>
437         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
438         /// <since_tizen> 4 </since_tizen>
439         public bool AddMedia(int tagId, IEnumerable<string> mediaIds)
440         {
441             return UpdateMember(tagId, mediaIds, Interop.Tag.AddMedia);
442         }
443
444         /// <summary>
445         /// Removes the media from a tag.
446         /// </summary>
447         /// <param name="tagId">The tag ID.</param>
448         /// <param name="mediaId">The media ID to remove from the tag.</param>
449         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
450         /// <remarks>The invalid media ID will be ignored.</remarks>
451         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
452         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
453         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
454         /// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
455         /// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
456         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
457         /// <since_tizen> 4 </since_tizen>
458         public bool RemoveMedia(int tagId, string mediaId)
459         {
460             ValidationUtil.ValidateNotNullOrEmpty(mediaId, nameof(mediaId));
461
462             return RemoveMedia(tagId, new string[] { mediaId });
463         }
464
465         /// <summary>
466         /// Removes the media set from a tag.
467         /// </summary>
468         /// <param name="tagId">The tag ID.</param>
469         /// <param name="mediaIds">The collection of media ID to remove from the tag.</param>
470         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
471         /// <remarks>The invalid IDs will be ignored.</remarks>
472         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
473         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
474         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
475         /// <exception cref="ArgumentNullException"><paramref name="mediaIds"/> is null.</exception>
476         /// <exception cref="ArgumentException">
477         ///     <paramref name="mediaIds"/> has no element.<br/>
478         ///     -or-<br/>
479         ///     <paramref name="mediaIds"/> contains null value.<br/>
480         ///     -or-<br/>
481         ///     <paramref name="mediaIds"/> contains a zero-length string or white space.
482         /// </exception>
483         /// <exception cref="ArgumentOutOfRangeException"><paramref name="tagId"/> is less than or equal to zero.</exception>
484         /// <since_tizen> 4 </since_tizen>
485         public bool RemoveMedia(int tagId, IEnumerable<string> mediaIds)
486         {
487             return UpdateMember(tagId, mediaIds, Interop.Tag.RemoveMedia);
488         }
489     }
490 }