[IOT-1532] added GroupAclManager for managing group between acl
authorJung Seungho <shonest.jung@samsung.com>
Mon, 7 Nov 2016 05:08:26 +0000 (14:08 +0900)
committerJee Hyeok Kim <jihyeok13.kim@samsung.com>
Mon, 21 Nov 2016 14:07:29 +0000 (14:07 +0000)
Change-Id: I5d99b4fbfcd0e3464411754919356326a75def3c
Signed-off-by: Minji Park <minjii.park@samsung.com>
Signed-off-by: Jung Seungho <shonest.jung@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/13579
Reviewed-by: Yeonghun Nam <yeonghun.nam@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jee Hyeok Kim <jihyeok13.kim@samsung.com>
(cherry picked from commit 35f6b5689995e5143ef7cbc1bace9688dd07d9a9)
Reviewed-on: https://gerrit.iotivity.org/gerrit/14551
Reviewed-by: Uze Choi <uzchoi@samsung.com>
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AceTable.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManager.java [new file with mode: 0644]
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManagerTest.java [new file with mode: 0644]

diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AceTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AceTable.java
new file mode 100644 (file)
index 0000000..bcc295c
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * //      http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+public class AceTable {
+
+    private String gid;
+    private String di;
+    private String uid;
+    private String aceid;
+    private String oid;
+
+    public AceTable(String gid, String di, String uid, String aceid, String oid,
+            String href) {
+        this.gid = gid;
+        this.di = di;
+        this.uid = uid;
+        this.aceid = aceid;
+        this.oid = oid;
+    }
+
+    public AceTable() {
+    }
+
+    public String getGid() {
+        return gid;
+    }
+
+    public void setGid(String gid) {
+        this.gid = gid;
+    }
+
+    public String getDi() {
+        return di;
+    }
+
+    public void setDi(String di) {
+        this.di = di;
+    }
+
+    public String getUid() {
+        return uid;
+    }
+
+    public void setUid(String uid) {
+        this.uid = uid;
+    }
+
+    public String getAceid() {
+        return aceid;
+    }
+
+    public void setAceid(String aceid) {
+        this.aceid = aceid;
+    }
+
+    public String getOid() {
+        return oid;
+    }
+
+    public void setOid(String oid) {
+        this.oid = oid;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManager.java
new file mode 100644 (file)
index 0000000..42a8935
--- /dev/null
@@ -0,0 +1,557 @@
+package org.iotivity.cloud.accountserver.resources.acl.group;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.db.AceTable;
+import org.iotivity.cloud.accountserver.db.GroupTable;
+import org.iotivity.cloud.accountserver.resources.acl.id.AceResource;
+import org.iotivity.cloud.accountserver.resources.acl.id.AclResource;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
+import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
+
+/**
+ *
+ * This class provides a set of APIs to manage between AclManager and
+ * GroupManager
+ * 
+ *
+ */
+
+public class GroupAclManager {
+    private static GroupAclManager          mGrAclManager    = new GroupAclManager();
+    private TypeCastingManager<AceTable>    mTypeAceTable    = new TypeCastingManager<AceTable>();
+    private TypeCastingManager<AceResource> mTypeAceResource = new TypeCastingManager<AceResource>();
+
+    private GroupAclManager() {
+    }
+
+    public static GroupAclManager getInstance() {
+        return mGrAclManager;
+    }
+
+    /**
+     * API to add acl table by members
+     * 
+     * @param gid
+     *            group id
+     * @param permission
+     *            resource permission of group acl in group
+     * @param members
+     *            member list which add into group
+     */
+    public void addAceByMembers(String gid, int permission,
+            ArrayList<String> members) {
+
+        // make default acelist for each new member
+        for (String device : getGroupDevices(gid)) {
+            addAceList(gid, device, makeAceList(members, permission, null));
+        }
+
+        // make acelist with specific resources for each new member
+        addAceByResources(gid, permission, getGroupResources(gid), members);
+    }
+
+    /**
+     * API to add acl table by devices
+     * 
+     * @param gid
+     *            group id
+     * @param permission
+     *            resource permission of group acl in group
+     * @param devices
+     *            device list which add into group
+     */
+    public void addAceByDevices(String gid, int permission,
+            ArrayList<String> devices) {
+
+        // make default acelist for each existing member
+        for (String device : devices) {
+            addAceList(gid, device,
+                    makeAceList(getGroupMembers(gid), permission, null));
+        }
+    }
+
+    /**
+     * API to add acl table by resources
+     * 
+     * @param gid
+     *            group id
+     * @param permission
+     *            resource permission of group acl in group
+     * @param resources
+     *            resource list which add into group
+     */
+    public void addAceByResources(String gid, int permission,
+            ArrayList<HashMap<String, Object>> resources) {
+
+        addAceByResources(gid, permission, resources, getGroupMembers(gid));
+    }
+
+    /**
+     * API to remove acl table by group
+     * 
+     * @param gid
+     *            group id
+     */
+    public void removeAceByGroup(String gid) {
+
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.KEYFIELD_GID, gid);
+
+        ArrayList<AceTable> getAceTable = searchAceTableList(condition);
+        if (getAceTable.isEmpty()) {
+            return;
+        }
+
+        removeAceList(getAceTable);
+        deleteAceRecords(condition);
+    }
+
+    /**
+     * API to remove acl table by members
+     * 
+     * @param members
+     *            member list which remove in group
+     * @param gid
+     *            group id
+     */
+    public void removeAceByMembers(ArrayList<String> members, String gid) {
+        for (String member : members) {
+            removeAceByMember(member, gid);
+            removeAceByOwner(member, gid);
+        }
+    }
+
+    /**
+     * API to remove acl table by devices
+     * 
+     * @param devices
+     *            device list which remove in group
+     * @param gid
+     *            group id
+     */
+    public void removeAceByDevices(ArrayList<String> devices, String gid) {
+        for (String device : devices) {
+            removeAceByDevice(device, gid);
+        }
+    }
+
+    /**
+     * API to remove acl table by resources
+     * 
+     * @param resources
+     *            resource list which remove in group
+     * @param gid
+     *            group id
+     */
+    public void removeAceByResources(
+            ArrayList<HashMap<String, Object>> resources, String gid) {
+        for (HashMap<String, Object> href : resources) {
+            removeAceByResource(
+                    href.get(Constants.KEYFIELD_ACE_RESOURCE_HREF).toString(),
+                    gid);
+        }
+    }
+
+    /**
+     * API to get device owner id
+     * 
+     * @param resources
+     *            resource list which remove in group
+     * @param gid
+     *            group id
+     */
+    public String getDeviceOwnerId(String di) {
+
+        String aclid = getAclid(di);
+
+        HashMap<String, Object> acl = AclResource.getInstance().getAcl(aclid)
+                .getInfo();
+
+        if (acl == null || acl.containsKey(Constants.REQ_OWNER_ID) == false) {
+            throw new BadRequestException(
+                    "Error while getting device owner id for " + di);
+        }
+
+        return acl.get(Constants.REQ_OWNER_ID).toString();
+    }
+
+    private void removeAceByMember(String uid, String gid) {
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.KEYFIELD_UID, uid);
+        condition.put(Constants.KEYFIELD_GID, gid);
+
+        ArrayList<AceTable> getAceTable = searchAceTableList(condition);
+        if (getAceTable.isEmpty()) {
+            return;
+        }
+
+        removeAceList(getAceTable);
+        deleteAceRecords(condition);
+    }
+
+    private void removeAceByOwner(String oid, String gid) {
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.KEYFIELD_OID, oid);
+        condition.put(Constants.KEYFIELD_GID, gid);
+
+        ArrayList<AceTable> getAceTable = searchAceTableList(condition);
+        if (getAceTable.isEmpty()) {
+            return;
+        }
+
+        removeAceList(getAceTable);
+        deleteAceRecords(condition);
+    }
+
+    private void removeAceByDevice(String di, String gid) {
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.KEYFIELD_DI, di);
+        condition.put(Constants.KEYFIELD_GID, gid);
+
+        ArrayList<AceTable> getAceTable = searchAceTableList(condition);
+        if (getAceTable.isEmpty()) {
+            return;
+        }
+
+        removeAceList(getAceTable);
+        deleteAceRecords(condition);
+    }
+
+    private void removeAceByResource(String href, String gid) {
+        String removeHref = extractHref(href);
+        String di = Arrays.asList(href.split("/")).get(2);
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.KEYFIELD_DI, di);
+        condition.put(Constants.KEYFIELD_GID, gid);
+
+        ArrayList<AceTable> aceTableList = searchAceTableList(condition);
+        ArrayList<HashMap<String, Object>> aceMapList = searchAceMapList(
+                aceTableList);
+
+        for (HashMap<String, Object> aceMap : aceMapList) {
+            ArrayList<HashMap<String, Object>> AceResourceList = (ArrayList) aceMap
+                    .get(Constants.KEYFIELD_ACE_RESOURCE);
+            ListIterator<HashMap<String, Object>> iterator = AceResourceList
+                    .listIterator();
+            while (iterator.hasNext()) {
+                AceResource res = new AceResource();
+                res = mTypeAceResource.convertMaptoObject(iterator.next(), res);
+
+                if (res.getHref().contains(removeHref)) {
+                    iterator.remove();
+                    break;
+                }
+            }
+
+            condition.put(Constants.KEYFIELD_UID,
+                    aceMap.get(Constants.KEYFIELD_ACE_SUBJECT_ID));
+
+            ArrayList<AceTable> getAceTable = searchAceTableList(condition);
+            if (getAceTable.isEmpty()) {
+                return;
+            }
+
+            if (AceResourceList.isEmpty()) {
+                removeAceList(getAceTable);
+                deleteAceRecords(condition);
+            } else {
+                updateAce(getAceTable.get(0), aceMap);
+            }
+
+        }
+    }
+
+    private ArrayList<AceTable> searchAceTableList(
+            HashMap<String, Object> condition) {
+        ArrayList<AceTable> getAceTableList = new ArrayList<>();
+        ArrayList<HashMap<String, Object>> getAceList = AccountDBManager
+                .getInstance().selectRecord(Constants.ACE_TABLE, condition);
+        if (getAceList == null) {
+            return null;
+        }
+        for (HashMap<String, Object> getAce : getAceList) {
+            AceTable getAceTable = new AceTable();
+            getAceTable = mTypeAceTable.convertMaptoObject(getAce, getAceTable);
+            getAceTableList.add(getAceTable);
+        }
+        return getAceTableList;
+    }
+
+    private ArrayList<HashMap<String, Object>> searchAceMapList(
+            ArrayList<AceTable> aceList) {
+        ArrayList<HashMap<String, Object>> getAceList = new ArrayList<>();
+        for (AceTable getAce : aceList) {
+            getAceList.add(getAce(getAce));
+        }
+        return getAceList;
+    }
+
+    private void removeAceList(ArrayList<AceTable> aceTableList) {
+        for (AceTable removeAce : aceTableList) {
+            removeAce(removeAce);
+        }
+    }
+
+    private void updateAce(AceTable updateAce, HashMap<String, Object> ace) {
+        AclResource.getInstance().updateACE(getAclid(updateAce),
+                getAceid(updateAce), ace);
+    }
+
+    private void removeAce(AceTable removeAce) {
+        AclResource.getInstance().deleteAclACE(getAclid(removeAce),
+                getAceid(removeAce));
+    }
+
+    private HashMap<String, Object> getAce(AceTable getAce) {
+        return AclResource.getInstance().getAclACE(getAclid(getAce),
+                getAceid(getAce));
+    }
+
+    private String extractHref(String href) {
+
+        List<String> segment = new ArrayList<String>(
+                Arrays.asList(href.split("/")));
+
+        // Remove prefix path
+        segment.remove(0);
+        segment.remove(0);
+        segment.remove(0);
+
+        StringBuilder uriPath = new StringBuilder();
+        for (String path : segment) {
+            uriPath.append("/" + path);
+        }
+
+        return uriPath.toString();
+    }
+
+    private String getAceid(AceTable aceTable) {
+        if (aceTable.getAceid() == null) {
+            throw new InternalServerErrorException("aceid is invalid");
+        }
+        return aceTable.getAceid();
+    }
+
+    private String getAclid(AceTable aceTable) {
+        String di = null;
+        if (aceTable.getDi() == null) {
+            throw new InternalServerErrorException("di is invalid");
+        }
+        di = aceTable.getDi();
+
+        return getAclid(di);
+    }
+
+    private String getAclid(String di) {
+
+        HashMap<String, Object> acl = AclResource.getInstance().getAclid(di);
+
+        if (acl == null || !acl.containsKey(Constants.KEYFIELD_ACLID)) {
+            throw new InternalServerErrorException("aclid is invalid");
+        }
+
+        return (String) acl.get(Constants.KEYFIELD_ACLID);
+    }
+
+    private void addAceList(String gid, String di,
+            ArrayList<HashMap<String, Object>> acelist) {
+
+        String aclid = getAclid(di);
+        String oid = getDeviceOwnerId(di);
+
+        acelist = (ArrayList<HashMap<String, Object>>) AclResource.getInstance()
+                .addAclACE(aclid, acelist);
+
+        insertAceRecords(gid, di, oid, acelist);
+    }
+
+    private void addAceByResources(String gid, int permission,
+            ArrayList<HashMap<String, Object>> resources,
+            ArrayList<String> members) {
+
+        HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = sortResources(
+                resources);
+
+        for (String di : sortedResources.keySet()) {
+
+            // query aceid using gid-di in GroupACE table
+            HashMap<String, Object> condition = new HashMap<>();
+            condition.put(Constants.KEYFIELD_GID, gid);
+            condition.put(Constants.KEYFIELD_DI, di);
+            ArrayList<AceTable> aceTables = searchAceTableList(condition);
+
+            if (aceTables == null || aceTables.isEmpty()) {
+                // add new ace
+                addAceList(gid, di, makeAceList(members, permission,
+                        sortedResources.get(di)));
+                continue;
+            } else {
+                // update ace
+                updateAceByResources(gid, permission, di, sortedResources,
+                        aceTables);
+            }
+        }
+    }
+
+    private void updateAceByResources(String gid, int permission, String di,
+            HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources,
+            ArrayList<AceTable> aceTables) {
+
+        String aclid = getAclid(aceTables.get(0));
+        String aceid = getAceid(aceTables.get(0));
+
+        @SuppressWarnings("unchecked")
+        ArrayList<HashMap<String, Object>> updatedAceResources = (ArrayList<HashMap<String, Object>>) AclResource
+                .getInstance().getAclACE(aclid, aceid)
+                .get(Constants.KEYFIELD_ACE_RESOURCE);
+
+        if (updatedAceResources.isEmpty() == false && updatedAceResources.get(0)
+                .get(Constants.KEYFIELD_ACE_RESOURCE_HREF).equals("*")) {
+
+            updatedAceResources.clear();
+        }
+
+        updatedAceResources.addAll(sortedResources.get(di));
+
+        for (AceTable acetable : aceTables) {
+            updateAce(acetable, makeAce(acetable.getUid(), permission,
+                    updatedAceResources));
+        }
+    }
+
+    private ArrayList<HashMap<String, Object>> makeAceList(
+            ArrayList<String> members, int permission,
+            ArrayList<HashMap<String, Object>> resources) {
+
+        ArrayList<HashMap<String, Object>> acelist = new ArrayList<>();
+
+        for (String member : members) {
+            acelist.add(makeAce(member, permission, resources));
+        }
+
+        return acelist;
+    }
+
+    private HashMap<String, Object> makeAce(String mid, int permission,
+            ArrayList<HashMap<String, Object>> resources) {
+
+        if (resources == null) {
+            resources = new ArrayList<>();
+            HashMap<String, Object> resource = new HashMap<>();
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, "*");
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_RT, Arrays.asList(""));
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_IF, Arrays.asList(""));
+
+            resources.add(resource);
+        }
+
+        HashMap<String, Object> newAce = new HashMap<>();
+        newAce.put(Constants.KEYFIELD_ACE_SUBJECT_ID, mid);
+        newAce.put(Constants.KEYFIELD_ACE_SUBJECT_TYPE, 1);
+        newAce.put(Constants.KEYFIELD_ACE_PERMISSION, permission);
+        newAce.put(Constants.KEYFIELD_ACE_RESOURCE, resources);
+
+        return newAce;
+    }
+
+    private void insertAceRecords(String gid, String di, String oid,
+            ArrayList<HashMap<String, Object>> acelist) {
+
+        for (HashMap<String, Object> ace : acelist) {
+
+            AceTable aceTable = new AceTable();
+            aceTable.setAceid(ace.get(Constants.KEYFIELD_ACE_ID).toString());
+            aceTable.setUid(
+                    ace.get(Constants.KEYFIELD_ACE_SUBJECT_ID).toString());
+            aceTable.setGid(gid);
+            aceTable.setDi(di);
+            aceTable.setOid(oid);
+
+            AccountDBManager.getInstance().insertAndReplaceRecord(
+                    Constants.ACE_TABLE,
+                    mTypeAceTable.convertObjectToMap(aceTable));
+        }
+    }
+
+    private void deleteAceRecords(HashMap<String, Object> condition) {
+
+        AccountDBManager.getInstance().deleteRecord(Constants.ACE_TABLE,
+                condition);
+    }
+
+    private ArrayList<String> getGroupMembers(String gid) {
+
+        GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
+        ArrayList<String> members = new ArrayList<>();
+
+        if (groupTable.getMembers() != null) {
+            members = groupTable.getMembers();
+        }
+        return members;
+    }
+
+    private ArrayList<String> getGroupDevices(String gid) {
+
+        GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
+        ArrayList<String> devices = new ArrayList<>();
+
+        if (groupTable.getDevices() != null) {
+            devices = groupTable.getDevices();
+        }
+        return devices;
+    }
+
+    private ArrayList<HashMap<String, Object>> getGroupResources(String gid) {
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
+
+        if (groupTable.getResources() == null) {
+            return resources;
+        }
+
+        for (Object resource : groupTable.getResources()) {
+
+            @SuppressWarnings("unchecked")
+            HashMap<String, Object> resourceInfo = (HashMap<String, Object>) resource;
+            resources.add(resourceInfo);
+        }
+
+        return resources;
+    }
+
+    // classify resources in group according to device id
+    private HashMap<String, ArrayList<HashMap<String, Object>>> sortResources(
+            ArrayList<HashMap<String, Object>> resources) {
+
+        HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = new HashMap<>();
+
+        for (HashMap<String, Object> resource : resources) {
+
+            HashMap<String, Object> resourceInfo = new HashMap<>(resource);
+
+            String href = resourceInfo.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                    .toString();
+            String di = Arrays.asList(href.split("/")).get(2);
+            href = extractHref(href);
+
+            resourceInfo.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, href);
+
+            if (sortedResources.containsKey(di) == false) {
+                sortedResources.put(di, new ArrayList<>());
+            }
+
+            sortedResources.get(di).add(resourceInfo);
+        }
+
+        return sortedResources;
+    }
+}
diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManagerTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupAclManagerTest.java
new file mode 100644 (file)
index 0000000..abc52cc
--- /dev/null
@@ -0,0 +1,878 @@
+package org.iotivity.cloud.accountserver.resources.acl.group;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.db.GroupTable;
+import org.iotivity.cloud.accountserver.db.MongoDB;
+import org.iotivity.cloud.accountserver.resources.acl.id.AclResource;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.util.Log;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GroupAclManagerTest {
+    private String                  mGid1               = "g1";
+    private String                  mGid2               = "g2";
+    private String                  mDi1                = "d1";
+    private String                  mDi2                = "d2";
+    private String                  mUid1               = "u1";
+    private String                  mUid2               = "u2";
+    private String                  mUid3               = "u3";
+
+    private HashMap<String, Object> mResourceLight1ofD1 = new HashMap<>();
+    private HashMap<String, Object> mResourceLight2ofD1 = new HashMap<>();
+    private HashMap<String, Object> mResourceLight1ofD2 = new HashMap<>();
+    private HashMap<String, Object> mResourceLight2ofD2 = new HashMap<>();
+    private HashMap<String, Object> mResourceAll        = new HashMap<>();
+    private int                     mPermission         = 15;
+
+    public GroupAclManager          mGroupAclManager    = GroupAclManager
+            .getInstance();
+
+    @Before
+    public void setUp() throws Exception {
+        AclResource.getInstance().createAcl(mUid1, mDi1);
+        AclResource.getInstance().createAcl(mUid2, mDi2);
+
+        mResourceLight1ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                "/di/d1/a/light/1");
+        mResourceLight1ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_RT,
+                Arrays.asList("core.light"));
+        mResourceLight1ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_IF,
+                Arrays.asList("oic.if.baseline"));
+
+        mResourceLight2ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                "/di/d1/a/light/2");
+        mResourceLight2ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_RT,
+                Arrays.asList("core.light"));
+        mResourceLight2ofD1.put(Constants.KEYFIELD_ACE_RESOURCE_IF,
+                Arrays.asList("oic.if.baseline"));
+
+        mResourceLight1ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                "/di/d2/a/light/1");
+        mResourceLight1ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_RT,
+                Arrays.asList("core.light"));
+        mResourceLight1ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_IF,
+                Arrays.asList("oic.if.baseline"));
+
+        mResourceLight2ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                "/di/d2/a/light/2");
+        mResourceLight2ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_RT,
+                Arrays.asList("core.light"));
+        mResourceLight2ofD2.put(Constants.KEYFIELD_ACE_RESOURCE_IF,
+                Arrays.asList("oic.if.baseline"));
+
+        mResourceAll.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, "*");
+        mResourceAll.put(Constants.KEYFIELD_ACE_RESOURCE_RT, Arrays.asList(""));
+        mResourceAll.put(Constants.KEYFIELD_ACE_RESOURCE_IF, Arrays.asList(""));
+    }
+
+    @After
+    public void resetAccountDatabase() throws Exception {
+        AclResource.getInstance().deleteAcl((String) AclResource.getInstance()
+                .getAclid(mDi1).get(Constants.KEYFIELD_ACLID));
+        AclResource.getInstance().deleteAcl((String) AclResource.getInstance()
+                .getAclid(mDi2).get(Constants.KEYFIELD_ACLID));
+
+        MongoDB mongoDB = new MongoDB(Constants.DB_NAME);
+        mongoDB.deleteTable(Constants.GROUP_TABLE);
+        mongoDB.createTable(Constants.GROUP_TABLE);
+        mongoDB.deleteTable(Constants.ACL_TABLE);
+        mongoDB.createTable(Constants.ACL_TABLE);
+        mongoDB.deleteTable(Constants.ACE_TABLE);
+        mongoDB.createTable(Constants.ACE_TABLE);
+    }
+
+    @Test
+    public void testAddAceByResourcesOnlyOwner() {
+        Log.v("--------------testAddAceByResourcesOnlyOwner------------");
+
+        // initialize group info --
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_MEMBERS, members);
+        setGroupInfo(mGid1, groupInfo);
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD1);
+        resources.add(mResourceLight2ofD1);
+
+        mGroupAclManager.addAceByResources(mGid1, mPermission, resources);
+
+        // check ACE not updated for d1-u1(device owner)
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition.put(Constants.KEYFIELD_UID, mUid1);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testAddAceByResources() {
+        Log.v("--------------testAddAceByResoruces------------");
+
+        // initialize group info --
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_MEMBERS, members);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD1);
+        resources.add(mResourceLight2ofD1);
+
+        mGroupAclManager.addAceByResources(mGid1, mPermission, resources);
+
+        // check ACE not updated for d1-u1(device owner)
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition1.put(Constants.KEYFIELD_UID, mUid1);
+        assertNull(getAceId(aceidCondition1));
+
+        // check ACETable and ACL for d1(light1, light2)-u2
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+        String aceIdg1d1 = getAceId(aceidCondition2);
+
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID, aceIdg1d1);
+
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid1);
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+
+        // remove prefix in href
+        for (HashMap<String, Object> resource : resources) {
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                    extractHref(
+                            resource.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                                    .toString()));
+        }
+
+        assertTrue(checkAclTable(mDi1, aceIdg1d1, mUid2, resources));
+    }
+
+    @Test
+    public void testAddAceByResourcesNoMembers() {
+        Log.v("--------------testAddAceByResorucesNoMembers------------");
+        setGroupInfo(mGid1, new HashMap<>());
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD1);
+        resources.add(mResourceLight2ofD1);
+
+        mGroupAclManager.addAceByResources(mGid1, mPermission, resources);
+
+        // check ACE not updated for d1(light1, light2)
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_DI, mDi1);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testAddAceByDevices() {
+        Log.v("--------------testAddAceByDevices------------");
+
+        // initialize group info --
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_MEMBERS, members);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+
+        mGroupAclManager.addAceByDevices(mGid1, mPermission, devices);
+
+        // check ACETable and ACL for d1-u2
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition.put(Constants.KEYFIELD_UID, mUid2);
+        String aceIdg1d1 = getAceId(aceidCondition);
+
+        HashMap<String, Object> aceCondition = new HashMap<>();
+        aceCondition.put(Constants.KEYFIELD_ACE_ID, aceIdg1d1);
+
+        aceidCondition.clear();
+        aceidCondition.put(Constants.KEYFIELD_OID, mUid1);
+        assertTrue(checkAceTable(aceCondition, aceidCondition));
+
+        assertTrue(checkAclTable(mDi1, aceIdg1d1, mUid2,
+                Arrays.asList(mResourceAll)));
+    }
+
+    @Test
+    public void testAddAceByDevicesOnlyOwner() {
+        Log.v("--------------testAddAceByDevicesOnlyOwner------------");
+
+        // initialize group info --
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_MEMBERS, members);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+
+        mGroupAclManager.addAceByDevices(mGid1, mPermission, devices);
+
+        // check ACE not updated for d1-u1(device owner)
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition.put(Constants.KEYFIELD_UID, mUid1);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testAddAceByDevicesNoMembers() {
+        Log.v("--------------testAddAceByDevicesNoMembers------------");
+        setGroupInfo(mGid1, new HashMap<>());
+
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+
+        mGroupAclManager.addAceByDevices(mGid1, mPermission, devices);
+
+        // check ACE not updated for d1
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_DI, mDi1);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testAddAceByMembersWithDevice() {
+        Log.v("--------------testAddAceByMembersWithDevice------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid2);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        // check ACETable and ACL for d1-u2
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition1.put(Constants.KEYFIELD_UID, mUid2);
+        String aceIdg1d1 = getAceId(aceidCondition1);
+
+        HashMap<String, Object> aceCondition = new HashMap<>();
+        aceCondition.put(Constants.KEYFIELD_ACE_ID, aceIdg1d1);
+
+        aceidCondition1.clear();
+        aceidCondition1.put(Constants.KEYFIELD_OID, mUid1);
+        assertTrue(checkAceTable(aceCondition, aceidCondition1));
+
+        assertTrue(checkAclTable(mDi1, aceIdg1d1, mUid2,
+                Arrays.asList(mResourceAll)));
+
+        // check ACE not updated for d2-u2(device owner)
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi2);
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+        assertNull(getAceId(aceidCondition2));
+    }
+
+    @Test
+    public void testAddAceByMembersWithDeviceAndResource() {
+        Log.v("--------------testAddAceByMembersWithDeviceAndResource------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD1);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        groupInfo.put(Constants.KEYFIELD_GROUP_RESOURCES, resources);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid2);
+        members.add(mUid3);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        // remove prefix in href
+        ArrayList<HashMap<String, Object>> resourcesWithExtractedHref = new ArrayList<>(
+                resources);
+        for (HashMap<String, Object> resource : resourcesWithExtractedHref) {
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                    extractHref(
+                            resource.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                                    .toString()));
+        }
+
+        /* d1(light1) */
+        // check ACETable and ACL for d1-u2
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition1.put(Constants.KEYFIELD_UID, mUid2);
+        String aceIdg1d1 = getAceId(aceidCondition1);
+
+        HashMap<String, Object> aceCondition1 = new HashMap<>();
+        aceCondition1.put(Constants.KEYFIELD_ACE_ID, aceIdg1d1);
+
+        aceidCondition1.clear();
+        aceidCondition1.put(Constants.KEYFIELD_OID, mUid1);
+        assertTrue(checkAceTable(aceCondition1, aceidCondition1));
+        assertTrue(checkAclTable(mDi1, aceIdg1d1, mUid2,
+                resourcesWithExtractedHref));
+
+        // check ACETable and ACL for d1-u3
+        aceidCondition1.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition1.put(Constants.KEYFIELD_UID, mUid3);
+        aceIdg1d1 = getAceId(aceidCondition1);
+
+        aceCondition1.put(Constants.KEYFIELD_ACE_ID, aceIdg1d1);
+
+        aceidCondition1.clear();
+        aceidCondition1.put(Constants.KEYFIELD_OID, mUid1);
+        assertTrue(checkAceTable(aceCondition1, aceidCondition1));
+        assertTrue(checkAclTable(mDi1, aceIdg1d1, mUid3,
+                resourcesWithExtractedHref));
+
+        /* d2(all resources) */
+        // check ACE not updated for d2-u2(device owner)
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi2);
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+        assertNull(getAceId(aceidCondition2));
+
+        // check ACETable and ACL for d2-u3
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid3);
+        String aceIdg1d2 = getAceId(aceidCondition2);
+
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID, aceIdg1d2);
+
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid2);
+        assertTrue(checkAceTable(aceidCondition2, aceidCondition2));
+        assertTrue(checkAclTable(mDi2, aceIdg1d2, mUid3,
+                Arrays.asList(mResourceAll)));
+    }
+
+    @Test
+    public void testAddAceByMembersNoDevice() {
+        Log.v("--------------testAddAceByMembersNoDevice------------");
+        setGroupInfo(mGid1, new HashMap<>());
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid2);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        // check ACE not updated
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.KEYFIELD_UID, mUid2);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testAddAceByMembersOwnerDevice() {
+        Log.v("--------------testAddAceByMembersOwnerDevice------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid2);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        // check ACE not updated for d2-u2(device owner)
+        HashMap<String, Object> aceidCondition = new HashMap<>();
+        aceidCondition.put(Constants.REQ_GROUP_ID, mGid1);
+        aceidCondition.put(Constants.REQ_GROUP_ID, mDi2);
+        aceidCondition.put(Constants.KEYFIELD_UID, mUid2);
+        assertNull(getAceId(aceidCondition));
+    }
+
+    @Test
+    public void testRemoveAceByGroup() {
+        Log.v("--------------testRemoveAceByGroup------------");
+
+        // initialize group info --
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_MEMBERS, members);
+        setGroupInfo(mGid1, groupInfo);
+        setGroupInfo(mGid2, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+
+        mGroupAclManager.addAceByDevices(mGid2, mPermission, devices);
+
+        mGroupAclManager.addAceByDevices(mGid1, mPermission - 11, devices);
+
+        mGroupAclManager.removeAceByGroup(mGid1);
+
+        String aceIdg1d1, aceIdg2d1 = null;
+        // verify ACE Group1
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.REQ_GROUP_ID, mGid1);
+
+        // verify AceId is Null Cases Group1
+        assertNull(getAceId(aceidCondition1));
+
+        // verify ACE Device1 in Group2
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.REQ_GROUP_ID, mGid2);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi1);
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID,
+                aceIdg1d1 = getAceId(aceidCondition2));
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid1);
+
+        // verify AceId is Null Cases Group2
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+        // verify ACL Device1 Group2
+        checkAclTable(mDi1, aceIdg1d1, mUid2, Arrays.asList(mResourceAll));
+
+        // verify ACE Device1 in Group2
+        HashMap<String, Object> aceCondition3 = new HashMap<>();
+        HashMap<String, Object> aceidCondition3 = new HashMap<>();
+        aceidCondition3.put(Constants.REQ_GROUP_ID, mGid2);
+        aceidCondition3.put(Constants.KEYFIELD_DI, mDi2);
+        aceidCondition3.put(Constants.KEYFIELD_UID, mUid1);
+
+        aceCondition3.put(Constants.KEYFIELD_ACE_ID,
+                aceIdg2d1 = getAceId(aceidCondition3));
+        aceidCondition3.clear();
+        aceidCondition3.put(Constants.KEYFIELD_OID, mUid2);
+
+        // verify AceId is true Cases Group2
+        assertTrue(checkAceTable(aceCondition3, aceidCondition3));
+        // verify ACL Device2 Group2
+        assertTrue(checkAclTable(mDi2, aceIdg2d1, mUid1,
+                Arrays.asList(mResourceAll)));
+    }
+
+    @Test
+    public void testRemoveAceByMembers() {
+        Log.v("--------------testRemoveAceByMembers------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        groupInfo.put(Constants.KEYFIELD_GROUP_RESOURCES, resources);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+        members.add(mUid3);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        members.remove(mUid2);
+        members.remove(mUid3);
+        mGroupAclManager.removeAceByMembers(members, mGid1);
+
+        String aceIdg1d1 = null;
+        // verify ACE User1
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.KEYFIELD_OID, mUid1);
+
+        // verify AceId is Null Cases User1
+        assertNull(getAceId(aceidCondition1));
+
+        // verify ACE User2
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid3);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi2);
+
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID,
+                aceIdg1d1 = getAceId(aceidCondition2));
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid2);
+
+        // remove prefix in href
+        for (HashMap<String, Object> resource : resources) {
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                    extractHref(
+                            resource.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                                    .toString()));
+        }
+        // verify AceId True
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+        // verify ACL Device1 Group2
+        assertTrue(checkAclTable(mDi2, aceIdg1d1, mUid3, resources));
+    }
+
+    @Test
+    public void testRemoveAceByDevices() {
+        Log.v("--------------testRemoveAceByDevices------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        groupInfo.put(Constants.KEYFIELD_GROUP_RESOURCES, resources);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+        members.add(mUid3);
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        devices.remove(mDi2);
+        mGroupAclManager.removeAceByDevices(devices, mGid1);
+
+        String aceIdu1d2 = null, aceIdu3d2 = null;
+        // verify ACE Device1
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi1);
+
+        // verify AceId is Null Cases User1
+        assertNull(getAceId(aceidCondition1));
+
+        // verify ACE ownerid=User2, subjectuuid=User1
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid1);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi2);
+
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID,
+                aceIdu1d2 = getAceId(aceidCondition2));
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid2);
+
+        // verify ACE ownerid=User2, subjectuuid=User3
+        HashMap<String, Object> aceCondition3 = new HashMap<>();
+        HashMap<String, Object> aceidCondition3 = new HashMap<>();
+        aceidCondition3.put(Constants.KEYFIELD_UID, mUid3);
+        aceidCondition3.put(Constants.KEYFIELD_DI, mDi2);
+
+        aceCondition3.put(Constants.KEYFIELD_ACE_ID,
+                aceIdu3d2 = getAceId(aceidCondition3));
+        aceidCondition3.clear();
+        aceidCondition3.put(Constants.KEYFIELD_OID, mUid2);
+
+        // remove prefix in href
+        for (HashMap<String, Object> resource : resources) {
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                    extractHref(
+                            resource.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                                    .toString()));
+        }
+
+        // verify AceId ownerid=User2, subjectuuid=User1 True
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+        // verify ACL Device2 User1
+        assertTrue(checkAclTable(mDi2, aceIdu1d2, mUid1,
+                Arrays.asList(mResourceLight1ofD2)));
+
+        // verify AceId ownerid=User2, subjectuuid=User3 True
+        assertTrue(checkAceTable(aceCondition3, aceidCondition3));
+        // verify ACL Device2 User1
+        assertTrue(checkAclTable(mDi2, aceIdu3d2, mUid3,
+                Arrays.asList(mResourceLight1ofD2)));
+
+    }
+
+    @Test
+    public void testRemoveAceByResourcesDeleteAce() {
+        Log.v("--------------testRemoveAceByResourcesDeleteAce------------");
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        groupInfo.put(Constants.KEYFIELD_GROUP_RESOURCES, resources);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        mGroupAclManager.removeAceByResources(
+                new ArrayList<>(Arrays.asList(mResourceLight1ofD2)), mGid1);
+
+        // verify ACE Device2
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi2);
+
+        // verify AceId is Null Cases User1
+        assertNull(getAceId(aceidCondition1));
+
+        String aceIdu1d2 = null;
+        // verify ACE ownerid=u1, subjectuuid=u2 Deivce=d1
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi1);
+
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID,
+                aceIdu1d2 = getAceId(aceidCondition2));
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid1);
+
+        // verify AceId ownerid=u1, subjectuuid=u2 True
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+        // verify ACL Device2 User1
+        assertTrue(checkAclTable(mDi1, aceIdu1d2, mUid2,
+                Arrays.asList(mResourceAll)));
+    }
+
+    @Test
+    public void testRemoveAceByResourcesRemainAce() {
+
+        // initialize group info --
+        ArrayList<String> devices = new ArrayList<>();
+        devices.add(mDi1);
+        devices.add(mDi2);
+        ArrayList<String> members = new ArrayList<>();
+        members.add(mUid1);
+        members.add(mUid2);
+
+        ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
+        resources.add(mResourceLight1ofD2);
+        resources.add(mResourceLight2ofD2);
+
+        HashMap<String, Object> groupInfo = new HashMap<>();
+        groupInfo.put(Constants.KEYFIELD_GROUP_DEVICES, devices);
+        groupInfo.put(Constants.KEYFIELD_GROUP_RESOURCES, resources);
+        setGroupInfo(mGid1, groupInfo);
+        // -- initialize group info
+
+        mGroupAclManager.addAceByMembers(mGid1, mPermission, members);
+
+        mGroupAclManager.removeAceByResources(
+                new ArrayList<>(Arrays.asList(mResourceLight1ofD2)), mGid1);
+
+        String aceIdu2d1 = null, aceIdu1d2 = null;
+        // verify ACE ownerid=u1, subjectuuid=u1 Deivce=d2
+        HashMap<String, Object> aceCondition1 = new HashMap<>();
+        HashMap<String, Object> aceidCondition1 = new HashMap<>();
+        aceidCondition1.put(Constants.KEYFIELD_UID, mUid1);
+        aceidCondition1.put(Constants.KEYFIELD_DI, mDi2);
+
+        aceCondition1.put(Constants.KEYFIELD_ACE_ID,
+                aceIdu1d2 = getAceId(aceidCondition1));
+        aceidCondition1.clear();
+        aceidCondition1.put(Constants.KEYFIELD_OID, mUid2);
+
+        // remove prefix in href
+        for (HashMap<String, Object> resource : resources) {
+            resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF,
+                    extractHref(
+                            resource.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
+                                    .toString()));
+        }
+        // verify AceId ownerid=u2, subjectuuid=u1 True
+        assertTrue(checkAceTable(aceCondition1, aceidCondition1));
+        // verify ACL Device2 User1
+        assertTrue(checkAclTable(mDi2, aceIdu1d2, mUid1,
+                Arrays.asList(mResourceLight2ofD2)));
+
+        // verify ACE ownerid=u1, subjectuuid=u2 Deivce=d1
+        HashMap<String, Object> aceCondition2 = new HashMap<>();
+        HashMap<String, Object> aceidCondition2 = new HashMap<>();
+        aceidCondition2.put(Constants.KEYFIELD_UID, mUid2);
+        aceidCondition2.put(Constants.KEYFIELD_DI, mDi1);
+
+        aceCondition2.put(Constants.KEYFIELD_ACE_ID,
+                aceIdu1d2 = getAceId(aceidCondition2));
+        aceidCondition2.clear();
+        aceidCondition2.put(Constants.KEYFIELD_OID, mUid1);
+
+        // verify AceId ownerid=u1, subjectuuid=u2 True
+        assertTrue(checkAceTable(aceCondition2, aceidCondition2));
+        // verify ACL Device2 User1
+        assertTrue(checkAclTable(mDi1, aceIdu1d2, mUid2,
+                Arrays.asList(mResourceAll)));
+    }
+
+    private boolean checkAclTable(String di, String aceid, String subjectUuid,
+            List<HashMap<String, Object>> resource) {
+        Log.v("--------------checkAclTable : " + di + " ------------");
+        HashMap<String, Object> getAclist = AclResource.getInstance()
+                .getAclACE((String) AclResource.getInstance().getAclid(di)
+                        .get(Constants.KEYFIELD_ACLID), aceid);
+        Log.v("check result : " + getAclist);
+        if (getAclist.isEmpty()) {
+            return false;
+        }
+
+        // check subject uuid
+        assertTrue(getAclist.containsKey(Constants.KEYFIELD_ACE_SUBJECT_ID));
+        assertTrue(getAclist.get(Constants.KEYFIELD_ACE_SUBJECT_ID)
+                .equals(subjectUuid));
+
+        // check resource
+        assertTrue(getAclist.containsKey(Constants.KEYFIELD_ACE_RESOURCE));
+        for (HashMap<String, Object> targetRes : resource) {
+            boolean isbreak = false;
+            for (HashMap<String, Object> res : (ArrayList<HashMap<String, Object>>) getAclist
+                    .get(Constants.KEYFIELD_ACE_RESOURCE)) {
+                assertTrue(
+                        res.containsKey(Constants.KEYFIELD_ACE_RESOURCE_HREF));
+                if (res.get(Constants.KEYFIELD_ACE_RESOURCE_HREF).equals(
+                        targetRes.get(Constants.KEYFIELD_ACE_RESOURCE_HREF))) {
+                    isbreak = true;
+                    break;
+                }
+            }
+            if (isbreak) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkAceTable(HashMap<String, Object> condition,
+            HashMap<String, Object> key) {
+        Log.v("--------------checkAceTable : " + condition.toString()
+                + " ------------");
+        HashMap<String, Object> getAce = getAceTable(condition).get(0);
+        Log.v("check result : " + getAce);
+        if (getAce.isEmpty()) {
+            return false;
+        }
+        for (String keyelement : key.keySet()) {
+            assertTrue(getAce.containsKey(keyelement));
+            assertTrue(getAce.get(keyelement).equals(key.get(keyelement)));
+        }
+        return true;
+    }
+
+    private String getAceId(HashMap<String, Object> condition) {
+
+        ArrayList<HashMap<String, Object>> aceTables = AccountDBManager
+                .getInstance().selectRecord(Constants.ACE_TABLE, condition);
+
+        if (aceTables == null || aceTables.isEmpty()) {
+            return null;
+        }
+
+        return (String) aceTables.get(0).get(Constants.KEYFIELD_ACE_ID);
+    }
+
+    private ArrayList<HashMap<String, Object>> getAceTable(
+            HashMap<String, Object> condition) {
+        return AccountDBManager.getInstance().selectRecord(Constants.ACE_TABLE,
+                condition);
+    }
+
+    private String extractHref(String href) {
+
+        List<String> segment = new ArrayList<String>(
+                Arrays.asList(href.split("/")));
+
+        // Remove prefix path
+        segment.remove(0);
+        segment.remove(0);
+        segment.remove(0);
+
+        StringBuilder uriPath = new StringBuilder();
+        for (String path : segment) {
+            uriPath.append("/" + path);
+        }
+
+        return uriPath.toString();
+    }
+
+    private void setGroupInfo(String gid, HashMap<String, Object> keyValue) {
+
+        GroupTable groupTable = new GroupTable();
+        groupTable.setGid(gid);
+        for (String key : keyValue.keySet()) {
+            groupTable.setPropertyValue(key, keyValue.get(key));
+        }
+
+        TypeCastingManager<GroupTable> typeGroup = new TypeCastingManager<GroupTable>();
+        AccountDBManager.getInstance().insertAndReplaceRecord(
+                Constants.GROUP_TABLE,
+                typeGroup.convertObjectToMap(groupTable));
+    }
+}