All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.toolkits.graph.HashMutableEdgeLabelledDirectedGraph Maven / Gradle / Ivy

package soot.toolkits.graph;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 1999 Patrice Pominville, Raja Vallee-Rai, Patrick Lam
 * Copyright (C) 2007 Richard L. Halpert
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * HashMap based implementation of a MutableEdgeLabelledDirectedGraph.
 *
 * @param 
 * @param 
 */
public class HashMutableEdgeLabelledDirectedGraph implements MutableEdgeLabelledDirectedGraph {
  private static final Logger logger = LoggerFactory.getLogger(HashMutableEdgeLabelledDirectedGraph.class);

  private static class DGEdge {

    N from;
    N to;

    public DGEdge(N from, N to) {
      this.from = from;
      this.to = to;
    }

    public N from() {
      return from;
    }

    public N to() {
      return to;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof DGEdge) {
        DGEdge other = (DGEdge) o;
        return from.equals(other.from) && to.equals(other.to);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(new Object[] { from, to });
    }
  }

  private static  List getCopy(Collection c) {
    return Collections.unmodifiableList(new ArrayList(c));
  }

  protected Map> nodeToPreds;
  protected Map> nodeToSuccs;

  protected Map, List> edgeToLabels;
  protected Map>> labelToEdges;

  protected Set heads;
  protected Set tails;

  public HashMutableEdgeLabelledDirectedGraph() {
    nodeToPreds = new HashMap>();
    nodeToSuccs = new HashMap>();
    edgeToLabels = new HashMap, List>();
    labelToEdges = new HashMap>>();
    heads = new HashSet();
    tails = new HashSet();
  }

  /**
   * Removes all nodes and edges.
   */
  public void clearAll() {
    nodeToPreds.clear();
    nodeToSuccs.clear();
    edgeToLabels.clear();
    labelToEdges.clear();
    heads.clear();
    tails.clear();
  }

  @Override
  public HashMutableEdgeLabelledDirectedGraph clone() {
    HashMutableEdgeLabelledDirectedGraph g = new HashMutableEdgeLabelledDirectedGraph();
    g.nodeToPreds.putAll(nodeToPreds);
    g.nodeToSuccs.putAll(nodeToSuccs);
    g.edgeToLabels.putAll(edgeToLabels);
    g.labelToEdges.putAll(labelToEdges);
    g.heads.addAll(heads);
    g.tails.addAll(tails);
    return g;
  }

  /* Returns an unbacked list of heads for this graph. */
  @Override
  public List getHeads() {
    return getCopy(heads);
  }

  /* Returns an unbacked list of tails for this graph. */
  @Override
  public List getTails() {
    return getCopy(tails);
  }

  @Override
  public List getPredsOf(N s) {
    List preds = nodeToPreds.get(s);
    if (preds != null) {
      return Collections.unmodifiableList(preds);
    }

    throw new RuntimeException(s + "not in graph!");
  }

  @Override
  public List getSuccsOf(N s) {
    List succs = nodeToSuccs.get(s);
    if (succs != null) {
      return Collections.unmodifiableList(succs);
    }

    throw new RuntimeException(s + "not in graph!");
  }

  @Override
  public int size() {
    return nodeToPreds.keySet().size();
  }

  @Override
  public Iterator iterator() {
    return nodeToPreds.keySet().iterator();
  }

  @Override
  public void addEdge(N from, N to, L label) {
    if (from == null || to == null) {
      throw new RuntimeException("edge from or to null");
    }

    if (label == null) {
      throw new RuntimeException("edge with null label");
    }

    if (containsEdge(from, to, label)) {
      return;
    }

    List succsList = nodeToSuccs.get(from);
    if (succsList == null) {
      throw new RuntimeException(from + " not in graph!");
    }

    List predsList = nodeToPreds.get(to);
    if (predsList == null) {
      throw new RuntimeException(to + " not in graph!");
    }

    heads.remove(to);
    tails.remove(from);

    if (!succsList.contains(to)) {
      succsList.add(to);
    }
    if (!predsList.contains(from)) {
      predsList.add(from);
    }

    DGEdge edge = new DGEdge(from, to);
    if (!edgeToLabels.containsKey(edge)) {
      edgeToLabels.put(edge, new ArrayList());
    }
    List labels = edgeToLabels.get(edge);

    if (!labelToEdges.containsKey(label)) {
      labelToEdges.put(label, new ArrayList>());
    }
    List> edges = labelToEdges.get(label);

    // if(!labels.contains(label))
    labels.add(label);
    // if(!edges.contains(edge))
    edges.add(edge);
  }

