Program: 12195
Project: 12195
Buggy source:
private void modifyInheritanceHierarchy(){
  IContainer contextContainer=(IContainer)sourceFile.getParent();
  PackageDeclaration contextPackageDeclaration=sourceCompilationUnit.getPackage();
  IContainer rootContainer=contextContainer;
  if (contextPackageDeclaration != null) {
    String packageName=contextPackageDeclaration.getName().getFullyQualifiedName();
    String[] subPackages=packageName.split("String_Node_Str");
    for (int i=0; i < subPackages.length; i++)     rootContainer=(IContainer)rootContainer.getParent();
  }
  String abstractClassFullyQualifiedName=typeCheckElimination.getAbstractClassName();
  IFile abstractClassFile=getFile(rootContainer,abstractClassFullyQualifiedName);
  IJavaElement abstractJavaElement=JavaCore.create(abstractClassFile);
  ITextEditor abstractEditor=null;
  try {
    abstractEditor=(ITextEditor)JavaUI.openInEditor(abstractJavaElement);
  }
 catch (  PartInitException e) {
    e.printStackTrace();
  }
catch (  JavaModelException e) {
    e.printStackTrace();
  }
  ICompilationUnit abstractICompilationUnit=(ICompilationUnit)abstractJavaElement;
  ASTParser abstractParser=ASTParser.newParser(AST.JLS3);
  abstractParser.setKind(ASTParser.K_COMPILATION_UNIT);
  abstractParser.setSource(abstractICompilationUnit);
  abstractParser.setResolveBindings(true);
  CompilationUnit abstractCompilationUnit=(CompilationUnit)abstractParser.createAST(null);
  AST abstractAST=abstractCompilationUnit.getAST();
  ASTRewrite abstractRewriter=ASTRewrite.create(abstractAST);
  TypeDeclaration abstractClassTypeDeclaration=null;
  List<AbstractTypeDeclaration> abstractTypeDeclarations=abstractCompilationUnit.types();
  for (  AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
    if (abstractTypeDeclaration instanceof TypeDeclaration) {
      TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
      if (typeDeclaration.resolveBinding().getQualifiedName().equals(typeCheckElimination.getAbstractClassName())) {
        abstractClassTypeDeclaration=typeDeclaration;
        break;
      }
    }
  }
  int abstractClassModifiers=abstractClassTypeDeclaration.getModifiers();
  if ((abstractClassModifiers & Modifier.ABSTRACT) == 0 && !abstractClassTypeDeclaration.isInterface()) {
    ListRewrite abstractModifiersRewrite=abstractRewriter.getListRewrite(abstractClassTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
    abstractModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  }
  ListRewrite abstractBodyRewrite=abstractRewriter.getListRewrite(abstractClassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
  MethodDeclaration abstractMethodDeclaration=abstractAST.newMethodDeclaration();
  abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.NAME_PROPERTY,abstractAST.newSimpleName(abstractMethodName),null);
  abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
  ListRewrite abstractMethodModifiersRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
  abstractMethodModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
  abstractMethodModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  ListRewrite abstractMethodParametersRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
  for (  SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
    abstractMethodParametersRewrite.insertLast(abstractMethodParameter,null);
  }
  for (  VariableDeclarationFragment fragment : typeCheckElimination.getAccessedLocalVariables()) {
    if (!fragment.equals(returnedVariable)) {
      SingleVariableDeclaration parameter=abstractAST.newSingleVariableDeclaration();
      VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)fragment.getParent();
      abstractRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,variableDeclarationStatement.getType(),null);
      abstractRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,fragment.getName(),null);
      abstractMethodParametersRewrite.insertLast(parameter,null);
    }
  }
  Set<VariableDeclarationFragment> accessedFields=typeCheckElimination.getAccessedFields();
  Set<VariableDeclarationFragment> assignedFields=typeCheckElimination.getAssignedFields();
  Set<MethodDeclaration> accessedMethods=typeCheckElimination.getAccessedMethods();
  Set<IMethodBinding> superAccessedMethods=typeCheckElimination.getSuperAccessedMethods();
  if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0) {
    SingleVariableDeclaration parameter=abstractAST.newSingleVariableDeclaration();
    SimpleName parameterType=abstractAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
    abstractRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,abstractAST.newSimpleType(parameterType),null);
    String parameterName=sourceTypeDeclaration.getName().getIdentifier();
    parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
    abstractRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,abstractAST.newSimpleName(parameterName),null);
    abstractMethodParametersRewrite.insertLast(parameter,null);
  }
  ListRewrite abstractMethodThrownExceptionsRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
  for (  ITypeBinding typeBinding : thrownExceptions) {
    abstractMethodThrownExceptionsRewrite.insertLast(abstractAST.newSimpleName(typeBinding.getName()),null);
  }
  abstractBodyRewrite.insertLast(abstractMethodDeclaration,null);
  generateRequiredImportDeclarationsBasedOnSignature();
  for (  ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
    addImportDeclaration(typeBinding,abstractCompilationUnit,abstractRewriter);
  }
  ITextFileBufferManager bufferManager=FileBuffers.getTextFileBufferManager();
  ITextFileBuffer abstractTextFileBuffer=bufferManager.getTextFileBuffer(abstractClassFile.getFullPath(),LocationKind.IFILE);
  IDocument abstractDocument=abstractTextFileBuffer.getDocument();
  TextEdit abstractEdit=abstractRewriter.rewriteAST(abstractDocument,null);
  try {
    UndoEdit abstractUndoEdit=abstractEdit.apply(abstractDocument,UndoEdit.CREATE_UNDO);
    undoRefactoring.put(abstractClassFile,abstractDocument,abstractUndoEdit);
  }
 catch (  MalformedTreeException e) {
    e.printStackTrace();
  }
