docs: public static <T extends ViewTraverse<T>> String replaceDataReferences(
              final String input,
              final MultiDataContext<T, DataContext> data,
              final T currentContext,
              final BiFunction<Integer, String, T> viewMap,
              final Converter<String, String> converter,
              boolean failOnUnexpanded,
              boolean blankIfUnexpanded
      )
      {
          if (null == data || null == input) {
              return input;
          }
          final Matcher m = PROPERTY_VIEW_REF_PATTERN.matcher(input);
          final StringBuffer sb = new StringBuffer();
          ArgumentVarExpander argExpander = new ArgumentVarExpander();
          while (m.find()) {
              final String variableRef = m.group(1);
              String value = argExpander.expandVariable(
                      data,
                      currentContext,
                      viewMap,
                      variableRef
              );
              if (null != value) {
                  if (null != converter) {
                      value = converter.convert(value);
                  }
                  m.appendReplacement(sb, Matcher.quoteReplacement(value));
              } else if (failOnUnexpanded) {
                  throw new DataContextUtils.UnresolvedDataReferenceException(input, m.group());
              } else if (blankIfUnexpanded) {
                  m.appendReplacement(sb, "");
              } else {
                  value = m.group(0);
                  if (null != converter) {
                      value = converter.convert(value);
                  }
                  m.appendReplacement(sb, Matcher.quoteReplacement(value));
              }
          }
          m.appendTail(sb);
          return sb.toString();
      }