[IoTConnectivity] Added Base implementation
[platform/core/csapi/iotcon.git] / Tizen.Network.IoTConnectivity / Tizen.Network.IoTConnectivity / Resource.cs
1 /// Copyright 2016 by Samsung Electronics, Inc.,
2 ///
3 /// This software is the confidential and proprietary information
4 /// of Samsung Electronics, Inc. ("Confidential Information"). You
5 /// shall not disclose such Confidential Information and shall use
6 /// it only in accordance with the terms of the license agreement
7 /// you entered into with Samsung.
8
9 using System;
10 using System.Collections.Generic;
11 using System.Collections.ObjectModel;
12
13 namespace Tizen.Network.IoTConnectivity
14 {
15     public abstract class Resource : IDisposable
16     {
17         private IntPtr _resourceHandle = IntPtr.Zero;
18         private bool _disposed = false;
19         private ObservableCollection<Resource> _children = new ObservableCollection<Resource>();
20         private IntPtr _observerHandle = IntPtr.Zero;
21
22         /// <summary>
23         /// The constructor
24         /// </summary>
25         /// <param name="uri">URI of the resource</param>
26         /// <param name="types">Resource types</param>
27         /// <param name="interfaces">Resource interfaces</param>
28         /// <param name="policy">Policy input of the resoruce</param>
29         public Resource(string uri, ResourceTypes types, ResourceInterfaces interfaces, ResourcePolicy policy)
30         {
31             UriPath = uri;
32             Types = types;
33             Interfaces = interfaces;
34             Policy = policy;
35
36             _children.CollectionChanged += ChildrenCollectionChanged;
37
38             int ret = Interop.IoTConnectivity.Server.Observers.Create(out _observerHandle);
39             if (ret != (int)IoTConnectivityError.None)
40             {
41                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create obsever handle");
42                 throw IoTConnectivityErrorFactory.GetException(ret);
43             }
44         }
45
46         ~Resource()
47         {
48             Dispose(false);
49         }
50
51         /// <summary>
52         /// Type details of the resource
53         /// </summary>
54         public ResourceTypes Types { get; internal set; }
55
56         /// <summary>
57         /// Interface details of the resource
58         /// </summary>
59         public ResourceInterfaces Interfaces { get; internal set; }
60
61         /// <summary>
62         /// The policy
63         /// </summary>
64         public ResourcePolicy Policy { get; internal set; }
65
66         /// <summary>
67         /// URI of the resource
68         /// </summary>
69         public string UriPath { get; internal set; }
70
71         /// <summary>
72         /// List of Child resources
73         /// </summary>
74         public ICollection<Resource> Children
75         {
76             get
77             {
78                 return _children;
79             }
80         }
81
82         internal IntPtr ResourceHandle
83         {
84             get
85             {
86                 return _resourceHandle;
87             }
88             set
89             {
90                 _resourceHandle = value;
91             }
92         }
93
94         /// <summary>
95         /// Notify the specified representation and qos.
96         /// </summary>
97         /// <param name="representation">Representation.</param>
98         /// <param name="qos">Qos.</param>
99         public void Notify(Representation representation, QualityOfService qos)
100         {
101             int ret = (int)IoTConnectivityError.None;
102             ret = Interop.IoTConnectivity.Server.Resource.Notify(_resourceHandle, representation._representationHandle, _observerHandle, (int)qos);
103             if (ret != (int)IoTConnectivityError.None)
104             {
105                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send notification");
106                 throw IoTConnectivityErrorFactory.GetException(ret);
107             }
108         }
109
110         /// <summary>
111         /// Called on the get event.
112         /// </summary>
113         /// <param name="request">Request.</param>
114         public abstract Response OnGet(Request request);
115
116         /// <summary>
117         /// Called on the put event.
118         /// </summary>
119         /// <param name="request">Request.</param>
120         public abstract Response OnPut(Request request);
121
122         /// <summary>
123         /// Called on the post event.
124         /// </summary>
125         /// <param name="request">Request.</param>
126         public abstract Response OnPost(Request request);
127
128         /// <summary>
129         /// Called on the delete event.
130         /// </summary>
131         /// <param name="request">Request.</param>
132         public abstract Response OnDelete(Request request);
133
134         /// <summary>
135         /// Called on the observing event.
136         /// </summary>
137         /// <param name="request">Request.</param>
138         /// <param name="policy">Policy.</param>
139         /// <param name="observeId">Observe identifier.</param>
140         public abstract bool OnObserving(Request request, ObserveType type, int observeId);
141
142         public void Dispose()
143         {
144             Dispose(true);
145             GC.SuppressFinalize(this);
146         }
147
148         protected virtual void Dispose(bool disposing)
149         {
150             if (_disposed)
151                 return;
152
153             if (disposing)
154             {
155                 Types.Dispose();
156                 Interfaces.Dispose();
157             }
158
159             Interop.IoTConnectivity.Server.Resource.Destroy(_resourceHandle);
160             Interop.IoTConnectivity.Server.Observers.Destroy(_observerHandle);
161             _disposed = true;
162         }
163
164         // This method is used as callback for Resource
165         internal void OnRequest(IntPtr resourceHandle, IntPtr requestHandle, IntPtr userData)
166         {
167             Request request = GetRequest(requestHandle);
168             Response response = null;
169
170             if (request == null)
171             {
172                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get Request");
173                 return;
174             }
175
176             try
177             {
178                 int observeType;
179                 int ret = Interop.IoTConnectivity.Server.Request.GetObserveType(requestHandle, out observeType);
180                 if (ret != (int)IoTConnectivityError.None)
181                 {
182                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe type");
183                     return;
184                 }
185
186                 if ((ObserveType)observeType != ObserveType.NoType)
187                 {
188                     int observeId;
189                     ret = Interop.IoTConnectivity.Server.Request.GetObserveId(requestHandle, out observeId);
190                     if (ret != (int)IoTConnectivityError.None)
191                     {
192                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe id");
193                         return;
194                     }
195                     switch ((ObserveType)observeType)
196                     {
197                         case ObserveType.Register:
198                         {
199                             if (OnObserving(request, ObserveType.Register, observeId))
200                             {
201                                 ret = Interop.IoTConnectivity.Server.Observers.Add(_observerHandle, observeId);
202                                 if (ret != (int)IoTConnectivityError.None)
203                                 {
204                                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add observer id");
205                                     return;
206                                 }
207                                 break;
208                             }
209                             else
210                             {
211                                 // If OnObserving for ObserveType.Register returns false, do not operate for Get operation after Observe operation.
212                                 return;
213                             }
214                         }
215                         case ObserveType.Deregister:
216                         {
217                             if (OnObserving(request, ObserveType.Deregister, observeId))
218                             {
219                                 ret = Interop.IoTConnectivity.Server.Observers.Remove(_observerHandle, observeId);
220                                 if (ret != (int)IoTConnectivityError.None)
221                                 {
222                                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove observer id");
223                                     return;
224                                 }
225                                 break;
226                             }
227                             else
228                             {
229                                 // If OnObserving for ObserveType.Deregister returns false, do not operate for Get operation after Observe operation.
230                                 return;
231                             }
232                         }
233                     }
234                 }
235
236                 int requestType;
237                 ret = Interop.IoTConnectivity.Server.Request.GetRequestType(requestHandle, out requestType);
238                 if (ret != (int)IoTConnectivityError.None)
239                 {
240                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get request type");
241                     return;
242                 }
243
244                 switch ((Interop.IoTConnectivity.Server.RequestType)requestType)
245                 {
246                     case Interop.IoTConnectivity.Server.RequestType.Put:
247                     {
248                         response = OnPut(request);
249                         break;
250                     }
251                     case Interop.IoTConnectivity.Server.RequestType.Get:
252                     {
253                         response = OnGet(request);
254                         break;
255                     }
256                     case Interop.IoTConnectivity.Server.RequestType.Post:
257                     {
258                         response = OnPost(request);
259                         break;
260                     }
261                     case Interop.IoTConnectivity.Server.RequestType.Delete:
262                     {
263                         response = OnDelete(request);
264                         break;
265                     }
266                     default:
267                     break;
268                 }
269                 if (response == null)
270                 {
271                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
272                     return;
273                 }
274
275                 if (!response.Send(requestHandle))
276                 {
277                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
278                     return;
279                 }
280             }
281             finally
282             {
283                 request.Dispose();
284                 response?.Dispose();
285             }
286         }
287
288         private Request GetRequest(IntPtr requestHandle)
289         {
290             string hostAddress;
291             int ret = Interop.IoTConnectivity.Server.Request.GetHostAddress(requestHandle, out hostAddress);
292             if (ret != (int)IoTConnectivityError.None)
293             {
294                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get host address");
295                 return null;
296             }
297
298             IntPtr optionsHandle = IntPtr.Zero;
299             ret = Interop.IoTConnectivity.Server.Request.GetOptions(requestHandle, out optionsHandle);
300             if (ret != (int)IoTConnectivityError.None)
301             {
302                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get options");
303                 return null;
304             }
305
306             IntPtr queryHandle = IntPtr.Zero;
307             ret = Interop.IoTConnectivity.Server.Request.GetQuery(requestHandle, out queryHandle);
308             if (ret != (int)IoTConnectivityError.None)
309             {
310                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get Query");
311                 return null;
312             }
313
314             IntPtr representationHandle = IntPtr.Zero;
315             ret = Interop.IoTConnectivity.Server.Request.GetRepresentation(requestHandle, out representationHandle);
316             if (ret != (int)IoTConnectivityError.None)
317             {
318                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get representation");
319                 return null;
320             }
321
322             ResourceOptions opts = null;
323             ResourceQuery query = null;
324             Representation representation = null;
325             try
326             {
327                 opts = (optionsHandle == IntPtr.Zero) ? null : new ResourceOptions(optionsHandle);
328             }
329             catch (Exception exp)
330             {
331                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceOptions: " + exp.Message);
332                 return null;
333             }
334
335             try
336             {
337                 query = (queryHandle == IntPtr.Zero) ? null : new ResourceQuery(queryHandle);
338             }
339             catch (Exception exp)
340             {
341                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceQuery: " + exp.Message);
342                 return null;
343             }
344
345             try
346             {
347                 representation = (representationHandle == IntPtr.Zero) ? null : new Representation(representationHandle); ;
348             }
349             catch (Exception exp)
350             {
351                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
352                 return null;
353             }
354
355             return new Request()
356             {
357                 HostAddress = hostAddress,
358                 Options = opts,
359                 Query = query,
360                 Representation = representation
361             };
362         }
363
364         private void ChildrenCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs eventArgs)
365         {
366             if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
367             {
368                 foreach (Resource r in eventArgs.NewItems)
369                 {
370                     int ret = Interop.IoTConnectivity.Server.Resource.BindChildResource(_resourceHandle, r._resourceHandle);
371                     if (ret != (int)IoTConnectivityError.None)
372                     {
373                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to bind resource ");
374                         throw IoTConnectivityErrorFactory.GetException(ret);
375                     }
376                 }
377             }
378             else if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
379             {
380                 foreach (Resource r in eventArgs.NewItems)
381                 {
382                     int ret = Interop.IoTConnectivity.Server.Resource.UnbindChildResource(_resourceHandle, r._resourceHandle);
383                     if (ret != (int)IoTConnectivityError.None)
384                     {
385                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to unbind resource");
386                         throw IoTConnectivityErrorFactory.GetException(ret);
387                     }
388                 }
389             }
390         }
391     }
392 }