docs: public static MtasSpanSequenceItem merge(MtasSpanSequenceItem item1,
        MtasSpanSequenceItem item2, MtasSpanQuery ignoreQuery,
        Integer maximumIgnoreLength) {
      if (item1 == null || item2 == null) {
        return null;
      } else {
        MtasSpanQuery q1 = item1.getQuery();
        MtasSpanQuery q2 = item2.getQuery();
        boolean optional = item1.optional && item2.optional;
        // first spanRecurrenceQuery
        if (q1 instanceof MtasSpanRecurrenceQuery) {
          MtasSpanRecurrenceQuery rq1 = (MtasSpanRecurrenceQuery) q1;
          // both spanRecurrenceQuery
          if (q2 instanceof MtasSpanRecurrenceQuery) {
            MtasSpanRecurrenceQuery rq2 = (MtasSpanRecurrenceQuery) q2;
            // equal query
            if (rq1.getQuery().equals(rq2.getQuery())) {
              // equal ignoreQuery settings
              boolean checkCondition;
              checkCondition = ignoreQuery != null
                  && rq1.getIgnoreQuery() != null;
              checkCondition = checkCondition
                  ? ignoreQuery.equals(rq1.getIgnoreQuery()) : false;
              checkCondition = checkCondition
                  ? maximumIgnoreLength.equals(rq1.getMaximumIgnoreLength())
                  : false;
              checkCondition = checkCondition ? rq2.getIgnoreQuery() != null
                  : false;
              checkCondition = checkCondition
                  ? ignoreQuery.equals(rq2.getIgnoreQuery()) : false;
              checkCondition = checkCondition
                  ? maximumIgnoreLength.equals(rq2.getMaximumIgnoreLength())
                  : false;
              if (checkCondition) {
                // at least one optional
                if (item1.optional || item2.optional) {
                  int minimum = Math.min(rq1.getMinimumRecurrence(),
                      rq2.getMinimumRecurrence());
                  int maximum = rq1.getMaximumRecurrence()
                      + rq2.getMaximumRecurrence();
                  // only if ranges match
                  if ((rq1.getMaximumRecurrence() + 1) >= rq2
                      .getMinimumRecurrence()
                      && (rq2.getMaximumRecurrence() + 1) >= rq1
                          .getMinimumRecurrence()) {
                    return new MtasSpanSequenceItem(
                        new MtasSpanRecurrenceQuery(rq1.getQuery(), minimum,
                            maximum, ignoreQuery, maximumIgnoreLength),
                        optional);
                  }
                  // not optional
                } else {
                  int minimum = rq1.getMinimumRecurrence()
                      + rq2.getMinimumRecurrence();
                  int maximum = rq1.getMaximumRecurrence()
                      + rq2.getMaximumRecurrence();
                  // only if ranges match
                  if ((rq1.getMaximumRecurrence() + 1) >= rq2
                      .getMinimumRecurrence()
                      && (rq2.getMaximumRecurrence() + 1) >= rq1
                          .getMinimumRecurrence()) {
                    return new MtasSpanSequenceItem(
                        new MtasSpanRecurrenceQuery(rq1.getQuery(), minimum,
                            maximum, ignoreQuery, maximumIgnoreLength),
                        optional);
                  }
                }
              }
            }
          } else {
            if (rq1.getQuery().equals(q2)) {
              boolean checkCondition;
              checkCondition = ignoreQuery != null;
              checkCondition &= rq1.getIgnoreQuery() != null;
              checkCondition &= ignoreQuery.equals(rq1.getIgnoreQuery());
              checkCondition &= rq1.getMaximumIgnoreLength() != null;
              checkCondition &= maximumIgnoreLength
                  .equals(rq1.getMaximumIgnoreLength());
              if (checkCondition) {
                if (!optional) {
                  if (item1.optional) {
                    if (rq1.getMinimumRecurrence() == 1) {
                      return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(
                          q2, 1, rq1.getMaximumRecurrence() + 1, ignoreQuery,
                          maximumIgnoreLength), false);
                    }
                  } else if (item2.optional) {
                    return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(
                        q2, rq1.getMinimumRecurrence(),
                        rq1.getMaximumRecurrence() + 1, ignoreQuery,
                        maximumIgnoreLength), false);
                  } else {
                    return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(
                        q2, rq1.getMinimumRecurrence() + 1,
                        rq1.getMaximumRecurrence() + 1, ignoreQuery,
                        maximumIgnoreLength), false);
                  }
                } else {
                  if (rq1.getMinimumRecurrence() == 1) {
                    return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(
                        q2, 1, rq1.getMaximumRecurrence() + 1, ignoreQuery,
                        maximumIgnoreLength), true);
                  }
                }
              }
            }
          }
          // second spanRecurrenceQuery
        } else if (q2 instanceof MtasSpanRecurrenceQuery) {
          MtasSpanRecurrenceQuery rq2 = (MtasSpanRecurrenceQuery) q2;
          if (rq2.getQuery().equals(q1)) {
            boolean checkCondition;
            checkCondition = ignoreQuery != null;
            checkCondition &= rq2.getIgnoreQuery() != null;
            checkCondition &= ignoreQuery.equals(rq2.getIgnoreQuery());
            checkCondition &= maximumIgnoreLength
                .equals(rq2.getMaximumIgnoreLength());
            if (checkCondition) {
              if (!optional) {
                if (item1.optional) {
                  return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(q1,
                      rq2.getMinimumRecurrence(), rq2.getMaximumRecurrence() + 1,
                      ignoreQuery, maximumIgnoreLength), false);
                } else if (item2.optional) {
                  if (rq2.getMinimumRecurrence() == 1) {
                    return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(
                        q1, 1, rq2.getMaximumRecurrence() + 1, ignoreQuery,
                        maximumIgnoreLength), false);
                  }
                } else {
                  return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(q1,
                      rq2.getMinimumRecurrence() + 1,
                      rq2.getMaximumRecurrence() + 1, ignoreQuery,
                      maximumIgnoreLength), false);
                }
              } else {
                if (rq2.getMinimumRecurrence() == 1) {
                  return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(q1,
                      1, rq2.getMaximumRecurrence() + 1, ignoreQuery,
                      maximumIgnoreLength), true);
                }
              }
            }
          }
          // both no spanRecurrenceQuery
        } else if (q1.equals(q2)) {
          // at least one optional
          if (item1.optional || item2.optional) {
            return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(q1, 1, 2,
                ignoreQuery, maximumIgnoreLength), optional);
          } else {
            return new MtasSpanSequenceItem(new MtasSpanRecurrenceQuery(q1, 2, 2,
                ignoreQuery, maximumIgnoreLength), optional);
          }
        }
        return null;
      }
    }