/**
   * 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);
    }
  }
  /**
   * This method inserts our jar library into the corresponding classpath.
   *
   * @param shell The corresponding shell of the plug-in.
   * @param project The project where the proposal should work.
   * @param entry The classpath entry of our library.
   * @param context The context of the selection.
   * @return The result of this process, if the library has been successful added.
   * @throws JavaModelException
   */
  private static boolean addToClasspath(
      final Shell shell,
      final IJavaProject project,
      final IClasspathEntry entry,
      final IRunnableContext context)
      throws JavaModelException {
    boolean returnValue = false;
    boolean goAhead = true;
    final IClasspathEntry[] oldEntries = project.getRawClasspath();
    final ArrayList<IClasspathEntry> newEntries =
        new ArrayList<IClasspathEntry>(oldEntries.length + 1);
    final boolean added = false;
    for (int i = 0; i < oldEntries.length; i++) {
      IClasspathEntry current = oldEntries[i];
      if (current.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
        final IPath path = current.getPath();

        if (path.equals(entry.getPath())) {
          returnValue = true;
          goAhead = false;
        } else if (path.matchingFirstSegments(entry.getPath()) > 0) {
          if (added) {
            final IClasspathEntry newEntry = null;
            current = newEntry;
          } else {
            current = entry;
          }
        }

      } else if (current.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
        final IPath path = current.getPath();
        if (path.segmentCount() > 0 && PerclipseActivator.PERFIDIX_HOME.equals(path.segment(0))) {
          if (added) {
            final IClasspathEntry newEntry = null;
            current = newEntry;
          } else {
            current = entry;
          }
        }
      }
      if (current != null && goAhead) {
        newEntries.add(current);
      }
    }
    if (goAhead) {
      if (!added) {
        newEntries.add(entry);
      }
      final IClasspathEntry[] newCPEntries =
          newEntries.toArray(new IClasspathEntry[newEntries.size()]);

      try {
        context.run(
            true,
            false,
            new IRunnableWithProgress() {
              public void run(final IProgressMonitor monitor) {
                try {
                  project.setRawClasspath(newCPEntries, monitor);
                } catch (JavaModelException e) {
                  PerclipseActivator.log(e);
                }
              }
            });
        returnValue = true;
      } catch (InvocationTargetException e) {
        PerclipseActivator.log(e);
        final Throwable thowi = e.getTargetException();
        if (thowi instanceof CoreException) {
          ErrorDialog.openError(
              shell,
              "Add Perfidix library to the build path",
              "Cannot Add",
              ((CoreException) thowi).getStatus());
        }
      } catch (InterruptedException e) {
        PerclipseActivator.log(e);
      }
    }

    return returnValue;
  }