@Test
  public void whenInsertDuplicatesInMultiSet_thenInserted() {
    final Multiset<String> names = HashMultiset.create();
    names.add("John");
    names.add("Adam", 3);
    names.add("John");

    assertEquals(2, names.count("John"));
    names.remove("John");
    assertEquals(1, names.count("John"));

    assertEquals(3, names.count("Adam"));
    names.remove("Adam", 2);
    assertEquals(1, names.count("Adam"));
  }
 public void testCreateWithSize() {
   Multiset<String> multiset = HashMultiset.create(50);
   multiset.add("foo", 2);
   multiset.add("bar");
   assertEquals(3, multiset.size());
   assertEquals(2, multiset.count("foo"));
 }
 public void testCreateWithComparator() {
   Multiset<String> multiset = TreeMultiset.create(Collections.reverseOrder());
   multiset.add("foo", 2);
   multiset.add("bar");
   assertEquals(3, multiset.size());
   assertEquals(2, multiset.count("foo"));
   assertEquals("[foo x 2, bar]", multiset.toString());
 }
 @Override
 public int count(Object element) {
   int count = unfiltered.count(element);
   if (count > 0) {
     @SuppressWarnings("unchecked") // element is equal to an E
     E e = (E) element;
     return predicate.apply(e) ? count : 0;
   }
   return 0;
 }
  /** An implementation of {@link Multiset#setCount(Object, int, int)}. */
  static <E> boolean setCountImpl(Multiset<E> self, E element, int oldCount, int newCount) {
    checkNonnegative(oldCount, "oldCount");
    checkNonnegative(newCount, "newCount");

    if (self.count(element) == oldCount) {
      self.setCount(element, newCount);
      return true;
    } else {
      return false;
    }
  }
 /**
  * Returns {@code true} if {@code subMultiset.count(o) <= superMultiset.count(o)} for all {@code
  * o}.
  *
  * @since 10.0
  */
 public static boolean containsOccurrences(Multiset<?> superMultiset, Multiset<?> subMultiset) {
   checkNotNull(superMultiset);
   checkNotNull(subMultiset);
   for (Entry<?> entry : subMultiset.entrySet()) {
     int superCount = superMultiset.count(entry.getElement());
     if (superCount < entry.getCount()) {
       return false;
     }
   }
   return true;
 }
  /** An implementation of {@link Multiset#setCount(Object, int)}. */
  static <E> int setCountImpl(Multiset<E> self, E element, int count) {
    checkNonnegative(count, "count");

    int oldCount = self.count(element);

    int delta = count - oldCount;
    if (delta > 0) {
      self.add(element, delta);
    } else if (delta < 0) {
      self.remove(element, -delta);
    }

    return oldCount;
  }
  /**
   * For each occurrence of an element {@code e} in {@code occurrencesToRemove}, removes one
   * occurrence of {@code e} in {@code multisetToModify}.
   *
   * <p>Equivalently, this method modifies {@code multisetToModify} so that {@code
   * multisetToModify.count(e)} is set to {@code Math.max(0, multisetToModify.count(e) -
   * occurrencesToRemove.count(e))}.
   *
   * <p>This is <i>not</i> the same as {@code multisetToModify.} {@link Multiset#removeAll
   * removeAll}{@code (occurrencesToRemove)}, which removes all occurrences of elements that appear
   * in {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent to, albeit
   * sometimes more efficient than, the following:
   *
   * <pre>{@code
   * for (E e : occurrencesToRemove) {
   *   multisetToModify.remove(e);
   * }
   * }</pre>
   *
   * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
   * @since 10.0 (missing in 18.0 when only the overload taking an {@code Iterable} was present)
   */
  public static boolean removeOccurrences(
      Multiset<?> multisetToModify, Multiset<?> occurrencesToRemove) {
    checkNotNull(multisetToModify);
    checkNotNull(occurrencesToRemove);

    boolean changed = false;
    Iterator<? extends Entry<?>> entryIterator = multisetToModify.entrySet().iterator();
    while (entryIterator.hasNext()) {
      Entry<?> entry = entryIterator.next();
      int removeCount = occurrencesToRemove.count(entry.getElement());
      if (removeCount >= entry.getCount()) {
        entryIterator.remove();
        changed = true;
      } else if (removeCount > 0) {
        multisetToModify.remove(entry.getElement(), removeCount);
        changed = true;
      }
    }
    return changed;
  }
 /** Delegate implementation which cares about the element type. */
 private static <E> boolean retainOccurrencesImpl(
     Multiset<E> multisetToModify, Multiset<?> occurrencesToRetain) {
   checkNotNull(multisetToModify);
   checkNotNull(occurrencesToRetain);
   // Avoiding ConcurrentModificationExceptions is tricky.
   Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
   boolean changed = false;
   while (entryIterator.hasNext()) {
     Entry<E> entry = entryIterator.next();
     int retainCount = occurrencesToRetain.count(entry.getElement());
     if (retainCount == 0) {
       entryIterator.remove();
       changed = true;
     } else if (retainCount < entry.getCount()) {
       multisetToModify.setCount(entry.getElement(), retainCount);
       changed = true;
     }
   }
   return changed;
 }
  /** An implementation of {@link Multiset#equals}. */
  static boolean equalsImpl(Multiset<?> multiset, Object object) {
    if (object == multiset) {
      return true;
    }
    if (object instanceof Multiset) {
      Multiset<?> that = (Multiset<?>) object;
      /*
       * We can't simply check whether the entry sets are equal, since that
       * approach fails when a TreeMultiset has a comparator that returns 0
       * when passed unequal elements.
       */

      if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) {
        return false;
      }
      for (Entry<?> entry : that.entrySet()) {
        if (multiset.count(entry.getElement()) != entry.getCount()) {
          return false;
        }
      }
      return true;
    }
    return false;
  }
 public void testCreateFromIterable() {
   Multiset<String> multiset = HashMultiset.create(Arrays.asList("foo", "bar", "foo"));
   assertEquals(3, multiset.size());
   assertEquals(2, multiset.count("foo"));
 }
 public void testCreateFromIterable() {
   Multiset<String> multiset = TreeMultiset.create(Arrays.asList("foo", "bar", "foo"));
   assertEquals(3, multiset.size());
   assertEquals(2, multiset.count("foo"));
   assertEquals("[bar, foo x 2]", multiset.toString());
 }
  /**
   * The core scoring method for statistics queries
   *
   * @param statisticsQuery query to be peformed on statisticsStorage
   * @param statisticsStorage core data for Statistics qeries
   * @param scoringExps an out parameter.
   *     <p>- If null, experiment counts result of statisticsQuery should be returned. if - If
   *     non-null, it serves as a flag that an optimised statisticsQuery should be performed to just
   *     collect Experiments for which non-zero counts exist for Statistics query. A typical call
   *     scenario in this case is just one efv per statisticsQuery, in which we can both: 1. check
   *     if the efv Attribute itself is a scoring one 2. map this Attribute and Experimeants in
   *     scoringExps to efo terms - via the reverse mapping efv-experiment-> efo term in EfoIndex
   *     (c.f. atlasStatisticsQueryService.getScoringAttributesForGenes())
   * @return Multiset of aggregated experiment counts, where the set of scores genes is intersected
   *     across statisticsQuery.getConditions(), and union-ed across attributes within each
   *     condition in statisticsQuery.getConditions().
   */
  public static Multiset<Integer> scoreQuery(
      StatisticsQueryCondition statisticsQuery,
      final StatisticsStorage statisticsStorage,
      Set<ExperimentInfo> scoringExps) {

    // gatherScoringExpsOnly -> experiment counts should be calculated for statisticsQuery
    // !gatherScoringExpsOnly -> scoring experiments should be collected (into scoringExps) only
    boolean gatherScoringExpsOnly = scoringExps != null;
    Set<StatisticsQueryOrConditions<StatisticsQueryCondition>> andStatisticsQueryConditions =
        statisticsQuery.getConditions();

    Multiset<Integer> results = null;

    if (andStatisticsQueryConditions.isEmpty()) { // End of recursion
      Set<Integer> bioEntityIdRestrictionSet = statisticsQuery.getBioEntityIdRestrictionSet();

      Set<EfAttribute> attributes = statisticsQuery.getAttributes();
      if (attributes.isEmpty()) {

        // No attributes were provided - we have to use pre-computed scores across all attributes
        Multiset<Integer> scoresAcrossAllEfos =
            statisticsStorage.getScoresAcrossAllEfos(statisticsQuery.getStatisticsType());
        results = intersect(scoresAcrossAllEfos, bioEntityIdRestrictionSet);
      } else {
        results = HashMultiset.create();
        setQueryExperiments(statisticsQuery, statisticsStorage);

        // For each experiment in the query, traverse through all attributes and add all gene
        // indexes into one ConciseSet. This way a gene can score
        // only once for a single experiment - across all OR attributes in this query. Once all
        // attributes have been traversed for a single experiment,
        // add ConciseSet to Multiset results
        for (ExperimentInfo exp : statisticsQuery.getExperiments()) {
          FastSet statsForExperiment = new FastSet();
          for (EfAttribute attr : attributes) {
            Map<ExperimentInfo, ConciseSet> expsToStats =
                getStatisticsForAttribute(
                    statisticsQuery.getStatisticsType(), attr, statisticsStorage);
            if (expsToStats != null) {
              if (expsToStats.isEmpty()) {
                log.debug(
                    "Failed to retrieve stats for stat: "
                        + statisticsQuery.getStatisticsType()
                        + " and attr: "
                        + attr);
              } else {
                if (expsToStats.get(exp) != null) {
                  if (!gatherScoringExpsOnly) {
                    statsForExperiment.addAll(
                        intersect(expsToStats.get(exp), bioEntityIdRestrictionSet));
                  } else if (containsAtLeastOne(expsToStats.get(exp), bioEntityIdRestrictionSet)) {
                    // exp contains at least one non-zero score for at least one gene index in
                    // bioEntityIdRestrictionSet -> add it to scoringExps
                    scoringExps.add(exp);
                  }
                } else {
                  log.debug(
                      "Failed to retrieve stats for stat: "
                          + statisticsQuery.getStatisticsType()
                          + " exp: "
                          + exp.getAccession()
                          + " and attr: "
                          + attr);
                }
              }
            }
          }
          if (!gatherScoringExpsOnly) {
            results.addAll(statsForExperiment);
          }
        }
      }
    } else {
      // run over all AND conditions, do "OR" inside (cf. scoreOrStatisticsQueryConditions()) ,
      // "AND"'ing over the whole thing
      for (StatisticsQueryOrConditions<StatisticsQueryCondition> orConditions :
          andStatisticsQueryConditions) {

        // Pass gene restriction set down to orConditions
        orConditions.setGeneRestrictionSet(statisticsQuery.getBioEntityIdRestrictionSet());
        // process OR conditions
        Multiset<Integer> condGenes =
            getScoresForOrConditions(orConditions, statisticsStorage, scoringExps);

        if (results == null) results = condGenes;
        else {
          Iterator<Multiset.Entry<Integer>> resultGenes = results.entrySet().iterator();

          while (resultGenes.hasNext()) {
            Multiset.Entry<Integer> entry = resultGenes.next();
            if (!condGenes.contains(
                entry.getElement())) // AND operation between different top query conditions
            resultGenes.remove();
            else
              // for all gene ids belonging to intersection of all conditions seen so far, we
              // accumulate experiment counts
              results.setCount(
                  entry.getElement(), entry.getCount() + condGenes.count(entry.getElement()));
          }
        }
      }
    }

    if (results == null) {
      results = HashMultiset.create();
    }
    return results;
  }