private void splitAggregationStoragesAndSend(
      String name, AggregationStorageMetadata metadata, AggregationStorage aggregationStorage) {
    Configuration conf = Configuration.get();

    int numSplits = metadata.getNumSplits();

    if (numSplits == 1) {
      AggregationStorageWrapper aggWrapper = new AggregationStorageWrapper(aggregationStorage);
      super.setAggregatedValue(conf.getAggregationSplitName(name, 0), aggWrapper);
    } else {
      Collection<Writable> keysToTransfer = new ArrayList<>(aggregationStorage.getNumberMappings());

      for (int i = 0; i < numSplits; ++i) {
        AggregationStorage aggStorageSplit =
            aggregationStorageFactory.createAggregationStorage(name);
        AggregationStorageWrapper aggStorageSplitWrapper =
            new AggregationStorageWrapper(aggStorageSplit);

        keysToTransfer.clear();

        for (Object key : aggregationStorage.getKeys()) {
          int owner = key.hashCode() % numSplits;

          if (owner < 0) {
            owner += numSplits;
          }

          if (owner != i) {
            continue;
          }

          keysToTransfer.add((Writable) key);
        }

        for (Writable key : keysToTransfer) {
          aggStorageSplit.transferKeyFrom(key, aggregationStorage);
        }

        super.setAggregatedValue(conf.getAggregationSplitName(name, i), aggStorageSplitWrapper);
      }
    }
  }
  @Override
  public <A extends Writable> void setAggregatedValue(String name, A value) {
    AggregationStorageMetadata metadata = Configuration.get().getAggregationMetadata(name);

    if (metadata == null) {
      super.setAggregatedValue(name, value);
    } else {
      if (!(value instanceof AggregationStorage)) {
        throw new RuntimeException(
            "Value of an Arabesque aggregation should be a subclass of AggregationStorage");
      }

      AggregationStorage aggregationStorage = (AggregationStorage) value;

      splitAggregationStoragesAndSend(name, metadata, aggregationStorage);
    }
  }