/*
  * Checks whether the visibility of the method can be changed to the given
  * level. If not, an error entry is added to the RefactoringStatus object.
  *
  * @param method method to be checked
  * @param visibility target method visibility
  * @param status
  */
 private void checkVisibilityChange(BinMethod method, int visibility, List errors) {
   if (BinModifier.hasFlag(method.getAccessModifier(), visibility)) {
     // method already has this visibility
     return;
   } else {
     List usages = getInvocationsForMethod(method);
     int[] allowedVisibilities = MinimizeAccessUtil.findMethodAccessRights(method, usages);
     Arrays.sort(allowedVisibilities);
     if (Arrays.binarySearch(allowedVisibilities, visibility) < 0) {
       errors.add(
           "The visibility of the method cannot be changed to "
               + new BinModifierFormatter(visibility, true).print());
     }
   }
 }
  /** @see net.sf.refactorit.refactorings.Refactoring#performChange */
  public TransformationList performChange() {
    TransformationList transList = new TransformationList();

    if (this.fieldVisibility != -1) {
      int changedAccessModifier = -1;
      MemberVisibilityAnalyzer accessAnalyzer = new MemberVisibilityAnalyzer(this.field);
      int allowedAccess = accessAnalyzer.getPosterioriFieldAccess(this.getAllUsages(), this.usages);
      if (this.fieldVisibility == BinModifier.PRIVATE) {
        if (allowedAccess != BinModifier.PRIVATE) {
          changedAccessModifier = allowedAccess;
        }
      } else if (this.fieldVisibility == BinModifier.PACKAGE_PRIVATE) {
        if ((allowedAccess != BinModifier.PRIVATE)
            && (allowedAccess != BinModifier.PACKAGE_PRIVATE)) {
          changedAccessModifier = allowedAccess;
        }
      } else if (this.fieldVisibility == BinModifier.PROTECTED) {
        if (allowedAccess == BinModifier.PUBLIC) {
          changedAccessModifier = allowedAccess;
        }
      }
      if (changedAccessModifier != -1) {
        transList
            .getStatus()
            .addEntry(
                "Couldn't change field access to "
                    + getAccessName(fieldVisibility)
                    + ".\n"
                    + "Using "
                    + getAccessName(changedAccessModifier)
                    + " access instead.",
                RefactoringStatus.WARNING);
        this.fieldVisibility = changedAccessModifier;
      }
    }

    Map usageMap = new HashMap();

    for (int i = 0; i < usages.size(); ++i) {
      EncapsulationInvocationData id = (EncapsulationInvocationData) usages.get(i);
      if (id.isEncapsulationPossible()) {
        CompilationUnit sf = id.getCompilationUnit();
        List usagesInSource = (List) usageMap.get(sf);
        if (usagesInSource == null) {
          usagesInSource = new ArrayList();
          usageMap.put(sf, usagesInSource);
        }
        usagesInSource.add(id);
      }
    }

    for (Iterator i = usageMap.keySet().iterator(); i.hasNext(); ) {
      CompilationUnit compilationUnit = (CompilationUnit) i.next();
      new EncapsulateEditor(field, getterName, setterName, (List) usageMap.get(compilationUnit))
          .generateEditors(transList);
    }

    int column = 0;
    int line = 0;

    BinClass hostingClass = (BinClass) getField().getOwner().getBinCIType();
    line = hostingClass.getEndLine();

    StringBuffer buffer = new StringBuffer();

    if (encapsulateRead) {
      BinMethod getter = getGetterMethod();
      if (getter == null) {
        buffer.append(createGetterBody());
      } else {
        transList.add(
            new ModifierEditor(
                getter, BinModifier.setFlags(getter.getModifiers(), this.getGetterVisibility())));
      }
    }

    if (encapsulateWrite) {
      BinMethod setter = getSetterMethod();
      if (setter == null) {
        buffer.append(createSetterBody());
      } else {
        transList.add(
            new ModifierEditor(
                setter, BinModifier.setFlags(setter.getModifiers(), this.getSetterVisibility())));
      }
    }

    if (buffer.length() > 0) {
      StringInserter inserter =
          new StringInserter(hostingClass.getCompilationUnit(), line, column, buffer.toString());
      transList.add(inserter);
    }

    if (this.fieldVisibility != -1) {
      transList.add(
          new ModifierEditor(field, BinModifier.setFlags(field.getModifiers(), fieldVisibility)));
    }

    return transList;
  }