/*
 * Copyright 2000-2010 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.refactoring.actions;

import com.intellij.lang.Language;
import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * @author yole
 */
public abstract class BasePlatformRefactoringAction extends BaseRefactoringAction {

  private Boolean myHidden = null;
  private final Condition<RefactoringSupportProvider> myCondition = new Condition<RefactoringSupportProvider>() {
    @Override
    public boolean value(RefactoringSupportProvider provider) {
      return getRefactoringHandler(provider) != null;
    }
  };

  public BasePlatformRefactoringAction() {
    LanguageRefactoringSupport.INSTANCE.addListener(new ExtensionPointListener<RefactoringSupportProvider>() {
      public void extensionAdded(RefactoringSupportProvider extension, @Nullable PluginDescriptor pluginDescriptor) {
        myHidden = null;
      }

      public void extensionRemoved(RefactoringSupportProvider extension, @Nullable PluginDescriptor pluginDescriptor) {
        myHidden = null;
      }
    });
  }

  @Override
  protected final RefactoringActionHandler getHandler(DataContext dataContext) {
    final Language[] languages = LangDataKeys.CONTEXT_LANGUAGES.getData(dataContext);
    if (languages != null) {
      Editor editor = LangDataKeys.EDITOR.getData(dataContext);
      PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
      PsiElement elementAtCaret = editor == null || file == null ? null : getElementAtCaret(editor, file);
      for (Language language : languages) {
        RefactoringActionHandler handler = getHandler(language, elementAtCaret);
        if (handler != null) {
          return handler;
        }
      }
    }
    else {
      PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
      if (element != null) {
        return getHandler(element.getLanguage(), element);
      }
    }
    return null;
  }

  @Nullable
  private RefactoringActionHandler getHandler(@NotNull Language language, PsiElement element) {
    List<RefactoringSupportProvider> providers = LanguageRefactoringSupport.INSTANCE.allForLanguage(language);
    if (providers.isEmpty()) return null;
    if (providers.size() == 1) return getRefactoringHandler(providers.get(0));
    if (element != null) {
      for (RefactoringSupportProvider provider : providers) {
        if (provider.isAvailable(element)) {
          return getRefactoringHandler(provider);
        }
      }
    }
    return null;
  }


  @Override
  protected boolean isAvailableOnElementInEditorAndFile(PsiElement element, Editor editor, PsiFile file, DataContext context) {
    return getHandler(context) != null; 
  }

  protected boolean isAvailableForLanguage(final Language language) {
    List<RefactoringSupportProvider> providers = LanguageRefactoringSupport.INSTANCE.allForLanguage(language);
    return ContainerUtil.find(providers, myCondition) != null;
  }

  @Nullable
  protected abstract RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider);

  @Override
  protected boolean isHidden() {
    if (myHidden == null) {
      myHidden = calcHidden();
    }
    return myHidden.booleanValue();
  }

  private boolean calcHidden() {
    for(Language l: Language.getRegisteredLanguages()) {
      if (isAvailableForLanguage(l)) {
        return false;
      }
    }
    return true;
  }
}

@@ -2365,125 +2365,261 @@
 ) %7B%0A
+%0A
     
-final Language%5B%5D languages = LangDataKeys.CONTEXT_LANGUAGES.getData(dataContext);%0A    if (languages != null) %7B%0A  
+PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext);%0A    if (element != null) %7B%0A      RefactoringActionHandler handler = getHandler(element.getLanguage(), element);%0A      if (handler != null) %7B%0A        return handler;%0A      %7D%0A    %7D%0A%0A
     
@@ -2672,26 +2672,24 @@
 taContext);%0A
-  
     PsiFile 
@@ -2747,77 +2747,61 @@
     
-  PsiElement elementAtCaret = 
+if (
 editor 
-=
+!
 = null 
-%7C%7C
+&&
  file 
-=
+!
 = null
- ? null :
+) %7B%0A      element =
  get
@@ -2840,108 +2840,78 @@
     
-for (Language language : languages) %7B%0A        RefactoringActionHandler handler = getHandler(l
+if (element != null) %7B%0A        return getHandler(element.getL
 anguage
+()
 , el
@@ -2915,23 +2915,16 @@
  element
-AtCaret
 );%0A     
@@ -2928,145 +2928,80 @@
     
-  if (handler != null) %7B%0A          return handler;%0A        %7D%0A      %7D%0A    %7D%0A    else %7B%0A      PsiElement element = LangDataKeys.PSI_ELEMENT
+%7D%0A    %7D%0A%0A    final Language%5B%5D languages = LangDataKeys.CONTEXT_LANGUAGES
 .get
@@ -3019,37 +3019,37 @@
 ntext);%0A    
-  
 if (
-element
+languages
  != null) %7B%0A
@@ -3058,49 +3058,108 @@
     
-  return getHandler(element.getL
+for (Language language : languages) %7B%0A        RefactoringActionHandler handler = getHandler(l
 anguage
-()
 , el
@@ -3158,32 +3158,99 @@
 uage, element);%0A
+        if (handler != null) %7B%0A          return handler;%0A        %7D%0A
       %7D%0A    %7D%0A  
@@ -3542,29 +3542,47 @@
 if (
-providers.size() == 1
+element == null && !providers.isEmpty()
 ) re

test fix