@Override
 public void add(Object obj) {
   // TODO Auto-generated method stub
   Pair<Value, Constraints> pair = (Pair<Value, Constraints>) obj;
   if (valueToConstraints.containsKey(pair.getO1())) {
     Constraints cons = valueToConstraints.get(pair.getO1());
     /*Maybe its union in some cases check.......not used nor*/
     cons.concatConstraints(pair.getO2());
   } else valueToConstraints.put(pair.getO1(), pair.getO2());
 }
  public ConstraintFlowSet concatConstraints(ConstraintFlowSet toBeConcatenated) {
    ConstraintFlowSet concatinatedConstraints = new ConstraintFlowSet();
    Iterator<Pair<Value, Constraints>> it1 = toBeConcatenated.toList().iterator();
    boolean found = false;
    while (it1.hasNext()) {
      Pair<Value, Constraints> pair = it1.next();
      Constraints baseConstraints = this.valueToConstraints.get(pair.getO1());
      if (baseConstraints != null) {
        found = true;
        Constraints c = baseConstraints.concatConstraints(pair.getO2());
        concatinatedConstraints.add(new Pair<Value, Constraints>(pair.getO1(), c));
      } else concatinatedConstraints.add(pair);
    }

    /*At constraints in flow1 but not in flow2*/
    Iterator<Pair<Value, Constraints>> it2 = this.toList().iterator();

    while (it2.hasNext()) {
      Pair<Value, Constraints> pair = it2.next();
      Constraints cAtFlow1 = concatinatedConstraints.valueToConstraints.get(pair.getO1());
      if (cAtFlow1 == null) concatinatedConstraints.add(pair);
    }

    return concatinatedConstraints;
  }
  public ConstraintFlowSet mergeConstraints(ConstraintFlowSet flow2) {
    ConstraintFlowSet mergedConstraints = new ConstraintFlowSet();
    Iterator<Pair<Value, Constraints>> it1 = this.toList().iterator();

    while (it1.hasNext()) {
      Pair<Value, Constraints> pair = it1.next();
      Constraints cInFlow2 = flow2.valueToConstraints.get(pair.getO1());
      // Constraints cInFlow2 = GetConstraintsInArray((ArraySparseSet) flow2, pair.getO1());
      if (cInFlow2 == null) mergedConstraints.add(pair);
      else {
        Constraints c = cInFlow2.mergeConstraintsAlongFlow(pair.getO2());
        mergedConstraints.add(new Pair<Value, Constraints>(pair.getO1(), c));
      }
    }
    /*At constraints in flow1 but not in flow2*/
    Iterator<Pair<Value, Constraints>> it2 = flow2.toList().iterator();

    while (it2.hasNext()) {
      Pair<Value, Constraints> pair = it2.next();
      Constraints cAtFlow1 = this.valueToConstraints.get(pair.getO1());
      ;
      if (cAtFlow1 == null) mergedConstraints.add(pair);
    }
    return mergedConstraints;
  }
 @Override
 public String toString() {
   String s = "";
   for (Object obj : this.toList()) {
     Pair<Value, Constraints> pair = (Pair<Value, Constraints>) obj;
     String constraints = pair.getO2().toString();
     String var = pair.getO1().toString();
     s = s + "{" + var + "->" + constraints + "}" + ",";
   }
   return s;
 }
  public ContextSensitiveInfo(PAG pag) {
    // set up method to node map
    for (Iterator iter = pag.getVarNodeNumberer().iterator(); iter.hasNext(); ) {
      VarNode varNode = (VarNode) iter.next();
      if (varNode instanceof LocalVarNode) {
        LocalVarNode local = (LocalVarNode) varNode;
        SootMethod method = local.getMethod();
        assert method != null : local;
        methodToNodes.put(method, local);
        if (SootUtil.isRetNode(local)) {
          methodToOutPorts.put(method, local);
        }
        if (SootUtil.isParamNode(local)) {
          methodToInPorts.put(method, local);
        }
      }
    }
    int callSiteNum = 0;
    // first, add regular assigns
    Set assignSources = pag.simpleSources();
    for (Iterator iter = assignSources.iterator(); iter.hasNext(); ) {
      VarNode assignSource = (VarNode) iter.next();
      if (skipNode(assignSource)) {
        continue;
      }
      boolean sourceGlobal = assignSource instanceof GlobalVarNode;
      Node[] assignTargets = pag.simpleLookup(assignSource);
      for (int i = 0; i < assignTargets.length; i++) {
        VarNode assignTarget = (VarNode) assignTargets[i];
        if (skipNode(assignTarget)) continue;
        boolean isFinalizerNode = false;
        if (assignTarget instanceof LocalVarNode) {
          LocalVarNode local = (LocalVarNode) assignTarget;
          SootMethod method = local.getMethod();
          if (method.toString().indexOf("finalize()") != -1 && SootUtil.isThisNode(local)) {
            isFinalizerNode = true;
          }
        }
        boolean targetGlobal = assignTarget instanceof GlobalVarNode;
        AssignEdge assignEdge = new AssignEdge(assignSource, assignTarget);
        // handle weird finalizers
        if (isFinalizerNode) {
          assignEdge.setParamEdge();
          Integer callSite = new Integer(callSiteNum++);
          assignEdge.setCallSite(callSite);
        }
        addAssignEdge(assignEdge);
        if (sourceGlobal) {
          if (targetGlobal) {
            // System.err.println("G2G " + assignSource + " --> "
            // + assignTarget);
          } else {
            SootMethod method = ((LocalVarNode) assignTarget).getMethod();
            // don't want to include things assigned something that
            // is already an in port
            if (!methodToInPorts.get(method).contains(assignTarget)) {
              methodToInPorts.put(method, assignSource);
            }
          }
        } else {
          if (targetGlobal) {
            SootMethod method = ((LocalVarNode) assignSource).getMethod();
            // don't want to include things assigned from something
            // that
            // is already an out port
            if (!methodToOutPorts.get(method).contains(assignSource)) {
              methodToOutPorts.put(method, assignTarget);
            }
          }
        }
      }
    }
    // now handle calls
    HashMultiMap callAssigns = pag.callAssigns;
    PrintWriter callSiteWriter = null;
    if (PRINT_CALL_SITE_INFO) {
      try {
        callSiteWriter = new PrintWriter(new FileWriter("callSiteInfo"), true);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    for (Iterator iter = callAssigns.keySet().iterator(); iter.hasNext(); ) {
      InvokeExpr ie = (InvokeExpr) iter.next();
      Integer callSite = new Integer(callSiteNum++);
      callSiteToInvokedMethod.put(callSite, ie.getMethod());
      SootMethod invokingMethod = pag.callToMethod.get(ie);
      callSiteToInvokingMethod.put(callSite, invokingMethod);
      if (PRINT_CALL_SITE_INFO) {
        callSiteWriter.println(callSite + " " + callSiteToInvokingMethod.get(callSite) + " " + ie);
      }
      if (pag.virtualCallsToReceivers.containsKey(ie)) {
        LocalVarNode receiver = (LocalVarNode) pag.virtualCallsToReceivers.get(ie);
        assert receiver != null;
        virtCallSiteToReceiver.put(callSite, receiver);
        receiverToVirtCallSites.put(receiver, callSite);
      }
      Set curEdges = callAssigns.get(ie);
      for (Iterator iterator = curEdges.iterator(); iterator.hasNext(); ) {
        Pair callAssign = (Pair) iterator.next();
        VarNode src = (VarNode) callAssign.getO1();
        VarNode dst = (VarNode) callAssign.getO2();
        if (skipNode(src)) {
          continue;
        }
        ArraySet edges = getAssignBarEdges(src);
        AssignEdge edge = null;
        for (int i = 0; i < edges.size() && edge == null; i++) {
          AssignEdge curEdge = (AssignEdge) edges.get(i);
          if (curEdge.getDst() == dst) {
            edge = curEdge;
          }
        }
        assert edge != null : "no edge from " + src + " to " + dst;
        boolean edgeFromOtherCallSite = edge.isCallEdge();
        if (edgeFromOtherCallSite) {
          edge = new AssignEdge(src, dst);
        }
        edge.setCallSite(callSite);
        callSiteToEdges.put(callSite, edge);
        if (SootUtil.isParamNode(dst)) {
          // assert src instanceof LocalVarNode : src + " " + dst;
          edge.setParamEdge();
          SootMethod invokedMethod = ((LocalVarNode) dst).getMethod();
          callSiteToTargets.put(callSite, invokedMethod);
          callSitesInvokingMethod.put(invokedMethod, callSite);
          // assert src instanceof LocalVarNode : src + " NOT LOCAL";
          if (src instanceof LocalVarNode) {
            callSitesInMethod.put(((LocalVarNode) src).getMethod(), callSite);
          }
        } else if (SootUtil.isRetNode(src)) {
          edge.setReturnEdge();
          SootMethod invokedMethod = ((LocalVarNode) src).getMethod();
          callSiteToTargets.put(callSite, invokedMethod);
          callSitesInvokingMethod.put(invokedMethod, callSite);
          if (dst instanceof LocalVarNode) {
            callSitesInMethod.put(((LocalVarNode) dst).getMethod(), callSite);
          }
        } else {
          assert false : "weird call edge " + callAssign;
        }
        if (edgeFromOtherCallSite) {
          addAssignEdge(edge);
        }
      }
    }
    // System.err.println(callSiteNum + " call sites");
    assert callEdgesReasonable();
    if (PRINT_CALL_SITE_INFO) {
      callSiteWriter.close();
    }
    // assert assignEdgesWellFormed(pag) == null :
    // assignEdgesWellFormed(pag);

  }