Program: 12086
Project: 12086
Buggy source:
private void createStateStrategyHierarchy(){
  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();
  }
  InheritanceTree tree=typeCheckElimination.getInheritanceTreeMatchingWithStaticTypes();
  IFile stateStrategyFile=null;
  if (tree != null) {
    DefaultMutableTreeNode rootNode=tree.getRootNode();
    stateStrategyFile=getFile(rootContainer,(String)rootNode.getUserObject());
  }
 else {
    if (contextContainer instanceof IProject) {
      IProject contextProject=(IProject)contextContainer;
      stateStrategyFile=contextProject.getFile(abstractClassName + "String_Node_Str");
    }
 else     if (contextContainer instanceof IFolder) {
      IFolder contextFolder=(IFolder)contextContainer;
      stateStrategyFile=contextFolder.getFile(abstractClassName + "String_Node_Str");
    }
  }
  boolean stateStrategyAlreadyExists=false;
  ICompilationUnit stateStrategyICompilationUnit=JavaCore.createCompilationUnitFrom(stateStrategyFile);
  javaElementsToOpenInEditor.add(stateStrategyICompilationUnit);
  ASTParser stateStrategyParser=ASTParser.newParser(AST.JLS4);
  stateStrategyParser.setKind(ASTParser.K_COMPILATION_UNIT);
  Document stateStrategyDocument=null;
  if (stateStrategyFile.exists()) {
    stateStrategyAlreadyExists=true;
    stateStrategyParser.setSource(stateStrategyICompilationUnit);
    stateStrategyParser.setResolveBindings(true);
  }
 else {
    stateStrategyDocument=new Document();
    stateStrategyParser.setSource(stateStrategyDocument.get().toCharArray());
  }
  CompilationUnit stateStrategyCompilationUnit=(CompilationUnit)stateStrategyParser.createAST(null);
  AST stateStrategyAST=stateStrategyCompilationUnit.getAST();
  ASTRewrite stateStrategyRewriter=ASTRewrite.create(stateStrategyAST);
  ListRewrite stateStrategyTypesRewrite=stateStrategyRewriter.getListRewrite(stateStrategyCompilationUnit,CompilationUnit.TYPES_PROPERTY);
  TypeDeclaration stateStrategyTypeDeclaration=null;
  if (stateStrategyAlreadyExists) {
    List<AbstractTypeDeclaration> abstractTypeDeclarations=stateStrategyCompilationUnit.types();
    for (    AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
      if (abstractTypeDeclaration instanceof TypeDeclaration) {
        TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
        if (typeDeclaration.getName().getIdentifier().equals(abstractClassName)) {
          stateStrategyTypeDeclaration=typeDeclaration;
          requiredImportDeclarationsForContext.add(stateStrategyTypeDeclaration.resolveBinding());
          int stateStrategyModifiers=stateStrategyTypeDeclaration.getModifiers();
          if ((stateStrategyModifiers & Modifier.ABSTRACT) == 0) {
            ListRewrite stateStrategyModifiersRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
            stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
          }
          break;
        }
      }
    }
  }
 else {
    if (sourceCompilationUnit.getPackage() != null) {
      stateStrategyRewriter.set(stateStrategyCompilationUnit,CompilationUnit.PACKAGE_PROPERTY,sourceCompilationUnit.getPackage(),null);
    }
    stateStrategyTypeDeclaration=stateStrategyAST.newTypeDeclaration();
    SimpleName stateStrategyName=stateStrategyAST.newSimpleName(abstractClassName);
    stateStrategyRewriter.set(stateStrategyTypeDeclaration,TypeDeclaration.NAME_PROPERTY,stateStrategyName,null);
    ListRewrite stateStrategyModifiersRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
    stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
    stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  }
  ListRewrite stateStrategyBodyRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
  MethodDeclaration getterMethod=typeCheckElimination.getTypeFieldGetterMethod();
  if (typeCheckElimination.getTypeField() != null) {
    if (getterMethod != null) {
      MethodDeclaration abstractGetterMethodDeclaration=stateStrategyAST.newMethodDeclaration();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,getterMethod.getName(),null);
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,getterMethod.getReturnType2(),null);
      ListRewrite abstractGetterMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
      stateStrategyBodyRewrite.insertLast(abstractGetterMethodDeclaration,null);
    }
 else {
      MethodDeclaration abstractGetterMethodDeclaration=stateStrategyAST.newMethodDeclaration();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName("String_Node_Str" + abstractClassName),null);
      VariableDeclarationFragment typeField=typeCheckElimination.getTypeField();
      Type returnType=((FieldDeclaration)typeField.getParent()).getType();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
      ListRewrite abstractGetterMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
      stateStrategyBodyRewrite.insertLast(abstractGetterMethodDeclaration,null);
    }
  }
  MethodDeclaration abstractMethodDeclaration=stateStrategyAST.newMethodDeclaration();
  stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName(typeCheckElimination.getAbstractMethodName()),null);
  if (returnedVariable == null && !typeCheckElimination.typeCheckCodeFragmentContainsReturnStatement()) {
    stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,stateStrategyAST.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;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          returnType=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          returnType=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          returnType=fieldDeclaration.getType();
        }
      }
      stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
    }
 else {
      stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
    }
  }
  ListRewrite abstractMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
  abstractMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
  abstractMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  ListRewrite abstractMethodParametersRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
  if (returnedVariable != null) {
    if (returnedVariable instanceof SingleVariableDeclaration) {
      SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
      abstractMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
    }
 else     if (returnedVariable instanceof VariableDeclarationFragment) {
      SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
      VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
      Type type=null;
      if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
        type=variableDeclarationStatement.getType();
      }
 else       if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
        VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
        type=variableDeclarationExpression.getType();
      }
 else       if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
        FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
        type=fieldDeclaration.getType();
      }
      stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
      stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
      abstractMethodParametersRewrite.insertLast(parameter,null);
    }
  }
  for (  SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
    if (!abstractMethodParameter.equals(returnedVariable)) {
      abstractMethodParametersRewrite.insertLast(abstractMethodParameter,null);
    }
  }
  for (  VariableDeclaration fragment : typeCheckElimination.getAccessedLocalVariables()) {
    if (!fragment.equals(returnedVariable)) {
      if (fragment instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)fragment;
        abstractMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
      }
 else       if (fragment instanceof VariableDeclarationFragment) {
        SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
        VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)fragment;
        Type type=null;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          type=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          type=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          type=fieldDeclaration.getType();
        }
        stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
        stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
        abstractMethodParametersRewrite.insertLast(parameter,null);
      }
    }
  }
  if (typeCheckElimination.getAccessedFields().size() > 0 || typeCheckElimination.getAssignedFields().size() > 0 || typeCheckElimination.getAccessedMethods().size() > 0 || typeCheckElimination.getSuperAccessedMethods().size() > 0 || typeCheckElimination.getSuperAccessedFieldBindings().size() > 0 || typeCheckElimination.getSuperAssignedFieldBindings().size() > 0) {
    SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
    SimpleName parameterType=stateStrategyAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
    stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,stateStrategyAST.newSimpleType(parameterType),null);
    String parameterName=sourceTypeDeclaration.getName().getIdentifier();
    parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
    stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName(parameterName),null);
    abstractMethodParametersRewrite.insertLast(parameter,null);
  }
  ListRewrite abstractMethodThrownExceptionsRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
  for (  ITypeBinding typeBinding : thrownExceptions) {
    abstractMethodThrownExceptionsRewrite.insertLast(stateStrategyAST.newSimpleName(typeBinding.getName()),null);
  }
  stateStrategyBodyRewrite.insertLast(abstractMethodDeclaration,null);
  generateRequiredImportDeclarationsBasedOnSignature();
  if (!stateStrategyAlreadyExists)   stateStrategyTypesRewrite.insertLast(stateStrategyTypeDeclaration,null);
  if (stateStrategyDocument != null) {
    try {
      for (      ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
        addImportDeclaration(typeBinding,stateStrategyCompilationUnit,stateStrategyRewriter);
      }
      TextEdit stateStrategyEdit=stateStrategyRewriter.rewriteAST(stateStrategyDocument,null);
      stateStrategyEdit.apply(stateStrategyDocument);
      CreateCompilationUnitChange createCompilationUnitChange=new CreateCompilationUnitChange(stateStrategyICompilationUnit,stateStrategyDocument.get(),stateStrategyFile.getCharset());
      createCompilationUnitChanges.put(stateStrategyICompilationUnit,createCompilationUnitChange);
    }
 catch (    CoreException e) {
      e.printStackTrace();
    }
catch (    MalformedTreeException e) {
      e.printStackTrace();
    }
catch (    BadLocationException e) {
      e.printStackTrace();
    }
  }
 else {
    try {
      MultiTextEdit stateStrategyMultiTextEdit=new MultiTextEdit();
      CompilationUnitChange stateStrategyCompilationUnitChange=new CompilationUnitChange("String_Node_Str",stateStrategyICompilationUnit);
      stateStrategyCompilationUnitChange.setEdit(stateStrategyMultiTextEdit);
      compilationUnitChanges.put(stateStrategyICompilationUnit,stateStrategyCompilationUnitChange);
      ImportRewrite stateStrategyImportRewrite=ImportRewrite.create(stateStrategyCompilationUnit,true);
      for (      ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
        if (!typeBinding.isNested())         stateStrategyImportRewrite.addImport(typeBinding);
      }
      TextEdit stateStrategyImportEdit=stateStrategyImportRewrite.rewriteImports(null);
      if (stateStrategyImportRewrite.getCreatedImports().length > 0) {
        stateStrategyMultiTextEdit.addChild(stateStrategyImportEdit);
        stateStrategyCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{stateStrategyImportEdit}));
      }
      TextEdit stateStrategyEdit=stateStrategyRewriter.rewriteAST();
      stateStrategyMultiTextEdit.addChild(stateStrategyEdit);
      stateStrategyCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{stateStrategyEdit}));
    }
 catch (    JavaModelException e) {
      e.printStackTrace();
    }
