/*
   * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
   */
  public final Point getSelection(final IDocument document) {

    int offset = fContext.getSelectionOffset();
    int length = fContext.getSelectionLength();

    final int delta = fWord.length() - fLength;
    if (offset <= fOffset && offset + length >= fOffset) length += delta;
    else if (offset > fOffset && offset + length > fOffset + fLength) {
      offset += delta;
      length -= delta;
    } else length += delta;

    return new Point(offset, length);
  }
  /**
   * This method inserts our proposal - jar library - into classpath.
   *
   * @param document see super method.
   * @see
   *     org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
   */
  public void apply(final IDocument document) {
    final IJavaProject project = context.getCompilationUnit().getJavaProject();
    final Shell shell = PerclipseActivator.getActivePage().getWorkbenchWindow().getShell();
    try {
      IClasspathEntry entry = null;
      if (isPerfidix) {
        entry = BuildPathSupport.getPerfidixClasspathEntry();
      }
      if (entry != null) {
        addToClasspath(shell, project, entry, new BusyIndicatorRunnableContext());
      }
      final int offset = context.getSelectionOffset();
      final int length = context.getSelectionLength();
      String str;
      str = document.get(offset, length);

      document.replace(offset, length, str);

    } catch (BadLocationException e) {
      PerclipseActivator.log(e);
    } catch (JavaModelException e) {
      PerclipseActivator.log(e);
    }
  }
 /** {@inheritDoc} */
 public Point getSelection(final IDocument arg0) {
   return new Point(context.getSelectionOffset(), context.getSelectionLength());
 }
  @Override
  public IJavaCompletionProposal[] getAssists(
      IInvocationContext context, IProblemLocation[] locations) throws CoreException {
    ICompilationUnit compilationUnit = context.getCompilationUnit();
    IType primaryType = compilationUnit.findPrimaryType();
    if (primaryType == null || !primaryType.isInterface()) ; // return null;

    IJavaElement[] elements =
        compilationUnit.codeSelect(context.getSelectionOffset(), context.getSelectionLength());
    for (IJavaElement element : elements) {
      if (element.getElementType() == IJavaElement.METHOD) {
        IMethod method = (IMethod) element;
        if (!method.getDeclaringType().isInterface()) return null;

        final String statementAnnotation = getStatementAnnotation(method);
        if (method.getParameters().length == 0 && statementAnnotation == null) return null;

        CompilationUnit astNode = getAstNode(compilationUnit);
        astNode.recordModifications();
        final MapperMethod mapperMethod = getMapperMethod(astNode, method);
        if (mapperMethod == null) return null;

        List<IJavaCompletionProposal> proposals = new ArrayList<IJavaCompletionProposal>();

        if (method.getParameters().length > 0) {
          proposals.add(
              new QuickAssistCompletionProposal("Add @Param to parameters") {
                private CompilationUnit astNode;

                private MapperMethod method;

                @SuppressWarnings("unchecked")
                @Override
                public void apply(IDocument document) {
                  List<SingleVariableDeclaration> params = method.parameters();
                  for (SingleVariableDeclaration param : params) {
                    List<IExtendedModifier> modifiers = param.modifiers();
                    if (!hasParamAnnotation(modifiers)) {
                      if (JavaMapperUtil.TYPE_ROW_BOUNDS.equals(
                          param.resolveBinding().getType().getQualifiedName())) continue;
                      AST ast = param.getAST();
                      SingleMemberAnnotation annotation = ast.newSingleMemberAnnotation();
                      annotation.setTypeName(ast.newName("Param"));
                      StringLiteral paramValue = ast.newStringLiteral();
                      paramValue.setLiteralValue(param.getName().getFullyQualifiedName());
                      annotation.setValue(paramValue);
                      param.modifiers().add(annotation);
                    }
                  }
                  TextEdit textEdit = astNode.rewrite(document, null);
                  try {
                    textEdit.apply(document);
                  } catch (MalformedTreeException e) {
                    Activator.log(Status.ERROR, e.getMessage(), e);
                  } catch (BadLocationException e) {
                    Activator.log(Status.ERROR, e.getMessage(), e);
                  }
                }

                private boolean hasParamAnnotation(List<IExtendedModifier> modifiers) {
                  for (IExtendedModifier modifier : modifiers) {
                    if (modifier.isAnnotation()
                        && "Param"
                            .equals(
                                ((Annotation) modifier).getTypeName().getFullyQualifiedName())) {
                      return true;
                    }
                  }
                  return false;
                }

                private QuickAssistCompletionProposal init(
                    CompilationUnit astNode, MapperMethod method) {
                  this.astNode = astNode;
                  this.method = method;
                  return this;
                }
              }.init(astNode, mapperMethod));
        }

        if (mapperMethod.getStatement() != null) {
          proposals.add(
              new QuickAssistCompletionProposal(
                  "Copy @" + statementAnnotation + " statement to clipboard") {
                @Override
                public void apply(IDocument document) {
                  Clipboard clipboard = new Clipboard(Display.getCurrent());
                  clipboard.setContents(
                      new Object[] {mapperMethod.getStatement()},
                      new Transfer[] {TextTransfer.getInstance()});
                }
              });
        }

        return proposals.toArray(new IJavaCompletionProposal[proposals.size()]);
      }
    }
    return null;
  }