code: private static ArrayList<Interval> mergeIntervals(String string, String mask) {
          ArrayList<Interval> result;
          try {
  
              // generate the matcher
              Pattern pattern = Pattern.compile(mask);
              Matcher matcher = pattern.matcher(string);
              if (!matcher.find()) {
                  return null;
              }
              int groupCount = matcher.groupCount();
              if (groupCount == 0) {
                  return null;
              }
  
              // pull out the potentially nested intervals
              ArrayList<Interval> intervals = new ArrayList<>();
              for (int i = 1; i <= groupCount; i++) {
                  intervals.add(new Interval(matcher.start(i), matcher.end(i)));
              }
  
              if (groupCount == 1) {
                  result = intervals;
              } else {
                  Collections.sort(intervals, new IntervalComparator());
                  int start = intervals.get(0).start;
                  int end = intervals.get(0).end;
                  result = new ArrayList<>();
                  for (int i = 1; i < intervals.size(); i++) {
                      if (intervals.get(i).start > end) {
                          // this is a new interval
                          result.add(new Interval(start, end));
                          start = intervals.get(i).start;
                          end = intervals.get(i).end;
                      } else {
                          end = Math.max(end, intervals.get(i).end);
                      }
                  }
                  // don't forget to add the last group into the final results
                  result.add(new Interval(start, end));
              }
  
          } catch (PatternSyntaxException e) {
              logger.error(e.getLocalizedMessage());
              result = null;
          }
  
          return result;
      }
docs: /*
  This method will "flatten" any nested intervals contained in "(" and ")" pairs in the
  specified string and merge them into a single interval that spans the outer-most pair.
  This is needed since java.util.Matcher does not guarantee that the sequence of the
  groups are maintained.