statistical defects fixed
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / acl / group / GroupBrokerManager.java
1 package org.iotivity.cloud.accountserver.resources.acl.group;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.ListIterator;
7 import java.util.UUID;
8
9 import org.iotivity.cloud.accountserver.Constants;
10 import org.iotivity.cloud.accountserver.db.AccountDBManager;
11 import org.iotivity.cloud.accountserver.db.GroupTable;
12 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
13 import org.iotivity.cloud.base.device.Device;
14 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
15 import org.iotivity.cloud.base.protocols.IRequest;
16 import org.iotivity.cloud.base.protocols.MessageBuilder;
17 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
18 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
19 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
20 import org.iotivity.cloud.util.Cbor;
21 import org.iotivity.cloud.util.Log;
22
23 /**
24  * This class provides a set of APIs manage a group broker
25  */
26 public class GroupBrokerManager {
27
28     private static GroupBrokerManager                   mGroupBrokerMgr    = new GroupBrokerManager();
29     private TypeCastingManager<GroupTable>              mTypeGroup         = new TypeCastingManager<>();
30     private HashMap<String, Object>                     mGroupResourceInfo = new HashMap<>();
31
32     private HashMap<String, ArrayList<GroupSubscriber>> mGroupSubscriber   = new HashMap<>();
33
34     private Cbor<HashMap<String, Object>>               mCbor              = new Cbor<>();
35
36     private GroupPolicyManager                          mGroupPolicyMgr    = new GroupPolicyManager();
37
38     private GroupBrokerManager() {
39         mGroupResourceInfo.put(Constants.RS_RESOURCE_TYPE,
40                 Constants.ACL_RESOURCE_TYPE);
41         mGroupResourceInfo.put(Constants.RS_INTERFACE,
42                 Constants.DEFAULT_INTERFACE);
43     }
44
45     /**
46      * Function to get GroupBrokerManager as a singleton
47      * 
48      * @return GroupBrokerManager as a singleton
49      */
50     public static GroupBrokerManager getInstance() {
51         return mGroupBrokerMgr;
52     }
53
54     private static class GroupSubscriber {
55         GroupSubscriber(Device subscriber, IRequest request) {
56             mSubscriber = subscriber;
57             mRequest = request;
58         }
59
60         public Device   mSubscriber;
61         public IRequest mRequest;
62     }
63
64     /**
65      * API to verify user's Authorization
66      * 
67      * @param uid
68      *            unique user id
69      * @param gid
70      *            group id
71      * @param properties
72      *            payload properties
73      * @param op
74      *            operation
75      */
76     public void verifyAuthorization(String uid, String gid,
77             ArrayList<String> properties, UserOperation op) {
78
79         if (gid == null) {
80             return;
81         }
82
83         mGroupPolicyMgr.verifyOperationAuthorization(gid, uid, op, properties);
84     }
85
86     /**
87      * API to get Group information
88      * 
89      * @param uid
90      *            unique user id
91      * @return response message
92      */
93     public HashMap<String, Object> getGroupList(String uid) {
94
95         return makeGetResponse(uid);
96
97     }
98
99     private HashMap<String, Object> makeGetResponse(String uid) {
100
101         ArrayList<HashMap<String, Object>> records = readGroupInfo(
102                 Constants.KEYFIELD_GROUP_MEMBERS, uid);
103
104         HashMap<String, Object> response = new HashMap<>();
105         // put group info
106         response.putAll(mGroupResourceInfo);
107         if (!records.isEmpty()) {
108             response.put(Constants.RESP_GROUPS, records);
109         }
110
111         Log.d("Group get response : " + response.toString());
112         return response;
113     }
114
115     private ArrayList<HashMap<String, Object>> readGroupInfo(String key,
116             String value) {
117         HashMap<String, Object> condition = new HashMap<>();
118         condition.put(key, value);
119         ArrayList<HashMap<String, Object>> records = AccountDBManager
120                 .getInstance().selectRecord(Constants.GROUP_TABLE, condition);
121         return records;
122     }
123
124     /**
125      * API to create a group
126      * 
127      * @param uid
128      *            unique user id
129      * @param gid
130      *            group id
131      * @param gname
132      *            group name
133      * @param parent
134      *            parent group id
135      * @return response message
136      */
137     public HashMap<String, Object> createGroup(String uid, String gid,
138             String gname, String parent) {
139
140         if (gname == null) {
141             gname = "DEFAULT_GNAME";
142         }
143
144         if (gid == null) {
145             gid = UUID.randomUUID().toString();
146         }
147
148         if (parent != null) {
149             // parent update
150             HashMap<String, Object> condition = new HashMap<>();
151             condition.put(Constants.KEYFIELD_GID, parent);
152             HashMap<String, Object> record = AccountDBManager.getInstance()
153                     .selectOneRecord(Constants.GROUP_TABLE, condition);
154
155             if (record.isEmpty()) {
156                 throw new BadRequestException("parent group is null");
157             }
158             ArrayList<String> subgroups = (ArrayList<String>) record
159                     .get(Constants.KEYFIELD_GROUP_SUBGROUPS);
160             if (subgroups == null) {
161                 subgroups = new ArrayList<String>();
162             }
163             subgroups.add(gid);
164             record.put(Constants.KEYFIELD_GROUP_SUBGROUPS, subgroups);
165             AccountDBManager.getInstance()
166                     .insertAndReplaceRecord(Constants.GROUP_TABLE, record);
167         }
168
169         storeGroupInfo(uid, gid, gname, parent);
170         return makePostResponse(uid, gid, gname, parent);
171     }
172
173     private HashMap<String, Object> makePostResponse(String uid, String gid,
174             String gname, String parent) {
175
176         HashMap<String, Object> response = new HashMap<>();
177         response.put(Constants.KEYFIELD_GID, gid);
178         response.put(Constants.KEYFIELD_GROUP_NAME, gname);
179         response.put(Constants.KEYFIELD_GROUP_OWNER, uid);
180         response.put(Constants.KEYFIELD_GROUP_MEMBERS, Arrays.asList(uid));
181         if (parent != null) {
182             response.put(Constants.KEYFIELD_GROUP_PARENT, parent);
183         }
184
185         Log.d("Group post response : " + response.toString());
186
187         return response;
188     }
189
190     private void storeGroupInfo(String uid, String gid, String gname,
191             String parent) {
192         GroupTable groupTable = new GroupTable();
193         groupTable.setGid(gid);
194         groupTable.setGname(gname);
195         groupTable.setOwner(uid);
196         ArrayList<String> members = new ArrayList<>();
197         members.add(uid);
198         groupTable.setMembers(members);
199         if (parent != null) {
200             groupTable.setParent(parent);
201         }
202
203         HashMap<String, Object> groupMap = mTypeGroup
204                 .convertObjectToMap(groupTable);
205         groupMap.putAll(mGroupResourceInfo);
206         AccountDBManager.getInstance().insertRecord(Constants.GROUP_TABLE,
207                 groupMap);
208
209     }
210
211     /**
212      * API to add a observer
213      * 
214      * @param uid
215      *            unique user id
216      * @param srcDevice
217      *            channel information
218      * @param request
219      *            request message
220      */
221     public void addObserver(String uid, Device srcDevice, IRequest request) {
222         ArrayList<GroupSubscriber> subscribers = mGroupSubscriber.get(uid);
223         if (subscribers == null) {
224             mGroupSubscriber.put(uid, new ArrayList<GroupSubscriber>(
225                     Arrays.asList(new GroupSubscriber(srcDevice, request))));
226             return;
227         }
228         // TODO control consecutive GET observe requests from single device
229         // removeObserverFromSubscriberList(uid, srcDevice, request);
230         GroupSubscriber subscriber = new GroupSubscriber(srcDevice, request);
231         subscribers.add(subscriber);
232         mGroupSubscriber.put(uid, subscribers);
233     }
234
235     /**
236      * API to remove a observer
237      * 
238      * @param uid
239      *            unique user id
240      * @param srcDevice
241      *            channel information
242      * @param request
243      *            request message
244      */
245     public void removeObserver(String uid, Device srcDevice, IRequest request) {
246         removeObserverFromSubscriberList(uid, srcDevice, request);
247     }
248
249     private void removeObserverFromSubscriberList(String uid, Device srcDevice,
250             IRequest request) {
251         ArrayList<GroupSubscriber> subscribers = mGroupSubscriber.get(uid);
252         if (subscribers != null) {
253             ListIterator<GroupSubscriber> iterator = subscribers.listIterator();
254             while (iterator.hasNext()) {
255                 GroupSubscriber subscriber = iterator.next();
256                 CoapRequest coapRequest = (CoapRequest) subscriber.mRequest;
257                 if (srcDevice.equals(subscriber.mSubscriber)
258                         && coapRequest.getTokenString().equals(
259                                 ((CoapRequest) request).getTokenString())) {
260                     iterator.remove();
261                     Log.d("subscriber removed, "
262                             + ((CoapRequest) request).getTokenString());
263                 }
264             }
265             mGroupSubscriber.put(uid, subscribers);
266         }
267     }
268
269     /**
270      * API to notify to observers
271      * 
272      * @param uidList
273      *            unique user id list
274      */
275     public void notifyToObservers(ArrayList<String> uidList) {
276
277         if (uidList == null) {
278             return;
279         }
280         for (String uid : uidList) {
281             ArrayList<GroupSubscriber> subscribers = mGroupSubscriber.get(uid);
282             if (subscribers != null) {
283                 ArrayList<String> subscriberTokenList = new ArrayList<>();
284                 for (GroupSubscriber subscriber : subscribers) {
285                     subscriberTokenList.add(((CoapRequest) subscriber.mRequest)
286                             .getTokenString());
287                     subscriber.mSubscriber.sendResponse(
288                             MessageBuilder.createResponse(subscriber.mRequest,
289                                     ResponseStatus.CONTENT,
290                                     ContentFormat.APPLICATION_CBOR,
291                                     mCbor.encodingPayloadToCbor(
292                                             makeGetResponse(uid))));
293                 }
294                 Log.d("subscriber : " + uid
295                         + " , subscriber internal Token list : "
296                         + subscriberTokenList);
297             }
298         }
299     }
300 }