0aca7ab17c879626192200f5b878e47564a04c92
[platform/upstream/iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / acl / group / Group.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.resources.acl.group;
23
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28
29 import org.iotivity.cloud.accountserver.Constants;
30 import org.iotivity.cloud.accountserver.db.AccountDBManager;
31 import org.iotivity.cloud.accountserver.db.GroupTable;
32 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
33 import org.iotivity.cloud.base.device.Device;
34 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
35 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
36 import org.iotivity.cloud.base.exception.ServerException.UnAuthorizedException;
37 import org.iotivity.cloud.base.protocols.IRequest;
38 import org.iotivity.cloud.base.protocols.MessageBuilder;
39 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
40 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
41 import org.iotivity.cloud.util.Cbor;
42
43 /**
44  *
45  * This class provides a set of APIs to handle group requests
46  *
47  */
48
49 public class Group {
50
51     private Cbor<HashMap<String, Object>>  mCbor      = new Cbor<>();
52     private String                         mGid       = null;
53     private TypeCastingManager<GroupTable> mTypeGroup = new TypeCastingManager<>();
54
55     public Group(String gid) {
56         mGid = gid;
57     }
58
59     private class GroupSubscriber {
60         GroupSubscriber(Device subscriber, IRequest request) {
61             mSubscriber = subscriber;
62             mRequest = request;
63         }
64
65         public Device   mSubscriber;
66         public IRequest mRequest;
67     }
68
69     private HashMap<String, GroupSubscriber> mSubscribers = new HashMap<>();
70
71     /**
72      * 
73      * API to add the member user id to the group table in the db
74      * 
75      * @param uuid
76      *            User id list which are provided by Sign-up process
77      */
78     public void addMember(HashSet<String> uuid) {
79
80         GroupTable groupTable = getGroupTable();
81
82         groupTable.setMidlist(groupTable.getMidlist() == null ? uuid
83                 : addGroupListSet(groupTable.getMidlist(), uuid));
84
85         AccountDBManager.getInstance().updateRecord(Constants.GROUP_TABLE,
86                 mTypeGroup.convertObjectToMap(groupTable));
87
88         notifyToSubscriber(getResponsePayload(true));
89     }
90
91     /**
92      * API to add the device id to the group table in the db
93      * 
94      * @param di
95      *            device id list to be stored
96      */
97     public void addDevice(HashSet<String> di) {
98
99         GroupTable groupTable = getGroupTable();
100
101         groupTable.setDilist(groupTable.getDilist() == null ? di
102                 : addGroupListSet(groupTable.getDilist(), di));
103
104         AccountDBManager.getInstance().updateRecord(Constants.GROUP_TABLE,
105                 mTypeGroup.convertObjectToMap(groupTable));
106
107         notifyToSubscriber(getResponsePayload(true));
108     }
109
110     /**
111      * API to remove member user id list from the group table in the db
112      * 
113      * @param uuid
114      *            User id list to be removed from the group table
115      */
116     public void removeMember(HashSet<String> uuid) {
117
118         GroupTable groupTable = getGroupTable();
119         if (groupTable.getGmid() == null) {
120             throw new InternalServerErrorException("group master is empty");
121         }
122         if (uuid.contains(groupTable.getGmid())) {
123             GroupResource.getInstance().deleteGroup(groupTable.getGmid(), mGid);
124             notifyToSubscriber(getResponsePayload(false));
125         } else {
126             if (groupTable.getMidlist() == null) {
127                 throw new BadRequestException("midList is invalid in Group");
128             }
129             groupTable.setMidlist(
130                     removeGroupListSet(groupTable.getMidlist(), uuid));
131             AccountDBManager.getInstance().updateRecord(Constants.GROUP_TABLE,
132                     mTypeGroup.convertObjectToMap(groupTable));
133             notifyToSubscriber(getResponsePayload(true));
134
135             Iterator<String> mid = uuid.iterator();
136             while (mid.hasNext()) {
137                 removeSubscriber(mid.next());
138             }
139         }
140     }
141
142     /**
143      * API to remove device id list from the group table in the db
144      * 
145      * @param di
146      *            device id list to be removed from the group table
147      */
148     public void removeDevice(HashSet<String> di) {
149
150         GroupTable groupTable = getGroupTable();
151         if (groupTable.getDilist() == null) {
152             throw new BadRequestException("deviceList is invalid in Group");
153         }
154         groupTable.setDilist(removeGroupListSet(groupTable.getDilist(), di));
155
156         AccountDBManager.getInstance().updateRecord(Constants.GROUP_TABLE,
157                 mTypeGroup.convertObjectToMap(groupTable));
158
159         notifyToSubscriber(getResponsePayload(true));
160     }
161
162     /**
163      * API to return the group information payload
164      * 
165      * @param mid
166      *            member id to verify if the id exists in the group table
167      * @return group information payload
168      */
169     public HashMap<String, Object> getInfo(String mid) {
170
171         verifyGroupTableMid(mid);
172
173         return getResponsePayload(true);
174     }
175
176     public boolean checkDeviceExistance(String di) {
177         return verifyGroupTableDi(di);
178     }
179
180     /**
181      * API to add group subscriber
182      * 
183      * @param mid
184      *            member id to verify if the id exists in the group table
185      * @param subscriber
186      *            subscriber device
187      * @param request
188      *            request message
189      * @return group information payload
190      */
191     public HashMap<String, Object> addSubscriber(String mid, Device subscriber,
192             IRequest request) {
193
194         // Check if the user has privilege to observe
195         verifyGroupTableMid(mid);
196
197         GroupSubscriber newSubscriber = new GroupSubscriber(subscriber,
198                 request);
199
200         mSubscribers.put(mid, newSubscriber);
201
202         return getInfo(
203                 request.getUriQueryMap().get(Constants.REQ_MEMBER).get(0));
204     }
205
206     /**
207      * API to unsubscribe group information
208      * 
209      * @param mid
210      *            user Id to unscribe group information
211      * @return group information payload
212      */
213     public HashMap<String, Object> removeSubscriber(String mid) {
214
215         HashMap<String, Object> responsePayload = getResponsePayload(true);
216
217         if (mSubscribers.containsKey(mid)) {
218             mSubscribers.remove(mid);
219         }
220
221         return responsePayload;
222     }
223
224     private void verifyGroupTableMid(String mid) {
225
226         GroupTable groupTable = getGroupTable();
227
228         if (groupTable.getMidlist() == null) {
229             throw new BadRequestException("midList is invalid in Group");
230         }
231         HashSet<String> midListSet = new HashSet<>(
232                 (Collection<? extends String>) groupTable.getMidlist());
233
234         if (!midListSet.contains(mid)) {
235
236             throw new UnAuthorizedException(
237                     mid + " is not Group member in gid=" + mGid);
238         }
239     }
240
241     private boolean verifyGroupTableDi(String di) {
242
243         GroupTable groupTable = getGroupTable();
244
245         if (groupTable.getDilist() == null) {
246             return false;
247         }
248
249         HashSet<String> diListSet = new HashSet<>(
250                 (Collection<? extends String>) groupTable.getDilist());
251
252         if (!diListSet.contains(di)) {
253             return false;
254         }
255         return true;
256     }
257
258     private void notifyToSubscriber(
259             HashMap<String, Object> notifiyBtyePayloadData) {
260         synchronized (mSubscribers) {
261
262             Iterator<String> iterator = mSubscribers.keySet().iterator();
263
264             while (iterator.hasNext()) {
265
266                 String key = iterator.next();
267
268                 GroupSubscriber groupSubscriber = mSubscribers.get(key);
269
270                 groupSubscriber.mSubscriber.sendResponse(
271                         MessageBuilder.createResponse(groupSubscriber.mRequest,
272                                 ResponseStatus.CONTENT,
273                                 ContentFormat.APPLICATION_CBOR,
274                                 mCbor.encodingPayloadToCbor(
275                                         notifiyBtyePayloadData)));
276             }
277         }
278     }
279
280     private GroupTable getGroupTable() {
281
282         GroupTable getGroupTable = new GroupTable();
283
284         getGroupTable = mTypeGroup
285                 .convertMaptoObject(
286                         AccountDBManager.getInstance().selectRecord(
287                                 Constants.GROUP_TABLE, getContdition()).get(0),
288                         getGroupTable);
289
290         return getGroupTable;
291     }
292
293     private HashMap<String, Object> getResponsePayload(boolean isAliveGroup) {
294
295         GroupTable groupTable = isAliveGroup ? getGroupTable() : null;
296
297         HashMap<String, Object> responsePayload = new HashMap<>();
298
299         responsePayload.put(Constants.REQ_GROUP_ID,
300                 isAliveGroup ? groupTable.getGid() : null);
301         responsePayload.put(Constants.REQ_GROUP_MASTER_ID,
302                 isAliveGroup ? groupTable.getGmid() : null);
303         responsePayload.put(Constants.REQ_MEMBER_LIST,
304                 isAliveGroup ? groupTable.getMidlist() : null);
305         responsePayload.put(Constants.REQ_DEVICE_ID_LIST,
306                 isAliveGroup ? groupTable.getDilist() : null);
307         responsePayload.put(Constants.REQ_GROUP_TYPE,
308                 isAliveGroup ? groupTable.getGtype() : null);
309
310         return responsePayload;
311     }
312
313     private HashSet<String> addGroupListSet(Object object,
314             HashSet<String> addList) {
315
316         HashSet<String> groupSet = new HashSet<>(
317                 (Collection<? extends String>) object);
318
319         groupSet.addAll(addList);
320
321         return groupSet;
322     }
323
324     private HashSet<String> removeGroupListSet(Object object,
325             HashSet<String> removeList) {
326
327         HashSet<String> groupSet = new HashSet<>(
328                 (Collection<? extends String>) object);
329
330         groupSet.removeAll(removeList);
331
332         return groupSet;
333     }
334
335     private HashMap<String, Object> getContdition() {
336
337         HashMap<String, Object> condition = new HashMap<>();
338         condition.put(Constants.REQ_GROUP_ID, mGid);
339         return condition;
340     }
341
342 }