class MustMayInitialize extends StructuredAnalysis {
  HashMap<Object, List> mapping;
  DavaFlowSet finalResult;

  public static final int MUST = 0;
  public static final int MAY = 1;

  int MUSTMAY;

  public MustMayInitialize(Object analyze, int MUSTorMAY) {
    super();
    mapping = new HashMap<Object, List>();
    MUSTMAY = MUSTorMAY;

    // System.out.println("MustOrMay value is"+MUSTorMAY);
    setMergeType();
    // the input to the process method is an empty DavaFlow Set meaning
    // out(start) ={} (no var initialized)
    finalResult = (DavaFlowSet) process(analyze, new DavaFlowSet());

    // finalResult contains the flowSet of having processed the whole of the
    // method
  }

  public DavaFlowSet emptyFlowSet() {
    return new DavaFlowSet();
  }

  public void setMergeType() {
    // System.out.println("here"+MUSTMAY);
    if (MUSTMAY == MUST) {
      MERGETYPE = INTERSECTION;
      // System.out.println("MERGETYPE set to intersection");
    } else if (MUSTMAY == MAY) {
      MERGETYPE = UNION;
      // System.out.println("MERGETYPE set to union");
    } else {
      throw new DavaFlowAnalysisException("Only allowed 0 or 1 for MUST or MAY values");
    }
  }

  /*
   * newInitialFlow set is used only for start of catch bodies and here we assume that no var is ever being initialized
   */
  @Override
  public DavaFlowSet newInitialFlow() {
    return new DavaFlowSet();
  }

  @Override
  public DavaFlowSet cloneFlowSet(DavaFlowSet flowSet) {
    return ((DavaFlowSet) flowSet).clone();
  }

  /*
   * By construction conditions never have assignment statements. Hence processing a condition has no effect on this analysis
   */
  @Override
  public DavaFlowSet processUnaryBinaryCondition(ASTUnaryBinaryCondition cond, DavaFlowSet input) {
    return input;
  }

  /*
   * By construction the synchronized Local is a Value and can definetly not have an assignment stmt Processing a synch local
   * has no effect on this analysis
   */
  @Override
  public DavaFlowSet processSynchronizedLocal(Local local, DavaFlowSet input) {
    return input;
  }

  /*
   * The switch key is stored as a value and hence can never have an assignment stmt Processing the switch key has no effect
   * on the analysis
   */
  @Override
  public DavaFlowSet processSwitchKey(Value key, DavaFlowSet input) {
    return input;
  }

  /*
   * This method internally invoked by the process method decides which Statement specialized method to call
   */
  @Override
  public DavaFlowSet processStatement(Stmt s, DavaFlowSet inSet) {<FILL_FUNCTION_BODY>}

  public boolean isMayInitialized(SootField field) {
    if (MUSTMAY == MAY) {
      Object temp = mapping.get(field);
      if (temp == null) {
        return false;
      } else {
        List list = (List) temp;
        if (list.size() == 0) {
          return false;
        } else {
          return true;
        }
      }
    } else {
      throw new RuntimeException("Cannot invoke isMayInitialized for a MUST analysis");
    }
  }

  public boolean isMayInitialized(Value local) {
    if (MUSTMAY == MAY) {
      Object temp = mapping.get(local);
      if (temp == null) {
        return false;
      } else {
        List list = (List) temp;
        if (list.size() == 0) {
          return false;
        } else {
          return true;
        }
      }
    } else {
      throw new RuntimeException("Cannot invoke isMayInitialized for a MUST analysis");
    }
  }

  public boolean isMustInitialized(SootField field) {
    if (MUSTMAY == MUST) {
      if (finalResult.contains(field)) {
        return true;
      }
      return false;
    } else {
      throw new RuntimeException("Cannot invoke isMustinitialized for a MAY analysis");
    }
  }

  public boolean isMustInitialized(Value local) {
    if (MUSTMAY == MUST) {
      if (finalResult.contains(local)) {
        return true;
      }
      return false;
    } else {
      throw new RuntimeException("Cannot invoke isMustinitialized for a MAY analysis");
    }
  }

  /*
   * Given a local ask for all def positions Notice this could be null in the case there was no definition
   */
  public List getDefs(Value local) {
    Object temp = mapping.get(local);
    if (temp == null) {
      return null;
    } else {
      return (List) temp;
    }
  }