catch (    CoreException e) {
      e.printStackTrace();
    }
  }
  List<ArrayList<Statement>> typeCheckStatements=typeCheckElimination.getTypeCheckStatements();
  List<String> subclassNames=new ArrayList<String>(staticFieldMap.values());
  subclassNames.addAll(additionalStaticFieldMap.values());
  if (tree != null) {
    DefaultMutableTreeNode rootNode=tree.getRootNode();
    DefaultMutableTreeNode leaf=rootNode.getFirstLeaf();
    while (leaf != null) {
      String qualifiedSubclassName=(String)leaf.getUserObject();
      String subclassName=null;
      if (qualifiedSubclassName.contains("String_Node_Str"))       subclassName=qualifiedSubclassName.substring(qualifiedSubclassName.lastIndexOf("String_Node_Str") + 1,qualifiedSubclassName.length());
 else       subclassName=qualifiedSubclassName;
      if (!subclassNames.contains(subclassName))       subclassNames.add(subclassName);
      leaf=leaf.getNextLeaf();
    }
  }
  List<SimpleName> staticFields=new ArrayList<SimpleName>(staticFieldMap.keySet());
  for (  SimpleName simpleName : additionalStaticFieldMap.keySet())   staticFields.add(simpleName);
  for (  Expression expression : typeCheckElimination.getTypeCheckExpressions()) {
    List<SimpleName> leafStaticFields=typeCheckElimination.getStaticFields(expression);
    if (leafStaticFields.size() > 1) {
      List<String> leafSubclassNames=new ArrayList<String>();
      for (      SimpleName leafStaticField : leafStaticFields) {
        leafSubclassNames.add(getTypeNameForNamedConstant(leafStaticField));
      }
      ArrayList<Statement> typeCheckStatements2=typeCheckElimination.getTypeCheckStatements(expression);
      createIntermediateClassAndItsSubclasses(leafStaticFields,leafSubclassNames,typeCheckStatements2,tree,rootContainer,contextContainer);
      staticFields.removeAll(leafStaticFields);
      subclassNames.removeAll(leafSubclassNames);
      typeCheckStatements.remove(typeCheckStatements2);
    }
  }
  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=null;
    if (tree != null) {
      DefaultMutableTreeNode rootNode=tree.getRootNode();
      DefaultMutableTreeNode leaf=rootNode.getFirstLeaf();
      while (leaf != null) {
        String qualifiedSubclassName=(String)leaf.getUserObject();
        if ((qualifiedSubclassName.contains("String_Node_Str") && qualifiedSubclassName.endsWith("String_Node_Str" + subclassNames.get(i))) || qualifiedSubclassName.equals(subclassNames.get(i))) {
          subclassFile=getFile(rootContainer,qualifiedSubclassName);
          break;
        }
        leaf=leaf.getNextLeaf();
      }
    }
 else {
      if (contextContainer instanceof IProject) {
        IProject contextProject=(IProject)contextContainer;
        subclassFile=contextProject.getFile(subclassNames.get(i) + "String_Node_Str");
      }
 else       if (contextContainer instanceof IFolder) {
        IFolder contextFolder=(IFolder)contextContainer;
        subclassFile=contextFolder.getFile(subclassNames.get(i) + "String_Node_Str");
      }
    }
    boolean subclassAlreadyExists=false;
    ICompilationUnit subclassICompilationUnit=JavaCore.createCompilationUnitFrom(subclassFile);
    javaElementsToOpenInEditor.add(subclassICompilationUnit);
    ASTParser subclassParser=ASTParser.newParser(AST.JLS4);
    subclassParser.setKind(ASTParser.K_COMPILATION_UNIT);
    Document subclassDocument=null;
    if (subclassFile.exists()) {
      subclassAlreadyExists=true;
      subclassParser.setSource(subclassICompilationUnit);
      subclassParser.setResolveBindings(true);
    }
 else {
      subclassDocument=new Document();
      subclassParser.setSource(subclassDocument.get().toCharArray());
    }
    CompilationUnit subclassCompilationUnit=(CompilationUnit)subclassParser.createAST(null);
    AST subclassAST=subclassCompilationUnit.getAST();
    ASTRewrite subclassRewriter=ASTRewrite.create(subclassAST);
    ListRewrite subclassTypesRewrite=subclassRewriter.getListRewrite(subclassCompilationUnit,CompilationUnit.TYPES_PROPERTY);
    TypeDeclaration subclassTypeDeclaration=null;
    if (subclassAlreadyExists) {
      List<AbstractTypeDeclaration> abstractTypeDeclarations=subclassCompilationUnit.types();
      for (      AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
        if (abstractTypeDeclaration instanceof TypeDeclaration) {
          TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
          if (typeDeclaration.getName().getIdentifier().equals(subclassNames.get(i))) {
            subclassTypeDeclaration=typeDeclaration;
            requiredImportDeclarationsForContext.add(subclassTypeDeclaration.resolveBinding());
            break;
          }
        }
      }
    }
 else {
      if (sourceCompilationUnit.getPackage() != null) {
        subclassRewriter.set(subclassCompilationUnit,CompilationUnit.PACKAGE_PROPERTY,sourceCompilationUnit.getPackage(),null);
      }
      Javadoc subclassJavaDoc=subclassAST.newJavadoc();
      TagElement subclassTagElement=subclassAST.newTagElement();
      subclassRewriter.set(subclassTagElement,TagElement.TAG_NAME_PROPERTY,TagElement.TAG_SEE,null);
      MemberRef subclassMemberRef=subclassAST.newMemberRef();
      IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
      ITypeBinding staticFieldNameDeclaringClass=null;
      if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
        IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
        staticFieldNameDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass();
      }
      subclassRewriter.set(subclassMemberRef,MemberRef.NAME_PROPERTY,subclassAST.newSimpleName(staticFieldNameBinding.getName()),null);
      subclassRewriter.set(subclassMemberRef,MemberRef.QUALIFIER_PROPERTY,subclassAST.newName(staticFieldNameDeclaringClass.getQualifiedName()),null);
      ListRewrite subclassTagElementFragmentsRewrite=subclassRewriter.getListRewrite(subclassTagElement,TagElement.FRAGMENTS_PROPERTY);
      subclassTagElementFragmentsRewrite.insertLast(subclassMemberRef,null);
      ListRewrite subclassJavaDocTagsRewrite=subclassRewriter.getListRewrite(subclassJavaDoc,Javadoc.TAGS_PROPERTY);
      subclassJavaDocTagsRewrite.insertLast(subclassTagElement,null);
      subclassTypeDeclaration=subclassAST.newTypeDeclaration();
      SimpleName subclassName=subclassAST.newSimpleName(subclassNames.get(i));
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.NAME_PROPERTY,subclassName,null);
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.SUPERCLASS_TYPE_PROPERTY,subclassAST.newSimpleType(subclassAST.newSimpleName(abstractClassName)),null);
      ListRewrite subclassModifiersRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
      subclassModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.JAVADOC_PROPERTY,subclassJavaDoc,null);
    }
    ListRewrite subclassBodyRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
    if (typeCheckElimination.getTypeField() != null) {
      if (getterMethod != null) {
        MethodDeclaration concreteGetterMethodDeclaration=subclassAST.newMethodDeclaration();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,getterMethod.getName(),null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,getterMethod.getReturnType2(),null);
        ListRewrite concreteGetterMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
        concreteGetterMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
        Block concreteGetterMethodBody=subclassAST.newBlock();
        ListRewrite concreteGetterMethodBodyRewrite=subclassRewriter.getListRewrite(concreteGetterMethodBody,Block.STATEMENTS_PROPERTY);
        ReturnStatement returnStatement=subclassAST.newReturnStatement();
        IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
        String staticFieldNameDeclaringClass=null;
        if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
          IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
          staticFieldNameDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass().getName();
        }
        FieldAccess fieldAccess=subclassAST.newFieldAccess();
        subclassRewriter.set(fieldAccess,FieldAccess.NAME_PROPERTY,staticFields.get(i),null);
        subclassRewriter.set(fieldAccess,FieldAccess.EXPRESSION_PROPERTY,subclassAST.newSimpleName(staticFieldNameDeclaringClass),null);
        subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,fieldAccess,null);
        concreteGetterMethodBodyRewrite.insertLast(returnStatement,null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteGetterMethodBody,null);
        subclassBodyRewrite.insertLast(concreteGetterMethodDeclaration,null);
      }
 else {
        MethodDeclaration concreteGetterMethodDeclaration=subclassAST.newMethodDeclaration();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName("String_Node_Str" + abstractClassName),null);
        VariableDeclarationFragment typeField=typeCheckElimination.getTypeField();
        Type returnType=((FieldDeclaration)typeField.getParent()).getType();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
        ListRewrite concreteGetterMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
        concreteGetterMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
        Block concreteGetterMethodBody=subclassAST.newBlock();
        ListRewrite concreteGetterMethodBodyRewrite=subclassRewriter.getListRewrite(concreteGetterMethodBody,Block.STATEMENTS_PROPERTY);
        ReturnStatement returnStatement=subclassAST.newReturnStatement();
        IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
        String staticFieldNameDeclaringClass=null;
        if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
          IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
          staticFieldNameDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass().getName();
        }
        FieldAccess fieldAccess=subclassAST.newFieldAccess();
        subclassRewriter.set(fieldAccess,FieldAccess.NAME_PROPERTY,staticFields.get(i),null);
        subclassRewriter.set(fieldAccess,FieldAccess.EXPRESSION_PROPERTY,subclassAST.newSimpleName(staticFieldNameDeclaringClass),null);
        subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,fieldAccess,null);
        concreteGetterMethodBodyRewrite.insertLast(returnStatement,null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteGetterMethodBody,null);
        subclassBodyRewrite.insertLast(concreteGetterMethodDeclaration,null);
      }
    }
    MethodDeclaration concreteMethodDeclaration=subclassAST.newMethodDeclaration();
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(typeCheckElimination.getAbstractMethodName()),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;
          if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
            VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
            returnType=variableDeclarationStatement.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
            VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
            returnType=variableDeclarationExpression.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
            returnType=fieldDeclaration.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);
    if (returnedVariable != null) {
      if (returnedVariable instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
        concreteMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
      }
 else       if (returnedVariable instanceof VariableDeclarationFragment) {
        SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
        VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
        Type type=null;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          type=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          type=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          type=fieldDeclaration.getType();
        }
        subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
        subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
        concreteMethodParametersRewrite.insertLast(parameter,null);
      }
    }
    for (    SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
      if (!abstractMethodParameter.equals(returnedVariable)) {
        concreteMethodParametersRewrite.insertLast(abstractMethodParameter,null);
      }
    }
    for (    VariableDeclaration fragment : typeCheckElimination.getAccessedLocalVariables()) {
      if (!fragment.equals(returnedVariable)) {
        if (fragment instanceof SingleVariableDeclaration) {
          SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)fragment;
          concreteMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
        }
 else         if (fragment instanceof VariableDeclarationFragment) {
          SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
          VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)fragment;
          Type type=null;
          if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
            VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
            type=variableDeclarationStatement.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
            VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
            type=variableDeclarationExpression.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
            type=fieldDeclaration.getType();
          }
          subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
          subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
          concreteMethodParametersRewrite.insertLast(parameter,null);
        }
      }
    }
    Set<VariableDeclarationFragment> accessedFields=typeCheckElimination.getAccessedFields();
    Set<VariableDeclarationFragment> assignedFields=typeCheckElimination.getAssignedFields();
    Set<MethodDeclaration> accessedMethods=typeCheckElimination.getAccessedMethods();
    Set<IMethodBinding> superAccessedMethods=typeCheckElimination.getSuperAccessedMethods();
    Set<IVariableBinding> superAccessedFields=typeCheckElimination.getSuperAccessedFieldBindings();
    Set<IVariableBinding> superAssignedFields=typeCheckElimination.getSuperAssignedFieldBindings();
    if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0 || superAccessedFields.size() > 0 || superAssignedFields.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);
      modifySourceVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields,superAccessedFields,superAssignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(enclosingIfStatementExpression);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newEnclosingIfStatementExpression);
      modifySourceMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      replaceThisExpressionWithContextParameterInMethodInvocationArguments(newMethodInvocations,subclassAST,subclassRewriter);
      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);
    }
    for (    Statement statement : statements) {
      Statement newStatement=(Statement)ASTNode.copySubtree(subclassAST,statement);
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(statement);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newStatement);
      modifySourceVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields,superAccessedFields,superAssignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(statement);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newStatement);
      modifySourceMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      replaceThisExpressionWithContextParameterInMethodInvocationArguments(newMethodInvocations,subclassAST,subclassRewriter);
      replaceThisExpressionWithContextParameterInClassInstanceCreationArguments(newStatement,subclassAST,subclassRewriter);
      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);
    if (!subclassAlreadyExists)     subclassTypesRewrite.insertLast(subclassTypeDeclaration,null);
    if (subclassDocument != null) {
      try {
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
          addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
        }
        Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=getRequiredImportDeclarationsBasedOnBranch(statements);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
          if (!requiredImportDeclarationsBasedOnSignature.contains(typeBinding))           addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
        }
        TextEdit subclassEdit=subclassRewriter.rewriteAST(subclassDocument,null);
        subclassEdit.apply(subclassDocument);
        CreateCompilationUnitChange createCompilationUnitChange=new CreateCompilationUnitChange(subclassICompilationUnit,subclassDocument.get(),subclassFile.getCharset());
        createCompilationUnitChanges.put(subclassICompilationUnit,createCompilationUnitChange);
      }
 catch (      CoreException e) {
        e.printStackTrace();
      }