  @Override
  public List getLabelsForEdges(N from, N to) {
    DGEdge edge = new DGEdge(from, to);
    return edgeToLabels.get(edge);
  }

  @Override
  public MutableDirectedGraph getEdgesForLabel(L label) {
    List> edges = labelToEdges.get(label);
    MutableDirectedGraph ret = new HashMutableDirectedGraph();
    if (edges == null) {
      return ret;
    }
    for (DGEdge edge : edges) {
      if (!ret.containsNode(edge.from())) {
        ret.addNode(edge.from());
      }
      if (!ret.containsNode(edge.to())) {
        ret.addNode(edge.to());
      }
      ret.addEdge(edge.from(), edge.to());
    }
    return ret;
  }

  @Override
  public void removeEdge(N from, N to, L label) {
    if (!containsEdge(from, to, label)) {
      return;
    }

    DGEdge edge = new DGEdge(from, to);
    List labels = edgeToLabels.get(edge);
    if (labels == null) {
      throw new RuntimeException("edge " + edge + " not in graph!");
    }

    List> edges = labelToEdges.get(label);
    if (edges == null) {
      throw new RuntimeException("label " + label + " not in graph!");
    }

    labels.remove(label);
    edges.remove(edge);

    // if this edge has no more labels, then it's gone!
    if (labels.isEmpty()) {
      edgeToLabels.remove(edge);

      List succsList = nodeToSuccs.get(from);
      if (succsList == null) {
        throw new RuntimeException(from + " not in graph!");
      }

      List predsList = nodeToPreds.get(to);
      if (predsList == null) {
        throw new RuntimeException(to + " not in graph!");
      }

      succsList.remove(to);
      predsList.remove(from);

      if (succsList.isEmpty()) {
        tails.add(from);
      }

      if (predsList.isEmpty()) {
        heads.add(to);
      }
    }

    // if this label has no more edges, then who cares?
    if (edges.isEmpty()) {
      labelToEdges.remove(label);
    }
  }

  @Override
  public void removeAllEdges(N from, N to) {
    if (!containsAnyEdge(from, to)) {
      return;
    }

    DGEdge edge = new DGEdge(from, to);
    List labels = edgeToLabels.get(edge);
    if (labels == null) {
      throw new RuntimeException("edge " + edge + " not in graph!");
    }

    for (L label : getCopy(labels)) {
      removeEdge(from, to, label);
    }
  }

  @Override
  public void removeAllEdges(L label) {
    if (!containsAnyEdge(label)) {
      return;
    }

    List> edges = labelToEdges.get(label);
    if (edges == null) {
      throw new RuntimeException("label " + label + " not in graph!");
    }

    for (DGEdge edge : getCopy(edges)) {
      removeEdge(edge.from(), edge.to(), label);
    }
  }

  @Override

  public boolean containsEdge(N from, N to, L label) {
    List labels = edgeToLabels.get(new DGEdge<>(from, to));
    return labels != null && labels.contains(label);
  }

  @Override

  public boolean containsAnyEdge(N from, N to) {
    List labels = edgeToLabels.get(new DGEdge<>(from, to));
    return labels != null && !labels.isEmpty();
  }

  @Override

  public boolean containsAnyEdge(L label) {
    List> edges = labelToEdges.get(label);
    return edges != null && !edges.isEmpty();
  }

  @Override
  public boolean containsNode(N node) {
    return nodeToPreds.keySet().contains(node);
  }

  @Override
  public void addNode(N node) {
    if (containsNode(node)) {
      throw new RuntimeException("Node already in graph");
    }

    nodeToSuccs.put(node, new ArrayList());
    nodeToPreds.put(node, new ArrayList());
    heads.add(node);
    tails.add(node);
  }

  @Override
  public void removeNode(N node) {
    for (N n : new ArrayList(nodeToSuccs.get(node))) {
      removeAllEdges(node, n);
    }
    nodeToSuccs.remove(node);

    for (N n : new ArrayList(nodeToPreds.get(node))) {
      removeAllEdges(n, node);
    }
    nodeToPreds.remove(node);

    heads.remove(node);
    tails.remove(node);
  }

  public void printGraph() {
    for (N node : this) {
      logger.debug("Node = " + node);

      logger.debug("Preds:");
      for (N pred : getPredsOf(node)) {
        DGEdge edge = new DGEdge(pred, node);
        List labels = edgeToLabels.get(edge);
        logger.debug("     " + pred + " [" + labels + "]");
      }

      logger.debug("Succs:");
      for (N succ : getSuccsOf(node)) {
        DGEdge edge = new DGEdge(node, succ);
        List labels = edgeToLabels.get(edge);
        logger.debug("     " + succ + " [" + labels + "]");
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy