/**
   * Puts back at the analysis dimension ordinal the initial discriminators that were found
   *
   * @param locations the locations to substitute
   * @param discriminator the initial discriminators that were found
   * @return the changed locations
   */
  protected Set<ILocation> substitute(Set<ILocation> locations, Object[] discriminators) {
    Set<ILocation> result = new HashSet<ILocation>();
    for (ILocation loc : locations) {
      Object[][] matrix = loc.arrayCopy();
      matrix[this.analysisDimensionOrdinal] = discriminators;
      result.add(new Location(matrix));
    }

    // Return the substituted result
    return result;
  }
  @SuppressWarnings("rawtypes")
  protected Set<ILocation> substituteAsPointLocations(ILocation location, Object[] discriminators) {
    Set<ILocation> result = new HashSet<ILocation>(Collections.singleton(location));

    Object[][] matrix;
    for (int i = 0; i < discriminators.length; i++) {

      // Temporary variable to stock the results
      Set<ILocation> tmpResult = new HashSet<ILocation>();
      for (ILocation loc : result) {
        final Object discriminator = discriminators[i];
        if (discriminator == null) {

          // Expand the null location with all the possible members of the
          // analysis dimension
          for (IMember allDiscriminators : this.analysisDimension.retrieveMembers(i)) {
            matrix = loc.arrayCopy();
            matrix[this.analysisDimensionOrdinal][i] =
                ((IAxisMember) allDiscriminators).getDiscriminator();
            tmpResult.add(new Location(matrix));
          }

        } else if (discriminator instanceof Collection) {

          // Expand the collection location with all the members of the location
          for (Object allDiscriminators : ((Collection) discriminator)) {
            matrix = loc.arrayCopy();
            matrix[this.analysisDimensionOrdinal][i] = allDiscriminators;
            tmpResult.add(new Location(matrix));
          }

        } else {

          // Put the the concrete discriminator as it is
          matrix = loc.arrayCopy();
          matrix[this.analysisDimensionOrdinal][i] = discriminator;
          tmpResult.add(new Location(matrix));
        }
      }

      // Export the results to the final variable
      // and clean the temporary variable
      result.clear();
      result.addAll(tmpResult);

      tmpResult.clear();
    }

    // Return the substituted result
    return result;
  }
  @Override
  public IImpact computeImpact(ILocation location, IActivePivotTransactionInfo event) {
    // The results will be stored in these variables
    Set<ILocation> impact = new HashSet<ILocation>();
    Set<ILocation> removedPointCandidates = null;

    // The original location
    Object[][] original = location.arrayCopy();

    // Find the discriminators at the analysis dimension ordinal
    Object[] discriminators = original[this.analysisDimensionOrdinal];

    // Substitute the current discriminator with the null one
    original[this.analysisDimensionOrdinal] = new Object[discriminators.length];

    ILocation rangeLocation = new Location(original);
    try {
      // Compute the added locations
      Set<ILocation> toAdd = event.computeAddedObjectsImpact(Collections.singleton(rangeLocation));

      // Substitute the default discriminator with the original discriminator
      toAdd = substitute(toAdd, discriminators);

      // Add it to the impact
      impact.addAll(toAdd);

      // Compute the locations to remove
      Set<ILocation> toRemove =
          event.computeRemovedObjectsImpact(Collections.singleton(rangeLocation));

      toRemove = substituteAsPointLocations(toRemove, discriminators);

      // add it to the impact
      impact.addAll(toRemove);

      // Update the removed impacts
      removedPointCandidates = toRemove;
    } catch (TransactionException e) {
      throw new QuartetRuntimeException(e);
    }
    return new Impact(location, impact, removedPointCandidates);
  }