  /*
   * Given a field ask for all def positions Notice this could be null in the case there was no definition
   */
  public List getDefs(SootField field) {
    Object temp = mapping.get(field);
    if (temp == null) {
      return null;
    } else {
      return (List) temp;
    }
  }

}

    /*
     * If this path will not be taken return no path straightaway
     */
    if (inSet == NOPATH) {
      return inSet;
    }

    if (s instanceof DefinitionStmt) {
      DavaFlowSet toReturn = (DavaFlowSet) cloneFlowSet(inSet);
      // x = expr;

      Value leftOp = ((DefinitionStmt) s).getLeftOp();

      SootField field = null;

      if (leftOp instanceof Local) {
        toReturn.add(leftOp);

        /*
         * Gather more information just in case someone might need the def points
         */
        Object temp = mapping.get(leftOp);
        List<Stmt> defs;

        if (temp == null) {
          // first definition
          defs = new ArrayList<Stmt>();
        } else {
          defs = (ArrayList<Stmt>) temp;
        }
        defs.add(s);
        mapping.put(leftOp, defs);

      } else if (leftOp instanceof FieldRef) {
        field = ((FieldRef) leftOp).getField();
        toReturn.add(field);

        /*
         * Gather more information just in case someone might need the def points
         */
        Object temp = mapping.get(field);
        List<Stmt> defs;

        if (temp == null) {
          // first definition
          defs = new ArrayList<Stmt>();
        } else {
          defs = (ArrayList<Stmt>) temp;
        }
        defs.add(s);

        mapping.put(field, defs);
      }
      return toReturn;
    }
    return inSet;
  
<methods>public void <init>() ,public abstract DavaFlowSet#RAW cloneFlowSet(DavaFlowSet#RAW) ,public void debug(java.lang.String, java.lang.String) ,public void debug(java.lang.String) ,public abstract DavaFlowSet#RAW emptyFlowSet() ,public DavaFlowSet#RAW getAfterSet(java.lang.Object) ,public DavaFlowSet#RAW getBeforeSet(java.lang.Object) ,public java.lang.String getLabel(soot.dava.internal.AST.ASTNode) ,public DavaFlowSet#RAW handleBreak(java.lang.String, DavaFlowSet#RAW, soot.dava.internal.AST.ASTNode) ,public DavaFlowSet#RAW handleContinue(java.lang.String, DavaFlowSet#RAW, soot.dava.internal.AST.ASTNode) ,public boolean isDifferent(DavaFlowSet#RAW, DavaFlowSet#RAW) ,public DavaFlowSet#RAW merge(DavaFlowSet#RAW, DavaFlowSet#RAW) ,public DavaFlowSet#RAW mergeExplicitAndImplicit(java.lang.String, DavaFlowSet#RAW, List#RAW, List#RAW) ,public abstract DavaFlowSet#RAW newInitialFlow() ,public void print(java.lang.Object) ,public DavaFlowSet#RAW process(java.lang.Object, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTIfElseNode(soot.dava.internal.AST.ASTIfElseNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTIfNode(soot.dava.internal.AST.ASTIfNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTLabeledBlockNode(soot.dava.internal.AST.ASTLabeledBlockNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTMethodNode(soot.dava.internal.AST.ASTMethodNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTNode(soot.dava.internal.AST.ASTNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTSynchronizedBlockNode(soot.dava.internal.AST.ASTSynchronizedBlockNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTTryNode(soot.dava.internal.AST.ASTTryNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processASTWhileNode(soot.dava.internal.AST.ASTWhileNode, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processAbruptStatements(soot.jimple.Stmt, DavaFlowSet#RAW) ,public DavaFlowSet#RAW processCondition(soot.dava.internal.AST.ASTCondition, DavaFlowSet#RAW) ,public final DavaFlowSet#RAW processSingleSubBodyNode(soot.dava.internal.AST.ASTNode, DavaFlowSet#RAW) ,public abstract DavaFlowSet#RAW processStatement(soot.jimple.Stmt, DavaFlowSet#RAW) ,public abstract DavaFlowSet#RAW processSwitchKey(soot.Value, DavaFlowSet#RAW) ,public abstract DavaFlowSet#RAW processSynchronizedLocal(soot.Local, DavaFlowSet#RAW) ,public abstract DavaFlowSet#RAW processUnaryBinaryCondition(soot.dava.internal.AST.ASTUnaryBinaryCondition, DavaFlowSet#RAW) ,public abstract void setMergeType() <variables>public static boolean DEBUG,public static boolean DEBUG_IF,public static boolean DEBUG_STATEMENTS,public static boolean DEBUG_TRY,public static boolean DEBUG_WHILE,final int INTERSECTION,public int MERGETYPE,DavaFlowSet#RAW NOPATH,final int UNDEFINED,final int UNION,HashMap#RAW afterSets,HashMap#RAW beforeSets