/**
   * Remembers the selection in the content assist history.
   *
   * @throws JavaModelException if anything goes wrong
   * @since 3.2
   */
  protected final void rememberSelection() throws JavaModelException {
    IType lhs = fInvocationContext.getExpectedType();
    IType rhs = (IType) getJavaElement();
    if (lhs != null && rhs != null)
      JavaPlugin.getDefault().getContentAssistHistory().remember(lhs, rhs);

    QualifiedTypeNameHistory.remember(getQualifiedTypeName());
  }
    public int compare(Object o1, Object o2) {
      if (((String) o1).equals(o2)) return 0;

      History history = QualifiedTypeNameHistory.getDefault();

      int pos1 = history.getPosition(o1);
      int pos2 = history.getPosition(o2);

      if (pos1 == pos2) return Collator.getInstance().compare(o1, o2);

      if (pos1 > pos2) {
        return -1;
      } else {
        return 1;
      }
    }
  private TypeNameMatch[] doChooseImports(
      TypeNameMatch[][] openChoices, final ISourceRange[] ranges) {
    // remember selection
    ISelection sel = fEditor != null ? fEditor.getSelectionProvider().getSelection() : null;
    TypeNameMatch[] result = null;
    ILabelProvider labelProvider =
        new TypeNameMatchLabelProvider(TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED);

    MultiElementListSelectionDialog dialog =
        new MultiElementListSelectionDialog(getShell(), labelProvider) {
          protected void handleSelectionChanged() {
            super.handleSelectionChanged();
            // show choices in editor
            doListSelectionChanged(getCurrentPage(), ranges);
          }
        };
    fIsQueryShowing = true;
    dialog.setTitle(ActionMessages.OrganizeImportsAction_selectiondialog_title);
    dialog.setMessage(ActionMessages.OrganizeImportsAction_selectiondialog_message);
    dialog.setElements(openChoices);
    dialog.setComparator(ORGANIZE_IMPORT_COMPARATOR);
    if (dialog.open() == Window.OK) {
      Object[] res = dialog.getResult();
      result = new TypeNameMatch[res.length];
      for (int i = 0; i < res.length; i++) {
        Object[] array = (Object[]) res[i];
        if (array.length > 0) {
          result[i] = (TypeNameMatch) array[0];
          QualifiedTypeNameHistory.remember(result[i].getFullyQualifiedName());
        }
      }
    }
    // restore selection
    if (sel instanceof ITextSelection) {
      ITextSelection textSelection = (ITextSelection) sel;
      fEditor.selectAndReveal(textSelection.getOffset(), textSelection.getLength());
    }
    fIsQueryShowing = false;
    return result;
  }
  /*
   * @see org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal#computeRelevance()
   */
  @Override
  protected int computeRelevance() {
    /*
     * There are two histories: the RHS history remembers types used for the current expected
     * type (left hand side), while the type history remembers recently used types in general).
     *
     * The presence of an RHS ranking is a much more precise sign for relevance as it proves the
     * subtype relationship between the proposed type and the expected type.
     *
     * The "recently used" factor (of either the RHS or general history) is less important, it should
     * not override other relevance factors such as if the type is already imported etc.
     */
    float rhsHistoryRank = fInvocationContext.getHistoryRelevance(getQualifiedTypeName());
    float typeHistoryRank =
        QualifiedTypeNameHistory.getDefault().getNormalizedPosition(getQualifiedTypeName());

    int recencyBoost = Math.round((rhsHistoryRank + typeHistoryRank) * 5);
    int rhsBoost = rhsHistoryRank > 0.0f ? 50 : 0;
    int baseRelevance = super.computeRelevance();

    return baseRelevance + rhsBoost + recencyBoost;
  }