catch (      MalformedTreeException e) {
        e.printStackTrace();
      }
catch (      BadLocationException e) {
        e.printStackTrace();
      }
    }
 else {
      try {
        MultiTextEdit subclassMultiTextEdit=new MultiTextEdit();
        CompilationUnitChange subclassCompilationUnitChange=new CompilationUnitChange("String_Node_Str",subclassICompilationUnit);
        subclassCompilationUnitChange.setEdit(subclassMultiTextEdit);
        compilationUnitChanges.put(subclassICompilationUnit,subclassCompilationUnitChange);
        ImportRewrite subclassImportRewrite=ImportRewrite.create(subclassCompilationUnit,true);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
          if (!typeBinding.isNested())           subclassImportRewrite.addImport(typeBinding);
        }
        Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=getRequiredImportDeclarationsBasedOnBranch(statements);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
          if (!typeBinding.isNested())           subclassImportRewrite.addImport(typeBinding);
        }
        TextEdit subclassImportEdit=subclassImportRewrite.rewriteImports(null);
        if (subclassImportRewrite.getCreatedImports().length > 0) {
          subclassMultiTextEdit.addChild(subclassImportEdit);
          subclassCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{subclassImportEdit}));
        }
        TextEdit subclassEdit=subclassRewriter.rewriteAST();
        subclassMultiTextEdit.addChild(subclassEdit);
        subclassCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{subclassEdit}));
      }
 catch (      JavaModelException e) {
        e.printStackTrace();
      }
