/**
   * Updates an existing {@link UdaDefinition} - if it was not found, nothing will be done. Checks
   * if the caller is the owner, performs business key uniqueness check if the id has changed and
   * validates the passed {@link VOUdaDefinition}.
   *
   * @param voDef the updated {@link VOUdaDefinition}
   * @param owner the owning {@link Organization}
   * @throws OperationNotPermittedException in case the calling {@link Organization} is not the
   *     owner
   * @throws ValidationException in case the passed {@link VOUdaDefinition} is invalid
   * @throws ConcurrentModificationException in case the {@link UdaDefinition} to update has been
   *     changed concurrently
   * @throws NonUniqueBusinessKeyException in case the change leads to a non-unique business key
   * @throws ObjectNotFoundException in case the {@link UdaDefinition} to update was not found
   */
  void updateDefinition(VOUdaDefinition voDef, Organization owner)
      throws OperationNotPermittedException, ValidationException, ConcurrentModificationException,
          NonUniqueBusinessKeyException, ObjectNotFoundException {

    UdaDefinition existing = ds.getReference(UdaDefinition.class, voDef.getKey());
    PermissionCheck.owns(existing, owner, logger, ctx);
    // target type and encryption flag must not be changed as it will cause
    // inconsistencies for all depending UDAs

    voDef.setTargetType(existing.getTargetType().name());
    voDef.setEncrypted(existing.isEncrypted());

    // verify business key uniqueness
    UdaDefinition tempForUniquenessCheck = null;
    tempForUniquenessCheck = UdaAssembler.toUdaDefinition(voDef);

    tempForUniquenessCheck.setOrganization(owner);
    tempForUniquenessCheck.setKey(existing.getKey());
    try {
      ds.validateBusinessKeyUniqueness(tempForUniquenessCheck);
      UdaAssembler.updateUdaDefinition(existing, voDef);
    } catch (NonUniqueBusinessKeyException e) {
      logger.logWarn(
          Log4jLogger.SYSTEM_LOG,
          e,
          LogMessageIdentifier.WARN_NON_UNIQUE_BUSINESS_KEY_UDA_DEFINITION);
      ctx.setRollbackOnly();
      throw e;
    }
  }
  /**
   * Deletes the passed list of {@link VOUdaDefinition}s - ignores the ones that are not found. For
   * the found ones, access permission and concurrent modification checks will be performed.
   *
   * @param defs the {@link VOUdaDefinition} to delete
   * @param caller the calling {@link Organization}
   * @throws OperationNotPermittedException
   * @throws ConcurrentModificationException
   */
  public void deleteUdaDefinitions(List<VOUdaDefinition> defs, Organization caller)
      throws OperationNotPermittedException, ConcurrentModificationException {

    for (VOUdaDefinition voDef : defs) {
      UdaDefinition existing = ds.find(UdaDefinition.class, voDef.getKey());
      if (existing == null) {
        // already deleted
        continue;
      }
      PermissionCheck.owns(existing, caller, logger, ctx);
      UdaAssembler.verifyVersionAndKey(existing, voDef);
      // cascade rule will cause deletion of udas as well
      ds.remove(existing);
    }
  }
 /**
  * Returns the SupportedCurrency domain object for the given currency code. Creates the object if
  * needed.
  */
 public static SupportedCurrency findOrCreate(DataService mgr, String currencyCode)
     throws NonUniqueBusinessKeyException {
   SupportedCurrency result = (SupportedCurrency) mgr.find(new SupportedCurrency(currencyCode));
   if (result == null) {
     result = persistCurrency(mgr, currencyCode);
   }
   return result;
 }
 @Override
 protected void setup(TestContainer container) {
   container.enableInterfaceMocking(true);
   dsMock = mock(DataService.class);
   when(dsMock.getCurrentUser()).thenReturn(givenUser());
   localizerMock = mock(LocalizerServiceLocal.class);
   when(localizerMock.getLocalizedTextFromDatabase(
           Mockito.anyString(), Mockito.anyLong(), Mockito.any(LocalizedObjectTypes.class)))
       .thenReturn(LOCALIZED_RESOURCE);
   logCollector.localizer = localizerMock;
 }
  /**
   * Persists that passed {@link UdaDefinition} and checks the business key uniqueness.
   *
   * @param def the {@link UdaDefinition} to persist
   * @throws NonUniqueBusinessKeyException in case a {@link UdaDefinition} with the same id and
   *     target type exist for the owning {@link Organization}
   */
  void createDefinition(UdaDefinition def) throws NonUniqueBusinessKeyException {

    try {
      ds.persist(def);
    } catch (NonUniqueBusinessKeyException e) {
      logger.logWarn(
          Log4jLogger.SYSTEM_LOG,
          e,
          LogMessageIdentifier.WARN_NON_UNIQUE_BUSINESS_KEY_UDA_DEFINITION);
      ctx.setRollbackOnly();
      throw e;
    }
  }
 @Before
 public void setup() throws Exception {
   dsMock = mock(DataService.class);
   Organization org = new Organization();
   org.setOrganizationId(ORGANIZATIONID);
   PlatformUser user = new PlatformUser();
   user.setUserId(USERID_1);
   user.setLocale("en");
   user.setOrganization(org);
   when(dsMock.getCurrentUser()).thenReturn(user);
   marketplace = new Marketplace();
   marketplace.setKey(1000l);
   doReturn(marketplace).when(dsMock).getReferenceByBusinessKey(any(Marketplace.class));
 }
  /**
   * Tries to save the passed list of {@link VOUdaDefinition}s. Checks if the passed values are
   * valid and permitted to be accessed.
   *
   * @param defs the {@link VOUdaDefinition}s to save
   * @param caller the calling (owning) {@link Organization}
   * @throws ValidationException in case of an invalid {@link VOUdaDefinition}
   * @throws OrganizationAuthoritiesException in case the calling {@link Organization} has
   *     insufficient roles to create {@link UdaDefinition}s of the set {@link UdaTargetType}.
   * @throws NonUniqueBusinessKeyException in case a {@link UdaDefinition} with the passed id and
   *     target type already exists for the owning {@link Organization}
   * @throws OperationNotPermittedException in case it was tries to update a {@link UdaDefinition}
   *     owned by another {@link Organization}.
   * @throws ConcurrentModificationException in case the {@link UdaDefinition} to update was
   *     concurrently changed
   * @throws ObjectNotFoundException in case on of the {@link UdaDefinition}s to update was not
   *     found
   */
  public void saveUdaDefinitions(List<VOUdaDefinition> defs, Organization caller)
      throws ValidationException, OrganizationAuthoritiesException, NonUniqueBusinessKeyException,
          OperationNotPermittedException, ConcurrentModificationException, ObjectNotFoundException {

    for (VOUdaDefinition voDef : defs) {
      // convert and validate
      UdaDefinition def;
      try {
        def = UdaAssembler.toUdaDefinition(voDef);
        def.setOrganization(caller);
      } catch (ValidationException e) {
        logger.logWarn(
            Log4jLogger.SYSTEM_LOG,
            e,
            LogMessageIdentifier.WARN_INVALID_UDA_DEFINITION,
            voDef.getUdaId());
        ctx.setRollbackOnly();
        throw e;
      }
      // check if target type is allowed for organization
      UdaTargetType type = def.getTargetType();
      if (!type.canSaveDefinition(caller.getGrantedRoleTypes())) {
        String roles = rolesToString(type.getRoles());
        OrganizationAuthoritiesException e =
            new OrganizationAuthoritiesException(
                "Insufficient authorization. Required role(s) '" + roles + "'.",
                new Object[] {roles});
        logger.logWarn(
            Log4jLogger.SYSTEM_LOG | Log4jLogger.AUDIT_LOG,
            e,
            LogMessageIdentifier.WARN_ORGANIZATION_ROLE_REQUIRED,
            Long.toString(caller.getKey()),
            roles);
        ctx.setRollbackOnly();
        throw e;
      }
      if (voDef.getKey() > 0) {
        updateDefinition(voDef, caller);
      } else {
        createDefinition(def);
      }
      UdaDefinition storedUda = (UdaDefinition) ds.find(def);
      if (storedUda == null) {
        return;
      }
      storeLocalizedAttributeName(storedUda.getKey(), voDef.getName(), voDef.getLanguage());
    }
  }
 private static SupportedCurrency persistCurrency(DataService mgr, String currencyCode)
     throws NonUniqueBusinessKeyException {
   SupportedCurrency currency = new SupportedCurrency(currencyCode);
   mgr.persist(currency);
   return currency;
 }
  @Before
  public void setup() throws Exception {
    ds = mock(DataService.class);

    pt = new PaymentType();
    pt.setPaymentTypeId(PaymentType.INVOICE);
    pt.setKey(12345);

    Organization op = new Organization();
    op.setOrganizationId(OrganizationRoleType.PLATFORM_OPERATOR.name());

    supplier = new Organization();
    supplier.setOrganizationId("supplier");
    Organizations.grantOrganizationRole(supplier, OrganizationRoleType.SUPPLIER);

    reseller = new Organization();
    reseller.setOrganizationId("reseller");
    Organizations.grantOrganizationRole(reseller, OrganizationRoleType.RESELLER);

    OrganizationReference ref =
        OrganizationReferences.addReference(
            op, supplier, OrganizationReferenceType.PLATFORM_OPERATOR_TO_SUPPLIER);
    OrganizationReferences.enablePayment(ref, pt)
        .setOrganizationRole(new OrganizationRole(OrganizationRoleType.SUPPLIER));

    ref =
        OrganizationReferences.addReference(
            op, reseller, OrganizationReferenceType.PLATFORM_OPERATOR_TO_RESELLER);
    OrganizationReferences.enablePayment(ref, pt)
        .setOrganizationRole(new OrganizationRole(OrganizationRoleType.RESELLER));

    customer = new Organization();
    customer.setOrganizationId("customer");

    noCustomer = new Organization();
    noCustomer.setOrganizationId("noCustomer");

    ref =
        OrganizationReferences.addReference(
            supplier, customer, OrganizationReferenceType.SUPPLIER_TO_CUSTOMER);
    OrganizationReferences.enablePayment(ref, pt);

    ref =
        OrganizationReferences.addReference(
            reseller, customer, OrganizationReferenceType.RESELLER_TO_CUSTOMER);
    OrganizationReferences.enablePayment(ref, pt);

    product = new Product();
    product.setKey(9876);
    product.setVendor(supplier);
    product.setType(ServiceType.TEMPLATE);
    product.setPaymentTypes(Arrays.asList(new ProductToPaymentType(product, pt)));

    pcf = new PaymentConfigurationFilter(ds);

    user = new PlatformUser();
    user.setOrganization(supplier);

    when(ds.getCurrentUser()).thenReturn(user);
    when(ds.getReference(eq(Product.class), eq(product.getKey()))).thenReturn(product);
    when(ds.getReference(eq(Product.class), eq(PROD_NOT_FOUND_KEY)))
        .thenThrow(new ObjectNotFoundException(ClassEnum.SERVICE, "product"));

    when(ds.getReferenceByBusinessKey(any(DomainObject.class)))
        .thenAnswer(
            new Answer<DomainObject<?>>() {

              public DomainObject<?> answer(InvocationOnMock invocation) throws Throwable {
                Object object = invocation.getArguments()[0];
                if (object instanceof Organization) {
                  Organization o = (Organization) object;
                  if (customer.getOrganizationId().equals(o.getOrganizationId())) {
                    return customer;
                  }
                  if (noCustomer.getOrganizationId().equals(o.getOrganizationId())) {
                    return noCustomer;
                  }
                  throw new ObjectNotFoundException(ClassEnum.ORGANIZATION, o.getOrganizationId());
                }
                throw new ObjectNotFoundException(
                    ClassEnum.ORGANIZATION, object.getClass().getName());
              }
            });
  }
  /**
   * Sets all values back to null, setting the chargeable information to false. As modifications to
   * the list of priced events have no effect, these objects stay untouched. Prices of selected
   * parameters and if existing their options will be set to 0.
   *
   * @return The modified price model.
   */
  public PriceModel resetToNonChargeable() {

    priceModel.setType(PriceModelType.FREE_OF_CHARGE);
    priceModel.setPeriod(null);
    priceModel.setPricePerPeriod(BigDecimal.ZERO);
    priceModel.setPricePerUserAssignment(BigDecimal.ZERO);
    priceModel.setCurrency(null);
    priceModel.setOneTimeFee(BigDecimal.ZERO);

    // handle events
    List<PricedEvent> events = priceModel.getConsideredEvents();
    for (PricedEvent pricedEvent : events) {
      pricedEvent.setHistoryModificationTime(txnTime);
      List<SteppedPrice> steppedPrices = pricedEvent.getSteppedPrices();
      for (SteppedPrice price : steppedPrices) {
        price.setHistoryModificationTime(txnTime);
      }
      mgr.remove(pricedEvent);
    }
    events.clear();

    // handle parameters
    List<PricedParameter> selectedParameters = priceModel.getSelectedParameters();
    for (PricedParameter pricedParameter : selectedParameters) {
      pricedParameter.setHistoryModificationTime(txnTime);
      List<SteppedPrice> steppedPrices = pricedParameter.getSteppedPrices();
      for (SteppedPrice price : steppedPrices) {
        price.setHistoryModificationTime(txnTime);
      }
      List<PricedProductRole> roleSpecificUserPrices = pricedParameter.getRoleSpecificUserPrices();
      for (PricedProductRole price : roleSpecificUserPrices) {
        price.setHistoryModificationTime(txnTime);
      }

      List<PricedOption> pricedOptions = pricedParameter.getPricedOptionList();
      for (PricedOption option : pricedOptions) {
        option.setHistoryModificationTime(txnTime);
        List<PricedProductRole> rolePrices = option.getRoleSpecificUserPrices();
        for (PricedProductRole rolePrice : rolePrices) {
          rolePrice.setHistoryModificationTime(txnTime);
        }
      }
      mgr.remove(pricedParameter);
    }
    selectedParameters.clear();

    // handle stepped prices
    List<SteppedPrice> steppedPrices = priceModel.getSteppedPrices();
    for (SteppedPrice steppedPrice : steppedPrices) {
      steppedPrice.setHistoryModificationTime(txnTime);
      mgr.remove(steppedPrice);
    }
    steppedPrices.clear();

    // handle role prices
    List<PricedProductRole> rolePrices = priceModel.getRoleSpecificUserPrices();
    for (PricedProductRole rolePrice : rolePrices) {
      rolePrice.setHistoryModificationTime(txnTime);
      mgr.remove(rolePrice);
    }
    rolePrices.clear();

    return priceModel;
  }