public void invoke(@NotNull Project project, Editor editor, PsiFile file)
      throws IncorrectOperationException {
    Set<String> classes = new LinkedHashSet<String>();
    Set<String> interfaces = new LinkedHashSet<String>();
    Set<String> unknownClasses = new LinkedHashSet<String>();
    Set<String> unknownInterfaces = new LinkedHashSet<String>();

    if (myExtendsClause != null) {
      collectRefs(
          myExtendsClause.getReferenceElementsGroovy(),
          classes,
          interfaces,
          myClass.isInterface() ? unknownInterfaces : unknownClasses);
      myExtendsClause.delete();
    }

    if (myImplementsClause != null) {
      collectRefs(
          myImplementsClause.getReferenceElementsGroovy(), classes, interfaces, unknownInterfaces);
      myImplementsClause.delete();
    }

    if (myClass.isInterface()) {
      interfaces.addAll(classes);
      unknownInterfaces.addAll(unknownClasses);
      addNewClause(interfaces, unknownInterfaces, project, true);
    } else {
      addNewClause(classes, unknownClasses, project, true);
      addNewClause(interfaces, unknownInterfaces, project, false);
    }
  }
  private static List<PsiClassType> getSuperTypes(PsiClass clazz) {
    if (clazz instanceof GrTypeDefinition) {
      final GrExtendsClause elist = ((GrTypeDefinition) clazz).getExtendsClause();
      final GrImplementsClause ilist = ((GrTypeDefinition) clazz).getImplementsClause();

      if (elist == null && ilist == null) return ContainerUtil.emptyList();

      final ArrayList<PsiClassType> types = new ArrayList<PsiClassType>();
      if (elist != null) ContainerUtil.addAll(types, elist.getReferencedTypes());
      if (ilist != null) ContainerUtil.addAll(types, ilist.getReferencedTypes());
      return types;
    } else {
      final PsiReferenceList elist = clazz.getExtendsList();
      final PsiReferenceList ilist = clazz.getImplementsList();

      if (elist == null && ilist == null) return ContainerUtil.emptyList();

      final ArrayList<PsiClassType> types = new ArrayList<PsiClassType>();
      if (elist != null) ContainerUtil.addAll(types, elist.getReferencedTypes());
      if (ilist != null) ContainerUtil.addAll(types, ilist.getReferencedTypes());
      return types;
    }
  }
  private static void startTemplate(
      GrTypeParameterList oldTypeParameterList,
      final Project project,
      final GrTypeDefinition psiClass,
      final GrTypeDefinition targetClass,
      boolean includeClassName) {
    PsiElementFactory jfactory = JavaPsiFacade.getElementFactory(project);
    final GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(project);
    GrCodeReferenceElement ref = elementFactory.createCodeReferenceElementFromClass(psiClass);
    try {
      if (psiClass.isInterface()) {
        GrImplementsClause clause = targetClass.getImplementsClause();
        if (clause == null) {
          clause =
              (GrImplementsClause)
                  targetClass.addAfter(
                      elementFactory.createImplementsClause(),
                      targetClass.getNameIdentifierGroovy());
        }
        ref = (GrCodeReferenceElement) clause.add(ref);
      } else {
        GrExtendsClause clause = targetClass.getExtendsClause();
        if (clause == null) {
          clause =
              (GrExtendsClause)
                  targetClass.addAfter(
                      elementFactory.createExtendsClause(), targetClass.getNameIdentifierGroovy());
        }
        ref = (GrCodeReferenceElement) clause.add(ref);
      }
      if (psiClass.hasTypeParameters() || includeClassName) {
        final Editor editor =
            CodeInsightUtil.positionCursor(
                project, targetClass.getContainingFile(), targetClass.getLBrace());
        final TemplateBuilderImpl templateBuilder =
            editor == null || ApplicationManager.getApplication().isUnitTestMode()
                ? null
                : (TemplateBuilderImpl)
                    TemplateBuilderFactory.getInstance().createTemplateBuilder(targetClass);

        if (includeClassName && templateBuilder != null) {
          templateBuilder.replaceElement(targetClass.getNameIdentifier(), targetClass.getName());
        }

        if (oldTypeParameterList != null) {
          for (PsiTypeParameter parameter : oldTypeParameterList.getTypeParameters()) {
            final PsiElement param =
                ref.getTypeArgumentList()
                    .add(elementFactory.createTypeElement(jfactory.createType(parameter)));
            if (templateBuilder != null) {
              templateBuilder.replaceElement(param, param.getText());
            }
          }
        }

        final GrTypeParameterList typeParameterList = targetClass.getTypeParameterList();
        assert typeParameterList != null;
        typeParameterList.replace(oldTypeParameterList);

        if (templateBuilder != null) {
          templateBuilder.setEndVariableBefore(ref);
          final Template template = templateBuilder.buildTemplate();
          template.addEndVariable();

          final PsiFile containingFile = targetClass.getContainingFile();

          PsiDocumentManager.getInstance(project)
              .doPostponedOperationsAndUnblockDocument(editor.getDocument());

          final TextRange textRange = targetClass.getTextRange();
          final int startClassOffset = textRange.getStartOffset();
          editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset());
          CreateFromUsageBaseFix.startTemplate(
              editor,
              template,
              project,
              new TemplateEditingAdapter() {
                @Override
                public void templateFinished(Template template, boolean brokenOff) {
                  chooseAndImplement(
                      psiClass,
                      project,
                      PsiTreeUtil.getParentOfType(
                          containingFile.findElementAt(startClassOffset), GrTypeDefinition.class),
                      editor);
                }
              },
              getTitle(psiClass));
        }
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }