class GroupsDelegator extends BaseDelegator implements IGroupsDelegator {

    @Override
    public List<IUserGroup> getUserGroups(final String userOrGroupName,
            final GetUserGroupsOptions opts) throws P4JavaException {

        List<Map<String, Object>> resultMaps = execMapCmdList(GROUPS,
                Parameters.processParameters(opts, null, userOrGroupName, server), null);

        Map<String, UserGroup> userGroupMap = new HashMap<>();
        if (nonNull(resultMaps)) {
            for (Map<String, Object> map : resultMaps) {
                ResultMapParser.handleErrorStr(map);
                UserGroup ugImpl;
                // The server returns the results not as a series of rows, each
                // row
                // representing a single group, but as a series of rows, each
                // row representing
                // a single *user*, meaning we need to do reverse correlation.
                // At least they come
                // back sorted by group name from the server, but even still,
                // this makes for
                // less than optimal decoding...
                String groupName = parseString(map, MapKeys.GROUP_LC_KEY);
                if (userGroupMap.containsKey(groupName)) {
                    ugImpl = userGroupMap.get(groupName);
                } else {
                    ugImpl = new UserGroup();
                    ugImpl.setName(groupName);
                    userGroupMap.put(groupName, ugImpl);
                }

                try {
                    String userName = parseString(map, MapKeys.USER_LC_KEY);
                    String maxScanRows = parseString(map, MapKeys.MAXSCANROWS_LC_KEY);
                    String maxLockTime = parseString(map, MapKeys.MAXLOCKTIME_LC_KEY);
                    String timeout = parseString(map, MapKeys.TIMEOUT_LC_KEY);
                    String passwordTimeout = parseString(map, MapKeys.PASSWORD_TIMEOUT_LC_KEY);
                    String maxResults = parseString(map, MapKeys.MAXRESULTS_LC_KEY);
                    String isOwner = parseString(map, MapKeys.ISOWNER_LC_KEY);
                    String isSubGroup = parseString(map, MapKeys.ISSUBGROUP_LC_KEY);

                    if ("1".equals(isOwner)) {
                        ugImpl.addOwner(userName);
                    }

                    if ("1".equals(isSubGroup)) {
                        ugImpl.addSubgroup(userName);
                    } else {
                        ugImpl.addUser(userName);
                    }

                    if (isNotBlank(maxScanRows)) {
                        ugImpl.setMaxScanRows(Integer.parseInt(maxScanRows));
                    }

                    if (isNotBlank(maxLockTime)) {
                        ugImpl.setMaxLockTime(Integer.parseInt(maxLockTime));
                    }

                    if (isNotBlank(timeout)) {
                        ugImpl.setTimeout(Integer.parseInt(timeout));
                    }

                    if (isNotBlank(maxResults)) {
                        ugImpl.setMaxResults(Integer.parseInt(maxResults));
                    }

                    if (isNotBlank(passwordTimeout)) {
                        ugImpl.setPasswordTimeout(Integer.parseInt(passwordTimeout));
                    }
                } catch (Throwable thr) {
                    Log.warn("Unexpected exception in ServerImpl.getUserGroups: %s",
                            thr.getMessage());
                    Log.exception(thr);
                }
            }
        }
        return new ArrayList<IUserGroup>(userGroupMap.values());
    }

    public  GroupsDelegator(IOptionsServer server);

}