public static TemplateVariable findVariable(
     final TemplateBuffer buffer, final String variableType) {
   final TemplateVariable[] variables = buffer.getVariables();
   for (final TemplateVariable cand : variables) {
     if (variableType.equals(cand.getType())) {
       return cand;
     }
   }
   return null;
 }
  private int getCursorOffset(TemplateBuffer buffer) {
    TemplateVariable[] variables = buffer.getVariables();
    for (int i = 0; i != variables.length; i++) {
      TemplateVariable variable = variables[i];
      if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME))
        return variable.getOffsets()[0];
    }

    return buffer.getString().length();
  }
  @Override
  public void resolve(final TemplateBuffer buffer, final TemplateContext context)
      throws MalformedTreeException, BadLocationException {
    Assert.isNotNull(context);
    final TemplateVariable[] variables = buffer.getVariables();

    final IDocument document = new Document(buffer.getString());
    final List<TextEdit> positions = TemplatesUtil.variablesToPositions(variables);
    final List<TextEdit> edits = new ArrayList<>(5);

    // iterate over all variables and try to resolve them
    for (int i = 0; i != variables.length; i++) {
      final TemplateVariable variable = variables[i];

      if (variable.isUnambiguous()) {
        continue;
      }

      // remember old values
      final int[] oldOffsets = variable.getOffsets();
      final int oldLength = variable.getLength();
      final String oldValue = variable.getDefaultValue();

      final String type = variable.getType();
      TemplateVariableResolver resolver = getResolver(type);
      if (resolver == null) {
        resolver = new TemplateVariableResolver();
        resolver.setType(type);
      }

      resolver.resolve(variable, context);

      final String value = variable.getDefaultValue();
      final String[] ln = document.getLegalLineDelimiters();
      final boolean multiLine = (TextUtilities.indexOf(ln, value, 0)[0] != -1);

      if (!oldValue.equals(value)) {
        // update buffer to reflect new value
        for (int k = 0; k != oldOffsets.length; k++) {
          String thisValue = value;
          if (multiLine) {
            final String indent = TemplatesUtil.searchIndentation(document, oldOffsets[k]);
            if (indent.length() > 0) {
              final StringBuilder temp = new StringBuilder(thisValue);
              int offset = 0;
              while (true) {
                final int[] search = TextUtilities.indexOf(ln, temp.toString(), offset);
                if (search[0] == -1) {
                  break;
                }
                offset = search[0] + ln[search[1]].length();
                temp.insert(offset, indent);
                offset += indent.length();
              }
              thisValue = temp.toString();
            }
          }
          edits.add(new ReplaceEdit(oldOffsets[k], oldLength, thisValue));
        }
      }
    }

    final MultiTextEdit edit = new MultiTextEdit(0, document.getLength());
    edit.addChildren(positions.toArray(new TextEdit[positions.size()]));
    edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
    edit.apply(document, TextEdit.UPDATE_REGIONS);

    TemplatesUtil.positionsToVariables(positions, variables);

    buffer.setContent(document.get(), variables);
  }