class BooleanConditionSimplification extends DepthFirstAdapter {

  public BooleanConditionSimplification(boolean verbose) {
    super(verbose);
  }

  public void caseASTStatementSequenceNode(ASTStatementSequenceNode node) {
  }

  public BooleanConditionSimplification() {
  }

  /*
   * The method checks whether a particular ASTBinaryCondition is a comparison of a local with a boolean If so the
   * ASTBinaryCondition is replaced by a ASTUnaryCondition
   */
  public void outASTIfNode(ASTIfNode node) {<FILL_FUNCTION_BODY>}

  public void outASTIfElseNode(ASTIfElseNode node) {
    ASTCondition condition = node.get_Condition();
    if (condition instanceof ASTBinaryCondition) {
      ConditionExpr condExpr = ((ASTBinaryCondition) condition).getConditionExpr();
      Value unary = checkBooleanUse(condExpr);
      if (unary != null) {
        node.set_Condition(new ASTUnaryCondition(unary));
      }
    }
  }

  public void outASTWhileNode(ASTWhileNode node) {
    ASTCondition condition = node.get_Condition();
    if (condition instanceof ASTBinaryCondition) {
      ConditionExpr condExpr = ((ASTBinaryCondition) condition).getConditionExpr();
      Value unary = checkBooleanUse(condExpr);
      if (unary != null) {
        node.set_Condition(new ASTUnaryCondition(unary));
      }
    }
  }

  public void outASTDoWhileNode(ASTDoWhileNode node) {
    ASTCondition condition = node.get_Condition();
    if (condition instanceof ASTBinaryCondition) {
      ConditionExpr condExpr = ((ASTBinaryCondition) condition).getConditionExpr();
      Value unary = checkBooleanUse(condExpr);
      if (unary != null) {
        node.set_Condition(new ASTUnaryCondition(unary));
      }
    }
  }

  private Value checkBooleanUse(ConditionExpr condition) {
    // check whether the condition qualifies as a boolean use
    if (condition instanceof NeExpr || condition instanceof EqExpr) {
      Value op1 = condition.getOp1();
      Value op2 = condition.getOp2();
      if (op1 instanceof DIntConstant) {
        Type op1Type = ((DIntConstant) op1).type;
        if (op1Type instanceof BooleanType) {
          return decideCondition(op2, ((DIntConstant) op1).toString(), condition);
        }
      } else if (op2 instanceof DIntConstant) {
        Type op2Type = ((DIntConstant) op2).type;
        if (op2Type instanceof BooleanType) {
          return decideCondition(op1, ((DIntConstant) op2).toString(), condition);
        }
      } else {
        return null;// meaning no Value used as boolean found
      }
    }
    return null; // meaning no local used as boolean found
  }

  /*
   * Used to decide what the condition should be if we are converting from ConditionExpr to Value A != false/0 --> A A !=
   * true/1 --> !A A == false/0 --> !A A == true/1 --> A
   */
  private Value decideCondition(Value A, String truthString, ConditionExpr condition) {
    int truthValue = 0;
    boolean notEqual = false;

    // find out whether we are dealing with a false or true
    if (truthString.compareTo("false") == 0) {
      truthValue = 0;
    } else if (truthString.compareTo("true") == 0) {
      truthValue = 1;
    } else {
      throw new RuntimeException();
    }

    // find out whether the comparison operator is != or ==
    if (condition instanceof NeExpr) {
      notEqual = true;
    } else if (condition instanceof EqExpr) {
      notEqual = false;
    } else {
      throw new RuntimeException();
    }

    // decide and return
    if (notEqual && truthValue == 0) { // A != false -->A
      return A;
    } else if (notEqual && truthValue == 1) {
      // A != true --> !A
      if (A instanceof DNotExpr) {
        // A is actually !B
        return ((DNotExpr) A).getOp();
      } else {
        return (new DNotExpr(A));
      }
    } else if (!notEqual && truthValue == 0) {
      // A == false --> !A
      if (A instanceof DNotExpr) {
        // A is actually !B
        return ((DNotExpr) A).getOp();
      } else {
        return new DNotExpr(A);
      }
    } else if (!notEqual && truthValue == 1) {
      // A == true --> A
      return A;
    } else {
      throw new RuntimeException();
    }
  }

}

    ASTCondition condition = node.get_Condition();
    if (condition instanceof ASTBinaryCondition) {
      ConditionExpr condExpr = ((ASTBinaryCondition) condition).getConditionExpr();
      Value unary = checkBooleanUse(condExpr);
      if (unary != null) {
        node.set_Condition(new ASTUnaryCondition(unary));
      }
    }
  