catch (      CoreException e) {
        e.printStackTrace();
      }
    }
  }
}

Fixed version (ground truth):
private void createStateStrategyHierarchy(){
  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();
  }
  InheritanceTree tree=typeCheckElimination.getInheritanceTreeMatchingWithStaticTypes();
  IFile stateStrategyFile=null;
  if (tree != null) {
    DefaultMutableTreeNode rootNode=tree.getRootNode();
    stateStrategyFile=getFile(rootContainer,(String)rootNode.getUserObject());
  }
 else {
    if (contextContainer instanceof IProject) {
      IProject contextProject=(IProject)contextContainer;
      stateStrategyFile=contextProject.getFile(abstractClassName + "String_Node_Str");
    }
 else     if (contextContainer instanceof IFolder) {
      IFolder contextFolder=(IFolder)contextContainer;
      stateStrategyFile=contextFolder.getFile(abstractClassName + "String_Node_Str");
    }
  }
  boolean stateStrategyAlreadyExists=false;
  ICompilationUnit stateStrategyICompilationUnit=JavaCore.createCompilationUnitFrom(stateStrategyFile);
  javaElementsToOpenInEditor.add(stateStrategyICompilationUnit);
  ASTParser stateStrategyParser=ASTParser.newParser(AST.JLS4);
  stateStrategyParser.setKind(ASTParser.K_COMPILATION_UNIT);
  Document stateStrategyDocument=null;
  if (stateStrategyFile.exists()) {
    stateStrategyAlreadyExists=true;
    stateStrategyParser.setSource(stateStrategyICompilationUnit);
    stateStrategyParser.setResolveBindings(true);
  }
 else {
    stateStrategyDocument=new Document();
    stateStrategyParser.setSource(stateStrategyDocument.get().toCharArray());
  }
  CompilationUnit stateStrategyCompilationUnit=(CompilationUnit)stateStrategyParser.createAST(null);
  AST stateStrategyAST=stateStrategyCompilationUnit.getAST();
  ASTRewrite stateStrategyRewriter=ASTRewrite.create(stateStrategyAST);
  ListRewrite stateStrategyTypesRewrite=stateStrategyRewriter.getListRewrite(stateStrategyCompilationUnit,CompilationUnit.TYPES_PROPERTY);
  TypeDeclaration stateStrategyTypeDeclaration=null;
  if (stateStrategyAlreadyExists) {
    List<AbstractTypeDeclaration> abstractTypeDeclarations=stateStrategyCompilationUnit.types();
    for (    AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
      if (abstractTypeDeclaration instanceof TypeDeclaration) {
        TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
        if (typeDeclaration.getName().getIdentifier().equals(abstractClassName)) {
          stateStrategyTypeDeclaration=typeDeclaration;
          requiredImportDeclarationsForContext.add(stateStrategyTypeDeclaration.resolveBinding());
          int stateStrategyModifiers=stateStrategyTypeDeclaration.getModifiers();
          if ((stateStrategyModifiers & Modifier.ABSTRACT) == 0) {
            ListRewrite stateStrategyModifiersRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
            stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
          }
          break;
        }
      }
    }
  }
 else {
    if (sourceCompilationUnit.getPackage() != null) {
      stateStrategyRewriter.set(stateStrategyCompilationUnit,CompilationUnit.PACKAGE_PROPERTY,sourceCompilationUnit.getPackage(),null);
    }
    stateStrategyTypeDeclaration=stateStrategyAST.newTypeDeclaration();
    SimpleName stateStrategyName=stateStrategyAST.newSimpleName(abstractClassName);
    stateStrategyRewriter.set(stateStrategyTypeDeclaration,TypeDeclaration.NAME_PROPERTY,stateStrategyName,null);
    ListRewrite stateStrategyModifiersRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
    stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
    stateStrategyModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  }
  ListRewrite stateStrategyBodyRewrite=stateStrategyRewriter.getListRewrite(stateStrategyTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
  MethodDeclaration getterMethod=typeCheckElimination.getTypeFieldGetterMethod();
  if (typeCheckElimination.getTypeField() != null) {
    if (getterMethod != null) {
      MethodDeclaration abstractGetterMethodDeclaration=stateStrategyAST.newMethodDeclaration();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,getterMethod.getName(),null);
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,getterMethod.getReturnType2(),null);
      ListRewrite abstractGetterMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
      stateStrategyBodyRewrite.insertLast(abstractGetterMethodDeclaration,null);
    }
 else {
      MethodDeclaration abstractGetterMethodDeclaration=stateStrategyAST.newMethodDeclaration();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName("String_Node_Str" + abstractClassName),null);
      VariableDeclarationFragment typeField=typeCheckElimination.getTypeField();
      Type returnType=((FieldDeclaration)typeField.getParent()).getType();
      stateStrategyRewriter.set(abstractGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
      ListRewrite abstractGetterMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      abstractGetterMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
      stateStrategyBodyRewrite.insertLast(abstractGetterMethodDeclaration,null);
    }
  }
  MethodDeclaration abstractMethodDeclaration=stateStrategyAST.newMethodDeclaration();
  stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName(typeCheckElimination.getAbstractMethodName()),null);
  if (returnedVariable == null && !typeCheckElimination.typeCheckCodeFragmentContainsReturnStatement()) {
    stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,stateStrategyAST.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;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          returnType=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          returnType=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          returnType=fieldDeclaration.getType();
        }
      }
      stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
    }
 else {
      stateStrategyRewriter.set(abstractMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,typeCheckElimination.getTypeCheckMethodReturnType(),null);
    }
  }
  ListRewrite abstractMethodModifiersRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
  abstractMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
  abstractMethodModifiersRewrite.insertLast(stateStrategyAST.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD),null);
  ListRewrite abstractMethodParametersRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.PARAMETERS_PROPERTY);
  if (returnedVariable != null) {
    if (returnedVariable instanceof SingleVariableDeclaration) {
      SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
      abstractMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
    }
 else     if (returnedVariable instanceof VariableDeclarationFragment) {
      SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
      VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
      Type type=null;
      if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
        VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
        type=variableDeclarationStatement.getType();
      }
 else       if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
        VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
        type=variableDeclarationExpression.getType();
      }
 else       if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
        FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
        type=fieldDeclaration.getType();
      }
      stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
      stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
      abstractMethodParametersRewrite.insertLast(parameter,null);
    }
  }
  for (  SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
    if (!abstractMethodParameter.equals(returnedVariable)) {
      abstractMethodParametersRewrite.insertLast(abstractMethodParameter,null);
    }
  }
  for (  VariableDeclaration fragment : typeCheckElimination.getAccessedLocalVariables()) {
    if (!fragment.equals(returnedVariable)) {
      if (fragment instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)fragment;
        abstractMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
      }
 else       if (fragment instanceof VariableDeclarationFragment) {
        SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
        VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)fragment;
        Type type=null;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          type=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          type=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          type=fieldDeclaration.getType();
        }
        stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
        stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
        abstractMethodParametersRewrite.insertLast(parameter,null);
      }
    }
  }
  if (typeCheckElimination.getAccessedFields().size() > 0 || typeCheckElimination.getAssignedFields().size() > 0 || typeCheckElimination.getAccessedMethods().size() > 0 || typeCheckElimination.getSuperAccessedMethods().size() > 0 || typeCheckElimination.getSuperAccessedFieldBindings().size() > 0 || typeCheckElimination.getSuperAssignedFieldBindings().size() > 0) {
    SingleVariableDeclaration parameter=stateStrategyAST.newSingleVariableDeclaration();
    SimpleName parameterType=stateStrategyAST.newSimpleName(sourceTypeDeclaration.getName().getIdentifier());
    stateStrategyRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,stateStrategyAST.newSimpleType(parameterType),null);
    String parameterName=sourceTypeDeclaration.getName().getIdentifier();
    parameterName=parameterName.substring(0,1).toLowerCase() + parameterName.substring(1,parameterName.length());
    stateStrategyRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,stateStrategyAST.newSimpleName(parameterName),null);
    abstractMethodParametersRewrite.insertLast(parameter,null);
  }
  ListRewrite abstractMethodThrownExceptionsRewrite=stateStrategyRewriter.getListRewrite(abstractMethodDeclaration,MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
  for (  ITypeBinding typeBinding : thrownExceptions) {
    abstractMethodThrownExceptionsRewrite.insertLast(stateStrategyAST.newSimpleName(typeBinding.getName()),null);
  }
  stateStrategyBodyRewrite.insertLast(abstractMethodDeclaration,null);
  generateRequiredImportDeclarationsBasedOnSignature();
  if (!stateStrategyAlreadyExists)   stateStrategyTypesRewrite.insertLast(stateStrategyTypeDeclaration,null);
  if (stateStrategyDocument != null) {
    try {
      for (      ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
        addImportDeclaration(typeBinding,stateStrategyCompilationUnit,stateStrategyRewriter);
      }
      TextEdit stateStrategyEdit=stateStrategyRewriter.rewriteAST(stateStrategyDocument,null);
      stateStrategyEdit.apply(stateStrategyDocument);
      CreateCompilationUnitChange createCompilationUnitChange=new CreateCompilationUnitChange(stateStrategyICompilationUnit,stateStrategyDocument.get(),stateStrategyFile.getCharset());
      createCompilationUnitChanges.put(stateStrategyICompilationUnit,createCompilationUnitChange);
    }
 catch (    CoreException e) {
      e.printStackTrace();
    }
catch (    MalformedTreeException e) {
      e.printStackTrace();
    }
catch (    BadLocationException e) {
      e.printStackTrace();
    }
  }
 else {
    try {
      MultiTextEdit stateStrategyMultiTextEdit=new MultiTextEdit();
      CompilationUnitChange stateStrategyCompilationUnitChange=new CompilationUnitChange("String_Node_Str",stateStrategyICompilationUnit);
      stateStrategyCompilationUnitChange.setEdit(stateStrategyMultiTextEdit);
      compilationUnitChanges.put(stateStrategyICompilationUnit,stateStrategyCompilationUnitChange);
      ImportRewrite stateStrategyImportRewrite=ImportRewrite.create(stateStrategyCompilationUnit,true);
      for (      ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
        if (!typeBinding.isNested())         stateStrategyImportRewrite.addImport(typeBinding);
      }
      TextEdit stateStrategyImportEdit=stateStrategyImportRewrite.rewriteImports(null);
      if (stateStrategyImportRewrite.getCreatedImports().length > 0) {
        stateStrategyMultiTextEdit.addChild(stateStrategyImportEdit);
        stateStrategyCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{stateStrategyImportEdit}));
      }
      TextEdit stateStrategyEdit=stateStrategyRewriter.rewriteAST();
      stateStrategyMultiTextEdit.addChild(stateStrategyEdit);
      stateStrategyCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{stateStrategyEdit}));
    }
 catch (    JavaModelException e) {
      e.printStackTrace();
    }