catch (  BadLocationException e) {
    e.printStackTrace();
  }
  abstractEditor.doSave(null);
  List<ArrayList<Statement>> typeCheckStatements=typeCheckElimination.getTypeCheckStatements();
  List<String> subclassNames=typeCheckElimination.getSubclassNames();
  DefaultMutableTreeNode root=typeCheckElimination.getExistingInheritanceTree().getRootNode();
  Enumeration<DefaultMutableTreeNode> enumeration=root.children();
  while (enumeration.hasMoreElements()) {
    DefaultMutableTreeNode child=enumeration.nextElement();
    String childClassName=(String)child.getUserObject();
    if (!subclassNames.contains(childClassName))     subclassNames.add(childClassName);
  }
  for (int i=0; i < subclassNames.size(); i++) {
    ArrayList<Statement> statements=null;
    DefaultMutableTreeNode remainingIfStatementExpression=null;
    if (i < typeCheckStatements.size()) {
      statements=typeCheckStatements.get(i);
      Expression expression=typeCheckElimination.getExpressionCorrespondingToTypeCheckStatementList(statements);
      remainingIfStatementExpression=typeCheckElimination.getRemainingIfStatementExpression(expression);
    }
 else {
      statements=typeCheckElimination.getDefaultCaseStatements();
    }
    IFile subclassFile=getFile(rootContainer,subclassNames.get(i));
    IJavaElement subclassJavaElement=JavaCore.create(subclassFile);
    ITextEditor subclassEditor=null;
    try {
      subclassEditor=(ITextEditor)JavaUI.openInEditor(subclassJavaElement);
    }
 catch (    PartInitException e) {
      e.printStackTrace();
    }
catch (    JavaModelException e) {
      e.printStackTrace();
    }
    ICompilationUnit subclassICompilationUnit=(ICompilationUnit)subclassJavaElement;
    ASTParser subclassParser=ASTParser.newParser(AST.JLS3);
    subclassParser.setKind(ASTParser.K_COMPILATION_UNIT);
    subclassParser.setSource(subclassICompilationUnit);
    subclassParser.setResolveBindings(true);
    CompilationUnit subclassCompilationUnit=(CompilationUnit)subclassParser.createAST(null);
    AST subclassAST=subclassCompilationUnit.getAST();
    ASTRewrite subclassRewriter=ASTRewrite.create(subclassAST);
    TypeDeclaration subclassTypeDeclaration=null;
    List<AbstractTypeDeclaration> subclassAbstractTypeDeclarations=subclassCompilationUnit.types();
    for (    AbstractTypeDeclaration abstractTypeDeclaration : subclassAbstractTypeDeclarations) {
      if (abstractTypeDeclaration instanceof TypeDeclaration) {
        TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
        if (typeDeclaration.resolveBinding().getQualifiedName().equals(subclassNames.get(i))) {
          subclassTypeDeclaration=typeDeclaration;
          break;
        }
      }
    }
    ListRewrite subclassBodyRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
    MethodDeclaration concreteMethodDeclaration=subclassAST.newMethodDeclaration();
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(abstractMethodName),null);
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
    ListRewrite concreteMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
    concreteMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
    ListRewrite concreteMethodParametersRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
    for (    SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
      concreteMethodParametersRewrite.insertLast(abstractMethodParameter,null);
    }
    for (    VariableDeclarationFragment fragment : typeCheckElimination.getAccessedLocalVariables()) {
      if (!fragment.equals(returnedVariable)) {
        SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)fragment.getParent();
        subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,variableDeclarationStatement.getType(),null);
        subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,fragment.getName(),null);
        concreteMethodParametersRewrite.insertLast(parameter,null);
      }
    }
    if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0) {
      SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
      SimpleName parameterType=subclassAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
      subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,subclassAST.newSimpleType(parameterType),null);
      String parameterName=sourceTypeDeclaration.getName().getIdentifier();
      parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
      subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(parameterName),null);
      concreteMethodParametersRewrite.insertLast(parameter,null);
    }
    ListRewrite concreteMethodThrownExceptionsRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
    for (    ITypeBinding typeBinding : thrownExceptions) {
      concreteMethodThrownExceptionsRewrite.insertLast(subclassAST.newSimpleName(typeBinding.getName()),null);
    }
    Block concreteMethodBody=subclassAST.newBlock();
    ListRewrite concreteMethodBodyRewrite=subclassRewriter.getListRewrite(concreteMethodBody,Block.STATEMENTS_PROPERTY);
    ExpressionExtractor expressionExtractor=new ExpressionExtractor();
    ListRewrite ifStatementBodyRewrite=null;
    if (remainingIfStatementExpression != null) {
      IfStatement enclosingIfStatement=subclassAST.newIfStatement();
      Expression enclosingIfStatementExpression=constructExpression(subclassAST,remainingIfStatementExpression);
      Expression newEnclosingIfStatementExpression=(Expression)ASTNode.copySubtree(subclassAST,enclosingIfStatementExpression);
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(enclosingIfStatementExpression);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newEnclosingIfStatementExpression);
      modifyVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(enclosingIfStatementExpression);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newEnclosingIfStatementExpression);
      modifyMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      subclassRewriter.set(enclosingIfStatement,IfStatement.EXPRESSION_PROPERTY,newEnclosingIfStatementExpression,null);
      Block ifStatementBody=subclassAST.newBlock();
      ifStatementBodyRewrite=subclassRewriter.getListRewrite(ifStatementBody,Block.STATEMENTS_PROPERTY);
      subclassRewriter.set(enclosingIfStatement,IfStatement.THEN_STATEMENT_PROPERTY,ifStatementBody,null);
      concreteMethodBodyRewrite.insertLast(enclosingIfStatement,null);
    }
    if (returnedVariable != null && !returnedVariable.resolveBinding().isParameter()) {
      VariableDeclarationFragment variableDeclarationFragment=subclassAST.newVariableDeclarationFragment();
      subclassRewriter.set(variableDeclarationFragment,VariableDeclarationFragment.NAME_PROPERTY,returnedVariable.getName(),null);
      subclassRewriter.set(variableDeclarationFragment,VariableDeclarationFragment.INITIALIZER_PROPERTY,returnedVariable.getInitializer(),null);
      VariableDeclarationStatement variableDeclarationStatement=subclassAST.newVariableDeclarationStatement(variableDeclarationFragment);
      subclassRewriter.set(variableDeclarationStatement,VariableDeclarationStatement.TYPE_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
      concreteMethodBodyRewrite.insertFirst(variableDeclarationStatement,null);
    }
    SimpleName invokerSimpleName=null;
    for (    Statement statement : statements) {
      Statement newStatement=(Statement)ASTNode.copySubtree(subclassAST,statement);
      boolean insert=true;
      if (statement instanceof VariableDeclarationStatement) {
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)statement;
        List<VariableDeclarationFragment> fragments=variableDeclarationStatement.fragments();
        VariableDeclarationFragment fragment=fragments.get(0);
        if (fragment.getInitializer() instanceof CastExpression) {
          CastExpression castExpression=(CastExpression)fragment.getInitializer();
          if (castExpression.getType().resolveBinding().isEqualTo(subclassTypeDeclaration.resolveBinding())) {
            invokerSimpleName=fragment.getName();
            insert=false;
          }
        }
      }
 else {
        StatementExtractor statementExtractor=new StatementExtractor();
        List<Statement> oldVariableDeclarations=statementExtractor.getVariableDeclarations(statement);
        List<Statement> newVariableDeclarations=statementExtractor.getVariableDeclarations(newStatement);
        int j=0;
        for (        Statement oldVariableDeclaration : oldVariableDeclarations) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)oldVariableDeclaration;
          List<VariableDeclarationFragment> fragments=variableDeclarationStatement.fragments();
          VariableDeclarationFragment fragment=fragments.get(0);
          if (fragment.getInitializer() instanceof CastExpression) {
            CastExpression castExpression=(CastExpression)fragment.getInitializer();
            if (castExpression.getType().resolveBinding().isEqualTo(subclassTypeDeclaration.resolveBinding())) {
              invokerSimpleName=fragment.getName();
              subclassRewriter.remove(newVariableDeclarations.get(j),null);
              break;
            }
          }
          j++;
        }
      }
      if (invokerSimpleName != null) {
        List<Expression> methodInvocations=expressionExtractor.getMethodInvocations(newStatement);
        for (        Expression expression : methodInvocations) {
          if (expression instanceof MethodInvocation) {
            MethodInvocation methodInvocation=(MethodInvocation)expression;
            Expression methodInvocationExpression=methodInvocation.getExpression();
            if (methodInvocationExpression instanceof SimpleName) {
              SimpleName simpleName=(SimpleName)methodInvocationExpression;
              if (simpleName.getIdentifier().equals(invokerSimpleName.getIdentifier())) {
                subclassRewriter.remove(simpleName,null);
              }
            }
          }
        }
      }
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(statement);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newStatement);
      modifyVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(statement);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newStatement);
      modifyMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      if (insert) {
        if (ifStatementBodyRewrite != null)         ifStatementBodyRewrite.insertLast(newStatement,null);
 else         concreteMethodBodyRewrite.insertLast(newStatement,null);
      }
    }
    if (returnedVariable != null) {
      ReturnStatement returnStatement=subclassAST.newReturnStatement();
      subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,returnedVariable.getName(),null);
      concreteMethodBodyRewrite.insertLast(returnStatement,null);
    }
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteMethodBody,null);
    subclassBodyRewrite.insertLast(concreteMethodDeclaration,null);
    for (    ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
      addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
    }
    Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=generateRequiredImportDeclarationsBasedOnBranch(statements);
    for (    ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
      if (!requiredImportDeclarationsBasedOnSignature.contains(typeBinding))       addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
    }
    ITextFileBuffer subclassTextFileBuffer=bufferManager.getTextFileBuffer(subclassFile.getFullPath(),LocationKind.IFILE);
    IDocument subclassDocument=subclassTextFileBuffer.getDocument();
    TextEdit subclassEdit=subclassRewriter.rewriteAST(subclassDocument,null);
    try {
      UndoEdit subclassUndoEdit=subclassEdit.apply(subclassDocument,UndoEdit.CREATE_UNDO);
      undoRefactoring.put(subclassFile,subclassDocument,subclassUndoEdit);
    }
 catch (    MalformedTreeException e) {
      e.printStackTrace();
    }