<methods>public void <init>() ,public void <init>(boolean) ,public void caseASTAndCondition(soot.dava.internal.AST.ASTAndCondition) ,public void caseASTBinaryCondition(soot.dava.internal.AST.ASTBinaryCondition) ,public void caseASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode) ,public void caseASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode) ,public void caseASTIfElseNode(soot.dava.internal.AST.ASTIfElseNode) ,public void caseASTIfNode(soot.dava.internal.AST.ASTIfNode) ,public void caseASTLabeledBlockNode(soot.dava.internal.AST.ASTLabeledBlockNode) ,public void caseASTMethodNode(soot.dava.internal.AST.ASTMethodNode) ,public void caseASTOrCondition(soot.dava.internal.AST.ASTOrCondition) ,public void caseASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) ,public void caseASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode) ,public void caseASTSynchronizedBlockNode(soot.dava.internal.AST.ASTSynchronizedBlockNode) ,public void caseASTTryNode(soot.dava.internal.AST.ASTTryNode) ,public void caseASTUnaryCondition(soot.dava.internal.AST.ASTUnaryCondition) ,public void caseASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode) ,public void caseASTWhileNode(soot.dava.internal.AST.ASTWhileNode) ,public void caseArrayRef(soot.jimple.ArrayRef) ,public void caseBinopExpr(soot.jimple.BinopExpr) ,public void caseCastExpr(soot.jimple.CastExpr) ,public void caseDVariableDeclarationStmt(soot.dava.internal.javaRep.DVariableDeclarationStmt) ,public void caseDefinitionStmt(soot.jimple.DefinitionStmt) ,public void caseExpr(soot.jimple.Expr) ,public void caseExprOrRefValueBox(soot.ValueBox) ,public void caseInstanceFieldRef(soot.jimple.InstanceFieldRef) ,public void caseInstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) ,public void caseInstanceOfExpr(soot.jimple.InstanceOfExpr) ,public void caseInvokeExpr(soot.jimple.InvokeExpr) ,public void caseInvokeStmt(soot.jimple.InvokeStmt) ,public void caseNewArrayExpr(soot.jimple.NewArrayExpr) ,public void caseNewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) ,public void caseRef(soot.jimple.Ref) ,public void caseReturnStmt(soot.jimple.ReturnStmt) ,public void caseStaticFieldRef(soot.jimple.StaticFieldRef) ,public void caseStmt(soot.jimple.Stmt) ,public void caseThrowStmt(soot.jimple.ThrowStmt) ,public void caseType(soot.Type) ,public void caseUnopExpr(soot.jimple.UnopExpr) ,public void caseValue(soot.Value) ,public void debug(java.lang.String, java.lang.String, java.lang.String) ,public void decideCaseExpr(soot.jimple.Expr) ,public void decideCaseExprOrRef(soot.Value) ,public void decideCaseRef(soot.jimple.Ref) ,public void inASTAndCondition(soot.dava.internal.AST.ASTAndCondition) ,public void inASTBinaryCondition(soot.dava.internal.AST.ASTBinaryCondition) ,public void inASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode) ,public void inASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode) ,public void inASTIfElseNode(soot.dava.internal.AST.ASTIfElseNode) ,public void inASTIfNode(soot.dava.internal.AST.ASTIfNode) ,public void inASTLabeledBlockNode(soot.dava.internal.AST.ASTLabeledBlockNode) ,public void inASTMethodNode(soot.dava.internal.AST.ASTMethodNode) ,public void inASTOrCondition(soot.dava.internal.AST.ASTOrCondition) ,public void inASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) ,public void inASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode) ,public void inASTSynchronizedBlockNode(soot.dava.internal.AST.ASTSynchronizedBlockNode) ,public void inASTTryNode(soot.dava.internal.AST.ASTTryNode) ,public void inASTUnaryCondition(soot.dava.internal.AST.ASTUnaryCondition) ,public void inASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode) ,public void inASTWhileNode(soot.dava.internal.AST.ASTWhileNode) ,public void inArrayRef(soot.jimple.ArrayRef) ,public void inBinopExpr(soot.jimple.BinopExpr) ,public void inCastExpr(soot.jimple.CastExpr) ,public void inDVariableDeclarationStmt(soot.dava.internal.javaRep.DVariableDeclarationStmt) ,public void inDefinitionStmt(soot.jimple.DefinitionStmt) ,public void inExpr(soot.jimple.Expr) ,public void inExprOrRefValueBox(soot.ValueBox) ,public void inInstanceFieldRef(soot.jimple.InstanceFieldRef) ,public void inInstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) ,public void inInstanceOfExpr(soot.jimple.InstanceOfExpr) ,public void inInvokeExpr(soot.jimple.InvokeExpr) ,public void inInvokeStmt(soot.jimple.InvokeStmt) ,public void inNewArrayExpr(soot.jimple.NewArrayExpr) ,public void inNewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) ,public void inRef(soot.jimple.Ref) ,public void inReturnStmt(soot.jimple.ReturnStmt) ,public void inStaticFieldRef(soot.jimple.StaticFieldRef) ,public void inStmt(soot.jimple.Stmt) ,public void inThrowStmt(soot.jimple.ThrowStmt) ,public void inType(soot.Type) ,public void inUnopExpr(soot.jimple.UnopExpr) ,public void inValue(soot.Value) ,public void normalRetrieving(soot.dava.internal.AST.ASTNode) ,public void outASTAndCondition(soot.dava.internal.AST.ASTAndCondition) ,public void outASTBinaryCondition(soot.dava.internal.AST.ASTBinaryCondition) ,public void outASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode) ,public void outASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode) ,public void outASTIfElseNode(soot.dava.internal.AST.ASTIfElseNode) ,public void outASTIfNode(soot.dava.internal.AST.ASTIfNode) ,public void outASTLabeledBlockNode(soot.dava.internal.AST.ASTLabeledBlockNode) ,public void outASTMethodNode(soot.dava.internal.AST.ASTMethodNode) ,public void outASTOrCondition(soot.dava.internal.AST.ASTOrCondition) ,public void outASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) ,public void outASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode) ,public void outASTSynchronizedBlockNode(soot.dava.internal.AST.ASTSynchronizedBlockNode) ,public void outASTTryNode(soot.dava.internal.AST.ASTTryNode) ,public void outASTUnaryCondition(soot.dava.internal.AST.ASTUnaryCondition) ,public void outASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode) ,public void outASTWhileNode(soot.dava.internal.AST.ASTWhileNode) ,public void outArrayRef(soot.jimple.ArrayRef) ,public void outBinopExpr(soot.jimple.BinopExpr) ,public void outCastExpr(soot.jimple.CastExpr) ,public void outDVariableDeclarationStmt(soot.dava.internal.javaRep.DVariableDeclarationStmt) ,public void outDefinitionStmt(soot.jimple.DefinitionStmt) ,public void outExpr(soot.jimple.Expr) ,public void outExprOrRefValueBox(soot.ValueBox) ,public void outInstanceFieldRef(soot.jimple.InstanceFieldRef) ,public void outInstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) ,public void outInstanceOfExpr(soot.jimple.InstanceOfExpr) ,public void outInvokeExpr(soot.jimple.InvokeExpr) ,public void outInvokeStmt(soot.jimple.InvokeStmt) ,public void outNewArrayExpr(soot.jimple.NewArrayExpr) ,public void outNewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) ,public void outRef(soot.jimple.Ref) ,public void outReturnStmt(soot.jimple.ReturnStmt) ,public void outStaticFieldRef(soot.jimple.StaticFieldRef) ,public void outStmt(soot.jimple.Stmt) ,public void outThrowStmt(soot.jimple.ThrowStmt) ,public void outType(soot.Type) ,public void outUnopExpr(soot.jimple.UnopExpr) ,public void outValue(soot.Value) <variables>public boolean DEBUG,boolean verbose