class ConfigurationProcessor implements PayloadProcessor {

    @Override
    public Payload process(Chain chain, Payload payload) {
        // system-level default configuration
        Map<String, Object> defCfg = Collections.emptyMap();
        if (!"concord-v2".equalsIgnoreCase(payload.getHeader(Payload.RUNTIME))) {
            defCfg = defaultCfg.getCfg();
        }

        // default configuration from policy
        Map<String, Object> policyDefCfg = getDefaultCfgFromPolicy(payload);

        // org configuration
        Map<String, Object> orgCfg = getOrgCfg(payload);

        ProjectEntry projectEntry = getProject(payload);

        // project configuration
        Map<String, Object> projectCfg = getProjectCfg(projectEntry);

        // _main.json file in the workspace
        Map<String, Object> workspaceCfg = getWorkspaceCfg(payload);

        // attached to the request JSON file
        Map<String, Object> attachedCfg = getAttachedCfg(payload);

        // existing configuration values from the payload
        Map<String, Object> payloadCfg = payload.getHeader(Payload.CONFIGURATION, Collections.emptyMap());

        // determine the active profile names
        List<String> activeProfiles = ProcessConfigurationUtils.getActiveProfiles(payloadCfg, attachedCfg, workspaceCfg, projectCfg, orgCfg);
        payload = payload.putHeader(Payload.ACTIVE_PROFILES, activeProfiles);

        // merged profile data
        Map<String, Object> profileCfg = getProfileCfg(payload, activeProfiles);

        // automatically provided variables
        Map<String, Object> providedCfg = ProcessConfigurationUtils.prepareProvidedCfg(payload, projectEntry);

        // configuration from the policy
        Map<String, Object> policyCfg = getPolicyCfg(payload);

        // create the resulting configuration
        Map<String, Object> m = ConfigurationUtils.deepMerge(defCfg, policyDefCfg, orgCfg, projectCfg, profileCfg, workspaceCfg, attachedCfg, payloadCfg, providedCfg, policyCfg);
        m.put(Constants.Request.ACTIVE_PROFILES_KEY, activeProfiles);

        payload = payload.putHeader(Payload.CONFIGURATION, m);

        return chain.process(payload);
    }

    @Inject public  ConfigurationProcessor(ProjectDao projectDao, OrganizationDao orgDao, DefaultProcessConfiguration defaultCfg);

}