catch (    BadLocationException e) {
      e.printStackTrace();
    }
    subclassEditor.doSave(null);
  }
}

Fixed version (ground truth):
private void modifyInheritanceHierarchy(){
  IContainer contextContainer=(IContainer)sourceFile.getParent();
  PackageDeclaration contextPackageDeclaration=sourceCompilationUnit.getPackage();
  IContainer rootContainer=contextContainer;
  if (contextPackageDeclaration != null) {
    String packageName=contextPackageDeclaration.getName().getFullyQualifiedName();
    String[] subPackages=packageName.split("String_Node_Str");
    for (int i=0; i < subPackages.length; i++)     rootContainer=(IContainer)rootContainer.getParent();
  }
  String abstractClassFullyQualifiedName=typeCheckElimination.getAbstractClassName();
  IFile abstractClassFile=getFile(rootContainer,abstractClassFullyQualifiedName);
  IJavaElement abstractJavaElement=JavaCore.create(abstractClassFile);
  ITextEditor abstractEditor=null;
  try {
    abstractEditor=(ITextEditor)JavaUI.openInEditor(abstractJavaElement);
  }
 catch (  PartInitException e) {
    e.printStackTrace();
  }
catch (  JavaModelException e) {
    e.printStackTrace();
  }
  ICompilationUnit abstractICompilationUnit=(ICompilationUnit)abstractJavaElement;
  ASTParser abstractParser=ASTParser.newParser(AST.JLS3);
  abstractParser.setKind(ASTParser.K_COMPILATION_UNIT);
  abstractParser.setSource(abstractICompilationUnit);
  abstractParser.setResolveBindings(true);
  CompilationUnit abstractCompilationUnit=(CompilationUnit)abstractParser.createAST(null);
  AST abstractAST=abstractCompilationUnit.getAST();
  ASTRewrite abstractRewriter=ASTRewrite.create(abstractAST);
  TypeDeclaration abstractClassTypeDeclaration=null;
  List<AbstractTypeDeclaration> abstractTypeDeclarations=abstractCompilationUnit.types();
  for (  AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
    if (abstractTypeDeclaration instanceof TypeDeclaration) {
      TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
      if (typeDeclaration.resolveBinding().getQualifiedName().equals(typeCheckElimination.getAbstractClassName())) {
        abstractClassTypeDeclaration=typeDeclaration;
        break;
      }
    }
  }
  int abstractClassModifiers=abstractClassTypeDeclaration.getModifiers();
  if ((abstractClassModifiers & Modifier.ABSTRACT) == 0 && !abstractClassTypeDeclaration.isInterface()) {
    ListRewrite abstractModifiersRewrite=abstractRewriter.getListRewrite(abstractClassTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
    abstractModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  }
  ListRewrite abstractBodyRewrite=abstractRewriter.getListRewrite(abstractClassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
  MethodDeclaration abstractMethodDeclaration=abstractAST.newMethodDeclaration();
  abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.NAME_PROPERTY,abstractAST.newSimpleName(abstractMethodName),null);
  if (returnedVariable == null && !typeCheckElimination.typeCheckCodeFragmentContainsReturnStatement()) {
    abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,abstractAST.newPrimitiveType(PrimitiveType.VOID),null);
  }
 else {
    if (returnedVariable != null) {
      Type returnType=null;
      if (returnedVariable instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
        returnType=singleVariableDeclaration.getType();
      }
 else       if (returnedVariable instanceof VariableDeclarationFragment) {
        VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
        returnType=variableDeclarationStatement.getType();
      }
      abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
    }
 else {
      abstractRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
    }
  }
  ListRewrite abstractMethodModifiersRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
  abstractMethodModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
  abstractMethodModifiersRewrite.insertLast(abstractAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  ListRewrite abstractMethodParametersRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
  for (  SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
    abstractMethodParametersRewrite.insertLast(abstractMethodParameter,null);
  }
  for (  VariableDeclarationFragment fragment : typeCheckElimination.getAccessedLocalVariables()) {
    if (!fragment.equals(returnedVariable)) {
      SingleVariableDeclaration parameter=abstractAST.newSingleVariableDeclaration();
      VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)fragment.getParent();
      abstractRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,variableDeclarationStatement.getType(),null);
      abstractRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,fragment.getName(),null);
      abstractMethodParametersRewrite.insertLast(parameter,null);
    }
  }
  Set<VariableDeclarationFragment> accessedFields=typeCheckElimination.getAccessedFields();
  Set<VariableDeclarationFragment> assignedFields=typeCheckElimination.getAssignedFields();
  Set<MethodDeclaration> accessedMethods=typeCheckElimination.getAccessedMethods();
  Set<IMethodBinding> superAccessedMethods=typeCheckElimination.getSuperAccessedMethods();
  if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0) {
    SingleVariableDeclaration parameter=abstractAST.newSingleVariableDeclaration();
    SimpleName parameterType=abstractAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
    abstractRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,abstractAST.newSimpleType(parameterType),null);
    String parameterName=sourceTypeDeclaration.getName().getIdentifier();
    parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
    abstractRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,abstractAST.newSimpleName(parameterName),null);
    abstractMethodParametersRewrite.insertLast(parameter,null);
  }
  ListRewrite abstractMethodThrownExceptionsRewrite=abstractRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
  for (  ITypeBinding typeBinding : thrownExceptions) {
    abstractMethodThrownExceptionsRewrite.insertLast(abstractAST.newSimpleName(typeBinding.getName()),null);
  }
  abstractBodyRewrite.insertLast(abstractMethodDeclaration,null);
  generateRequiredImportDeclarationsBasedOnSignature();
  for (  ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
    addImportDeclaration(typeBinding,abstractCompilationUnit,abstractRewriter);
  }
  ITextFileBufferManager bufferManager=FileBuffers.getTextFileBufferManager();
  ITextFileBuffer abstractTextFileBuffer=bufferManager.getTextFileBuffer(abstractClassFile.getFullPath(),LocationKind.IFILE);
  IDocument abstractDocument=abstractTextFileBuffer.getDocument();
  TextEdit abstractEdit=abstractRewriter.rewriteAST(abstractDocument,null);
  try {
    UndoEdit abstractUndoEdit=abstractEdit.apply(abstractDocument,UndoEdit.CREATE_UNDO);
    undoRefactoring.put(abstractClassFile,abstractDocument,abstractUndoEdit);
  }
 catch (  MalformedTreeException e) {
    e.printStackTrace();
  }