catch (    CoreException e) {
      e.printStackTrace();
    }
  }
  List<ArrayList<Statement>> typeCheckStatements=typeCheckElimination.getTypeCheckStatements();
  List<String> subclassNames=new ArrayList<String>(staticFieldMap.values());
  subclassNames.addAll(additionalStaticFieldMap.values());
  if (tree != null) {
    DefaultMutableTreeNode rootNode=tree.getRootNode();
    DefaultMutableTreeNode leaf=rootNode.getFirstLeaf();
    while (leaf != null) {
      String qualifiedSubclassName=(String)leaf.getUserObject();
      String subclassName=null;
      if (qualifiedSubclassName.contains("String_Node_Str"))       subclassName=qualifiedSubclassName.substring(qualifiedSubclassName.lastIndexOf("String_Node_Str") + 1,qualifiedSubclassName.length());
 else       subclassName=qualifiedSubclassName;
      if (!subclassNames.contains(subclassName))       subclassNames.add(subclassName);
      leaf=leaf.getNextLeaf();
    }
  }
  List<SimpleName> staticFields=new ArrayList<SimpleName>(staticFieldMap.keySet());
  for (  SimpleName simpleName : additionalStaticFieldMap.keySet())   staticFields.add(simpleName);
  for (  Expression expression : typeCheckElimination.getTypeCheckExpressions()) {
    List<SimpleName> leafStaticFields=typeCheckElimination.getStaticFields(expression);
    if (leafStaticFields.size() > 1) {
      List<String> leafSubclassNames=new ArrayList<String>();
      for (      SimpleName leafStaticField : leafStaticFields) {
        leafSubclassNames.add(getTypeNameForNamedConstant(leafStaticField));
      }
      ArrayList<Statement> typeCheckStatements2=typeCheckElimination.getTypeCheckStatements(expression);
      createIntermediateClassAndItsSubclasses(leafStaticFields,leafSubclassNames,typeCheckStatements2,tree,rootContainer,contextContainer);
      staticFields.removeAll(leafStaticFields);
      subclassNames.removeAll(leafSubclassNames);
      typeCheckStatements.remove(typeCheckStatements2);
    }
  }
  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=null;
    if (tree != null) {
      DefaultMutableTreeNode rootNode=tree.getRootNode();
      DefaultMutableTreeNode leaf=rootNode.getFirstLeaf();
      while (leaf != null) {
        String qualifiedSubclassName=(String)leaf.getUserObject();
        if ((qualifiedSubclassName.contains("String_Node_Str") && qualifiedSubclassName.endsWith("String_Node_Str" + subclassNames.get(i))) || qualifiedSubclassName.equals(subclassNames.get(i))) {
          subclassFile=getFile(rootContainer,qualifiedSubclassName);
          break;
        }
        leaf=leaf.getNextLeaf();
      }
    }
 else {
      if (contextContainer instanceof IProject) {
        IProject contextProject=(IProject)contextContainer;
        subclassFile=contextProject.getFile(subclassNames.get(i) + "String_Node_Str");
      }
 else       if (contextContainer instanceof IFolder) {
        IFolder contextFolder=(IFolder)contextContainer;
        subclassFile=contextFolder.getFile(subclassNames.get(i) + "String_Node_Str");
      }
    }
    boolean subclassAlreadyExists=false;
    ICompilationUnit subclassICompilationUnit=JavaCore.createCompilationUnitFrom(subclassFile);
    javaElementsToOpenInEditor.add(subclassICompilationUnit);
    ASTParser subclassParser=ASTParser.newParser(AST.JLS4);
    subclassParser.setKind(ASTParser.K_COMPILATION_UNIT);
    Document subclassDocument=null;
    if (subclassFile.exists()) {
      subclassAlreadyExists=true;
      subclassParser.setSource(subclassICompilationUnit);
      subclassParser.setResolveBindings(true);
    }
 else {
      subclassDocument=new Document();
      subclassParser.setSource(subclassDocument.get().toCharArray());
    }
    CompilationUnit subclassCompilationUnit=(CompilationUnit)subclassParser.createAST(null);
    AST subclassAST=subclassCompilationUnit.getAST();
    ASTRewrite subclassRewriter=ASTRewrite.create(subclassAST);
    ListRewrite subclassTypesRewrite=subclassRewriter.getListRewrite(subclassCompilationUnit,CompilationUnit.TYPES_PROPERTY);
    TypeDeclaration subclassTypeDeclaration=null;
    if (subclassAlreadyExists) {
      List<AbstractTypeDeclaration> abstractTypeDeclarations=subclassCompilationUnit.types();
      for (      AbstractTypeDeclaration abstractTypeDeclaration : abstractTypeDeclarations) {
        if (abstractTypeDeclaration instanceof TypeDeclaration) {
          TypeDeclaration typeDeclaration=(TypeDeclaration)abstractTypeDeclaration;
          if (typeDeclaration.getName().getIdentifier().equals(subclassNames.get(i))) {
            subclassTypeDeclaration=typeDeclaration;
            requiredImportDeclarationsForContext.add(subclassTypeDeclaration.resolveBinding());
            break;
          }
        }
      }
    }
 else {
      if (sourceCompilationUnit.getPackage() != null) {
        subclassRewriter.set(subclassCompilationUnit,CompilationUnit.PACKAGE_PROPERTY,sourceCompilationUnit.getPackage(),null);
      }
      Javadoc subclassJavaDoc=subclassAST.newJavadoc();
      TagElement subclassTagElement=subclassAST.newTagElement();
      subclassRewriter.set(subclassTagElement,TagElement.TAG_NAME_PROPERTY,TagElement.TAG_SEE,null);
      MemberRef subclassMemberRef=subclassAST.newMemberRef();
      IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
      ITypeBinding staticFieldNameDeclaringClass=null;
      if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
        IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
        staticFieldNameDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass();
      }
      subclassRewriter.set(subclassMemberRef,MemberRef.NAME_PROPERTY,subclassAST.newSimpleName(staticFieldNameBinding.getName()),null);
      subclassRewriter.set(subclassMemberRef,MemberRef.QUALIFIER_PROPERTY,subclassAST.newName(staticFieldNameDeclaringClass.getQualifiedName()),null);
      ListRewrite subclassTagElementFragmentsRewrite=subclassRewriter.getListRewrite(subclassTagElement,TagElement.FRAGMENTS_PROPERTY);
      subclassTagElementFragmentsRewrite.insertLast(subclassMemberRef,null);
      ListRewrite subclassJavaDocTagsRewrite=subclassRewriter.getListRewrite(subclassJavaDoc,Javadoc.TAGS_PROPERTY);
      subclassJavaDocTagsRewrite.insertLast(subclassTagElement,null);
      subclassTypeDeclaration=subclassAST.newTypeDeclaration();
      SimpleName subclassName=subclassAST.newSimpleName(subclassNames.get(i));
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.NAME_PROPERTY,subclassName,null);
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.SUPERCLASS_TYPE_PROPERTY,subclassAST.newSimpleType(subclassAST.newSimpleName(abstractClassName)),null);
      ListRewrite subclassModifiersRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.MODIFIERS2_PROPERTY);
      subclassModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
      subclassRewriter.set(subclassTypeDeclaration,TypeDeclaration.JAVADOC_PROPERTY,subclassJavaDoc,null);
    }
    ListRewrite subclassBodyRewrite=subclassRewriter.getListRewrite(subclassTypeDeclaration,TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
    if (typeCheckElimination.getTypeField() != null) {
      if (getterMethod != null) {
        MethodDeclaration concreteGetterMethodDeclaration=subclassAST.newMethodDeclaration();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,getterMethod.getName(),null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,getterMethod.getReturnType2(),null);
        ListRewrite concreteGetterMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
        concreteGetterMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
        Block concreteGetterMethodBody=subclassAST.newBlock();
        ListRewrite concreteGetterMethodBodyRewrite=subclassRewriter.getListRewrite(concreteGetterMethodBody,Block.STATEMENTS_PROPERTY);
        ReturnStatement returnStatement=subclassAST.newReturnStatement();
        IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
        String staticFieldNameDeclaringClass=null;
        if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
          IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
          ITypeBinding staticFieldDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass();
          String staticFieldDeclaringClassQualifiedName=staticFieldDeclaringClass.getQualifiedName();
          IPackageBinding packageBinding=staticFieldDeclaringClass.getPackage();
          if (packageBinding != null) {
            String packageBindingQualifiedName=packageBinding.getName();
            staticFieldNameDeclaringClass=staticFieldDeclaringClassQualifiedName.substring(packageBindingQualifiedName.length() + 1,staticFieldDeclaringClassQualifiedName.length());
          }
 else {
            staticFieldNameDeclaringClass=staticFieldDeclaringClassQualifiedName;
          }
        }
        FieldAccess fieldAccess=subclassAST.newFieldAccess();
        subclassRewriter.set(fieldAccess,FieldAccess.NAME_PROPERTY,staticFields.get(i),null);
        if (!staticFieldNameDeclaringClass.contains("String_Node_Str")) {
          subclassRewriter.set(fieldAccess,FieldAccess.EXPRESSION_PROPERTY,subclassAST.newSimpleName(staticFieldNameDeclaringClass),null);
        }
 else {
          QualifiedName qualifiedName=subclassAST.newQualifiedName(subclassAST.newName(staticFieldNameDeclaringClass.substring(0,staticFieldNameDeclaringClass.lastIndexOf("String_Node_Str"))),subclassAST.newSimpleName(staticFieldNameDeclaringClass.substring(staticFieldNameDeclaringClass.lastIndexOf("String_Node_Str") + 1,staticFieldNameDeclaringClass.length())));
          subclassRewriter.set(fieldAccess,FieldAccess.EXPRESSION_PROPERTY,qualifiedName,null);
        }
        subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,fieldAccess,null);
        concreteGetterMethodBodyRewrite.insertLast(returnStatement,null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteGetterMethodBody,null);
        subclassBodyRewrite.insertLast(concreteGetterMethodDeclaration,null);
      }
 else {
        MethodDeclaration concreteGetterMethodDeclaration=subclassAST.newMethodDeclaration();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName("String_Node_Str" + abstractClassName),null);
        VariableDeclarationFragment typeField=typeCheckElimination.getTypeField();
        Type returnType=((FieldDeclaration)typeField.getParent()).getType();
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.RETURN_TYPE2_PROPERTY,returnType,null);
        ListRewrite concreteGetterMethodModifiersRewrite=subclassRewriter.getListRewrite(concreteGetterMethodDeclaration,MethodDeclaration.MODIFIERS2_PROPERTY);
        concreteGetterMethodModifiersRewrite.insertLast(subclassAST.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD),null);
        Block concreteGetterMethodBody=subclassAST.newBlock();
        ListRewrite concreteGetterMethodBodyRewrite=subclassRewriter.getListRewrite(concreteGetterMethodBody,Block.STATEMENTS_PROPERTY);
        ReturnStatement returnStatement=subclassAST.newReturnStatement();
        IBinding staticFieldNameBinding=staticFields.get(i).resolveBinding();
        String staticFieldNameDeclaringClass=null;
        if (staticFieldNameBinding != null && staticFieldNameBinding.getKind() == IBinding.VARIABLE) {
          IVariableBinding staticFieldNameVariableBinding=(IVariableBinding)staticFieldNameBinding;
          staticFieldNameDeclaringClass=staticFieldNameVariableBinding.getDeclaringClass().getName();
        }
        FieldAccess fieldAccess=subclassAST.newFieldAccess();
        subclassRewriter.set(fieldAccess,FieldAccess.NAME_PROPERTY,staticFields.get(i),null);
        subclassRewriter.set(fieldAccess,FieldAccess.EXPRESSION_PROPERTY,subclassAST.newSimpleName(staticFieldNameDeclaringClass),null);
        subclassRewriter.set(returnStatement,ReturnStatement.EXPRESSION_PROPERTY,fieldAccess,null);
        concreteGetterMethodBodyRewrite.insertLast(returnStatement,null);
        subclassRewriter.set(concreteGetterMethodDeclaration,MethodDeclaration.BODY_PROPERTY,concreteGetterMethodBody,null);
        subclassBodyRewrite.insertLast(concreteGetterMethodDeclaration,null);
      }
    }
    MethodDeclaration concreteMethodDeclaration=subclassAST.newMethodDeclaration();
    subclassRewriter.set(concreteMethodDeclaration,MethodDeclaration.NAME_PROPERTY,subclassAST.newSimpleName(typeCheckElimination.getAbstractMethodName()),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;
          if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
            VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
            returnType=variableDeclarationStatement.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
            VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
            returnType=variableDeclarationExpression.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
            returnType=fieldDeclaration.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);
    if (returnedVariable != null) {
      if (returnedVariable instanceof SingleVariableDeclaration) {
        SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)returnedVariable;
        concreteMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
      }
 else       if (returnedVariable instanceof VariableDeclarationFragment) {
        SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
        VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)returnedVariable;
        Type type=null;
        if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
          VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
          type=variableDeclarationStatement.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
          VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
          type=variableDeclarationExpression.getType();
        }
 else         if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
          FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
          type=fieldDeclaration.getType();
        }
        subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
        subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
        concreteMethodParametersRewrite.insertLast(parameter,null);
      }
    }
    for (    SingleVariableDeclaration abstractMethodParameter : typeCheckElimination.getAccessedParameters()) {
      if (!abstractMethodParameter.equals(returnedVariable)) {
        concreteMethodParametersRewrite.insertLast(abstractMethodParameter,null);
      }
    }
    for (    VariableDeclaration fragment : typeCheckElimination.getAccessedLocalVariables()) {
      if (!fragment.equals(returnedVariable)) {
        if (fragment instanceof SingleVariableDeclaration) {
          SingleVariableDeclaration singleVariableDeclaration=(SingleVariableDeclaration)fragment;
          concreteMethodParametersRewrite.insertLast(singleVariableDeclaration,null);
        }
 else         if (fragment instanceof VariableDeclarationFragment) {
          SingleVariableDeclaration parameter=subclassAST.newSingleVariableDeclaration();
          VariableDeclarationFragment variableDeclarationFragment=(VariableDeclarationFragment)fragment;
          Type type=null;
          if (variableDeclarationFragment.getParent() instanceof VariableDeclarationStatement) {
            VariableDeclarationStatement variableDeclarationStatement=(VariableDeclarationStatement)variableDeclarationFragment.getParent();
            type=variableDeclarationStatement.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof VariableDeclarationExpression) {
            VariableDeclarationExpression variableDeclarationExpression=(VariableDeclarationExpression)variableDeclarationFragment.getParent();
            type=variableDeclarationExpression.getType();
          }
 else           if (variableDeclarationFragment.getParent() instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration=(FieldDeclaration)variableDeclarationFragment.getParent();
            type=fieldDeclaration.getType();
          }
          subclassRewriter.set(parameter,SingleVariableDeclaration.TYPE_PROPERTY,type,null);
          subclassRewriter.set(parameter,SingleVariableDeclaration.NAME_PROPERTY,variableDeclarationFragment.getName(),null);
          concreteMethodParametersRewrite.insertLast(parameter,null);
        }
      }
    }
    Set<VariableDeclarationFragment> accessedFields=typeCheckElimination.getAccessedFields();
    Set<VariableDeclarationFragment> assignedFields=typeCheckElimination.getAssignedFields();
    Set<MethodDeclaration> accessedMethods=typeCheckElimination.getAccessedMethods();
    Set<IMethodBinding> superAccessedMethods=typeCheckElimination.getSuperAccessedMethods();
    Set<IVariableBinding> superAccessedFields=typeCheckElimination.getSuperAccessedFieldBindings();
    Set<IVariableBinding> superAssignedFields=typeCheckElimination.getSuperAssignedFieldBindings();
    if (accessedFields.size() > 0 || assignedFields.size() > 0 || accessedMethods.size() > 0 || superAccessedMethods.size() > 0 || superAccessedFields.size() > 0 || superAssignedFields.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);
      modifySourceVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields,superAccessedFields,superAssignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(enclosingIfStatementExpression);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newEnclosingIfStatementExpression);
      modifySourceMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      replaceThisExpressionWithContextParameterInMethodInvocationArguments(newMethodInvocations,subclassAST,subclassRewriter);
      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);
    }
    for (    Statement statement : statements) {
      Statement newStatement=(Statement)ASTNode.copySubtree(subclassAST,statement);
      List<Expression> oldVariableInstructions=expressionExtractor.getVariableInstructions(statement);
      List<Expression> newVariableInstructions=expressionExtractor.getVariableInstructions(newStatement);
      modifySourceVariableInstructionsInSubclass(oldVariableInstructions,newVariableInstructions,subclassAST,subclassRewriter,accessedFields,assignedFields,superAccessedFields,superAssignedFields);
      List<Expression> oldMethodInvocations=expressionExtractor.getMethodInvocations(statement);
      List<Expression> newMethodInvocations=expressionExtractor.getMethodInvocations(newStatement);
      modifySourceMethodInvocationsInSubclass(oldMethodInvocations,newMethodInvocations,subclassAST,subclassRewriter,accessedMethods,superAccessedMethods);
      replaceThisExpressionWithContextParameterInMethodInvocationArguments(newMethodInvocations,subclassAST,subclassRewriter);
      replaceThisExpressionWithContextParameterInClassInstanceCreationArguments(newStatement,subclassAST,subclassRewriter);
      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);
    if (!subclassAlreadyExists)     subclassTypesRewrite.insertLast(subclassTypeDeclaration,null);
    if (subclassDocument != null) {
      try {
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
          addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
        }
        Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=getRequiredImportDeclarationsBasedOnBranch(statements);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
          if (!requiredImportDeclarationsBasedOnSignature.contains(typeBinding))           addImportDeclaration(typeBinding,subclassCompilationUnit,subclassRewriter);
        }
        TextEdit subclassEdit=subclassRewriter.rewriteAST(subclassDocument,null);
        subclassEdit.apply(subclassDocument);
        CreateCompilationUnitChange createCompilationUnitChange=new CreateCompilationUnitChange(subclassICompilationUnit,subclassDocument.get(),subclassFile.getCharset());
        createCompilationUnitChanges.put(subclassICompilationUnit,createCompilationUnitChange);
      }
 catch (      CoreException e) {
        e.printStackTrace();
      }
