class FactorLifecycleServiceImpl implements FactorLifecycleService {

    @Override
    public Factor enroll(FactorType factorType, ProviderType provider, FactorProfile profile, OktaUser user) throws OktaException
    {
        Preconditions.checkNotNull(factorType, "factorType is null");
        Preconditions.checkNotNull(provider, "provider is null");

        if (user != null)
        {
            String apiPath = buildEnrollmentPath(factorType, user);

            // Builds enroll request body
            JSONObject body = new JSONObject();
            body.put(OktaAPIConstants.FACTOR_TYPE, factorType.getFactorType());
            body.put(OktaAPIConstants.PROVIDER, provider.name());
            JSONObject enrollProfile = buildEnrollmentProfile(factorType, profile);
            if (enrollProfile != null && enrollProfile.length() > 0)
            {
                body.put(OktaAPIConstants.PROFILE, enrollProfile);
            }

            ResponseEntity<Factor> exchange = oktaRestService.doRestCall(apiPath, HttpMethod.POST, Factor.class, body.toString());
            if (!exchange.getStatusCode().is2xxSuccessful())
            {
                LOGGER.debug("Failed to enroll factor [{}, {}]", ErrorResponse.class.cast(exchange.getBody()).getErrorSummary(),
                        ErrorResponse.class.cast(exchange.getBody()).getErrorId());
                throw new OktaException(buildErrorMessage(exchange.getBody()));
            }

            return exchange.getBody();
        }
        return null;
    }

}