catch (  BadLocationException e) {
    e.printStackTrace();
  }
  abstractEditor.doSave(null);
  List<ArrayList<Statement>> typeCheckStatements=typeCheckElimination.getTypeCheckStatements();
  List<String> subclassNames=typeCheckElimination.getSubclassNames();
  DefaultMutableTreeNode root=typeCheckElimination.getExistingInheritanceTree().getRootNode();
  Enumeration<DefaultMutableTreeNode> enumeration=root.children();
  while (enumeration.hasMoreElements()) {
    DefaultMutableTreeNode child=enumeration.nextElement();
    String childClassName=(String)child.getUserObject();
    if (!subclassNames.contains(childClassName))     subclassNames.add(childClassName);
  }
  for (int i=0; i < subclassNames.size(); i++) {
    ArrayList<Statement> statements=null;
    DefaultMutableTreeNode remainingIfStatementExpression=null;
    if (i < typeCheckStatements.size()) {
      statements=typeCheckStatements.get(i);
      Expression expression=typeCheckElimination.getExpressionCorrespondingToTypeCheckStatementList(statements);
      remainingIfStatementExpression=typeCheckElimination.getRemainingIfStatementExpression(expression);
    }
 else {
      statements=typeCheckElimination.getDefaultCaseStatements();
    }
    IFile subclassFile=getFile(rootContainer,subclassNames.get(i));
    IJavaElement subclassJavaElement=JavaCore.create(subclassFile);
    ITextEditor subclassEditor=null;
    try {
      subclassEditor=(ITextEditor)JavaUI.openInEditor(subclassJavaElement);
    }
 catch (    PartInitException e) {
      e.printStackTrace();
    }
catch (    JavaModelException e) {
      e.printStackTrace();
    }
    ICompilationUnit subclassICompilationUnit=(ICompilationUnit)subclassJavaElement;
    ASTParser subclassParser=ASTParser.newParser(AST.JLS3);
    subclassParser.setKind(ASTParser.K_COMPILATION_UNIT);
    subclassParser.setSource(subclassICompilationUnit);
    subclassParser.setResolveBindings(true);
    CompilationUnit subclassCompilationUnit=(CompilationUnit)subclassParser.createAST(null);
    AST subclassAST=subclassCompilationUnit.getAST();
    ASTRewrite subclassRewriter=ASTRewrite.create(subclassAST);
    TypeDeclaration subclassTypeDeclaration=null;
    List<AbstractTypeDeclaration> subclassAbstractTypeDeclarations=subclassCompilationUnit.types();
    for (    AbstractTypeDeclaration abstractTypeDeclaration : subclassAbstractTypeDeclarations) {
      if (abstractTypeDeclaration instanceof TypeDeclaration) {
        TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
        if (typeDeclaration.resolveBinding().getQualifiedName().equals(subclassNames.get(i))) {
          subclassTypeDeclaration=typeDeclaration;
          break;
        }
      }
    }
    ListRewrite subclassBodyRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
    MethodDeclaration concreteMethodDeclaration=subclassAST.newMethodDeclaration();
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(abstractMethodName),null);
    if (returnedVariable == null && !typeCheckElimination.typeCheckCodeFragmentContainsReturnStatement()) {
      subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,subclassAST.newPrimitiveType(PrimitiveType.VOID),null);
    }
 else {
      if (returnedVariable != null) {
        Type returnType=null;
        if (returnedVariable instanceof SingleVariableDeclaration) {
          SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
          returnType=singleVariableDeclaration.getType();
        }
 else         if (returnedVariable instanceof VariableDeclarationFragment) {
          VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          returnType=variableDeclarationStatement.getType();
        }
        subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
      }
 else {
        subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
      }
    }
    ListRewrite concreteMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
    concreteMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
    ListRewrite concreteMethodParametersRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
    for (    SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
      concreteMethodParametersRewrite.insertLast(abstractMethodParameter,null);
    }
    for (    VariableDeclarationFragment fragment : typeCheckElimination.getAccessedLocalVariables()) {
      if (!fragment.equals(returnedVariable)) {
        SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)fragment.getParent();
        subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,variableDeclarationStatement.getType(),null);
        subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,fragment.getName(),null);
        concreteMethodParametersRewrite.insertLast(parameter,null);
      }
    }
    if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0) {
      SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
      SimpleName parameterType=subclassAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
      subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,subclassAST.newSimpleType(parameterType),null);
      String parameterName=sourceTypeDeclaration.getName().getIdentifier();
      parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
      subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(parameterName),null);
      concreteMethodParametersRewrite.insertLast(parameter,null);
    }
    ListRewrite concreteMethodThrownExceptionsRewrite=subclassRewriter.getListRewrite(concreteMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
    for (    ITypeBinding typeBinding : thrownExceptions) {
      concreteMethodThrownExceptionsRewrite.insertLast(subclassAST.newSimpleName(typeBinding.getName()),null);
    }
    Block concreteMethodBody=subclassAST.newBlock();
    ListRewrite concreteMethodBodyRewrite=subclassRewriter.getListRewrite(concreteMethodBody,Block.STATEMENTS_PROPERTY);
    ExpressionExtractor expressionExtractor=new ExpressionExtractor();
    ListRewrite ifStatementBodyRewrite=null;
    if (remainingIfStatementExpression != null) {
      IfStatement enclosingIfStatement=subclassAST.newIfStatement();
      Expression enclosingIfStatementExpression=constructExpression(subclassAST,remainingIfStatementExpression);
      Expression newEnclosingIfStatementExpression=(Expression)ASTNode.copySubtree(subclassAST,enclosingIfStatementExpression);
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(enclosingIfStatementExpression);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newEnclosingIfStatementExpression);
      modifyVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(enclosingIfStatementExpression);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newEnclosingIfStatementExpression);
      modifyMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      subclassRewriter.set(enclosingIfStatement,IfStatement.EXPRESSION_PROPERTY,newEnclosingIfStatementExpression,null);
      Block ifStatementBody=subclassAST.newBlock();
      ifStatementBodyRewrite=subclassRewriter.getListRewrite(ifStatementBody,Block.STATEMENTS_PROPERTY);
      subclassRewriter.set(enclosingIfStatement,IfStatement.THEN_STATEMENT_PROPERTY,ifStatementBody,null);
      concreteMethodBodyRewrite.insertLast(enclosingIfStatement,null);
    }
    if (returnedVariable != null && !returnedVariable.resolveBinding().isParameter()) {
      VariableDeclarationFragment variableDeclarationFragment=subclassAST.newVariableDeclarationFragment();
      subclassRewriter.set(variableDeclarationFragment,VariableDeclarationFragment.NAME_PROPERTY,returnedVariable.getName(),null);
      subclassRewriter.set(variableDeclarationFragment,VariableDeclarationFragment.INITIALIZER_PROPERTY,returnedVariable.getInitializer(),null);
      VariableDeclarationStatement variableDeclarationStatement=subclassAST.newVariableDeclarationStatement(variableDeclarationFragment);
      subclassRewriter.set(variableDeclarationStatement,VariableDeclarationStatement.TYPE_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
      concreteMethodBodyRewrite.insertFirst(variableDeclarationStatement,null);
    }
    SimpleName invokerSimpleName=null;
    for (    Statement statement : statements) {
      Statement newStatement=(Statement)ASTNode.copySubtree(subclassAST,statement);
      boolean insert=true;
      if (statement instanceof VariableDeclarationStatement) {
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)statement;
        List<VariableDeclarationFragment> fragments=variableDeclarationStatement.fragments();
        VariableDeclarationFragment fragment=fragments.get(0);
        if (fragment.getInitializer() instanceof CastExpression) {
          CastExpression castExpression=(CastExpression)fragment.getInitializer();
          if (castExpression.getType().resolveBinding().isEqualTo(subclassTypeDeclaration.resolveBinding())) {
            invokerSimpleName=fragment.getName();
            insert=false;
          }
        }
      }
 else {
        StatementExtractor statementExtractor=new StatementExtractor();
        List<Statement> oldVariableDeclarations=statementExtractor.getVariableDeclarations(statement);
        List<Statement> newVariableDeclarations=statementExtractor.getVariableDeclarations(newStatement);
        int j=0;
        for (        Statement oldVariableDeclaration : oldVariableDeclarations) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)oldVariableDeclaration;
          List<VariableDeclarationFragment> fragments=variableDeclarationStatement.fragments();
          VariableDeclarationFragment fragment=fragments.get(0);
          if (fragment.getInitializer() instanceof CastExpression) {
            CastExpression castExpression=(CastExpression)fragment.getInitializer();
            if (castExpression.getType().resolveBinding().isEqualTo(subclassTypeDeclaration.resolveBinding())) {
              invokerSimpleName=fragment.getName();
              subclassRewriter.remove(newVariableDeclarations.get(j),null);
              break;
            }
          }
          j++;
        }
      }
      if (invokerSimpleName != null) {
        List<Expression> methodInvocations=expressionExtractor.getMethodInvocations(newStatement);
        for (        Expression expression : methodInvocations) {
          if (expression instanceof MethodInvocation) {
            MethodInvocation methodInvocation=(MethodInvocation)expression;
            Expression methodInvocationExpression=methodInvocation.getExpression();
            if (methodInvocationExpression instanceof SimpleName) {
              SimpleName simpleName=(SimpleName)methodInvocationExpression;
              if (simpleName.getIdentifier().equals(invokerSimpleName.getIdentifier())) {
                subclassRewriter.remove(simpleName,null);
              }
            }
          }
        }
      }
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(statement);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newStatement);
      modifyVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(statement);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newStatement);
      modifyMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      if (insert) {
        if (ifStatementBodyRewrite != null)         ifStatementBodyRewrite.insertLast(newStatement,null);
 else         concreteMethodBodyRewrite.insertLast(newStatement,null);
      }
    }
    if (returnedVariable != null) {
      ReturnStatement returnStatement=subclassAST.newReturnStatement();
      subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,returnedVariable.getName(),null);
      concreteMethodBodyRewrite.insertLast(returnStatement,null);
    }
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteMethodBody,null);
    subclassBodyRewrite.insertLast(concreteMethodDeclaration,null);
    for (    ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
      addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
    }
    Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=generateRequiredImportDeclarationsBasedOnBranch(statements);
    for (    ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
      if (!requiredImportDeclarationsBasedOnSignature.contains(typeBinding))       addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
    }
    ITextFileBuffer subclassTextFileBuffer=bufferManager.getTextFileBuffer(subclassFile.getFullPath(),LocationKind.IFILE);
    IDocument subclassDocument=subclassTextFileBuffer.getDocument();
    TextEdit subclassEdit=subclassRewriter.rewriteAST(subclassDocument,null);
    try {
      UndoEdit subclassUndoEdit=subclassEdit.apply(subclassDocument,UndoEdit.CREATE_UNDO);
      undoRefactoring.put(subclassFile,subclassDocument,subclassUndoEdit);
    }
 catch (    MalformedTreeException e) {
      e.printStackTrace();
    }
catch (    BadLocationException e) {
      e.printStackTrace();
    }
    subclassEditor.doSave(null);
  }
}