catch (      MalformedTreeException e) {
        e.printStackTrace();
      }
catch (      BadLocationException e) {
        e.printStackTrace();
      }
    }
 else {
      try {
        MultiTextEdit subclassMultiTextEdit=new MultiTextEdit();
        CompilationUnitChange subclassCompilationUnitChange=new CompilationUnitChange("String_Node_Str",subclassICompilationUnit);
        subclassCompilationUnitChange.setEdit(subclassMultiTextEdit);
        compilationUnitChanges.put(subclassICompilationUnit,subclassCompilationUnitChange);
        ImportRewrite subclassImportRewrite=ImportRewrite.create(subclassCompilationUnit,true);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnSignature) {
          if (!typeBinding.isNested())           subclassImportRewrite.addImport(typeBinding);
        }
        Set<ITypeBinding> requiredImportDeclarationsBasedOnBranch=getRequiredImportDeclarationsBasedOnBranch(statements);
        for (        ITypeBinding typeBinding : requiredImportDeclarationsBasedOnBranch) {
          if (!typeBinding.isNested())           subclassImportRewrite.addImport(typeBinding);
        }
        TextEdit subclassImportEdit=subclassImportRewrite.rewriteImports(null);
        if (subclassImportRewrite.getCreatedImports().length > 0) {
          subclassMultiTextEdit.addChild(subclassImportEdit);
          subclassCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{subclassImportEdit}));
        }
        TextEdit subclassEdit=subclassRewriter.rewriteAST();
        subclassMultiTextEdit.addChild(subclassEdit);
        subclassCompilationUnitChange.addTextEditGroup(new TextEditGroup("String_Node_Str",new TextEdit[]{subclassEdit}));
      }
 catch (      JavaModelException e) {
        e.printStackTrace();
      }
catch (      CoreException e) {
        e.printStackTrace();
      }
    }
  }
}