private double computeFactorForUsageDetails(UsageDetails usageDetails, PricingPeriod period) {
    double factor = 0.0D;

    for (UsageDetails.UsagePeriod usagePeriod : usageDetails.getUsagePeriods()) {
      factor +=
          computeFractionalFactor(usagePeriod.getStartTime(), usagePeriod.getEndTime(), period);
    }

    return factor;
  }
  @Override
  public UserAssignmentFactors computeUserAssignmentsFactors(
      List<UsageLicenseHistory> ulHistList,
      PriceModelHistory referencePMHistory,
      BillingInput billingInput,
      long periodStart,
      long periodEnd) {

    // now determine the billable period for every user
    final UserAssignmentFactors result = new UserAssignmentFactors();
    Long referenceUserKey = null;
    long periodEndTime = periodEnd;
    for (UsageLicenseHistory ulHist : ulHistList) {
      if (referenceUserKey == null || referenceUserKey.longValue() != ulHist.getUserObjKey()) {
        // if a new user has to be handled, only reset the
        // temporary variables
        referenceUserKey = Long.valueOf(ulHist.getUserObjKey());
        periodEndTime = periodEnd;
      }

      // if the status is not deleted, register the used period,
      // which is from mod date to period end time
      if (ulHist.getModtype() != ModificationType.DELETE) {
        long entryModTime = ulHist.getModdate().getTime();
        UsageDetails ud = new UsageDetails();
        ud.addUsagePeriod(Math.max(entryModTime, periodStart), periodEndTime);

        if (ulHist.getRoleDefinitionObjKey() != null) {
          result.addUsageDataForUserAndRole(
              referenceUserKey,
              ulHist.getDataContainer().getApplicationUserId(),
              ulHist.getRoleDefinitionObjKey(),
              ud);
        } else {
          result.addUsageDataForUser(
              referenceUserKey, ulHist.getDataContainer().getApplicationUserId(), ud);
        }
      }

      periodEndTime = ulHist.getModdate().getTime();
    }

    // the periods for each user of this subscription have been
    // determined. Now handle them according to the settings in the
    // price model
    Set<Long> userKeys = result.getUserKeys();
    if (userKeys != null) {
      for (Long userKey : userKeys) {
        UserAssignmentDetails userAssignmentDetails = result.getUserAssignmentDetails(userKey);
        final double modifiedFactorForDefinedHandling =
            computeFactorForUsageDetails(
                userAssignmentDetails.getUsageDetails(), referencePMHistory.getPeriod());

        // update in user table for later xml representation
        UsageDetails ud = new UsageDetails();
        ud.setFactor(modifiedFactorForDefinedHandling);
        result.addUsageDataForUser(userKey, userAssignmentDetails.getUserId(), ud);

        // the periods for each user of this subscription have been
        // determined. Now handle them according to the settings in the
        // price model
        for (Long roleKey : userAssignmentDetails.getRoleKeys()) {
          final UsageDetails usageDetails = userAssignmentDetails.getUsageDetails(roleKey);
          final double roleAssignmentFactor =
              computeFactorForUsageDetails(usageDetails, referencePMHistory.getPeriod());
          userAssignmentDetails.addRoleFactor(roleKey, roleAssignmentFactor);
        }
      }
    }
    return result;
  }