statistical defects fixed
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / acl / group / GroupAclManager.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.List;
7 import java.util.ListIterator;
8
9 import org.iotivity.cloud.accountserver.Constants;
10 import org.iotivity.cloud.accountserver.db.AccountDBManager;
11 import org.iotivity.cloud.accountserver.db.AceTable;
12 import org.iotivity.cloud.accountserver.db.GroupTable;
13 import org.iotivity.cloud.accountserver.resources.acl.id.AceResource;
14 import org.iotivity.cloud.accountserver.resources.acl.id.AclResource;
15 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
16 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
17 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
18
19 /**
20  *
21  * This class provides a set of APIs to manage between AclManager and
22  * GroupManager
23  * 
24  *
25  */
26
27 public class GroupAclManager {
28     private static GroupAclManager          mGrAclManager    = new GroupAclManager();
29     private TypeCastingManager<AceTable>    mTypeAceTable    = new TypeCastingManager<AceTable>();
30     private TypeCastingManager<AceResource> mTypeAceResource = new TypeCastingManager<AceResource>();
31
32     private GroupAclManager() {
33     }
34
35     public static GroupAclManager getInstance() {
36         return mGrAclManager;
37     }
38
39     /**
40      * API to add acl table by members
41      * 
42      * @param gid
43      *            group id
44      * @param permission
45      *            resource permission of group acl in group
46      * @param members
47      *            member list which add into group
48      */
49     public void addAceByMembers(String gid, int permission,
50             ArrayList<String> members) {
51
52         // make default acelist for each new member
53         for (String device : getGroupDevices(gid)) {
54             addAceList(gid, device, makeAceList(members, permission, null));
55         }
56
57         // make acelist with specific resources for each new member
58         addAceByResources(gid, permission, getGroupResources(gid), members);
59     }
60
61     /**
62      * API to add acl table by devices
63      * 
64      * @param gid
65      *            group id
66      * @param permission
67      *            resource permission of group acl in group
68      * @param devices
69      *            device list which add into group
70      */
71     public void addAceByDevices(String gid, int permission,
72             ArrayList<String> devices) {
73
74         // make default acelist for each existing member
75         for (String device : devices) {
76             addAceList(gid, device,
77                     makeAceList(getGroupMembers(gid), permission, null));
78         }
79     }
80
81     /**
82      * API to add acl table by resources
83      * 
84      * @param gid
85      *            group id
86      * @param permission
87      *            resource permission of group acl in group
88      * @param resources
89      *            resource list which add into group
90      */
91     public void addAceByResources(String gid, int permission,
92             ArrayList<HashMap<String, Object>> resources) {
93
94         addAceByResources(gid, permission, resources, getGroupMembers(gid));
95     }
96
97     /**
98      * API to remove acl table by group
99      * 
100      * @param gid
101      *            group id
102      */
103     public void removeAceByGroup(String gid) {
104
105         HashMap<String, Object> condition = new HashMap<>();
106         condition.put(Constants.KEYFIELD_GID, gid);
107
108         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
109         if (getAceTable.isEmpty()) {
110             return;
111         }
112
113         removeAceList(getAceTable);
114         deleteAceRecords(condition);
115     }
116
117     /**
118      * API to remove acl table by members
119      * 
120      * @param members
121      *            member list which remove in group
122      * @param gid
123      *            group id
124      */
125     public void removeAceByMembers(ArrayList<String> members, String gid) {
126         for (String member : members) {
127             removeAceByMember(member, gid);
128             removeAceByOwner(member, gid);
129         }
130     }
131
132     /**
133      * API to remove acl table by devices
134      * 
135      * @param devices
136      *            device list which remove in group
137      * @param gid
138      *            group id
139      */
140     public void removeAceByDevices(ArrayList<String> devices, String gid) {
141         for (String device : devices) {
142             removeAceByDevice(device, gid);
143         }
144     }
145
146     /**
147      * API to remove acl table by resources
148      * 
149      * @param resources
150      *            resource list which remove in group
151      * @param gid
152      *            group id
153      */
154     public void removeAceByResources(
155             ArrayList<HashMap<String, Object>> resources, String gid) {
156         for (HashMap<String, Object> href : resources) {
157             removeAceByResource(
158                     href.get(Constants.KEYFIELD_ACE_RESOURCE_HREF).toString(),
159                     gid);
160         }
161     }
162
163     /**
164      * API to get device owner id
165      * 
166      * @param resources
167      *            resource list which remove in group
168      * @param gid
169      *            group id
170      */
171     public String getDeviceOwnerId(String di) {
172
173         String aclid = getAclid(di);
174
175         HashMap<String, Object> acl = AclResource.getInstance().getAcl(aclid)
176                 .getInfo();
177
178         if (acl == null || acl.containsKey(Constants.REQ_OWNER_ID) == false) {
179             throw new BadRequestException(
180                     "Error while getting device owner id for " + di);
181         }
182
183         return acl.get(Constants.REQ_OWNER_ID).toString();
184     }
185
186     private void removeAceByMember(String uid, String gid) {
187         HashMap<String, Object> condition = new HashMap<>();
188         condition.put(Constants.KEYFIELD_UID, uid);
189         condition.put(Constants.KEYFIELD_GID, gid);
190
191         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
192         if (getAceTable.isEmpty()) {
193             return;
194         }
195
196         removeAceList(getAceTable);
197         deleteAceRecords(condition);
198     }
199
200     private void removeAceByOwner(String oid, String gid) {
201         HashMap<String, Object> condition = new HashMap<>();
202         condition.put(Constants.KEYFIELD_OID, oid);
203         condition.put(Constants.KEYFIELD_GID, gid);
204
205         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
206         if (getAceTable.isEmpty()) {
207             return;
208         }
209
210         removeAceList(getAceTable);
211         deleteAceRecords(condition);
212     }
213
214     private void removeAceByDevice(String di, String gid) {
215         HashMap<String, Object> condition = new HashMap<>();
216         condition.put(Constants.KEYFIELD_DI, di);
217         condition.put(Constants.KEYFIELD_GID, gid);
218
219         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
220         if (getAceTable.isEmpty()) {
221             return;
222         }
223
224         removeAceList(getAceTable);
225         deleteAceRecords(condition);
226     }
227
228     private void removeAceByResource(String href, String gid) {
229         String removeHref = extractHref(href);
230         String di = Arrays.asList(href.split("/")).get(2);
231         HashMap<String, Object> condition = new HashMap<>();
232         condition.put(Constants.KEYFIELD_DI, di);
233         condition.put(Constants.KEYFIELD_GID, gid);
234
235         ArrayList<AceTable> aceTableList = searchAceTableList(condition);
236         ArrayList<HashMap<String, Object>> aceMapList = searchAceMapList(
237                 aceTableList);
238
239         for (HashMap<String, Object> aceMap : aceMapList) {
240             ArrayList<HashMap<String, Object>> AceResourceList = (ArrayList) aceMap
241                     .get(Constants.KEYFIELD_ACE_RESOURCE);
242             ListIterator<HashMap<String, Object>> iterator = AceResourceList
243                     .listIterator();
244             while (iterator.hasNext()) {
245                 AceResource res = new AceResource();
246                 res = mTypeAceResource.convertMaptoObject(iterator.next(), res);
247
248                 if (res.getHref().contains(removeHref)) {
249                     iterator.remove();
250                     break;
251                 }
252             }
253
254             condition.put(Constants.KEYFIELD_UID,
255                     aceMap.get(Constants.KEYFIELD_ACE_SUBJECT_ID));
256
257             ArrayList<AceTable> getAceTable = searchAceTableList(condition);
258             if (getAceTable.isEmpty()) {
259                 return;
260             }
261
262             if (AceResourceList.isEmpty()) {
263                 removeAceList(getAceTable);
264                 deleteAceRecords(condition);
265             } else {
266                 updateAce(getAceTable.get(0), aceMap);
267             }
268
269         }
270     }
271
272     private ArrayList<AceTable> searchAceTableList(
273             HashMap<String, Object> condition) {
274         ArrayList<AceTable> getAceTableList = new ArrayList<>();
275         ArrayList<HashMap<String, Object>> getAceList = AccountDBManager
276                 .getInstance().selectRecord(Constants.ACE_TABLE, condition);
277         for (HashMap<String, Object> getAce : getAceList) {
278             AceTable getAceTable = new AceTable();
279             getAceTable = mTypeAceTable.convertMaptoObject(getAce, getAceTable);
280             getAceTableList.add(getAceTable);
281         }
282         return getAceTableList;
283     }
284
285     private ArrayList<HashMap<String, Object>> searchAceMapList(
286             ArrayList<AceTable> aceList) {
287         ArrayList<HashMap<String, Object>> getAceList = new ArrayList<>();
288         for (AceTable getAce : aceList) {
289             getAceList.add(getAce(getAce));
290         }
291         return getAceList;
292     }
293
294     private void removeAceList(ArrayList<AceTable> aceTableList) {
295         for (AceTable removeAce : aceTableList) {
296             removeAce(removeAce);
297         }
298     }
299
300     private void updateAce(AceTable updateAce, HashMap<String, Object> ace) {
301         AclResource.getInstance().updateACE(getAclid(updateAce),
302                 getAceid(updateAce), ace);
303     }
304
305     private void removeAce(AceTable removeAce) {
306         AclResource.getInstance().deleteAclACE(getAclid(removeAce),
307                 getAceid(removeAce));
308     }
309
310     private HashMap<String, Object> getAce(AceTable getAce) {
311         return AclResource.getInstance().getAclACE(getAclid(getAce),
312                 getAceid(getAce));
313     }
314
315     private String extractHref(String href) {
316
317         List<String> segment = new ArrayList<String>(
318                 Arrays.asList(href.split("/")));
319
320         // Remove prefix path
321         segment.remove(0);
322         segment.remove(0);
323         segment.remove(0);
324
325         StringBuilder uriPath = new StringBuilder();
326         for (String path : segment) {
327             uriPath.append("/" + path);
328         }
329
330         return uriPath.toString();
331     }
332
333     private String getAceid(AceTable aceTable) {
334         if (aceTable.getAceid() == null) {
335             throw new InternalServerErrorException("aceid is invalid");
336         }
337         return aceTable.getAceid();
338     }
339
340     private String getAclid(AceTable aceTable) {
341         String di = null;
342         if (aceTable.getDi() == null) {
343             throw new InternalServerErrorException("di is invalid");
344         }
345         di = aceTable.getDi();
346
347         return getAclid(di);
348     }
349
350     private String getAclid(String di) {
351
352         HashMap<String, Object> acl = AclResource.getInstance().getAclid(di);
353
354         if (acl == null || !acl.containsKey(Constants.KEYFIELD_ACLID)) {
355             throw new InternalServerErrorException("aclid is invalid");
356         }
357
358         return (String) acl.get(Constants.KEYFIELD_ACLID);
359     }
360
361     private void addAceList(String gid, String di,
362             ArrayList<HashMap<String, Object>> acelist) {
363
364         String aclid = getAclid(di);
365         String oid = getDeviceOwnerId(di);
366
367         acelist = (ArrayList<HashMap<String, Object>>) AclResource.getInstance()
368                 .addAclACE(aclid, acelist);
369
370         insertAceRecords(gid, di, oid, acelist);
371     }
372
373     private void addAceByResources(String gid, int permission,
374             ArrayList<HashMap<String, Object>> resources,
375             ArrayList<String> members) {
376
377         HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = sortResources(
378                 resources);
379
380         for (String di : sortedResources.keySet()) {
381
382             // query aceid using gid-di in GroupACE table
383             HashMap<String, Object> condition = new HashMap<>();
384             condition.put(Constants.KEYFIELD_GID, gid);
385             condition.put(Constants.KEYFIELD_DI, di);
386             ArrayList<AceTable> aceTables = searchAceTableList(condition);
387
388             if (aceTables == null || aceTables.isEmpty()) {
389                 // add new ace
390                 addAceList(gid, di, makeAceList(members, permission,
391                         sortedResources.get(di)));
392                 continue;
393             } else {
394                 // update ace
395                 updateAceByResources(gid, permission, di, sortedResources,
396                         aceTables);
397             }
398         }
399     }
400
401     private void updateAceByResources(String gid, int permission, String di,
402             HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources,
403             ArrayList<AceTable> aceTables) {
404
405         String aclid = getAclid(aceTables.get(0));
406         String aceid = getAceid(aceTables.get(0));
407
408         @SuppressWarnings("unchecked")
409         ArrayList<HashMap<String, Object>> updatedAceResources = (ArrayList<HashMap<String, Object>>) AclResource
410                 .getInstance().getAclACE(aclid, aceid)
411                 .get(Constants.KEYFIELD_ACE_RESOURCE);
412
413         if (updatedAceResources.isEmpty() == false && updatedAceResources.get(0)
414                 .get(Constants.KEYFIELD_ACE_RESOURCE_HREF).equals("*")) {
415
416             updatedAceResources.clear();
417         }
418
419         updatedAceResources.addAll(sortedResources.get(di));
420
421         for (AceTable acetable : aceTables) {
422             updateAce(acetable, makeAce(acetable.getUid(), permission,
423                     updatedAceResources));
424         }
425     }
426
427     private ArrayList<HashMap<String, Object>> makeAceList(
428             ArrayList<String> members, int permission,
429             ArrayList<HashMap<String, Object>> resources) {
430
431         ArrayList<HashMap<String, Object>> acelist = new ArrayList<>();
432
433         for (String member : members) {
434             acelist.add(makeAce(member, permission, resources));
435         }
436
437         return acelist;
438     }
439
440     private HashMap<String, Object> makeAce(String mid, int permission,
441             ArrayList<HashMap<String, Object>> resources) {
442
443         if (resources == null) {
444             resources = new ArrayList<>();
445             HashMap<String, Object> resource = new HashMap<>();
446             resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, "*");
447             resource.put(Constants.KEYFIELD_ACE_RESOURCE_RT, Arrays.asList(""));
448             resource.put(Constants.KEYFIELD_ACE_RESOURCE_IF, Arrays.asList(""));
449
450             resources.add(resource);
451         }
452
453         HashMap<String, Object> newAce = new HashMap<>();
454         newAce.put(Constants.KEYFIELD_ACE_SUBJECT_ID, mid);
455         newAce.put(Constants.KEYFIELD_ACE_SUBJECT_TYPE, 1);
456         newAce.put(Constants.KEYFIELD_ACE_PERMISSION, permission);
457         newAce.put(Constants.KEYFIELD_ACE_RESOURCE, resources);
458
459         return newAce;
460     }
461
462     private void insertAceRecords(String gid, String di, String oid,
463             ArrayList<HashMap<String, Object>> acelist) {
464
465         for (HashMap<String, Object> ace : acelist) {
466
467             AceTable aceTable = new AceTable();
468             aceTable.setAceid(ace.get(Constants.KEYFIELD_ACE_ID).toString());
469             aceTable.setUid(
470                     ace.get(Constants.KEYFIELD_ACE_SUBJECT_ID).toString());
471             aceTable.setGid(gid);
472             aceTable.setDi(di);
473             aceTable.setOid(oid);
474
475             AccountDBManager.getInstance().insertAndReplaceRecord(
476                     Constants.ACE_TABLE,
477                     mTypeAceTable.convertObjectToMap(aceTable));
478         }
479     }
480
481     private void deleteAceRecords(HashMap<String, Object> condition) {
482
483         AccountDBManager.getInstance().deleteRecord(Constants.ACE_TABLE,
484                 condition);
485     }
486
487     private ArrayList<String> getGroupMembers(String gid) {
488
489         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
490         ArrayList<String> members = new ArrayList<>();
491
492         if (groupTable.getMembers() != null) {
493             members = groupTable.getMembers();
494         }
495         return members;
496     }
497
498     private ArrayList<String> getGroupDevices(String gid) {
499
500         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
501         ArrayList<String> devices = new ArrayList<>();
502
503         if (groupTable.getDevices() != null) {
504             devices = groupTable.getDevices();
505         }
506         return devices;
507     }
508
509     private ArrayList<HashMap<String, Object>> getGroupResources(String gid) {
510
511         ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
512         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
513
514         if (groupTable.getResources() == null) {
515             return resources;
516         }
517
518         for (Object resource : groupTable.getResources()) {
519
520             @SuppressWarnings("unchecked")
521             HashMap<String, Object> resourceInfo = (HashMap<String, Object>) resource;
522             resources.add(resourceInfo);
523         }
524
525         return resources;
526     }
527
528     // classify resources in group according to device id
529     private HashMap<String, ArrayList<HashMap<String, Object>>> sortResources(
530             ArrayList<HashMap<String, Object>> resources) {
531
532         HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = new HashMap<>();
533
534         for (HashMap<String, Object> resource : resources) {
535
536             HashMap<String, Object> resourceInfo = new HashMap<>(resource);
537
538             String href = resourceInfo.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
539                     .toString();
540             String di = Arrays.asList(href.split("/")).get(2);
541             href = extractHref(href);
542
543             resourceInfo.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, href);
544
545             if (sortedResources.containsKey(di) == false) {
546                 sortedResources.put(di, new ArrayList<>());
547             }
548
549             sortedResources.get(di).add(resourceInfo);
550         }
551
552         return sortedResources;
553     }
554 }