class AccessTokenRequest {

    public AccessTokenRequest(final String scope) {

        final String[] scopeList = scope.split(" ");

        // the format of our scopes for role access token are:
        // <domainName>:domain
        // <domainName>:role.<roleName>
        // the format of our scopes for openid are:
        // openid <domainName>:service.<serviceName>

        Set<String> scopeRoleNames = new HashSet<>();
        for (String scopeItem : scopeList) {

            // first check if we haven an openid scope requested

            if (OBJECT_OPENID.equalsIgnoreCase(scopeItem)) {
                openidScope = true;
                continue;
            }

            // next check if we have a service scope required by openid

            int idx = scopeItem.indexOf(OBJECT_SERVICE);
            if (idx != -1) {
                final String scopeDomainName = scopeItem.substring(0, idx);
                if (domainName != null && !scopeDomainName.equals(domainName)) {
                    throw error("Multiple domains in scope", scope);
                }
                final String scopeServiceName = scopeItem.substring(idx + OBJECT_SERVICE.length());
                if (serviceName != null && !scopeServiceName.equals(serviceName)) {
                    throw error("Multiple services in scope", scope);
                }
                domainName = scopeDomainName;
                serviceName = scopeServiceName;
                continue;
            }

            // next check if we have a domain scope

            if (scopeItem.endsWith(OBJECT_DOMAIN)) {
                final String scopeDomainName = scopeItem.substring(0, scopeItem.length() - OBJECT_DOMAIN.length());
                if (domainName != null && !scopeDomainName.equals(domainName)) {
                    throw error("Multiple domains in scope", scope);
                }
                domainName = scopeDomainName;
                sendScopeResponse = true;
                continue;
            }

            // finally check if we have a role scope

            idx = scopeItem.indexOf(OBJECT_ROLE);
            if (idx != -1) {
                final String scopeDomainName = scopeItem.substring(0, idx);
                if (domainName != null && !scopeDomainName.equals(domainName)) {
                    throw error("Multiple domains in scope", scope);
                }
                domainName = scopeDomainName;
                scopeRoleNames.add(scopeItem.substring(idx + OBJECT_ROLE.length()));
                continue;
            }

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Skipping unknown scope {}", scopeItem);
            }
        }

        // if we don't have a domain then it's invalid scope

        if (domainName == null || domainName.isEmpty()) {
            throw error("No domains in scope", scope);
        }

        // if the scope response is set to true then we had
        // an explicit request for all roles in the domain
        // so we're going to ignore the role names requested

        if (!sendScopeResponse && !scopeRoleNames.isEmpty()) {
            roleNames = scopeRoleNames;
        }

        // for openid scope we must have the openid scope
        // along with the service name since the audience
        // must be set for that service only

        if (openidScope && (serviceName == null || serviceName.isEmpty())) {
            throw error("No audience service name for openid scope", scope);
        }
    }

    public  AccessTokenRequest(final String scope);

}