@Override
  public UserResult createUsers(String instanceId, List<User> users, User requestingUser) {
    logger.info("Create users for service instance with ID {}.", instanceId);

    ServiceInstance instance = null;

    try {

      instance = instanceDAO.getInstanceById(instanceId);

      checkInstanceAvailability(instance);

      final APPlatformController controller =
          APPlatformControllerFactory.getInstance(instance.getControllerId());
      final ProvisioningSettings settings =
          configService.getProvisioningSettings(instance, UserMapper.toServiceUser(requestingUser));

      // Forward request
      final InstanceStatusUsers status =
          controller.createUsers(instance.getInstanceId(), settings, mapToServiceUsers(users));
      if (status != null) {
        // get modified users
        if (status.getChangedUsers() != null) {
          // merge returned users with existing users
          mergeServiceUsers(users, status.getChangedUsers());
        }

        // forward call to provisioning service on application instance
        if (status.isInstanceProvisioningRequested()) {
          final ProvisioningService provisioning = provisioningFactory.getInstance(instance);
          final UserResult result = provisioning.createUsers(instanceId, users, requestingUser);
          if (provResult.isError(result)) {
            return result;
          }

          // Get modified users
          if (result.getUsers() != null) {
            users = result.getUsers();
          }
        }

        // If everything worked well we will save all changed parameters
        instance.setInstanceParameters(status.getChangedParameters());
      }

      instance.setProvisioningStatus(ProvisioningStatus.WAITING_FOR_USER_CREATION);
      em.persist(instance);

      timerService.initTimers();

      final UserResult result = provResult.getOKResult(UserResult.class);
      result.setUsers(users);
      return result;

    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
      return provResult.getErrorResult(
          UserResult.class, e, getLocale(requestingUser), instance, instanceId);
    }
  }
  InstanceDescription getInstanceDescription(InstanceRequest request, User requestingUser)
      throws APPlatformException, BadResultException {
    final HashMap<String, String> parameters = createParameterMap(request.getParameterValue());
    String controllerId = parameters.get(InstanceParameter.CONTROLLER_ID);
    if (controllerId == null) {
      logger.warn("The technical service does not define a controller implementation");
      throw new BadResultException(Messages.get(request.getDefaultLocale(), "error_configuration"));
    }

    HashMap<String, String> controllerSettings =
        configService.getControllerConfigurationSettings(controllerId);
    final ProvisioningSettings settings =
        new ProvisioningSettings(parameters, controllerSettings, request.getDefaultLocale());
    settings.setOrganizationId(request.getOrganizationId());
    settings.setOrganizationName(request.getOrganizationName());
    settings.setSubscriptionId(request.getSubscriptionId());
    settings.setBesLoginUrl(request.getLoginUrl());

    ServiceInstance si = new ServiceInstance();
    si.setInstanceParameters(createParameters(si, parameters));
    si.setControllerId(controllerId);

    settings.setAuthentication(
        configService.getAuthenticationForBESTechnologyManager(controllerId, si, null));
    configService.copyCredentialsFromControllerSettings(settings, controllerSettings);
    settings.setRequestingUser(UserMapper.toServiceUser(requestingUser));

    final APPlatformController controller = APPlatformControllerFactory.getInstance(controllerId);

    final InstanceDescription descr = controller.createInstance(settings);

    // Check whether instanceId is filled and unique
    if (Strings.isEmpty(descr.getInstanceId())) {
      logger.error("Instance ID not specified by controller.");
      throw new BadResultException(
          Messages.get(request.getDefaultLocale(), "error_instanceid_empty"));
    }
    if (instanceDAO.exists(descr.getInstanceId())) {
      logger.error("Instance ID " + descr.getInstanceId() + " already used by another instance.");
      throw new BadResultException(
          Messages.get(
              request.getDefaultLocale(), "error_instanceid_exists", descr.getInstanceId()));
    }
    return descr;
  }
  @Override
  public BaseResult deactivateInstance(String instanceId, User requestingUser) {
    logger.info("Deactivate instance {}.", instanceId);
    ServiceInstance instance = null;

    try {

      instance = instanceDAO.getInstanceById(instanceId);

      checkInstanceAvailability(instance);

      final APPlatformController controller =
          APPlatformControllerFactory.getInstance(instance.getControllerId());
      final ProvisioningSettings settings =
          configService.getProvisioningSettings(instance, UserMapper.toServiceUser(requestingUser));

      // Forward request
      final InstanceStatus status =
          controller.deactivateInstance(instance.getInstanceId(), settings);
      if (status != null) {
        // forward call to provisioning service on application instance
        if (status.isInstanceProvisioningRequested()) {
          final ProvisioningService provisioning = provisioningFactory.getInstance(instance);
          final BaseResult result = provisioning.deactivateInstance(instanceId, requestingUser);
          if (provResult.isError(result)) {
            return result;
          }
        }

        // If everything worked well we will save all changed parameters
        instance.setInstanceParameters(status.getChangedParameters());
      }

      // Update current state
      instance.setProvisioningStatus(ProvisioningStatus.WAITING_FOR_SYSTEM_DEACTIVATION);
      em.persist(instance);

      timerService.initTimers();

      return provResult.newOkBaseResult();

    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
      return provResult.getErrorResult(
          BaseResult.class, e, getLocale(requestingUser), instance, instanceId);
    }
  }
  private BaseResult modifySubscription(
      String instanceId,
      String subscriptionId,
      List<ServiceParameter> parameterValues,
      final HashMap<String, String> parameterMap,
      ProvisioningStatus targetStatus,
      User requestingUser) {

    ServiceInstance instance = null;

    try {
      instance = instanceDAO.getInstanceById(instanceId);

      instance.prepareRollback();

      checkInstanceAvailability(instance);

      final HashMap<String, String> controllerSettings =
          configService.getControllerConfigurationSettings(instance.getControllerId());
      final APPlatformController controller =
          APPlatformControllerFactory.getInstance(instance.getControllerId());

      final ProvisioningSettings currentSettings =
          configService.getProvisioningSettings(instance, UserMapper.toServiceUser(requestingUser));
      final ProvisioningSettings newSettings =
          new ProvisioningSettings(parameterMap, controllerSettings, instance.getDefaultLocale());
      newSettings.setAuthentication(currentSettings.getAuthentication());
      configService.copyCredentialsFromControllerSettings(newSettings, controllerSettings);
      newSettings.setRequestingUser(UserMapper.toServiceUser(requestingUser));
      newSettings.setSubscriptionId(subscriptionId);

      // Forward modification request
      final InstanceStatus status =
          controller.modifyInstance(instance.getInstanceId(), currentSettings, newSettings);
      if (status != null) {
        // forward call to provisioning service on application instance
        if (status.isInstanceProvisioningRequested()) {
          final ProvisioningService provisioning = provisioningFactory.getInstance(instance);
          final List<ServiceParameter> filteredParameters =
              InstanceParameterFilter.getFilteredInstanceParametersForService(parameterValues);
          final BaseResult result =
              provisioning.modifySubscription(
                  instanceId, subscriptionId, filteredParameters, requestingUser);
          if (provResult.isError(result)) {
            return result;
          }
        }

        // If everything worked well we will save all changed parameters
        instance.setInstanceParameters(status.getChangedParameters());
      }

      instance.setProvisioningStatus(targetStatus);
      instance.setSubscriptionId(subscriptionId);
      em.persist(instance);

      timerService.initTimers();

      return provResult.newOkBaseResult();
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
      return provResult.getErrorResult(
          BaseResult.class, e, getLocale(requestingUser), instance, instanceId);
    }
  }