model/src/main/java/eu/internetofus/common/model/Merges.java
/**
   * Merge a list field that is mergeable too.
   *
   * @param context          to use.
   * @param fieldName        name of the field to merge.
   * @param target           field value to merge.
   * @param source           field value to merge.
   * @param equalsIdentifier function to check if two models have the same
   *                         identifier.
   * @param setter           function to set the merged field list into the merged
   *                         model.
   *
   * @param <M>              type of merging model.
   * @param <T>              type of the field.
   * @param <C>              type of validation context to use.
   *
   * @return the future that will provide the merged lists.
   */
Merge a list field that is mergeable too.
@param context          to use.
@param fieldName        name of the field to merge.
@param target           field value to merge.
@param source           field value to merge.
@param equalsIdentifier function to check if two models have the same
identifier.
@param setter           function to set the merged field list into the merged
model.

@param               type of merging model.
@param               type of the field.
@param               type of validation context to use.

@return the future that will provide the merged lists.
Merge a list field that is mergeable too . @param context to use . @param fieldName name of the field to merge . @param target field value to merge . @param source field value to merge . @param equalsIdentifier function to check if two models have the same identifier . @param setter function to set the merged field list into the merged model . @param type of merging model . @param type of the field . @param type of validation context to use . @return the future that will provide the merged lists .
static <C extends ValidateContext<C>, M, T extends Mergeable<T, C> & Validable<C>> Function<M, Future<M>> mergeListField(
      final C context, final String fieldName, final List<T> target, final List<T> source,
      final BiPredicate<T, T> equalsIdentifier, final BiConsumer<M, List<T>> setter) {
    return merged -> {
      if (target != null && source != null) {
        final Promise<List<T>> promise = Promise.promise();
        promise.complete(new ArrayList<>());
        var future = promise.future();
        final var copy = new ArrayList<>(target);
        for (final var sourceElement : source) {
          var found = false;
          final var max = copy.size();
          for (var i = 0; i < max; i++) {
            final var targetElement = copy.get(i);
            if (equalsIdentifier.test(targetElement, sourceElement)) {
              copy.remove(i);
              final var elementContext = context.createFieldElementContext(fieldName, i);
              future = future
                  .compose(mergedElements -> targetElement.merge(sourceElement, elementContext).map(mergedElement -> {
                    mergedElements.add(mergedElement);
                    return mergedElements;
                  }));
              found = true;
              break;
            }
          }
          if (!found) {
            future = future.compose(mergedElements -> {
              mergedElements.add(sourceElement);
              return Future.succeededFuture(mergedElements);
            });
          }
        }
        return future.map(mergedElements -> {
          setter.accept(merged, mergedElements);
          return merged;
        });
      } else {
        if (source != null) {
          setter.accept(merged, source);
        } else {
          setter.accept(merged, target);
        }
        return Future.succeededFuture(merged);
      }
    };
  }
static < C extends ValidateContext < C > , M , T extends Mergeable < T , C > & Validable < C > > Function < M , Future < M > > mergeListField ( final C context , final String fieldName , final List < T > target , final List < T > source , final BiPredicate < T , T > equalsIdentifier , final BiConsumer < M , List < T > > setter ) { return merged -> { if ( target != null && source != null ) { final Promise < List < T > > promise = Promise . promise ( ) ; promise . complete ( new ArrayList < > ( ) ) ; var future = promise . future ( ) ; final var copy = new ArrayList < > ( target ) ; for ( final var sourceElement : source ) { var found = false ; final var max = copy . size ( ) ; for ( var i = 0 ; i < max ; i ++ ) { final var targetElement = copy . get ( i ) ; if ( equalsIdentifier . test ( targetElement , sourceElement ) ) { copy . remove ( i ) ; final var elementContext = context . createFieldElementContext ( fieldName , i ) ; future = future . compose ( mergedElements -> targetElement . merge ( sourceElement , elementContext ) . map ( mergedElement -> { mergedElements . add ( mergedElement ) ; return mergedElements ; } ) ) ; found = true ; break ; } } if ( ! found ) { future = future . compose ( mergedElements -> { mergedElements . add ( sourceElement ) ; return Future . succeededFuture ( mergedElements ) ; } ) ; } } return future . map ( mergedElements -> { setter . accept ( merged , mergedElements ) ; return merged ; } ) ; } else { if ( source != null ) { setter . accept ( merged , source ) ; } else { setter . accept ( merged , target ) ; } return Future . succeededFuture ( merged ) ; } } ; }
Merge a list field that is mergeable too.
Merge a list field that is mergeable too .