// todo: inline
  private static void generateBean(
      final PsiClass aClass,
      final String[] properties,
      final HashMap<String, String> property2fqClassName)
      throws MyException {
    final StringBuffer membersBuffer = new StringBuffer();
    final StringBuffer methodsBuffer = new StringBuffer();

    final CodeStyleManager formatter = CodeStyleManager.getInstance(aClass.getProject());
    final JavaCodeStyleManager styler = JavaCodeStyleManager.getInstance(aClass.getProject());

    for (final String property : properties) {
      LOG.assertTrue(property != null);
      final String type = property2fqClassName.get(property);
      LOG.assertTrue(type != null);

      generateProperty(styler, property, type, membersBuffer, methodsBuffer);
    }

    final PsiClass fakeClass;
    try {
      fakeClass =
          JavaPsiFacade.getInstance(aClass.getProject())
              .getElementFactory()
              .createClassFromText(membersBuffer.toString() + methodsBuffer.toString(), null);

      final PsiField[] fields = fakeClass.getFields();
      for (final PsiField field : fields) {
        aClass.add(field);
      }

      final PsiMethod[] methods = fakeClass.getMethods();
      for (final PsiMethod method : methods) {
        aClass.add(method);
      }

      styler.shortenClassReferences(aClass);
      formatter.reformat(aClass);
    } catch (IncorrectOperationException e) {
      throw new MyException(e.getMessage());
    }
  }
 private boolean hasOnlyMain(PsiClass aClass) {
   final PsiMethod[] methods = aClass.getMethods();
   if (methods.length == 0) {
     return false;
   }
   for (PsiMethod method : methods) {
     if (method.isConstructor()) {
       continue;
     }
     if (!method.hasModifierProperty(PsiModifier.STATIC)) {
       return false;
     }
     if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
       continue;
     }
     if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
       return false;
     }
     final String name = method.getName();
     if (!name.equals(HardcodedMethodConstants.MAIN)) {
       return false;
     }
     final PsiType returnType = method.getReturnType();
     if (!PsiType.VOID.equals(returnType)) {
       return false;
     }
     final PsiParameterList parameterList = method.getParameterList();
     if (parameterList.getParametersCount() != 1) {
       return false;
     }
     final PsiParameter[] parameters = parameterList.getParameters();
     final PsiParameter parameter = parameters[0];
     final PsiType type = parameter.getType();
     if (!type.equalsToText("java.lang.String[]")) {
       return false;
     }
   }
   return true;
 }
  @NotNull
  private static List<PsiMember> findByMap(
      @NotNull PsiClass aClass, String name, boolean checkBases, @NotNull MemberType type) {
    if (name == null) return Collections.emptyList();

    if (checkBases) {
      Map<String, List<Pair<PsiMember, PsiSubstitutor>>> allMethodsMap = getMap(aClass, type);
      List<Pair<PsiMember, PsiSubstitutor>> list = allMethodsMap.get(name);
      if (list == null) return Collections.emptyList();
      List<PsiMember> ret = new ArrayList<PsiMember>(list.size());
      for (final Pair<PsiMember, PsiSubstitutor> info : list) {
        ret.add(info.getFirst());
      }

      return ret;
    } else {
      PsiMember[] members = null;
      switch (type) {
        case METHOD:
          members = aClass.getMethods();
          break;
        case CLASS:
          members = aClass.getInnerClasses();
          break;
        case FIELD:
          members = aClass.getFields();
          break;
      }

      List<PsiMember> list = new ArrayList<PsiMember>();
      for (PsiMember member : members) {
        if (name.equals(member.getName())) {
          list.add(member);
        }
      }
      return list;
    }
  }
  /** Should be invoked in command and write action */
  @SuppressWarnings({"HardCodedStringLiteral"})
  public static void generateDataBindingMethods(final WizardData data) throws MyException {
    if (data.myBindToNewBean) {
      data.myBeanClass = createBeanClass(data);
    } else {
      if (!CommonRefactoringUtil.checkReadOnlyStatus(
          data.myBeanClass.getProject(), data.myBeanClass)) {
        return;
      }
    }

    final HashMap<String, String> binding2beanGetter = new HashMap<String, String>();
    final HashMap<String, String> binding2beanSetter = new HashMap<String, String>();

    final FormProperty2BeanProperty[] bindings = data.myBindings;
    for (final FormProperty2BeanProperty form2bean : bindings) {
      if (form2bean == null || form2bean.myBeanProperty == null) {
        continue;
      }

      // check that bean contains the property, and if not, try to add the property to the bean
      {
        final String setterName = PropertyUtil.suggestSetterName(form2bean.myBeanProperty.myName);
        final PsiMethod[] methodsByName = data.myBeanClass.findMethodsByName(setterName, true);
        if (methodsByName.length < 1) {
          // bean does not contain this property
          // try to add...

          LOG.assertTrue(
              !data.myBindToNewBean); // just generated bean class should contain all necessary
                                      // properties

          if (!data.myBeanClass.isWritable()) {
            throw new MyException(
                "Cannot add property to non writable class " + data.myBeanClass.getQualifiedName());
          }

          final StringBuffer membersBuffer = new StringBuffer();
          final StringBuffer methodsBuffer = new StringBuffer();

          final Project project = data.myBeanClass.getProject();
          final CodeStyleManager formatter = CodeStyleManager.getInstance(project);
          final JavaCodeStyleManager styler = JavaCodeStyleManager.getInstance(project);

          generateProperty(
              styler,
              form2bean.myBeanProperty.myName,
              form2bean.myBeanProperty.myType,
              membersBuffer,
              methodsBuffer);

          final PsiClass fakeClass;
          try {
            fakeClass =
                JavaPsiFacade.getInstance(data.myBeanClass.getProject())
                    .getElementFactory()
                    .createClassFromText(membersBuffer.toString() + methodsBuffer.toString(), null);

            final PsiField[] fields = fakeClass.getFields();
            {
              final PsiElement result = data.myBeanClass.add(fields[0]);
              styler.shortenClassReferences(result);
              formatter.reformat(result);
            }

            final PsiMethod[] methods = fakeClass.getMethods();
            {
              final PsiElement result = data.myBeanClass.add(methods[0]);
              styler.shortenClassReferences(result);
              formatter.reformat(result);
            }
            {
              final PsiElement result = data.myBeanClass.add(methods[1]);
              styler.shortenClassReferences(result);
              formatter.reformat(result);
            }
          } catch (IncorrectOperationException e) {
            throw new MyException(e.getMessage());
          }
        }
      }

      final PsiMethod propertySetter =
          PropertyUtil.findPropertySetter(
              data.myBeanClass, form2bean.myBeanProperty.myName, false, true);
      final PsiMethod propertyGetter =
          PropertyUtil.findPropertyGetter(
              data.myBeanClass, form2bean.myBeanProperty.myName, false, true);

      if (propertyGetter == null) {
        // todo
        continue;
      }
      if (propertySetter == null) {
        // todo
        continue;
      }

      final String binding = form2bean.myFormProperty.getLwComponent().getBinding();
      binding2beanGetter.put(binding, propertyGetter.getName());
      binding2beanSetter.put(binding, propertySetter.getName());
    }

    final String dataBeanClassName = data.myBeanClass.getQualifiedName();

    final LwRootContainer[] rootContainer = new LwRootContainer[1];
    final FormProperty[] formProperties =
        exposeForm(data.myProject, data.myFormFile, rootContainer);

    final StringBuffer getDataBody = new StringBuffer();
    final StringBuffer setDataBody = new StringBuffer();
    final StringBuffer isModifiedBody = new StringBuffer();

    // iterate exposed formproperties

    for (final FormProperty formProperty : formProperties) {
      final String binding = formProperty.getLwComponent().getBinding();
      if (!binding2beanGetter.containsKey(binding)) {
        continue;
      }

      getDataBody.append("data.");
      getDataBody.append(binding2beanSetter.get(binding));
      getDataBody.append("(");
      getDataBody.append(binding);
      getDataBody.append(".");
      getDataBody.append(formProperty.getComponentPropertyGetterName());
      getDataBody.append("());\n");

      setDataBody.append(binding);
      setDataBody.append(".");
      setDataBody.append(formProperty.getComponentPropertySetterName());
      setDataBody.append("(data.");
      setDataBody.append(binding2beanGetter.get(binding));
      setDataBody.append("());\n");

      final String propertyClassName = formProperty.getComponentPropertyClassName();
      if ("boolean".equals(propertyClassName)) {
        isModifiedBody.append("if (");
        //
        isModifiedBody.append(binding);
        isModifiedBody.append(".");
        isModifiedBody.append(formProperty.getComponentPropertyGetterName());
        isModifiedBody.append("()");
        //
        isModifiedBody.append("!= ");
        //
        isModifiedBody.append("data.");
        isModifiedBody.append(binding2beanGetter.get(binding));
        isModifiedBody.append("()");
        //
        isModifiedBody.append(") return true;\n");
      } else {
        isModifiedBody.append("if (");
        //
        isModifiedBody.append(binding);
        isModifiedBody.append(".");
        isModifiedBody.append(formProperty.getComponentPropertyGetterName());
        isModifiedBody.append("()");
        //
        isModifiedBody.append("!= null ? ");
        //
        isModifiedBody.append("!");
        //
        isModifiedBody.append(binding);
        isModifiedBody.append(".");
        isModifiedBody.append(formProperty.getComponentPropertyGetterName());
        isModifiedBody.append("()");
        //
        isModifiedBody.append(".equals(");
        //
        isModifiedBody.append("data.");
        isModifiedBody.append(binding2beanGetter.get(binding));
        isModifiedBody.append("()");
        isModifiedBody.append(") : ");
        //
        isModifiedBody.append("data.");
        isModifiedBody.append(binding2beanGetter.get(binding));
        isModifiedBody.append("()");
        isModifiedBody.append("!= null");
        //
        isModifiedBody.append(") return true;\n");
      }
    }
    isModifiedBody.append("return false;\n");

    final String textOfMethods =
        "public void setData("
            + dataBeanClassName
            + " data){\n"
            + setDataBody.toString()
            + "}\n"
            + "\n"
            + "public void getData("
            + dataBeanClassName
            + " data){\n"
            + getDataBody.toString()
            + "}\n"
            + "\n"
            + "public boolean isModified("
            + dataBeanClassName
            + " data){\n"
            + isModifiedBody.toString()
            + "}\n";

    // put them to the bound class

    final Module module = ModuleUtil.findModuleForFile(data.myFormFile, data.myProject);
    LOG.assertTrue(module != null);
    final PsiClass boundClass =
        FormEditingUtil.findClassToBind(module, rootContainer[0].getClassToBind());
    LOG.assertTrue(boundClass != null);

    if (!CommonRefactoringUtil.checkReadOnlyStatus(module.getProject(), boundClass)) {
      return;
    }

    // todo: check that this method does not exist yet

    final PsiClass fakeClass;
    try {
      fakeClass =
          JavaPsiFacade.getInstance(data.myProject)
              .getElementFactory()
              .createClassFromText(textOfMethods, null);

      final PsiMethod methodSetData = fakeClass.getMethods()[0];
      final PsiMethod methodGetData = fakeClass.getMethods()[1];
      final PsiMethod methodIsModified = fakeClass.getMethods()[2];

      final PsiMethod existing1 = boundClass.findMethodBySignature(methodSetData, false);
      final PsiMethod existing2 = boundClass.findMethodBySignature(methodGetData, false);
      final PsiMethod existing3 = boundClass.findMethodBySignature(methodIsModified, false);

      // warning already shown
      if (existing1 != null) {
        existing1.delete();
      }
      if (existing2 != null) {
        existing2.delete();
      }
      if (existing3 != null) {
        existing3.delete();
      }

      final CodeStyleManager formatter = CodeStyleManager.getInstance(module.getProject());
      final JavaCodeStyleManager styler = JavaCodeStyleManager.getInstance(module.getProject());

      final PsiElement setData = boundClass.add(methodSetData);
      styler.shortenClassReferences(setData);
      formatter.reformat(setData);

      final PsiElement getData = boundClass.add(methodGetData);
      styler.shortenClassReferences(getData);
      formatter.reformat(getData);

      if (data.myGenerateIsModified) {
        final PsiElement isModified = boundClass.add(methodIsModified);
        styler.shortenClassReferences(isModified);
        formatter.reformat(isModified);
      }

      final OpenFileDescriptor descriptor =
          new OpenFileDescriptor(
              setData.getProject(),
              setData.getContainingFile().getVirtualFile(),
              setData.getTextOffset());
      FileEditorManager.getInstance(data.myProject).openTextEditor(descriptor, true);
    } catch (IncorrectOperationException e) {
      throw new MyException(e.getMessage());
    }
  }
  private static boolean processDeclarationsInClassNotCached(
      @NotNull PsiClass aClass,
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @Nullable Set<PsiClass> visited,
      PsiElement last,
      @NotNull PsiElement place,
      boolean isRaw,
      @NotNull LanguageLevel languageLevel) {
    if (visited == null) visited = new THashSet<PsiClass>();
    if (!visited.add(aClass)) return true;
    processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass);
    final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
    final NameHint nameHint = processor.getHint(NameHint.KEY);

    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) {
      if (nameHint != null) {
        final PsiField fieldByName = aClass.findFieldByName(nameHint.getName(state), false);
        if (fieldByName != null && !processor.execute(fieldByName, state)) return false;
      } else {
        final PsiField[] fields = aClass.getFields();
        for (final PsiField field : fields) {
          if (!processor.execute(field, state)) return false;
        }
      }
    }

    PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();

    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) {
      PsiSubstitutor baseSubstitutor = state.get(PsiSubstitutor.KEY);
      final PsiMethod[] methods =
          nameHint != null
              ? aClass.findMethodsByName(nameHint.getName(state), false)
              : aClass.getMethods();
      for (final PsiMethod method : methods) {
        PsiSubstitutor finalSubstitutor = checkRaw(isRaw, factory, method, baseSubstitutor);
        ResolveState methodState =
            finalSubstitutor == baseSubstitutor
                ? state
                : state.put(PsiSubstitutor.KEY, finalSubstitutor);
        if (!processor.execute(method, methodState)) return false;
      }
    }

    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
      if (last != null && last.getParent() == aClass) {
        // Parameters
        final PsiTypeParameterList list = aClass.getTypeParameterList();
        if (list != null
            && !list.processDeclarations(processor, ResolveState.initial(), last, place))
          return false;
      }

      if (!(last instanceof PsiReferenceList) && !(last instanceof PsiModifierList)) {
        // Inners
        if (nameHint != null) {
          final PsiClass inner = aClass.findInnerClassByName(nameHint.getName(state), false);
          if (inner != null) {
            if (!processor.execute(inner, state)) return false;
          }
        } else {
          final PsiClass[] inners = aClass.getInnerClasses();
          for (final PsiClass inner : inners) {
            if (!processor.execute(inner, state)) return false;
          }
        }
      }
    }

    return last instanceof PsiReferenceList
        || processSuperTypes(
            aClass, processor, visited, last, place, state, isRaw, factory, languageLevel);
  }