docs: private List<Match> _glue(List<Match> subMatchesQueue,
        Boolean subMatchesOptional, QueueItem item) throws IOException {
      List<Match> newSubMatchesQueue = new ArrayList<>();
      // no previous queue, only use current item
      if (subMatchesQueue.isEmpty()) {
        if (item.filledPosition) {
          for (Integer endPosition : item.queue.get(item.lowestPosition)) {
            Match m = new Match(item.lowestPosition, endPosition);
            if (!newSubMatchesQueue.contains(m)) {
              newSubMatchesQueue.add(m);
            }
          }
        }
        return newSubMatchesQueue;
        // previous queue
      } else {
        // startposition from queue
        int startPosition = subMatchesQueue.get(0).startPosition;
        // previous queue optional, current item optional
        if (subMatchesOptional && item.sequenceSpans.optional) {
          // forget previous, because current has lower startposition
          if (item.filledPosition && item.lowestPosition < startPosition) {
            for (Integer endPosition : item.queue.get(item.lowestPosition)) {
              Match m = new Match(item.lowestPosition, endPosition);
              if (!newSubMatchesQueue.contains(m)) {
                newSubMatchesQueue.add(m);
              }
            }
            // merge with previous
          } else if (item.filledPosition) {
            if (item.lowestPosition.equals(startPosition)) {
              for (Integer endPosition : item.queue.get(item.lowestPosition)) {
                Match m = new Match(item.lowestPosition, endPosition);
                if (!newSubMatchesQueue.contains(m)) {
                  newSubMatchesQueue.add(m);
                }
              }
            }
            newSubMatchesQueue.addAll(subMatchesQueue);
            for (Match m : subMatchesQueue) {
              if (item.queue.containsKey(m.endPosition)) {
                for (Integer endPosition : item.queue.get(m.endPosition)) {
                  Match o = new Match(m.startPosition, endPosition);
                  if (!newSubMatchesQueue.contains(o)) {
                    newSubMatchesQueue.add(o);
                  }
                }
              }
            }
            // no filled position
          } else {
            newSubMatchesQueue.addAll(subMatchesQueue);
          }
          // previous queue optional, current item not optional
        } else if (subMatchesOptional && !item.sequenceSpans.optional) {
          assert item.filledPosition : "span not optional, should contain items";
          // forget previous
          if (item.lowestPosition < startPosition) {
            for (Integer endPosition : item.queue.get(item.lowestPosition)) {
              Match m = new Match(item.lowestPosition, endPosition);
              if (!newSubMatchesQueue.contains(m)) {
                newSubMatchesQueue.add(m);
              }
            }
            // merge with previous
          } else {
            if (item.lowestPosition.equals(startPosition)) {
              for (Integer endPosition : item.queue.get(item.lowestPosition)) {
                Match m = new Match(item.lowestPosition, endPosition);
                if (!newSubMatchesQueue.contains(m)) {
                  newSubMatchesQueue.add(m);
                }
              }
            }
            for (Match m : subMatchesQueue) {
              if (item.queue.containsKey(m.endPosition)) {
                for (Integer endPosition : item.queue.get(m.endPosition)) {
                  Match o = new Match(m.startPosition, endPosition);
                  if (!newSubMatchesQueue.contains(o)) {
                    newSubMatchesQueue.add(o);
                  }
                }
              }
            }
          }
          // previous queue not optional, current item optional
        } else if (!subMatchesOptional && item.sequenceSpans.optional) {
          newSubMatchesQueue.addAll(subMatchesQueue);
          // merge with previous
          if (item.filledPosition) {
            for (Match m : subMatchesQueue) {
              if (item.queue.containsKey(m.endPosition)) {
                for (Integer endPosition : item.queue.get(m.endPosition)) {
                  Match o = new Match(m.startPosition, endPosition);
                  if (!newSubMatchesQueue.contains(o)) {
                    newSubMatchesQueue.add(o);
                  }
                }
              }
            }
          }
          // previous queue not optional, current item not optional
        } else if (!subMatchesOptional && !item.sequenceSpans.optional
            && item.filledPosition) {
          for (Match m : subMatchesQueue) {
            Set<Integer> ignoreList = ignoreItem.getFullEndPositionList(docId,
                m.endPosition);
            Integer[] checkList;
            if (ignoreList == null) {
              checkList = new Integer[] { m.endPosition };
            } else {
              checkList = new Integer[1 + ignoreList.size()];
              checkList = ignoreList.toArray(checkList);
              checkList[ignoreList.size()] = m.endPosition;
            }
            for (Integer checkEndPosition : checkList) {
              if (item.queue.containsKey(checkEndPosition)) {
                for (Integer endPosition : item.queue.get(checkEndPosition)) {
                  Match o = new Match(m.startPosition, endPosition);
                  if (!newSubMatchesQueue.contains(o)) {
                    newSubMatchesQueue.add(o);
                  }
                }
              }
            }
          }
        }
      }
      return newSubMatchesQueue;
    }