//////////////////////////////////////////////////////////////////////////////
  // interface "RecommenderService" implementation
  @Override
  public List<ItemVO<Integer, Integer>> getActionHistory(
      Integer tenantId,
      Integer userId,
      String sessionId,
      Integer consideredActionTypeId,
      Integer consideredItemTypeId,
      Double ratingThreshold,
      Integer numberOfLastActionsConsidered) {
    List<ItemVO<Integer, Integer>> itemsActedOn =
        actionService.getItemsByUserActionAndType(
            tenantId,
            userId,
            sessionId,
            consideredActionTypeId,
            consideredItemTypeId,
            ratingThreshold,
            numberOfLastActionsConsidered);

    return itemsActedOn;
  }
  private List<RecommendedItemVO<Integer, Integer>> doFiltering(
      Integer tenantId,
      Integer userId,
      String sessionId,
      Integer actionTypeId,
      Integer itemTypeId,
      List<RecommendedItemVO<Integer, Integer>> recommendedItems,
      boolean useAveragePredictionValues) {
    // filter duplicates
    recommendedItems = filterDuplicates(recommendedItems, useAveragePredictionValues);

    // filter out shortly acted on items
    List<ItemVO<Integer, Integer>> itemsActedOn = null;
    if (userId != null || sessionId != null) {
      itemsActedOn =
          actionService.getItemsByUserActionAndType(
              tenantId, userId, sessionId, actionTypeId, itemTypeId, null, null);
    }

    if (itemsActedOn != null && itemsActedOn.size() > 0) {
      filterAlreadyActedOn(recommendedItems, itemsActedOn);
    }
    return recommendedItems;
  }
  @Override
  public RecommendationVO<Integer, Integer> getItemsBasedOnActionHistory(
      Integer tenantId,
      Integer userId,
      String sessionId,
      Integer consideredActionTypeId,
      Integer consideredItemTypeId,
      Double ratingThreshold,
      Integer numberOfLastActionsConsidered,
      Integer assocTypeId,
      Integer requestedItemTypeId) {
    List<ItemVO<Integer, Integer>> itemsActedOn =
        actionService.getItemsByUserActionAndType(
            tenantId,
            userId,
            sessionId,
            consideredActionTypeId,
            consideredItemTypeId,
            ratingThreshold,
            numberOfLastActionsConsidered);
    List<AssociatedItemVO<Integer, Integer>> currentAssociatedItems;
    List<RecommendedItemVO<Integer, Integer>> allRecommendedItems = null;

    for (ItemVO<Integer, Integer> currentItem : itemsActedOn) {
      currentAssociatedItems =
          itemAssocService.getItemsTo(
              currentItem,
              assocTypeId,
              requestedItemTypeId,
              new IAConstraintVO<Integer, Integer>(
                  maximumNumberOfRelatedItemsPerItem, null, tenantId, true));
      if (currentAssociatedItems != null) {
        if (allRecommendedItems == null) {
          allRecommendedItems = convertAssociatedItems(currentAssociatedItems, currentItem);
        } else {
          allRecommendedItems.addAll(convertAssociatedItems(currentAssociatedItems, currentItem));
        }
      }
    }

    // filter duplicates and history
    if (filterResults) {
      allRecommendedItems =
          doFiltering(
              tenantId,
              userId,
              sessionId,
              consideredActionTypeId,
              requestedItemTypeId,
              allRecommendedItems,
              DEFAULT_USE_AVERAGE_PREDICTION_VALUES_FOR_DUPLICATES);
    }

    // create recommendation object
    RecommendationVO<Integer, Integer> recommendation =
        new RecommendationVO<Integer, Integer>(
            tenantId,
            userId,
            null,
            requestedItemTypeId,
            assocTypeId,
            consideredActionTypeId,
            RECOMMENDATION_STRATEGY_ITEMS_BASED_ON_ACTION_HISTORY,
            EXPLANATION_ITEMS_BASED_ON_ACTION_HISTORY,
            allRecommendedItems);

    // HINT: implement an aspect (instead of directly using this) (Mantis Issue: #650)
    if (recommendationHistoryService != null)
      recommendationHistoryService.insertRecommendation(recommendation);

    return recommendation;
  }